package core import ( "fmt" "net" "time" ) // Handler is a byte code specific packet handler. type Handler func([]byte, *Client) // Server represents a UDP server. type Server struct { socket *net.UDPConn clients map[string]*Client handlers [256]Handler } // New creates a new server. func New() *Server { return &Server{ clients: make(map[string]*Client), } } // AddHandler adds the handler for the given byte code. func (s *Server) AddHandler(code byte, handler Handler) { s.handlers[code] = handler } // SendTo sends the data to a client. func (s *Server) SendTo(data []byte, client *Client) { _, err := s.socket.WriteToUDP(data, client.address) if err != nil { fmt.Println("Error sending response:", err) } } // Run starts the server on the given port. func (s *Server) Run(port int) { s.socket = listen(port) defer s.socket.Close() s.read() } // listen creates a socket for the server and starts listening for incoming packets. func listen(port int) *net.UDPConn { addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", port)) if err != nil { panic(err) } connection, err := net.ListenUDP("udp", addr) if err != nil { panic(err) } return connection } // read is a blocking call which will read incoming packets and handle them. func (s *Server) read() { buffer := make([]byte, 4096) for { n, addr, err := s.socket.ReadFromUDP(buffer) if err != nil { fmt.Println("Error reading from UDP connection:", err) continue } if n == 0 { continue } go s.handle(buffer[:n], addr) } } // handle deals with an incoming packet. func (s *Server) handle(data []byte, addr *net.UDPAddr) { c := s.getClient(addr) c.lastPacket = time.Now() // fmt.Printf("Received %d bytes from %s: %s\n", len(data), c, string(data)) handler := s.handlers[data[0]] if handler == nil { fmt.Println("Unknown packet type.") return } handler(data, c) } // getClient either returns a new or existing client for the requested address. func (s *Server) getClient(addr *net.UDPAddr) *Client { c, exists := s.clients[addr.String()] if exists { return c } c = &Client{ address: addr, } s.clients[addr.String()] = c return c }