From 302388379ffcc6b870f5ace76660144b2c0c427a Mon Sep 17 00:00:00 2001 From: vaporvee Date: Wed, 17 Apr 2024 16:40:14 +0200 Subject: [PATCH] finalized basic udp server --- server/main.go | 113 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/server/main.go b/server/main.go index 5567082..eb110ea 100644 --- a/server/main.go +++ b/server/main.go @@ -1,72 +1,117 @@ package main import ( + "crypto/rand" + "encoding/base64" "encoding/json" "fmt" - "net/http" + "io" + "net" "os" - "github.com/gorilla/websocket" "github.com/joho/godotenv" ) -var upgrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, +type Payload struct { + Type string `json:"type"` + Message string `json:"msg,omitempty"` + Direction *struct { + X int `json:"x,omitempty"` + Y int `json:"y,omitempty"` + } `json:"direction,omitempty"` + SessionID string `json:"session_id,omitempty"` } -var clients = make(map[*websocket.Conn]bool) // connected clients -var broadcast = make(chan []byte) // broadcast channel +// Generate a unique session ID +func generateSessionID() string { + b := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + return "" + } + return base64.URLEncoding.EncodeToString(b) +} func main() { godotenv.Load() - http.HandleFunc("/ws", handleConnections) - go handleMessages() - fmt.Println("Server running on " + os.Getenv("PORT")) - http.ListenAndServeTLS(os.Getenv("PORT"), "cert.pem", "key.pem", nil) -} + port := os.Getenv("PORT") + if port == "" { + port = "4477" // Default port if not specified + } -func handleConnections(w http.ResponseWriter, r *http.Request) { - conn, err := upgrader.Upgrade(w, r, nil) + addr, err := net.ResolveUDPAddr("udp", ":"+port) if err != nil { fmt.Println(err) return } - defer conn.Close() // Closes the connection at the end - clients[conn] = true // Add a new WebSocket connection to the clients map. + conn, err := net.ListenUDP("udp", addr) + if err != nil { + fmt.Println(err) + return + } + defer conn.Close() + + fmt.Println("Server running on " + port) + + buf := make([]byte, 1024) + clients := make(map[string]string) // Map to keep track of clients and their session IDs for { - _, msg, err := conn.ReadMessage() + n, addr, err := conn.ReadFromUDP(buf) if err != nil { - delete(clients, conn) - break + fmt.Println(err) + continue } - // Parse the received message as JSON - var payload map[string]interface{} - err = json.Unmarshal(msg, &payload) + var payload Payload + err = json.Unmarshal(buf[:n], &payload) if err != nil { fmt.Println("Error parsing JSON:", err) continue } - // Check if the JSON object contains the key "type" with the value "broadcast" - if payload["type"] == "broadcast" { - broadcast <- msg // Send received WebSocket Message to Broadcast + // Use the client's IP and port as the key to uniquely identify the connection + key := addr.String() + + // Check if the client's connection already has a session ID + if _, ok := clients[key]; !ok { + // The client is new, generate a session ID + sessionID := generateSessionID() + clients[key] = sessionID + // Send the session ID back to the client + responsePayload := Payload{SessionID: sessionID} + response, _ := json.Marshal(responsePayload) + conn.WriteToUDP(response, addr) + } + + switch payload.Type { + case "init": + fmt.Printf("Received initiation generated SessionID: %s", clients[key]) + case "move": + fmt.Printf("Received move message from Session ID: %s : X=%d, Y=%d\n", clients[key], payload.Direction.X, payload.Direction.Y) + // Handle movement logic here + case "message": + fmt.Printf("Received message from Session ID: %s : %s\n", clients[key], payload.Message) + broadcastMessage(conn, clients, payload.Message) + default: + fmt.Printf("Received unknown message type Session ID: %s\n", clients[key]) } } } -func handleMessages() { - for { - msg := <-broadcast - for client := range clients { - err := client.WriteMessage(websocket.TextMessage, msg) - if err != nil { - client.Close() - delete(clients, client) - } +func broadcastMessage(conn *net.UDPConn, clients map[string]string, message string) { + for clientKey := range clients { + // Parse the clientKey to get the *net.UDPAddr + clientAddr, err := net.ResolveUDPAddr("udp", clientKey) + if err != nil { + fmt.Println("Error resolving UDP address:", err) + continue } + payload := Payload{ + Type: "message", + Message: message, + } + response, _ := json.Marshal(payload) + conn.WriteToUDP(response, clientAddr) } }