-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
143 lines (116 loc) · 2.97 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"database/sql"
"fmt"
"log"
"net"
"strings"
_ "github.com/go-sql-driver/mysql"
)
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_ROOMLIST:
s.listRooms(cmd.client)
case CMD_MSG:
s.msg(cmd.client, cmd.args)
case CMD_QUIT:
s.quit(cmd.client)
case CMD_HELP:
s.help(cmd.client)
}
}
}
func (s *server) newClient(conn net.Conn) {
log.Printf("New client has joined: %s", conn.RemoteAddr().String())
c := &client{
conn: conn,
nick: "anonymous",
commands: s.commands,
}
c.msg(fmt.Sprint("Welcome to the chat-server!"))
c.readInput()
}
func (s *server) nick(c *client, args []string) {
if len(args) < 2 {
c.msg("Nick is required. usage: /nick NAME")
return
}
c.nick = args[1]
c.msg(fmt.Sprintf("OK, now you're %s", c.nick))
}
func (s *server) join(c *client, args []string) {
if len(args) < 2 {
c.msg("Room name is required. usage: /join ROOM_NAME")
return
}
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 joined the room", c.nick))
c.msg(fmt.Sprintf("welcome to %s", roomName))
}
func (s *server) listRooms(c *client) {
var rooms []string
for name := range s.rooms {
rooms = append(rooms, name)
}
c.msg(fmt.Sprintf("available rooms: %s", strings.Join(rooms, ", ")))
}
func (s *server) msg(c *client, args []string) {
if len(args) < 2 {
c.msg("message is required, usage: /msg MSG")
return
}
msg := strings.Join(args[1:], " ")
c.room.broadcast(c, c.nick+": "+msg)
db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/chat")
if err != nil {
log.Fatalf("Could not connect to database: %s", err)
}
defer db.Close()
insert, err := db.Query("INSERT INTO test (name, room, msg) VALUES (?, ?, ?)", c.nick, c.room.name, msg)
if err != nil {
log.Fatalf("Cannot upload to database: %s", err)
}
defer insert.Close()
}
func (s *server) quit(c *client) {
log.Printf("client has left the chat: %s", c.conn.RemoteAddr().String())
s.quitCurrentRoom(c)
c.msg("sad to see you go =(")
c.conn.Close()
}
func (s *server) help(c *client) {
c.msg("Commands:\n/nick\n/join\n/roomlist\n/msg\n/quit\n")
}
func (s *server) quitCurrentRoom(c *client) {
if c.room != nil {
oldRoom := s.rooms[c.room.name]
delete(s.rooms[c.room.name].members, c.conn.RemoteAddr())
oldRoom.broadcast(c, fmt.Sprintf("%s has left the room", c.nick))
}
}