110 lines
2.1 KiB
Go
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))
|
|
}
|
|
}
|