databag/net/server/internal/sturn/sturn.go

171 lines
3.2 KiB
Go
Raw Normal View History

2023-04-07 19:30:05 +00:00
package sturn
2023-04-07 18:42:17 +00:00
import (
// "encoding/json"
2023-04-08 00:47:04 +00:00
"encoding/hex"
2023-04-07 18:42:17 +00:00
"sync"
2023-04-08 00:47:04 +00:00
"github.com/theckman/go-securerandom"
2023-04-07 18:42:17 +00:00
// "time"
2023-04-08 00:47:04 +00:00
"errors"
2023-04-07 18:42:17 +00:00
"fmt"
"net"
)
var sturn *Sturn
2023-04-07 19:30:05 +00:00
const SturnKeepAlive = 3600
2023-04-07 22:02:31 +00:00
const SturnMaxSize = 1024
const SturnMaxBindFail = 16
2023-04-08 00:47:04 +00:00
const SturnNonceSize = 8
const SturnPassSize = 8
2023-04-07 18:42:17 +00:00
2023-04-10 22:14:51 +00:00
type SturnAllocation struct {
source string
transaction []byte
response []byte
port int
2023-04-11 05:41:39 +00:00
permissions []string
conn net.PacketConn
2023-04-10 22:14:51 +00:00
}
2023-04-07 18:42:17 +00:00
type SturnSession struct {
2023-04-08 00:47:04 +00:00
user string
auth string
2023-04-11 05:41:39 +00:00
allocations map[string]*SturnAllocation
2023-04-07 18:42:17 +00:00
}
type Sturn struct {
sync sync.Mutex
2023-04-08 00:47:04 +00:00
sessionId int
sessions map[string]*SturnSession
closing bool
2023-04-08 05:59:09 +00:00
port int
2023-04-07 18:42:17 +00:00
conn *net.PacketConn
closed chan bool
2023-04-07 22:02:31 +00:00
buf []byte
2023-04-08 00:47:04 +00:00
publicIp string
2023-04-08 05:59:09 +00:00
relayStart int
relayCount int
relayPorts map[int]bool
relayIndex int
2023-04-07 18:42:17 +00:00
}
2023-04-08 05:59:09 +00:00
func Listen(port int, relayStart int, relayCount int) (error) {
2023-04-07 18:42:17 +00:00
if (sturn != nil) {
(*sturn.conn).Close()
<-sturn.closed
sturn = nil
}
address := fmt.Sprintf(":%d", port)
conn, err := net.ListenPacket("udp", address)
if err != nil {
return err
}
2023-04-08 05:59:09 +00:00
relayPorts := make(map[int]bool)
for i := 0; i < relayCount; i++ {
relayPorts[i] = true
}
2023-04-10 22:14:51 +00:00
sturn = &Sturn{
2023-04-08 00:47:04 +00:00
sessionId: 0,
closing: false,
2023-04-07 18:42:17 +00:00
port: port,
relayStart: relayStart,
2023-04-08 05:59:09 +00:00
relayCount: relayCount,
relayPorts: relayPorts,
2023-04-07 18:42:17 +00:00
conn: &conn,
2023-04-07 22:02:31 +00:00
buf: make([]byte, SturnMaxSize),
2023-04-10 22:14:51 +00:00
sessions: make(map[string]*SturnSession),
2023-04-07 18:42:17 +00:00
}
go sturn.serve(conn);
return nil
}
func Close() {
if (sturn != nil) {
(*sturn.conn).Close()
<-sturn.closed
sturn = nil
}
}
func (s *Sturn) serve(conn net.PacketConn) {
for {
2023-04-07 22:02:31 +00:00
buf := make([]byte, SturnMaxSize)
2023-04-07 18:42:17 +00:00
n, addr, err := conn.ReadFrom(buf)
if err != nil {
fmt.Println(err)
return
}
2023-04-07 19:30:05 +00:00
s.handleMessage(buf[:n], addr);
2023-04-07 18:42:17 +00:00
}
2023-04-07 19:30:05 +00:00
2023-04-08 00:47:04 +00:00
s.sync.Lock()
s.closing = true
for _, session := range s.sessions {
// TODO cleanup session
fmt.Println(session)
}
s.sync.Unlock()
2023-04-07 19:30:05 +00:00
2023-04-07 18:42:17 +00:00
s.closed <- true
}
2023-04-08 00:47:04 +00:00
func TestSession() {
if sturn != nil {
sturn.sync.Lock()
defer sturn.sync.Unlock()
if sturn.closing {
return
}
session := &SturnSession{
user: "user",
auth: "pass",
2023-04-11 05:41:39 +00:00
allocations: make(map[string]*SturnAllocation),
2023-04-08 00:47:04 +00:00
}
sturn.sessions["user"] = session
}
}
func (s *Sturn) addSession() (*SturnSession, error) {
s.sync.Lock()
defer s.sync.Unlock()
if !s.closing {
return nil, errors.New("closing sturn")
}
s.sessionId += 1
user := fmt.Sprintf("%08d", s.sessionId)
authBin, authErr := securerandom.Bytes(SturnPassSize)
if authErr != nil {
return nil, authErr
}
session := &SturnSession{
user: user,
auth: hex.EncodeToString(authBin),
2023-04-11 05:41:39 +00:00
allocations: make(map[string]*SturnAllocation),
2023-04-08 00:47:04 +00:00
}
s.sessions[user] = session
return session, nil
}
2023-04-08 05:59:09 +00:00
func (s *Sturn) getRelayPort() (int, error) {
s.relayIndex += 1;
for i := 0; i < s.relayCount; i++ {
key := (i + s.relayIndex) % s.relayCount;
if s.relayPorts[key] {
s.relayPorts[key] = false
return s.relayStart + key, nil
}
}
return 0, errors.New("no available relay port")
}
func (s *Sturn) setRelayPort(port int) {
key := port - s.relayStart
s.relayPorts[key] = true
}