func SQuit(hook string, msg *parser.Message, ircd *IRCd) { split, reason := msg.Args[0], msg.Args[1] if split == Config.SID { split = msg.SenderID } // Forward for sid := range server.Iter() { if sid != msg.SenderID { msg := msg.Dup() msg.DestIDs = []string{sid} ircd.ToServer <- msg } } if server.IsLocal(split) { ircd.ToServer <- &parser.Message{ Command: parser.CMD_ERROR, Args: []string{ "SQUIT: " + reason, }, } } sids := server.Unlink(split) peers := user.Netsplit(sids) notify := channel.Netsplit(Config.SID, peers) log.Debug.Printf("NET SPLIT: %s", split) log.Debug.Printf(" - SIDs: %v", sids) log.Debug.Printf(" - Peers: %v", peers) log.Debug.Printf(" - Notify: %v", notify) for uid, peers := range notify { if len(peers) > 0 { ircd.ToClient <- &parser.Message{ Prefix: uid, Command: parser.CMD_QUIT, Args: []string{ "*.net *.split", }, DestIDs: peers, } } } // Delete all of the peers if len(peers) > 0 { ircd.ToClient <- &parser.Message{ Command: parser.INT_DELUSER, DestIDs: peers, } } }
func (s *IRCd) manageServers() { defer s.running.Done() sid2conn := make(map[string]*conn.Conn) upstream := "" _ = upstream var open bool = true var msg *parser.Message for open { // Check if we are connected to our upstream // TODO(kevlar): upstream select { //// Incoming and outgoing messages to and from servers // Messages directly from connections case msg = <-s.fromServer: var conn *conn.Conn var ok bool if conn, ok = sid2conn[msg.SenderID]; !ok { log.Debug.Printf("{%s} >> [DROPPING] %s\n", msg.SenderID, msg) continue } log.Debug.Printf("{%s} >> %s\n", msg.SenderID, msg) if msg.Command == parser.CMD_ERROR { if conn != nil { log.Debug.Printf("{%s} ** Connection terminated remotely", msg.SenderID) sid2conn[msg.SenderID] = nil, false conn.UnsubscribeClose(s.serverClosing) conn.Close() if server.IsLocal(msg.SenderID) { DispatchServer(&parser.Message{ SenderID: msg.SenderID, Command: parser.CMD_SQUIT, Args: []string{ msg.SenderID, "Unexpected ERROR on connection", }, }, s) } } continue } DispatchServer(msg, s) // Messages from hooks case msg, open = <-s.ToServer: // Count the number of messages sent sentcount := 0 for _, dest := range msg.DestIDs { log.Debug.Printf("{%v} << %s\n", dest, msg) if conn, ok := sid2conn[dest]; ok { conn.WriteMessage(msg) sentcount++ } else { log.Warn.Printf("Unknown SID %s", dest) } } if sentcount == 0 { log.Warn.Printf("Dropped outgoing server message: %s", msg) } //// Connection management // Connecting servers case conn := <-s.newServer: sid := conn.ID() sid2conn[sid] = conn server.Get(sid, true) log.Debug.Printf("{%s} ** Registered connection", sid) conn.Subscribe(s.fromServer) conn.SubscribeClose(s.serverClosing) // Disconnecting servers case closeid := <-s.serverClosing: log.Debug.Printf("{%s} ** Connection closed", closeid) sid2conn[closeid] = nil, false if server.IsLocal(closeid) { DispatchServer(&parser.Message{ SenderID: closeid, Command: parser.CMD_SQUIT, Args: []string{ closeid, "Connection close", }, }, s) } } } }