2022-11-17 19:49:25 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
2023-09-12 21:19:14 +00:00
|
|
|
"log"
|
2022-11-17 19:49:25 +00:00
|
|
|
"net"
|
|
|
|
"protohackers/pkg/conn"
|
|
|
|
)
|
|
|
|
|
2023-09-12 21:19:14 +00:00
|
|
|
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)
|
|
|
|
)
|
|
|
|
|
2022-11-17 19:49:25 +00:00
|
|
|
func main() {
|
2023-09-12 21:19:14 +00:00
|
|
|
go broadcast()
|
|
|
|
err := conn.StartSimple(newUserHandler)
|
2022-11-17 19:49:25 +00:00
|
|
|
if err != nil {
|
2023-09-12 21:19:14 +00:00
|
|
|
log.Fatalln(err)
|
2022-11-17 19:49:25 +00:00
|
|
|
}
|
2023-09-12 21:19:14 +00:00
|
|
|
}
|
2022-11-17 19:49:25 +00:00
|
|
|
|
2023-09-12 21:19:14 +00:00
|
|
|
func broadcast() {
|
2022-11-17 19:49:25 +00:00
|
|
|
for {
|
2023-09-12 21:19:14 +00:00
|
|
|
select {
|
|
|
|
case m := <-messages:
|
|
|
|
for _, cl := range room {
|
|
|
|
if m.client == cl {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
cl.sendMessage(m.msg)
|
|
|
|
}
|
2022-11-17 19:49:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-12 21:19:14 +00:00
|
|
|
func userList() []byte {
|
|
|
|
m := "* The room contains: "
|
|
|
|
if len(room) > 0 {
|
|
|
|
for _, c := range room {
|
|
|
|
m += fmt.Sprintf("%s, ", c.name)
|
2022-11-17 19:49:25 +00:00
|
|
|
}
|
2023-09-12 21:19:14 +00:00
|
|
|
m = m[:len(m)-2]
|
2022-11-17 19:49:25 +00:00
|
|
|
}
|
2023-09-12 21:19:14 +00:00
|
|
|
return []byte(m + "\n")
|
2022-11-17 19:49:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-12 21:19:14 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 19:49:25 +00:00
|
|
|
}
|