package main import ( "bufio" "encoding/json" "fmt" "math/rand" "net" "strings" "sync" "time" ) type Client struct { conn net.Conn username string room *Room } type Room struct { code string password string clients map[*Client]bool lock sync.Mutex } var ( rooms = make(map[string]*Room) mu sync.Mutex ) // Helper function to generate a 4-hexadecimal room code func generateRoomCode() string { rand.Seed(time.Now().UnixNano()) return fmt.Sprintf("%04x", rand.Intn(0xFFFF)) } // Handle client connection func handleClient(client *Client) { defer client.conn.Close() reader := bufio.NewReader(client.conn) for { line, err := reader.ReadString('\n') if err != nil { if client.room != nil { leaveRoom(client) } fmt.Println("Client disconnected:", client.conn.RemoteAddr()) return } processCommand(client, strings.TrimSpace(line)) } } // Process client commands func processCommand(client *Client, input string) { parts := strings.SplitN(input, " ", 2) if len(parts) < 1 { return } cmd := strings.ToUpper(parts[0]) args := "" if len(parts) > 1 { args = parts[1] } switch cmd { case "CREATE": createRoom(client, args) case "JOIN": joinRoom(client, args) case "LEAVE": leaveRoom(client) case "MESSAGE": sendMessage(client, args) case "SYNC": handleSync(client, args) default: client.conn.Write([]byte("Unknown command\n")) } } // Create a room with an optional password func createRoom(client *Client, args string) { mu.Lock() defer mu.Unlock() password := "" if args != "" { password = args // Treat all input after CREATE as a password } roomCode := generateRoomCode() // Room code is generated automatically room := &Room{ code: roomCode, password: password, clients: make(map[*Client]bool), } rooms[roomCode] = room client.conn.Write([]byte(fmt.Sprintf("Room created with code: %s\n", roomCode))) } // Join a room using its 4-hexadecimal code and optional password func joinRoom(client *Client, args string) { parts := strings.SplitN(args, " ", 2) roomCode := parts[0] password := "" if len(parts) == 2 { password = parts[1] } mu.Lock() room, exists := rooms[roomCode] mu.Unlock() if !exists { client.conn.Write([]byte("Room not found\n")) return } if room.password != "" && room.password != password { client.conn.Write([]byte("Incorrect password\n")) return } room.lock.Lock() room.clients[client] = true client.room = room room.lock.Unlock() client.conn.Write([]byte(fmt.Sprintf("Joined room: %s\n", roomCode))) broadcastMessage(client.room, fmt.Sprintf("%s has joined the room\n", client.username)) } // Leave the current room func leaveRoom(client *Client) { if client.room == nil { client.conn.Write([]byte("You are not in any room\n")) return } client.room.lock.Lock() delete(client.room.clients, client) client.room.lock.Unlock() broadcastMessage(client.room, fmt.Sprintf("%s has left the room\n", client.username)) client.conn.Write([]byte("You have left the room\n")) client.room = nil } // Send a message to all clients in the current room func sendMessage(client *Client, message string) { if client.room == nil { client.conn.Write([]byte("You are not in any room\n")) return } timestamp := time.Now().Format("2006-01-02 15:04:05") formattedMessage := fmt.Sprintf("[%s] %s: %s\n", timestamp, client.username, message) broadcastMessage(client.room, formattedMessage) } // Broadcast a message to all clients in the room func broadcastMessage(room *Room, message string) { room.lock.Lock() defer room.lock.Unlock() for client := range room.clients { client.conn.Write([]byte(message)) } } // Handle the SYNC command, expecting a JSON payload func handleSync(client *Client, payload string) { var data map[string]interface{} err := json.Unmarshal([]byte(payload), &data) if err != nil { client.conn.Write([]byte("Invalid JSON\n")) return } // You can process the JSON payload here as needed client.conn.Write([]byte("Sync received\n")) } // Start the server func startServer() { listener, err := net.Listen("tcp", ":5518") if err != nil { fmt.Println("Error starting server:", err) return } defer listener.Close() fmt.Println("Server started on port 5518") for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } go func() { conn.Write([]byte("Enter your username: ")) username, _ := bufio.NewReader(conn).ReadString('\n') username = strings.TrimSpace(username) client := &Client{ conn: conn, username: username, } conn.Write([]byte(fmt.Sprintf("Welcome %s!\n", username))) handleClient(client) }() } } func main() { startServer() }