diff --git a/config/config.go b/config/config.go index b013274..d861154 100644 --- a/config/config.go +++ b/config/config.go @@ -6,8 +6,9 @@ import ( ) type Config struct { - LocalAddr UDP `json:"localAddr"` - RemoteAddr UDP `json:"remoteAddr"` + LocalAddr UDP `json:"localAddr"` + RemoteAddr UDP `json:"remoteAddr"` + Server Server `json:"server"` } type UDP struct { @@ -15,6 +16,13 @@ type UDP struct { Port int `json:"port"` } +type Server struct { + Enable bool `json:"enable"` + Expire int64 `json:"expire"` + MAX int `json:"max"` + UDP UDP `json:"udp"` +} + func ParseConfig(file string) (*Config, error) { raw, err := os.ReadFile(file) if err != nil { diff --git a/main.go b/main.go index 930b641..de05e22 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( config2 "github.com/usrpserv/config" + "github.com/usrpserv/server" "github.com/usrpserv/usrp" "log" "net" @@ -16,6 +17,10 @@ func main() { client := usrp.NewClient(net.UDPAddr{Port: config.RemoteAddr.Port, IP: net.ParseIP(config.RemoteAddr.IP)}, net.UDPAddr{Port: config.LocalAddr.Port, IP: net.ParseIP(config.LocalAddr.IP)}) defer client.Sock.Close() + serv := server.New() + if err = serv.Run(config); err != nil { + log.Println(err) + } connectedIP := make(map[string]net.UDPAddr, 1) listenAddr := net.UDPAddr{ Port: 4810, @@ -52,12 +57,14 @@ func main() { if err = client.WriteFrame(buffer, n); err != nil { log.Println(err) } + serv.SendData(buffer[32:n], config.Server.Expire) if frame.PTT == 0 { log.Println("END OF TRANSMISSION") } } }() c := func(buffer []byte, size int) { + serv.SendData(buffer[32:size], config.Server.Expire) for _, c := range connectedIP { _, err := netListener.WriteToUDP(buffer[:size], &c) if err != nil { diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..83268b1 --- /dev/null +++ b/server/server.go @@ -0,0 +1,98 @@ +package server + +import ( + "fmt" + "github.com/usrpserv/config" + "log" + "net" + "sync" + "time" +) + +type Clients struct { + sync.Mutex + Client map[string]Client + Sock *net.UDPConn +} + +type Client struct { + Connected time.Time + Network net.UDPAddr +} + +func New() Clients { + var clients Clients + clients.Mutex = sync.Mutex{} + clients.Client = make(map[string]Client, 8) + return clients +} + +func (c *Clients) remove(name string) { + delete(c.Client, name) +} + +func (c *Clients) Add(name string, addr *net.UDPAddr) { + c.Lock() + defer c.Unlock() + if client, ok := c.Client[name]; ok { + if time.Since(client.Connected).Minutes() < 1 { + return + } + client.Connected = time.Now() + log.Printf("client %s has updated", name) + return + } + log.Println("adding client:", name) + c.Client[name] = Client{ + Connected: time.Now(), + Network: *addr, + } +} + +func (c *Clients) Run(config *config.Config) error { + if !config.Server.Enable { + log.Println("Server not enabled") + return nil + } + var err error + c.Sock, err = net.ListenUDP("udp4", &net.UDPAddr{IP: net.ParseIP(config.Server.UDP.IP), Port: config.Server.UDP.Port}) + if err != nil { + return err + } + buffer := make([]byte, 32) + go func() { + for { + n, addr, err := c.Sock.ReadFromUDP(buffer) + if err != nil { + log.Printf("Error reading from %v\n", err) + } + if n < 1 { + continue + } + c.Add(addr.String(), addr) + } + }() + return nil +} + +func (c *Clients) SendData(data []byte, expire int64) { + if len(data) == 0 { + return + } + c.Lock() + defer c.Unlock() + for key, client := range c.Client { + _, err := c.Sock.WriteToUDP(data, &client.Network) + if err != nil { + log.Println(err) + c.remove(key) + continue + } + if time.Now().Sub(client.Connected) > time.Duration(expire)*time.Minute { + log.Println("removing client:", key) + c.remove(key) + continue + } + fmt.Println("Sending to client:", key) + } +}