Make Message an interface with attached handling behavior.

This commit is contained in:
Jeremy Latt 2012-04-17 18:16:57 -07:00
parent d1f8c7657b
commit fed72a7aa3
6 changed files with 190 additions and 96 deletions

View file

@ -3,19 +3,24 @@ package irc
import (
"log"
"net"
"regexp"
"strings"
)
type Server struct {
ch chan Message
ch chan *ClientMessage
nicks map[string]*Client
}
type ClientMessage struct {
client *Client
message Message
}
func NewServer() *Server {
server := Server{make(chan Message), make(map[string]*Client)}
server := new(Server)
server.ch = make(chan *ClientMessage)
server.nicks = make(map[string]*Client)
go server.Receive()
return &server
return server
}
func (s *Server) Listen(addr string) {
@ -30,71 +35,12 @@ func (s *Server) Listen(addr string) {
log.Print("Server.Listen: ", err)
continue
}
go NewClient(conn).Communicate(s)
go NewClient(conn).Communicate(s.ch)
}
}
func (s *Server) Receive() {
for message := range s.ch {
log.Printf("C -> S: %s %s", message.command, message.args)
switch message.command {
case "PING":
message.client.Send(MessagePong())
case "USER":
s.UserCommand(message.client, message.args)
case "NICK":
s.NickCommand(message.client, message.args)
case "QUIT":
s.QuitCommand(message.client, message.args)
default:
message.client.Send(ErrUnknownCommand(message.client.Nick(), message.command))
}
for m := range s.ch {
m.message.Handle(s, m.client)
}
}
func (s *Server) Send(m Message) {
s.ch <- m
}
// commands
func (s *Server) UserCommand(c *Client, args string) {
parts := strings.SplitN(args, " ", 4)
username, _, _, realname := parts[0], parts[1], parts[2], parts[3]
if c.username != "" {
c.Send(ErrAlreadyRegistered(c.nick))
return
}
c.username, c.realname = username, realname
s.TryRegister(c)
}
func (s *Server) NickCommand(c *Client, nick string) {
if s.nicks[nick] != nil {
c.Send(ErrNickNameInUse(nick))
return
}
c.nick = nick
s.nicks[nick] = c
s.TryRegister(c)
}
func (s *Server) TryRegister(c *Client) {
if (!c.registered && c.nick != "" && c.username != "") {
c.registered = true
c.Send(
ReplyWelcome(c.Nick(), c.username, "localhost"),
ReplyYourHost(c.Nick(), "irc.jlatt.com"),
ReplyCreated(c.Nick(), "2012/04/07"),
ReplyMyInfo(c.Nick(), "irc.jlatt.com"))
}
}
func (s *Server) QuitCommand(c *Client, args string) {
re := regexp.MustCompile("^" + RE_QUIT + "$")
matches := re.FindAllStringSubmatch(args, -1)
if matches != nil {
c.Send(MessageError())
}
delete(s.nicks, c.nick)
}