go-tcp-chat/server.go
2023-12-24 12:50:44 +08:00

110 lines
2.1 KiB
Go

package main
import (
"errors"
"fmt"
"log"
"net"
"strings"
)
type server struct {
rooms map[string]*room
commands chan command
}
func newServer() *server {
return &server{
rooms: make(map[string]*room),
commands: make(chan command),
}
}
func (s *server) run() {
for cmd := range s.commands {
switch cmd.id {
case CMD_NICK:
s.nick(cmd.client, cmd.args)
case CMD_JOIN:
s.join(cmd.client, cmd.args)
case CMD_ROOMS:
s.listRooms(cmd.client, cmd.args)
case CMD_MSG:
s.msg(cmd.client, cmd.args)
case CMD_QUIT:
s.quit(cmd.client, cmd.args)
}
}
}
func (s *server) newClient(conn net.Conn) {
log.Printf("new client has connected: %s", conn.RemoteAddr().String())
c := &client{
conn: conn,
nick: "anonymous",
commands: s.commands,
}
c.readInput()
}
func (s *server) nick(c *client, args []string) {
c.nick = args[1]
c.msg(fmt.Sprintf("all right, I will call you %s", c.nick))
}
func (s *server) join(c *client, args []string) {
roomName := args[1]
r, ok := s.rooms[roomName]
if !ok {
r = &room{
name: roomName,
members: make(map[net.Addr]*client),
}
s.rooms[roomName] = r
}
r.members[c.conn.RemoteAddr()] = c
s.quitCurrentRoom(c)
c.room = r
r.broadcast(c, fmt.Sprintf("%s has joined the room", c.nick))
c.msg(fmt.Sprintf("Wecome to %s", r.name))
}
func (s *server) listRooms(c *client, args []string) {
var rooms []string
for name := range s.rooms {
rooms = append(rooms, name)
}
c.msg(fmt.Sprintf("available rooms are: %s", strings.Join(rooms, ", ")))
}
func (s *server) msg(c *client, args []string) {
if c.room == nil {
c.err(errors.New("you must join the room first"))
return
}
c.room.broadcast(c, c.nick+": "+strings.Join(args[1:], " "))
}
func (s *server) quit(c *client, args []string) {
log.Printf("client has disconnection: %s", c.conn.RemoteAddr().String())
s.quitCurrentRoom(c)
c.msg("sad to see you go :(")
c.conn.Close()
}
func (s *server) quitCurrentRoom(c *client) {
if c.room != nil {
delete(c.room.members, c.conn.RemoteAddr())
c.room.broadcast(c, fmt.Sprintf("%s has left the room", c.nick))
}
}