diff --git a/addr.go b/addr.go deleted file mode 100644 index 938aed7..0000000 --- a/addr.go +++ /dev/null @@ -1,32 +0,0 @@ -package ircd - -import ( - "strings" -) - -func AddrName(addr string) string { - parts := strings.SplitN(addr, "@", 2) - return parts[0] -} - -func AddrHost(addr string) string { - parts := strings.SplitN(addr, "@", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - -func AddrSplit(addr string) (string, string) { - parts := strings.SplitN(addr, "@", 2) - if len(parts) > 1 { - return parts[0], parts[1] - } - return parts[0], "" -} - -func AddrJoin(name string, host string) string { - return name + "@" + host -} - -// vi:ts=4:sw=4:et \ No newline at end of file diff --git a/channel.go b/channel.go deleted file mode 100644 index 2461765..0000000 --- a/channel.go +++ /dev/null @@ -1,159 +0,0 @@ -package ircd - -import ( - "time" -) - -type ChangedByTS struct { - By string - Time int64 -} - -type ChannelModes string - -type Channel struct { - Name string - - server *Server - - topic string - topicChanged ChangedByTS - flags string - keys map[int]string - args map[int]string - bans map[int]string - - receive chan *Message - destroy chan bool - - invites map[string]bool - clients map[string]ChannelModes -} - -func NewChannel(srv *Server, name string) *Channel { - ch := &Channel{Name: name, server: srv, topic: "", flags: ""} - ch.receive = make(chan *Message, 1024) - ch.destroy = make(chan bool) - ch.clients = make(map[string]ChannelModes) - go ch.loop() - return ch -} - -func (ch *Channel) Receive(msg *Message) { - ch.receive <- msg -} - -func (ch *Channel) loop() { - for { - time.Sleep(1e6) - select { - case msg := <-ch.receive: - cmd := msg.Cmd - hook, exists := chCommandHooks[cmd] - if !exists { - ch.server.sendCommand(msg.Src, ERR_UNKNOWNCOMMAND, cmd, - "Unknown command.") - return - } - argc := len(msg.Args) - if argc < hook.MinArgs { - ch.server.sendCommand(msg.Src, ERR_NEEDMOREPARAMS, cmd, - "Not enough parameters.") - return - } - hook.HookFn(ch, msg) - case <-ch.destroy: - break - default: - continue - } - } -} - -func (ch *Channel) recvMsg(msg *Message) { -} - -func (ch *Channel) sendMsg(msg *Message) { - ch.server.sendMsg(msg) -} - -func (ch *Channel) bcMsg(msg *Message, localEcho bool) { - msg.Ctx = ch.Name - for client, _ := range ch.clients { - if client != msg.Src || localEcho { - msg.Dst = client - ch.server.sendMsgToClient(msg) - } - } -} - -func (ch *Channel) AddMode(mode string) { - // -} - -type ChCommandHook struct { - HookFn func(ch *Channel, msg *Message) - MinArgs int - NeedOper bool - NeedAuth bool -} - -var chCommandHooks = map[string]ChCommandHook{ - CMD_QUIT: {chHandleCmdQuit, 0, false, false}, - CMD_JOIN: {chHandleCmdJoin, 0, false, false}, - CMD_PART: {chHandleCmdPart, 0, false, false}, - CMD_MODE: {chHandleCmdMode, 0, false, false}, - CMD_TOPIC: {chHandleCmdTopic, 0, false, false}, - CMD_NAMES: {chHandleCmdNames, 0, false, false}, - CMD_LIST: {chHandleCmdList, 0, false, false}, - CMD_INVITE: {chHandleCmdInvite, 0, false, false}, - CMD_KICK: {chHandleCmdKick, 0, false, false}, - CMD_PRIVMSG: {chHandleCmdPrivmsg, 0, false, false}, - CMD_NOTICE: {chHandleCmdNotice, 0, false, false}, - CMD_USERS: {chHandleCmdUsers, 0, false, false}, -} - -func chHandleCmdQuit(ch *Channel, msg *Message) { - ch.bcMsg(M(msg.Src, "", msg.Ctx, "QUIT", "", ""), true) - delete(ch.clients, msg.Src) -} - -func chHandleCmdJoin(ch *Channel, msg *Message) { - ch.clients[msg.Src] = "" - ch.bcMsg(M(msg.Src, "", msg.Ctx, "JOIN", "", ""), true) -} - -func chHandleCmdPart(ch *Channel, msg *Message) { - ch.bcMsg(M(msg.Src, "", msg.Ctx, "PART", "", ""), true) - delete(ch.clients, msg.Src) -} - -func chHandleCmdMode(ch *Channel, msg *Message) { -} - -func chHandleCmdTopic(ch *Channel, msg *Message) { -} - -func chHandleCmdNames(ch *Channel, msg *Message) { -} - -func chHandleCmdList(ch *Channel, msg *Message) { -} - -func chHandleCmdInvite(ch *Channel, msg *Message) { -} - -func chHandleCmdKick(ch *Channel, msg *Message) { -} - -func chHandleCmdPrivmsg(ch *Channel, msg *Message) { - ch.bcMsg(msg, false) -} - -func chHandleCmdNotice(ch *Channel, msg *Message) { -} - -func chHandleCmdUsers(ch *Channel, msg *Message) { -} - -// vi:ts=4:sw=4:et \ No newline at end of file diff --git a/client.go b/client.go index 231caeb..a8c8365 100644 --- a/client.go +++ b/client.go @@ -1,26 +1,20 @@ -package ircd +// vim:ts=4:sts=4:sw=4:noet:tw=72 + +package main import ( "bufio" - "code.dnix.de/xlog" "fmt" "io" "net" "strings" "time" + + "code.dnix.de/an/irc" + "code.dnix.de/an/xlog" ) -type Client interface { - Name() string - Send(*Message) - Receive(*Message) - Register() chan bool - AddMode(string) - DelMode(string) - HasMode(string) bool -} - -type RemoteClient struct { +type Client struct { server *Server name string @@ -32,23 +26,22 @@ type RemoteClient struct { isAuthed bool isClosed bool - receive chan *Message + receive chan *irc.Message register chan bool - conn net.Conn - writeq chan string - channels map[*Channel]bool + conn net.Conn + writeq chan string } -func NewRemoteClient(srv *Server, conn net.Conn) *RemoteClient { - cl := new(RemoteClient) +func NewClient(srv *Server, conn net.Conn) *Client { + cl := new(Client) cl.server = srv cl.name = "" cl.password = "" cl.modes = "" - cl.receive = make(chan *Message) + cl.receive = make(chan *irc.Message) cl.register = make(chan bool) cl.isRegistered = false @@ -61,58 +54,45 @@ func NewRemoteClient(srv *Server, conn net.Conn) *RemoteClient { go cl.connWriter() go cl.loop() - xlog.Info("Client connected.") + xlog.Info("Client connected") return cl } -func (cl *RemoteClient) Name() string { +func (cl *Client) Name() string { return cl.name } -func (cl *RemoteClient) Send(msg *Message) { - cl.server.Receive <- msg +func (cl *Client) Send(msg *irc.Message) { + msg.Pre = cl.name + cl.server.Dispatch <- msg } -func (cl *RemoteClient) Receive(msg *Message) { +func (cl *Client) Receive(msg *irc.Message) { cl.receive <- msg } -func (cl *RemoteClient) Register() chan bool { +func (cl *Client) Register() chan bool { return cl.register } -func (cl *RemoteClient) AddMode(mode string) { +func (cl *Client) AddMode(mode string) { cl.modes = cl.modes + mode } -func (cl *RemoteClient) DelMode(mode string) { +func (cl *Client) DelMode(mode string) { cl.modes = strings.Replace(cl.modes, mode, "", -1) } -func (cl *RemoteClient) HasMode(mode string) bool { +func (cl *Client) HasMode(mode string) bool { return strings.IndexRune(cl.modes, rune(mode[0])) != -1 } -func (cl *RemoteClient) writeMsg(msg *Message) { - var src, ctx, cmd, args, text string - - src = fmt.Sprintf("%s!%s@%s", msg.Src, msg.Src, cl.server.Host) - ctx = msg.Ctx - cmd = msg.Cmd - text = msg.Text - args = "" - for _, arg := range msg.Args { - args += " " + arg - } - if text != "" { - cl.writeLine(fmt.Sprintf(":%s %s %s%s :%s", src, cmd, ctx, args, text)) - } else { - cl.writeLine(fmt.Sprintf(":%s %s %s%s", src, cmd, ctx, args)) - } +func (cl *Client) writeMsg(msg *irc.Message) { + cl.writeLine(msg.String()) } -func (cl *RemoteClient) loop() { +func (cl *Client) loop() { for { time.Sleep(1 * time.Millisecond) if cl.isClosed { @@ -127,7 +107,7 @@ func (cl *RemoteClient) loop() { } } -func (cl *RemoteClient) destroy(s string) { +func (cl *Client) destroy(s string) { if cl.isClosed { return } @@ -143,20 +123,20 @@ func (cl *RemoteClient) destroy(s string) { } } -func (cl *RemoteClient) writeLine(format string, a ...interface{}) { +func (cl *Client) writeLine(format string, a ...interface{}) { cl.writeq <- fmt.Sprintf(format, a...) } -func (cl *RemoteClient) connReader() { +func (cl *Client) connReader() { input := bufio.NewReader(cl.conn) for { s, err := input.ReadString('\n') if err == io.EOF { - cl.destroy("Connection lost.") + cl.destroy("Connection lost") return } if err != nil { - cl.destroy(fmt.Sprintf("Read error (%s).", err.Error())) + cl.destroy(fmt.Sprintf("Read error (%s)", err.Error())) return } s = strings.Trim(s, "\r\n") @@ -164,17 +144,17 @@ func (cl *RemoteClient) connReader() { } } -func (cl *RemoteClient) connWriter() { +func (cl *Client) connWriter() { for line := range cl.writeq { written := 0 bytes := []byte(line + "\r\n") for written < len(line) { n, err := cl.conn.Write(bytes[written:]) if err == io.EOF { - cl.destroy("Connection lost.") + cl.destroy("Connection lost") return } else if err != nil { - cl.destroy(fmt.Sprintf("Write error (%s).", err.Error())) + cl.destroy(fmt.Sprintf("Write error (%s)", err.Error())) return } written += n @@ -182,93 +162,63 @@ func (cl *RemoteClient) connWriter() { } } -var lineFuncs = map[string]func(*RemoteClient, *Message) bool{ - CMD_PASS: handleLinePass, - CMD_NICK: handleLineNick, - CMD_USER: handleLineUser, - // CMD_OPER: handleLineOper, - // CMD_QUIT: handleLineQuit, - CMD_JOIN: handleLineJoin, - CMD_PART: handleLinePart, - CMD_MODE: handleLineMode, - // CMD_TOPIC: handleLineTopic, - // CMD_NAMES: handleLineNames, - // CMD_LIST: handleLineList, - // CMD_INVITE: handleLineInvite, - // CMD_KICK: handleLineKick, - // CMD_VERSION: handleLineVersion, - // CMD_STATS: handleLineStats, - // CMD_TIME: handleLineTime, - // CMD_ADMIN: handleLineAdmin, - // CMD_INFO: handleLineInfo, - CMD_PRIVMSG: handleLinePrivmsg, - // CMD_NOTICE: handleLineNotice, - // CMD_WHO: handleLineWho, - // CMD_WHOIS: handleLineWhois, - // CMD_WHOWAS: handleLineWhowas, - // CMD_KILL: handleLineKill, - CMD_PING: handleLinePing, - // CMD_PONG: handleLinePong, - // CMD_ERROR: handleLineError, - // CMD_AWAY: handleLineAway, - CMD_REHASH: handleLineRehash, - // CMD_RESTART: handleLineRestart, - // CMD_SUMMON: handleLineSummon, - // CMD_USERS: handleLineUsers, - // CMD_USERHOST: handleLineUserhost, - // CMD_ISON: handleLineIson, +var lineFuncs = map[string]func(*Client, *irc.Message) bool{ + "PASS": handleLinePass, + "NICK": handleLineNick, + "USER": handleLineUser, + // "OPER: handleLineOper, + // "QUIT: handleLineQuit, + "JOIN": handleLineJoin, + "PART": handleLinePart, + "MODE": handleLineMode, + // "TOPIC: handleLineTopic, + // "NAMES: handleLineNames, + // "LIST: handleLineList, + // "INVITE: handleLineInvite, + // "KICK: handleLineKick, + // "VERSION: handleLineVersion, + // "STATS: handleLineStats, + // "TIME: handleLineTime, + // "ADMIN: handleLineAdmin, + // "INFO: handleLineInfo, + "PRIVMSG": handleLinePrivmsg, + // "NOTICE: handleLineNotice, + // "WHO: handleLineWho, + // "WHOIS: handleLineWhois, + // "WHOWAS: handleLineWhowas, + // "KILL: handleLineKill, + "PING": handleLinePing, + // "PONG: handleLinePong, + // "ERROR: handleLineError, + // "AWAY: handleLineAway, + "REHASH": handleLineRehash, + // "RESTART: handleLineRestart, + // "SUMMON: handleLineSummon, + // "USERS: handleLineUsers, + // "USERHOST: handleLineUserhost, + // "ISON: handleLineIson, } -func (cl *RemoteClient) handleLine(s string) { +func (cl *Client) handleLine(s string) { xlog.Debug("Raw: [%s] '%s'.", cl.name, s) - msg := M("", "", "", "", "", "") - args := strings.SplitN(s, " :", 2) - if len(args) > 1 { - msg.Text = args[1] - } - args = strings.Fields(args[0]) - msg.Cmd = strings.ToUpper(args[0]) - if len(args) > 1 { - msg.Args = args[1:] - } - msg.Src = cl.name - msg.Dst = "" - if _, exists := lineFuncs[msg.Cmd]; !exists { - // xlog.Warning("No such command (%s).", msg.Cmd) - return - } - if route := lineFuncs[msg.Cmd](cl, msg); route { - // xlog.Warning("Routing to server (%s).", msg.Cmd) - cl.Send(msg) - } + cl.Send(irc.Parse(s)) } -func checkAuth(cl *RemoteClient) { +func checkAuth(cl *Client) { if cl.name == "" || cl.password == "" { return } } -func handleLinePass(cl *RemoteClient, msg *Message) bool { +func handleLinePass(cl *Client, msg *irc.Message) bool { cl.password = msg.Args[0] return false } -func handleLineNick(cl *RemoteClient, msg *Message) bool { +func handleLineNick(cl *Client, msg *irc.Message) bool { if cl.name != "" { - // TODO multiple registration not possible return false } - /* - if _, exists := cl.Server.Clients[msg.Args[0]]; exists { - cl.destroy("User '" + msg.Args[0] + "' already connected.") - } else { - cl.name = msg.Args[0] - cl.isRegistered = true - cl.Server.AddClient <- cl - xlog.Info("User '%s' registered.", msg.Args[0]) - } - */ if len(msg.Args) < 1 { xlog.Warning("Nicksalat!") return false @@ -284,40 +234,30 @@ func handleLineNick(cl *RemoteClient, msg *Message) bool { return false } -func handleLineUser(cl *RemoteClient, msg *Message) bool { +func handleLineUser(cl *Client, msg *irc.Message) bool { return false } -func handleLineJoin(cl *RemoteClient, msg *Message) bool { - msg.Dst = msg.Args[0] - msg.Args = make([]string, 0) +func handleLineJoin(cl *Client, msg *irc.Message) bool { return true } -func handleLinePart(cl *RemoteClient, msg *Message) bool { - msg.Dst = msg.Args[0] - msg.Args = make([]string, 0) +func handleLinePart(cl *Client, msg *irc.Message) bool { return true } -func handleLineMode(cl *RemoteClient, msg *Message) bool { - msg.Dst = msg.Args[0] - msg.Args = make([]string, 0) +func handleLineMode(cl *Client, msg *irc.Message) bool { return true } -func handleLinePrivmsg(cl *RemoteClient, msg *Message) bool { - msg.Dst = msg.Args[0] - msg.Args = make([]string, 0) +func handleLinePrivmsg(cl *Client, msg *irc.Message) bool { return true } -func handleLinePing(cl *RemoteClient, msg *Message) bool { +func handleLinePing(cl *Client, msg *irc.Message) bool { return true } -func handleLineRehash(cl *RemoteClient, msg *Message) bool { +func handleLineRehash(cl *Client, msg *irc.Message) bool { return true } - -// vim:ts=4:sts=4:sw=4:noet:tw=72 diff --git a/entity.go b/entity.go deleted file mode 100644 index 76a6d42..0000000 --- a/entity.go +++ /dev/null @@ -1,6 +0,0 @@ -package ircd - -type Entity interface { -} - -// vi:ts=4:sw=4:et \ No newline at end of file diff --git a/message.go b/message.go deleted file mode 100644 index e145984..0000000 --- a/message.go +++ /dev/null @@ -1,24 +0,0 @@ -package ircd - -import ( - "strings" -) - -type Message struct { - Src string - Dst string - Ctx string - Cmd string - Args []string - Text string -} - -func M(src, dst, ctx, cmd, args, text string) *Message { - argv := []string{} - if args != "" { - argv = strings.Split(args, " ") - } - return &Message{src, dst, ctx, cmd, argv, text} -} - -// vi:ts=4:sw=4:et \ No newline at end of file diff --git a/protocol.go b/protocol.go index 5ac4cb5..30969ff 100644 --- a/protocol.go +++ b/protocol.go @@ -1,4 +1,4 @@ -package ircd +package main const ( // Commands @@ -203,4 +203,4 @@ const ( ERR_UNKNOWNSTAT = "910" // STATS error for unknown STAT request ) -// vi:ts=4:sw=4:et \ No newline at end of file +// vi:ts=4:sw=4:et diff --git a/server.go b/server.go index 6c3f804..138d953 100644 --- a/server.go +++ b/server.go @@ -1,16 +1,19 @@ -package ircd +// vim:ts=4:sts=4:sw=4:noet:tw=72 + +package main import ( - "code.dnix.de/conf" "fmt" "net" "os" + "runtime" "strconv" "strings" "time" - // "io" - "code.dnix.de/xlog" - "runtime" + + "code.dnix.de/an/conf" + "code.dnix.de/an/irc" + "code.dnix.de/an/xlog" ) const ( @@ -30,22 +33,21 @@ type ControlMsg struct { } type Server struct { - Config *conf.ConfigFile - - Receive chan *Message - AddClient chan Client - DelClient chan Client + Dispatch chan *irc.Message + AddClient chan *Client + DelClient chan *Client Host string - info string - software string - version string - created string - motd string - clients map[string]Client - channels map[string]*Channel - ports map[int]bool - configPath string + info string + software string + version string + created string + motd string + clients map[string]*Client + subscriptions map[string][]string + ports map[int]bool + config *conf.ConfigFile + configPath string } func init() { @@ -55,19 +57,18 @@ func init() { func NewServer(configPath, software, version string) *Server { srv := &Server{software: software, version: version, created: "yes"} - srv.Receive = make(chan *Message, 1024) - srv.AddClient = make(chan Client, 1024) - srv.DelClient = make(chan Client, 1024) + srv.Dispatch = make(chan *irc.Message, 1024) + srv.AddClient = make(chan *Client, 1024) + srv.DelClient = make(chan *Client, 1024) srv.Host = "dnix.de" - srv.clients = make(map[string]Client) - srv.channels = make(map[string]*Channel) + srv.clients = make(map[string]*Client) + srv.subscriptions = make(map[string][]string) srv.info = "" srv.motd = `foo bar baz.` srv.configPath = configPath srv.loadConfig() - - loglevel, _ := srv.Config.GetInt("system", "loglevel") + loglevel, _ := srv.config.GetInt("system", "loglevel") xlog.Init(loglevel) return srv @@ -76,278 +77,260 @@ func NewServer(configPath, software, version string) *Server { // Open the listening port and start the main server loop. func (srv *Server) Run() { xlog.Info("%s/%s", srv.software, srv.version) - srv.Host, _ = srv.Config.GetString("server", "host") - srv.info, _ = srv.Config.GetString("server", "info") - port, _ := srv.Config.GetInt("net", "port") + srv.Host, _ = srv.config.GetString("server", "host") + srv.info, _ = srv.config.GetString("server", "info") + port, _ := srv.config.GetInt("net", "port") go srv.listen(port) - srv.loop() + srv.dispatch() } -func (srv *Server) loop() { - xlog.Debug("Entering server main loop.") +func (srv *Server) dispatch() { + xlog.Debug("Entering msg dispatcher") for { time.Sleep(1 * time.Millisecond) select { - case msg := <-srv.Receive: + case msg := <-srv.Dispatch: srv.recvMsg(msg) case cl := <-srv.AddClient: - if _, exists := srv.clients[cl.Name()]; exists { - xlog.Warning("Client registration failed: '%s'.", cl.Name()) + name := cl.Name() + if _, exists := srv.clients[name]; exists { + xlog.Warning("Client registration failed: '%s'", name) go func() { cl.Register() <- false }() continue } go func() { cl.Register() <- true }() - srv.clients[cl.Name()] = cl - xlog.Info("Client registered: '%s'.", cl.Name()) - xlog.Info("Server has %d client(s).", len(srv.clients)) - xlog.Debug("Goroutines running: %d.", runtime.NumGoroutine()) + srv.clients[name] = cl + xlog.Info("Client registered: '%s'", name) + xlog.Info("Server has %d client(s)", len(srv.clients)) + xlog.Debug("Goroutines running: %d", runtime.NumGoroutine()) srv.clientLogon(cl) srv.clientMotd(cl) case cl := <-srv.DelClient: - delete(srv.clients, cl.Name()) - xlog.Info("Client deleted: '%s'.", cl.Name()) - xlog.Info("Server has %d client(s).", len(srv.clients)) - xlog.Debug("Goroutines running: %d.", runtime.NumGoroutine()) + name := cl.Name() + delete(srv.clients, name) + xlog.Info("Client deleted: '%s'", name) + xlog.Info("Server has %d client(s)", len(srv.clients)) + xlog.Debug("Goroutines running: %d", runtime.NumGoroutine()) default: - for name, ch := range srv.channels { - if len(ch.clients) == 0 { - ch.destroy <- true - delete(srv.channels, name) - xlog.Info("Channel destroyed: %s.", name) - } - } } } } func (srv *Server) listen(port int) { if _, exists := srv.ports[port]; exists { - xlog.Warning("Port %i already opened.", port) + xlog.Warning("Port %i already opened", port) } listen, err := net.Listen("tcp", ":"+strconv.Itoa(port)) if err != nil { - xlog.Fatal("Cannot listen on port %i (%s). Exiting.", + xlog.Fatal("Cannot listen on port %i (%s), exiting", port, err.Error()) os.Exit(-1) } - xlog.Info("Start listening on port %d.", port) + xlog.Info("Start listening on port %d", port) for { time.Sleep(1e6) conn, err := listen.Accept() if err != nil { - // return err + xlog.Error(err.Error()) + } else { + NewClient(srv, conn) } - NewRemoteClient(srv, conn) } } func (srv *Server) loadConfig() { - conf, err := conf.ReadConfigFile(srv.configPath) + cfg, err := conf.ReadConfigFile(srv.configPath) if err != nil { - xlog.Fatal("Can't read config file (%s).", err.Error()) + xlog.Fatal("Can't read config file (%s)", err.Error()) os.Exit(-1) } - srv.Config = conf + srv.config = cfg } -func (srv *Server) recvMsg(msg *Message) { - if AddrHost(msg.Dst) != "" { - // TODO send remote - return - } - if AddrHost(msg.Src) != "" { - // TODO from remote - return - } - if msg.Dst != "" { +func (srv *Server) recvMsg(msg *irc.Message) { + if msg.Args[0] != "" { srv.sendMsg(msg) return } cmd := msg.Cmd hook, exists := srvCommandHooks[cmd] if !exists { - srv.sendCommand(msg.Src, ERR_UNKNOWNCOMMAND, cmd, "Unknown command.") + srv.sendCommand(msg.Pre, ERR_UNKNOWNCOMMAND, cmd, "Unknown command") return } argc := len(msg.Args) if argc < hook.MinArgs { - srv.sendCommand(msg.Src, ERR_NEEDMOREPARAMS, cmd, - "Not enough parameters.") + srv.sendCommand(msg.Pre, ERR_NEEDMOREPARAMS, cmd, + "Not enough parameters") return } hook.HookFn(srv, msg) } -func (srv *Server) sendMsg(msg *Message) { - // Splitting this into two functions is necessary to avoid an - // initialization loop in channel.go when broadcasting channel messages. - if strings.HasPrefix(msg.Dst, "#") { +func (srv *Server) sendMsg(msg *irc.Message) { + if strings.HasPrefix(msg.Args[0], "#") { srv.sendMsgToChannel(msg) } else { srv.sendMsgToClient(msg) } } -func (srv *Server) sendMsgToChannel(msg *Message) { - if _, exists := srv.channels[msg.Dst]; !exists { - if msg.Cmd != "JOIN" { - srv.sendCommand(msg.Src, ERR_NOSUCHCHANNEL, msg.Dst, "No such channel.") - return - } - srv.channels[msg.Dst] = NewChannel(srv, msg.Dst) - xlog.Info("Channel created: %s.", msg.Dst) - } - ch := srv.channels[msg.Dst] - ch.Receive(msg) -} - -func (srv *Server) sendMsgToClient(msg *Message) { - if _, exists := srv.clients[msg.Dst]; !exists { - xlog.Error("Client '%s' does not exist.", msg.Dst) +func (srv *Server) sendMsgToChannel(msg *irc.Message) { + subj := msg.Args[0] + if _, exists := srv.subscriptions[subj]; !exists { return } - cl := srv.clients[msg.Dst] + subs := srv.subscriptions[subj] + for _, sub := range subs { + if _, exists := srv.clients[sub]; !exists { + continue + } + cl := srv.clients[sub] + cl.Receive(msg) + } +} + +func (srv *Server) sendMsgToClient(msg *irc.Message) { + if _, exists := srv.clients[msg.Args[0]]; !exists { + xlog.Error("Client '%s' does not exist", msg.Args[0]) + return + } + cl := srv.clients[msg.Args[0]] cl.Receive(msg) } -func (srv *Server) sendRemote(msg *Message) { +func (srv *Server) sendCommand(dst, cmd, args, trail string) { + srv.sendMsg(irc.M(srv.Host, cmd, args, trail)) } -func (srv *Server) sendCommand(dst, cmd, args, text string) { - srv.sendMsg(M(srv.Host, dst, dst, cmd, args, text)) +func (srv *Server) sendClient(cl *Client, cmd, args, trail string) { + srv.sendMsg(irc.M(srv.Host, cmd, cl.Name()+" "+args, trail)) } -func (srv *Server) sendClient(cl Client, cmd, args, text string) { - srv.sendMsg(M(srv.Host, cl.Name(), cl.Name(), cmd, args, text)) -} - -func (srv *Server) clientLogon(cl Client) { +func (srv *Server) clientLogon(cl *Client) { srv.sendClient(cl, RPL_WELCOME, "", "Willkommen!") srv.sendClient(cl, RPL_YOURHOST, "", - fmt.Sprintf("Your host is %s, running on %s/%s.", + fmt.Sprintf("Your host is %s, running on %s/%s", srv.Host, srv.software, srv.version)) - srv.sendClient(cl, RPL_CREATED, "", - "This server was created. Yes. Really.") + srv.sendClient(cl, RPL_CREATED, "", fmt.Sprintf("Created: %s", srv.created)) srv.sendClient(cl, RPL_MYINFO, fmt.Sprintf(myinfo, srv.Host, srv.software, srv.version), "") - srv.sendClient(cl, RPL_ISUPPORT, isupport, "are supported by this server.") + srv.sendClient(cl, RPL_ISUPPORT, isupport, "are supported by this server") } -func (srv *Server) clientMotd(cl Client) { +func (srv *Server) clientMotd(cl *Client) { srv.sendClient(cl, RPL_MOTDSTART, "", fmt.Sprintf("- %s Message of the day -", srv.Host)) for _, line := range strings.Split(srv.motd, "\n") { srv.sendClient(cl, RPL_MOTD, "", fmt.Sprintf("- %s", line)) } - srv.sendClient(cl, RPL_ENDOFMOTD, "", "End of MOTD command.") + srv.sendClient(cl, RPL_ENDOFMOTD, "", "End of MOTD command") } type SrvCommandHook struct { - HookFn func(srv *Server, msg *Message) + HookFn func(srv *Server, msg *irc.Message) MinArgs int NeedOper bool NeedAuth bool } var srvCommandHooks = map[string]SrvCommandHook{ - "OPER": {srvHandleCmdOper, 1, false, false}, - "QUIT": {srvHandleCmdQuit, 0, false, false}, - "MODE": {srvHandleCmdMode, 1, false, false}, - "LIST": {srvHandleCmdList, 0, false, false}, - "VERSION": {srvHandleCmdVersion, 0, false, false}, - "STATS": {srvHandleCmdStats, 0, false, false}, - "TIME": {srvHandleCmdTime, 0, false, false}, - "ADMIN": {srvHandleCmdAdmin, 0, false, false}, - "INFO": {srvHandleCmdInfo, 0, false, false}, - "WHO": {srvHandleCmdWho, 0, false, false}, - "WHOIS": {srvHandleCmdWhois, 0, false, false}, - "WHOWAS": {srvHandleCmdWhowas, 0, false, false}, - "KILL": {srvHandleCmdKill, 0, false, false}, - "PING": {srvHandleCmdPing, 0, false, false}, - "PONG": {srvHandleCmdPong, 0, false, false}, - "ERROR": {srvHandleCmdError, 0, false, false}, - "AWAY": {srvHandleCmdAway, 0, false, false}, - "REHASH": {srvHandleCmdRehash, 0, false, false}, - "RESTART": {srvHandleCmdRestart, 0, false, false}, - "SUMMON": {srvHandleCmdSummon, 0, false, false}, - "USERS": {srvHandleCmdUsers, 0, false, false}, - "USERHOST": {srvHandleCmdUserhost, 0, false, false}, - "ISON": {srvHandleCmdIson, 0, false, false}, + "OPER": {srvHandleCmdOper, 1, false, false}, + "QUIT": {srvHandleCmdQuit, 0, false, false}, + "MODE": {srvHandleCmdMode, 1, false, false}, + "LIST": {srvHandleCmdList, 0, false, false}, + "VERSION": {srvHandleCmdVersion, 0, false, false}, + "STATS": {srvHandleCmdStats, 0, false, false}, + "TIME": {srvHandleCmdTime, 0, false, false}, + "ADMIN": {srvHandleCmdAdmin, 0, false, false}, + "INFO": {srvHandleCmdInfo, 0, false, false}, + "WHO": {srvHandleCmdWho, 0, false, false}, + "WHOIS": {srvHandleCmdWhois, 0, false, false}, + "WHOWAS": {srvHandleCmdWhowas, 0, false, false}, + "KILL": {srvHandleCmdKill, 0, false, false}, + "PING": {srvHandleCmdPing, 0, false, false}, + "PONG": {srvHandleCmdPong, 0, false, false}, + "ERROR": {srvHandleCmdError, 0, false, false}, + "AWAY": {srvHandleCmdAway, 0, false, false}, + "REHASH": {srvHandleCmdRehash, 0, false, false}, + "RESTART": {srvHandleCmdRestart, 0, false, false}, + "SUMMON": {srvHandleCmdSummon, 0, false, false}, + "USERS": {srvHandleCmdUsers, 0, false, false}, + "USERHOST": {srvHandleCmdUserhost, 0, false, false}, + "ISON": {srvHandleCmdIson, 0, false, false}, } -func srvHandleCmdOper(srv *Server, msg *Message) { +func srvHandleCmdOper(srv *Server, msg *irc.Message) { } -func srvHandleCmdQuit(srv *Server, msg *Message) { +func srvHandleCmdQuit(srv *Server, msg *irc.Message) { } -func srvHandleCmdMode(srv *Server, msg *Message) { +func srvHandleCmdMode(srv *Server, msg *irc.Message) { } -func srvHandleCmdList(srv *Server, msg *Message) { +func srvHandleCmdList(srv *Server, msg *irc.Message) { } -func srvHandleCmdVersion(srv *Server, msg *Message) { +func srvHandleCmdVersion(srv *Server, msg *irc.Message) { } -func srvHandleCmdStats(srv *Server, msg *Message) { +func srvHandleCmdStats(srv *Server, msg *irc.Message) { } -func srvHandleCmdTime(srv *Server, msg *Message) { +func srvHandleCmdTime(srv *Server, msg *irc.Message) { } -func srvHandleCmdAdmin(srv *Server, msg *Message) { +func srvHandleCmdAdmin(srv *Server, msg *irc.Message) { } -func srvHandleCmdInfo(srv *Server, msg *Message) { +func srvHandleCmdInfo(srv *Server, msg *irc.Message) { } -func srvHandleCmdWho(srv *Server, msg *Message) { +func srvHandleCmdWho(srv *Server, msg *irc.Message) { } -func srvHandleCmdWhois(srv *Server, msg *Message) { +func srvHandleCmdWhois(srv *Server, msg *irc.Message) { } -func srvHandleCmdWhowas(srv *Server, msg *Message) { +func srvHandleCmdWhowas(srv *Server, msg *irc.Message) { } -func srvHandleCmdKill(srv *Server, msg *Message) { +func srvHandleCmdKill(srv *Server, msg *irc.Message) { } -func srvHandleCmdPing(srv *Server, msg *Message) { - srv.sendCommand(msg.Src, "PONG", "", msg.Args[0]) +func srvHandleCmdPing(srv *Server, msg *irc.Message) { + srv.sendCommand(msg.Pre, "PONG", "", msg.Args[0]) } -func srvHandleCmdPong(srv *Server, msg *Message) { +func srvHandleCmdPong(srv *Server, msg *irc.Message) { } -func srvHandleCmdError(srv *Server, msg *Message) { +func srvHandleCmdError(srv *Server, msg *irc.Message) { } -func srvHandleCmdAway(srv *Server, msg *Message) { +func srvHandleCmdAway(srv *Server, msg *irc.Message) { } -func srvHandleCmdRehash(srv *Server, msg *Message) { +func srvHandleCmdRehash(srv *Server, msg *irc.Message) { srv.loadConfig() - srv.sendCommand(msg.Src, RPL_REHASHING, "", "Rehashing.") + srv.sendCommand(msg.Pre, RPL_REHASHING, "", "Rehashing.") xlog.Info("Rehashing.") } -func srvHandleCmdRestart(srv *Server, msg *Message) { +func srvHandleCmdRestart(srv *Server, msg *irc.Message) { } -func srvHandleCmdSummon(srv *Server, msg *Message) { +func srvHandleCmdSummon(srv *Server, msg *irc.Message) { } -func srvHandleCmdUsers(srv *Server, msg *Message) { +func srvHandleCmdUsers(srv *Server, msg *irc.Message) { } -func srvHandleCmdUserhost(srv *Server, msg *Message) { +func srvHandleCmdUserhost(srv *Server, msg *irc.Message) { } -func srvHandleCmdIson(srv *Server, msg *Message) { +func srvHandleCmdIson(srv *Server, msg *irc.Message) { } - -// vim:ts=4:sts=4:sw=4:noet:tw=72 diff --git a/user.go b/user.go deleted file mode 100644 index 2db13cd..0000000 --- a/user.go +++ /dev/null @@ -1,35 +0,0 @@ -package ircd - -import ( -// "dnix/conf" -// "dnix/xlog" -// "encoding/json" -// "os" -// "time" -) - -type UserRecord struct { - Name string - Pass string - FriendsPending []string - Friends []string - LastLogin int64 -} - -/* -func LoadUser(cfg *conf.ConfigFile, name string) { - path, _ := cfg.GetString("server", "user_path") + "name" - file, err := os.Open(path) - if err != nil { - xlog.Error("Can't open user file '%s' (%s).", name, err.Error()) - return - } - buf := make([]byte, 10000) - _, err := file.Read(buf) - if err != nil { - xlog.Error("Can't read user file '%s' (%s).", name, err.Error()) - } -} -*/ - -// vi:ts=4:sw=4:et \ No newline at end of file