// Input goroutine function for a client. // Own readings on the socket. func input(c *Client) { // Stop panics here, so they only disconnect the client they affect. //defer func() { // recover() //}() // Delete the client when this returns. errMsg := "Input Error" defer func() { c.mutex.Lock() c.disconnecting |= 4 // Marks input as done. c.delete(errMsg) c.mutex.Unlock() }() irc.ReadLine(c.conn, make([]byte, 2096), func(line []byte) { // Parse the line, ignoring any specified origin. _, command, params, perr := irc.Parse(Commands, line, c.u.Registered()) // If we successfully got a command, run it. if command != nil { // If it's an oper command, check permissions. if command.OperFlag != "" && !perm.HasOperCommand(c.u, command.OperFlag, command.Name) { c.SendLineTo(nil, "481", ":You do not have the appropriate privileges to use this command.") return } command.Handler(c, params) } else if perr != nil { // The IRC protocol is stupid. switch perr.Num { case irc.CmdNotFound: if c.u.Registered() { c.SendLineTo(nil, "421", "%s :%s", perr.CmdName, perr) } case irc.CmdForRegistered: c.SendFrom(nil, "451 %s :%s", perr.CmdName, perr) case irc.CmdForUnregistered: c.SendFrom(nil, "462 %s :%s", c.u.Nick(), perr) default: c.SendFrom(nil, "461 %s %s :%s", c.u.Nick(), perr.CmdName, perr) } } }) }
// Handle a single (potential) server link. // outgoing indicates whether it is outgoing or incoming. func link(c *net.TCPConn, outgoing bool) { errMsg := "Input Error" serverMutex.Lock() // Create a new server, and add it to the server list. l := new(local) l.local = l l.next = servers if servers != nil { servers.prev = &(l.server) } servers = &(l.server) l.c = c serverMutex.Unlock() // Defer deletion of the server. If it's already deleted, no harm done. defer func() { l.Delete(errMsg) }() if outgoing { link_auth(l) } errMsg = irc.ReadLine(l.c, make([]byte, 20960), func(line []byte) { // Parse the line. prefix, command, params, perr := irc.Parse(commands, line, l.authed) // Look up the server or user this command is from. var source interface{} if len(prefix) == 9 { u := core.GetUser(string(prefix)) if u == nil { source = nil } else if u.Owner() != me { source = nil } else { userver := u.Owndata().(*server) if userver.local == l { source = u } } } else if len(prefix) == 3 { v := core.GetSID(string(prefix)) if v == nil { source = nil } else if s, ok := v.(*server); ok { if s.local == l { source = s } } } else if len(prefix) == 0 { // No prefix; it's from this server. source = &(l.server) } else { // Prefix is gibberish. source = nil } // If we successfully got a command and source, run it. if source != nil && command != nil { command.Handler(source, params) } else if perr != nil { // The IRC protocol is stupid. switch perr.Num { case irc.CmdNotFound: irc.SendLine(l, from(nil), l.sid, "421", "%s :%s", perr.CmdName, perr) case irc.CmdForRegistered: irc.SendFrom(l, from(nil), "451 %s :%s", perr.CmdName, perr) case irc.CmdForUnregistered: irc.SendFrom(l, from(nil), "462 %s :%s", l.sid, perr) default: irc.SendFrom(l, from(nil), "461 %s %s :%s", l.sid, perr.CmdName, perr) } } }) }