From 60506584cbc55287529138e4e59c2a5f84561806 Mon Sep 17 00:00:00 2001 From: Andreas Neue Date: Mon, 18 Jul 2016 21:22:03 +0200 Subject: [PATCH] Implemented Client as an Interface --- client.go | 92 ++++++++++++++++++++++++++++++------------------------- server.go | 35 +++++++++------------ 2 files changed, 65 insertions(+), 62 deletions(-) diff --git a/client.go b/client.go index 4e56ced..96c6a8b 100644 --- a/client.go +++ b/client.go @@ -14,7 +14,15 @@ import ( "code.dnix.de/an/xlog" ) -type Client struct { +type Client interface { + Name() string + Send(*irc.Message) + Receive(*irc.Message) + Register() chan bool + Destroy() +} + +type RemoteClient struct { server *Server name string @@ -33,8 +41,8 @@ type Client struct { writeq chan string } -func NewClient(srv *Server, conn net.Conn) *Client { - cl := new(Client) +func NewRemoteClient(srv *Server, conn net.Conn) *RemoteClient { + cl := new(RemoteClient) cl.server = srv cl.name = "" @@ -52,47 +60,58 @@ func NewClient(srv *Server, conn net.Conn) *Client { go cl.connReader() go cl.connWriter() - go cl.loop() + go cl.dispatch() - xlog.Info("Client connected") + xlog.Info("RemoteClient connected") return cl } -func (cl *Client) Name() string { +func (cl *RemoteClient) Name() string { return cl.name } -func (cl *Client) Send(msg *irc.Message) { +func (cl *RemoteClient) Send(msg *irc.Message) { msg.Pre = cl.name cl.server.Dispatch <- msg } -func (cl *Client) Receive(msg *irc.Message) { +func (cl *RemoteClient) Receive(msg *irc.Message) { cl.receive <- msg } -func (cl *Client) Register() chan bool { +func (cl *RemoteClient) Register() chan bool { return cl.register } -func (cl *Client) AddMode(mode string) { +func (cl *RemoteClient) AddMode(mode string) { cl.modes = cl.modes + mode } -func (cl *Client) DelMode(mode string) { +func (cl *RemoteClient) DelMode(mode string) { cl.modes = strings.Replace(cl.modes, mode, "", -1) } -func (cl *Client) HasMode(mode string) bool { +func (cl *RemoteClient) HasMode(mode string) bool { return strings.IndexRune(cl.modes, rune(mode[0])) != -1 } -func (cl *Client) writeMsg(msg *irc.Message) { - cl.writeLine(msg.String()) +func (cl *RemoteClient) Destroy() { + if cl.isClosed { + return + } + cl.isClosed = true + close(cl.writeq) + cl.conn.Write([]byte("ERROR :Closing link")) + cl.conn.Close() + if cl.name != "" { + xlog.Info("RemoteClient '%s' disconnected", cl.name) + } else { + xlog.Info("RemoteClient disconnected") + } } -func (cl *Client) loop() { +func (cl *RemoteClient) dispatch() { for { time.Sleep(1 * time.Millisecond) if cl.isClosed { @@ -107,26 +126,7 @@ func (cl *Client) loop() { } } -func (cl *Client) destroy() { - if cl.isClosed { - return - } - cl.isClosed = true - close(cl.writeq) - cl.conn.Write([]byte("ERROR :Closing link")) - cl.conn.Close() - if cl.name != "" { - xlog.Info("Client '%s' disconnected", cl.name) - } else { - xlog.Info("Client disconnected") - } -} - -func (cl *Client) writeLine(format string, a ...interface{}) { - cl.writeq <- fmt.Sprintf(format, a...) -} - -func (cl *Client) connReader() { +func (cl *RemoteClient) connReader() { input := bufio.NewReader(cl.conn) for { if cl.isClosed { @@ -149,7 +149,7 @@ func (cl *Client) connReader() { } } -func (cl *Client) connWriter() { +func (cl *RemoteClient) connWriter() { for line := range cl.writeq { written := 0 bytes := []byte(line + "\r\n") @@ -170,13 +170,21 @@ func (cl *Client) connWriter() { xlog.Debug("connWriter: exiting") } -var lineFuncs = map[string]func(*Client, *irc.Message) bool{ +func (cl *RemoteClient) writeMsg(msg *irc.Message) { + cl.writeLine(msg.String()) +} + +func (cl *RemoteClient) writeLine(format string, a ...interface{}) { + cl.writeq <- fmt.Sprintf(format, a...) +} + +var lineFuncs = map[string]func(*RemoteClient, *irc.Message) bool{ "PASS": handleLinePass, "NICK": handleLineNick, "USER": handleLineUser, } -func (cl *Client) handleLine(s string) { +func (cl *RemoteClient) handleLine(s string) { xlog.Debug("handleLine: [%s] '%s'", cl.name, s) msg := irc.Parse(s) hook, exists := lineFuncs[msg.Cmd] @@ -189,18 +197,18 @@ func (cl *Client) handleLine(s string) { } } -func checkAuth(cl *Client) { +func checkAuth(cl *RemoteClient) { if cl.name == "" || cl.password == "" { return } } -func handleLinePass(cl *Client, msg *irc.Message) bool { +func handleLinePass(cl *RemoteClient, msg *irc.Message) bool { cl.password = msg.Args[0] return false } -func handleLineNick(cl *Client, msg *irc.Message) bool { +func handleLineNick(cl *RemoteClient, msg *irc.Message) bool { if cl.name != "" { return false } @@ -220,6 +228,6 @@ func handleLineNick(cl *Client, msg *irc.Message) bool { return false } -func handleLineUser(cl *Client, msg *irc.Message) bool { +func handleLineUser(cl *RemoteClient, msg *irc.Message) bool { return false } diff --git a/server.go b/server.go index 5aab0ef..c62fa03 100644 --- a/server.go +++ b/server.go @@ -27,15 +27,10 @@ var flagConfig string var myinfo string = "%s %s/%s * *" var isupport string = "ALIAS FRIEND UNFRIEND CASEMAPPING=rfc1459 CHANLIMIT=#:1024 CHANMODES=b,k,l,imnpst CHANNELLEN=200 CHANTYPES=# EXCEPTS=e KICKLEN MAXLIST=b:50,e:50 MODES=1 NETWORK=dnix.de NICKLEN=32 PREFIX=(aohv)&@%%+ SAFELIST STATUSMSG=&@%%+ TOPICLEN" -type ControlMsg struct { - Opcode int - Client *Client -} - type Server struct { Dispatch chan *irc.Message - AddClient chan *Client - DelClient chan *Client + AddClient chan Client + DelClient chan Client host string info string @@ -43,7 +38,7 @@ type Server struct { version string created string motd string - clients map[string]*Client + clients map[string]Client channels map[string]map[string]string ports map[int]bool config *conf.ConfigFile @@ -58,10 +53,10 @@ func NewServer(configPath, software, version string) *Server { srv := &Server{software: software, version: version, created: "yes"} srv.Dispatch = make(chan *irc.Message, 1024) - srv.AddClient = make(chan *Client, 1024) - srv.DelClient = make(chan *Client, 1024) + srv.AddClient = make(chan Client, 1024) + srv.DelClient = make(chan Client, 1024) - srv.clients = make(map[string]*Client) + srv.clients = make(map[string]Client) srv.channels = make(map[string]map[string]string) srv.configPath = configPath srv.loadConfig() @@ -102,7 +97,7 @@ func (srv *Server) listen(address string, port int) { if err != nil { xlog.Error(err.Error()) } else { - NewClient(srv, conn) + NewRemoteClient(srv, conn) } } } @@ -130,7 +125,7 @@ func (srv *Server) dispatch() { srv.clientMotd(cl) case cl := <-srv.DelClient: name := cl.Name() - cl.destroy() + cl.Destroy() //go func() { // time.Sleep(10 * time.Second) delete(srv.clients, name) @@ -169,7 +164,7 @@ func (srv *Server) recvMsg(msg *irc.Message) { func (srv *Server) sendMsg(msg *irc.Message) { if strings.HasPrefix(msg.Args[0], "#") { - srv.sendMsgToChannel(msg) + srv.channelBroadcast(msg.Args[0], msg) } else { srv.sendMsgToClient(msg) } @@ -213,7 +208,7 @@ func (srv *Server) sendReply(tar, cmd, args, trail string) { cl.Receive(irc.M(srv.host, cmd, args, trail)) } -func (srv *Server) clientLogon(cl *Client) { +func (srv *Server) clientLogon(cl Client) { srv.sendReply(cl.Name(), RPL_WELCOME, "", "Willkommen!") srv.sendReply(cl.Name(), RPL_YOURHOST, "", fmt.Sprintf("Your host is %s, running on %s/%s", @@ -226,7 +221,7 @@ func (srv *Server) clientLogon(cl *Client) { isupport+" are supported by this server") } -func (srv *Server) clientMotd(cl *Client) { +func (srv *Server) clientMotd(cl Client) { srv.sendReply(cl.Name(), RPL_MOTDSTART, "", fmt.Sprintf("- %s Message of the day -", srv.host)) for _, line := range strings.Split(srv.motd, "\n") { @@ -237,7 +232,7 @@ func (srv *Server) clientMotd(cl *Client) { func (srv *Server) channelBroadcast(ch string, msg *irc.Message) { for nick, _ := range srv.channels[ch] { - if msg.Pre == nick { + if msg.Pre == nick && msg.Cmd == "PRIVMSG" { continue } srv.clients[nick].Receive(msg) @@ -245,6 +240,7 @@ func (srv *Server) channelBroadcast(ch string, msg *irc.Message) { } func (srv *Server) channelJoin(nick, ch string) { + println("join") if _, exists := srv.channels[ch]; !exists { srv.channels[ch] = make(map[string]string) } @@ -263,7 +259,7 @@ func (srv *Server) channelPart(nick, ch, reason string) { return } srv.channelBroadcast(ch, irc.M(nick, "PART", ch, reason)) - delete(srv.channels[ch][nick]) + delete(srv.channels[ch], nick) } type SrvCommandHook struct { @@ -308,11 +304,10 @@ func srvHandleCmdPrivmsg(srv *Server, msg *irc.Message) { func srvHandleCmdJoin(srv *Server, msg *irc.Message) { srv.channelJoin(msg.Pre, msg.Args[0]) - } func srvHandleCmdPart(srv *Server, msg *irc.Message) { - srv.channelPart(msg.Pre, msg.Args[0], msg.Trailing) + srv.channelPart(msg.Pre, msg.Args[0], msg.Trail) } func srvHandleCmdOper(srv *Server, msg *irc.Message) {