116 lines
2.1 KiB
Go
116 lines
2.1 KiB
Go
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
|
|
}
|