package main import ( "bufio" "fmt" "log" "net" "protohackers/pkg/conn" ) type message struct { msg []byte client *client } func msg(s string, c *client) message { return message{[]byte(s), c} } var ( room = make([]*client, 0) messages = make(chan message, 32) ) func main() { go broadcast() err := conn.StartSimple(newUserHandler) if err != nil { log.Fatalln(err) } } func broadcast() { for { select { case m := <-messages: for _, cl := range room { if m.client == cl { continue } cl.sendMessage(m.msg) } } } } func userList() []byte { m := "* The room contains: " if len(room) > 0 { for _, c := range room { m += fmt.Sprintf("%s, ", c.name) } m = m[:len(m)-2] } return []byte(m + "\n") } func newUserHandler(c net.Conn) { cl, err := newClient(c) if err != nil { return } cl.sendMessage(userList()) fmt.Printf("New client %s\n", cl.name) messages <- msg(fmt.Sprintf("* %s has entered the room\n", cl.name), cl) room = append(room, cl) input := bufio.NewScanner(cl.c) for input.Scan() { m := fmt.Sprintf("[%s] %s\n", cl.name, input.Text()) messages <- msg(m, cl) } for i, p := range room { if p == cl { name := cl.name cl.c.Close() room = append(room[:i], room[i+1:]...) fmt.Printf("%s has left", cl.name) messages <- msg(fmt.Sprintf("* %s has left the room\n", name), cl) break } } }