def handleCmd_EOS(self, prefix, args): if prefix != self.server_name: return if self.ism.syncd: return LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.sendLine("TKL + Q * %s* %s 0 %d :Reserved for Dtella" % (cfg.dc_to_irc_prefix, scfg.my_host, time.time())) self.ism.killConflictingUsers() # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def connectionMade(self): scfg = getServiceConfig() LOG.info("Connected to IRC server.") self.challenge = make_challenge() my_capabs = [ ("NICKMAX", 32), ("HALFOP", 1), ("CHANMAX", 65), ("MAXMODES", 20), ("IDENTMAX", 12), ("MAXQUIT", 255), ("MAXTOPIC", 307), ("MAXKICK", 255), ("MAXGECOS", 128), ("MAXAWAY", 200), ("IP6SUPPORT", 1), ("PROTOCOL", 1201), ("CHALLENGE", self.challenge), ] my_capabs_str = ' '.join("%s=%s" % x for x in my_capabs) self.sendLine("CAPAB START") self.sendLine("CAPAB CAPABILITIES :%s" % my_capabs_str) self.sendLine("CAPAB END")
def handleCmd_SERVER(self, prefix, args): if prefix: # Not from our connected server return if self.server_name: # Could be a dupe? Ignore it. return # We got a reply from the our connected IRC server, so our password # was just accepted. Send the Dtella state information into IRC. # Save server name CHECK(args[0]) self.server_name = args[0] LOG.info("IRC Server Name: %s" % self.server_name) # Tell the ReconnectingClientFactory that we're cool self.factory.resetDelay() # This isn't very correct, because the Dtella nicks # haven't been sent yet, but it's the best we can practically do. scfg = getServiceConfig() cloak_checksum = scfg.hostmasker.getChecksum() self.sendLine("NETINFO 0 %d 0 %s 0 0 0 :%s" % (time.time(), cloak_checksum, scfg.network_name)) self.sendLine(":%s EOS" % scfg.my_host)
def handleCmd_EOS(self, prefix, args): if prefix != self.server_name: return if self.ism.syncd: return LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.sendLine( "TKL + Q * %s* %s 0 %d :Reserved for Dtella" % (cfg.dc_to_irc_prefix, scfg.my_host, time.time())) self.ism.killConflictingUsers() # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def handleCmd_PING(self, prefix, args): LOG.info("PING? PONG!") scfg = getServiceConfig() if len(args) == 1: self.sendLine("PONG %s :%s" % (scfg.my_host, args[0])) elif len(args) == 2: self.sendLine("PONG %s :%s" % (args[1], args[0]))
def connectionLost(self, result): LOG.info("Lost IRC connection.") if self.ism.syncd: self.ism.removeMeFromMain() if self.shutdown_deferred: self.shutdown_deferred.callback("Bye!")
def handleCmd_ENDBURST(self, prefix, args): if self.ism.syncd: # FIXME LOG.warning("Ignoring ENDBURST") return CHECK(self.server_name) LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.ism.killConflictingUsers() self.sendLine(":%s ADDLINE Q %s* %s %d 0 :%s" % (self.sid, cfg.dc_to_irc_prefix, scfg.my_host, time.time(), self.qline_reason)) # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def handleCmd_ENDBURST(self, prefix, args): if self.ism.syncd: # FIXME LOG.warning("Ignoring ENDBURST") return CHECK(self.server_name) LOG.info("Finished receiving IRC sync data.") self.showirc = True # Check for conflicting bridges. if self.ism.findConflictingBridge(): LOG.error("My nick prefix is in use! Terminating.") self.transport.loseConnection() reactor.stop() return # Set up nick reservation scfg = getServiceConfig() self.ism.killConflictingUsers() self.sendLine( ":%s ADDLINE Q %s* %s %d 0 :%s" % (self.sid, cfg.dc_to_irc_prefix, scfg.my_host, time.time(), self.qline_reason)) # Send my own bridge nick self.pushBotJoin(do_nick=True) # When we enter the syncd state, register this instance with Dtella. # This will eventually trigger event_DtellaUp, where we send our state. self.schedulePing() self.ism.addMeToMain()
def killConflictingUsers(self): # Find any reserved nicks, and KILL them. CHECK(self.ircs and not self.syncd) bad_users = [u for u in set(self.users.itervalues()) if matches_dc_to_irc_prefix(u.inick)] LOG.info("Conflicting users: %r" % bad_users) for u in bad_users: self.ircs.event_KillUser(u) self.removeUser(u)
def cleanupOnExit(self): LOG.info("Reactor is shutting down. Doing cleanup.") self.shutdown(reconnect='no') self.state.saveState() # Cleanly close the IRC connection before terminating if self.ism: return self.ism.shutdown()
def removeQLine(self, nickmask): self.qlines.pop(nickmask, None) LOG.info("Removed Q-line: " + nickmask) # If some other bridge removes our reservation, abort. if self.syncd and (nickmask == cfg.dc_to_irc_prefix + "*"): LOG.error("My own Q-line was removed! Terminating.") if self.ircs: self.ircs.transport.loseConnection() reactor.stop()
def killConflictingUsers(self): # Find any reserved nicks, and KILL them. CHECK(self.ircs and not self.syncd) bad_users = [ u for u in set(self.users.itervalues()) if matches_dc_to_irc_prefix(u.inick) ] LOG.info("Conflicting users: %r" % bad_users) for u in bad_users: self.ircs.event_KillUser(u) self.removeUser(u)
def addQLine(self, nickmask, reason): nick_re = wild_to_regex(nickmask) # After EOS, auto-remove any Q-lines which conflict with mine. # This may cause a conflicting bridge to abort. if self.syncd and nick_re.match(cfg.dc_to_irc_prefix): if self.ircs: self.ircs.pushRemoveQLine(nickmask) LOG.info("Conflicted Q-line: " + nickmask) return self.qlines[nickmask] = (nick_re, reason) LOG.info("Added Q-line: " + nickmask)
def runClient(dc_port): #Logging for Dtella Client setLogFile("dtella.log", 1<<20, 1) LOG.debug("Client Logging Manager Initialized") from dtella.client.main import DtellaMain_Client dtMain = DtellaMain_Client() import dtella.local_config as local from dtella.common.util import get_version_string def botErrorReporter(text): dch = dtMain.dch if dch: dch.bot.say( "Something bad happened. You might want to email this to " "[email protected] so we'll know about it:\n" "Version: %s %s\n%s" % (local.hub_name, get_version_string()[3:], text)) addTwistedErrorCatcher(botErrorReporter) addTwistedErrorCatcher(LOG.critical) from dtella.client.dc import DCFactory dfactory = DCFactory(dtMain, dc_port) LOG.info("%s %s" % (local.hub_name, local.version)) def cb(first): try: reactor.listenTCP(dc_port, dfactory, interface='127.0.0.1') except twisted.internet.error.CannotListenError: if first: LOG.warning("TCP bind failed. Killing old process...") if terminate(dc_port): LOG.info("Ok. Sleeping...") reactor.callLater(2.0, cb, False) else: LOG.error("Kill failed. Giving up.") reactor.stop() else: LOG.error("Bind failed again. Giving up.") reactor.stop() else: LOG.info("Listening on 127.0.0.1:%d" % dc_port) dtMain.startConnecting() reactor.callWhenRunning(cb, True) reactor.run()
def runClient(dc_port): #Logging for Dtella Client setLogFile("dtella.log", 1 << 20, 1) LOG.debug("Client Logging Manager Initialized") from dtella.client.main import DtellaMain_Client dtMain = DtellaMain_Client() import dtella.local_config as local from dtella.common.util import get_version_string def botErrorReporter(text): dch = dtMain.dch if dch: dch.bot.say( "Something bad happened. You might want to email this to " "[email protected] so we'll know about it:\n" "Version: %s %s\n%s" % (local.hub_name, get_version_string()[3:], text)) addTwistedErrorCatcher(botErrorReporter) addTwistedErrorCatcher(LOG.critical) from dtella.client.dc import DCFactory dfactory = DCFactory(dtMain, dc_port) LOG.info("%s %s" % (local.hub_name, local.version)) def cb(first): try: reactor.listenTCP(dc_port, dfactory, interface='127.0.0.1') except twisted.internet.error.CannotListenError: if first: LOG.warning("TCP bind failed. Killing old process...") if terminate(dc_port): LOG.info("Ok. Sleeping...") reactor.callLater(2.0, cb, False) else: LOG.error("Kill failed. Giving up.") reactor.stop() else: LOG.error("Bind failed again. Giving up.") reactor.stop() else: LOG.info("Listening on 127.0.0.1:%d" % dc_port) dtMain.startConnecting() reactor.callWhenRunning(cb, True) reactor.run()
def event_DtellaUp(self): osm = self.getOnlineStateManager() LOG.info("Sending Dtella state to IRC...") nicks = osm.nkm.nickmap.values() nicks.sort(key=lambda n: n.nick) for n in nicks: try: # This event does everything we need. self.event_AddNick(n) except NickError: osm.nkm.removeNode(n, "Bad Nick") n.setNoUser()
def cb(first): try: reactor.listenTCP(dc_port, dfactory, interface='127.0.0.1') except twisted.internet.error.CannotListenError: if first: LOG.warning("TCP bind failed. Killing old process...") if terminate(dc_port): LOG.info("Ok. Sleeping...") reactor.callLater(2.0, cb, False) else: LOG.error("Kill failed. Giving up.") reactor.stop() else: LOG.error("Bind failed again. Giving up.") reactor.stop() else: LOG.info("Listening on 127.0.0.1:%d" % dc_port) dtMain.startConnecting()
def handleCmd_SQUIT(self, prefix, args): # :n.dhirc.com SQUIT remote.dtella.org :Remote host closed hostname = args[0] try: # All servers have been registered as users. sid = self.ism.findUser(hostname).uuid.lower() if len(sid) != 3: raise KeyError except KeyError: LOG.error("SQUIT: unknown server: %s" % hostname) return # Find all the users belonging to this server. This should # never match nicks, because only UUIDs start with a number. remove_uuids = [uuid for uuid in self.ism.users if uuid.startswith(sid)] # Drop them off the network. for uuid in remove_uuids: LOG.info("SQUIT: removing user: %s" % uuid) self.ism.removeUser(self.ism.findUser(uuid))
def findConflictingBridge(self): # Determine if another bridge conflicts with me. # Return True if we need to abort. CHECK(self.ircs and not self.syncd) stale_qlines = [] for nickmask, (q, reason) in self.qlines.iteritems(): # Look for Q-lines which conflict with my prefix. if not q.match(cfg.dc_to_irc_prefix): continue LOG.info("Found a conflicting Q-line: %s" % nickmask) # If any nicks exist under that Q-line, we'll need to abort. for u in set(self.users.itervalues()): if q.match(u.inick): LOG.info("... and a nick to go with it: %s" % u.inick) return True stale_qlines.append(nickmask) # Remove all stale Q-lines from the network. LOG.info("Stale qlines: %r" % stale_qlines) for nickmask in stale_qlines: del self.qlines[nickmask] self.ircs.pushRemoveQLine(nickmask) # Conflict has been neutralized. return False
def handleCmd_SQUIT(self, prefix, args): # :n.dhirc.com SQUIT remote.dtella.org :Remote host closed hostname = args[0] try: # All servers have been registered as users. sid = self.ism.findUser(hostname).uuid.lower() if len(sid) != 3: raise KeyError except KeyError: LOG.error("SQUIT: unknown server: %s" % hostname) return # Find all the users belonging to this server. This should # never match nicks, because only UUIDs start with a number. remove_uuids = [ uuid for uuid in self.ism.users if uuid.startswith(sid) ] # Drop them off the network. for uuid in remove_uuids: LOG.info("SQUIT: removing user: %s" % uuid) self.ism.removeUser(self.ism.findUser(uuid))
def handleCmd_SERVER(self, prefix, args): # :foo.dhirc.com SERVER s.dhirc.com * 1 00A :Services hostname = args[0] password = args[1] sid = args[3] # Register each server as a user, because it's easier. LOG.info("Recording server: hostname=%s sid=%s" % (hostname, sid)) self.ism.addUser(hostname, sid) if prefix: # Not my directly-connected server. return if self.server_name: # Could be a dupe? Ignore it. return # We got a reply from the our connected IRC server, so our password # was just accepted. Send the Dtella state information into IRC. scfg = getServiceConfig() # Save server name CHECK(args[0]) self.server_name = args[0] # Verify challenge response. if scfg.recvpass is None: LOG.info("Skipping validation of recvpass") else: ch_response = args[1] if ch_response != ihmac(scfg.recvpass, self.challenge): raise ValueError("Incorrect recvpass") LOG.info("Correct recvpass") LOG.info("IRC Server Name: %s" % self.server_name) # Tell the ReconnectingClientFactory that we're cool self.factory.resetDelay() self.sendLine("BURST %d" % time.time()) self.sendLine("ENDBURST")
def event_KillUser(self, u): scfg = getServiceConfig() LOG.info("Killing nick: " + u.inick) self.sendLine(":%s KILL %s :%s (nick reserved for Dtella)" % (scfg.my_host, u.inick, scfg.my_host))
def pushRemoveQLine(self, nickmask): scfg = getServiceConfig() LOG.info("Telling network to remove Q-line: %s" % nickmask) self.sendLine("TKL - Q * %s %s" % (nickmask, scfg.my_host))
def pushRemoveQLine(self, nickmask): scfg = getServiceConfig() LOG.info("Telling network to remove Q-line: %s" % nickmask) self.sendLine(":%s DELLINE Q %s" % (self.sid, nickmask))
class IRCStateManager(object): implements(IDtellaStateObserver) def __init__(self, main, ircs=None, uuid_generator=None): self.main = main self.ircs = ircs self.syncd = False self.uuid_generator = uuid_generator # inick.lower() -> User object # *also* indexed by uuid.lower(), if those are enabled. self.users = {} # If we're using UUIDs, create dicts to keep track of them. if self.uuid_generator: # uuid.lower() -> Node() self.dt_uuids = {} # Set of all User()s in the Dtella channel. self.chanusers = set() self.topic = "" self.topic_whoset = "" # always a dnick self.topic_locked = False self.moderated = False # string -> compiled regex self.chanbans = {} # string -> (compiled regex, reason) self.qlines = {} # Network bans: (ip, mask), both ints. self.bans = set() # Set up the dc->irc bot. if self.uuid_generator: bot_uuid = self.uuid_generator() else: bot_uuid = None self.bot_user = User(cfg.dc_to_irc_bot, bot_uuid) # --- These methods are called from the IRC server --- def addMeToMain(self): CHECK(not self.syncd) self.syncd = True self.main.addIRCStateManager(self) def removeMeFromMain(self): # After calling this, I'm basically a dead object. self.main.removeIRCStateManager(self) def addUser(self, inick, uuid=None): # Start tracking a new IRC user. CHECK(inick.lower() not in self.users) if self.uuid_generator: CHECK(number_prefix(uuid)) CHECK(uuid.lower() not in self.users) # If the nick is a uuid, it must be its own uuid. if number_prefix(inick): CHECK(inick.lower() == uuid.lower()) else: CHECK(uuid is None) u = User(inick, uuid) # Don't allow nicks which match my prefix. if self.syncd and matches_dc_to_irc_prefix(u.inick): if self.ircs: self.ircs.event_KillUser(u) return self.users[inick.lower()] = u if self.uuid_generator: self.users[uuid.lower()] = u return u def removeUser(self, u, message=None): self.partChannel(u, message) # If inick is not a uuid, remove from index. if not (self.uuid_generator and number_prefix(u.inick)): CHECK(self.users.pop(u.inick.lower()) is u) # If a uuid is defined, remove from index. if self.uuid_generator: CHECK(self.users.pop(u.uuid.lower()) is u) def findUser(self, inick): # Note: inick may also be a uuid. return self.users[inick.lower()] def changeNick(self, u, new_inick): old_inick = u.inick if old_inick.lower() == new_inick.lower(): # TODO: report case changes to Dtella? u.inick = new_inick return if self.uuid_generator and number_prefix(new_inick): # If nick is changing to a uuid, it must be its own uuid. CHECK(new_inick.lower() == u.uuid.lower()) else: # Otherwise, the nick must not already exist. CHECK(new_inick.lower() not in self.users) if not (self.uuid_generator and number_prefix(u.inick)): # If old nick is not a uuid, remove it from the index. CHECK(self.users.pop(u.inick.lower()) is u) # Don't allow IRC nicks which match my prefix. conflicted = (self.syncd and matches_dc_to_irc_prefix(new_inick)) if conflicted: # Report exit from Dtella before updating nick. self.partChannel(u) # Update nick. Note that UUID is unchanged. u.inick = new_inick self.users[new_inick.lower()] = u if conflicted: # Nick matches my prefix, diediedie! if self.ircs: self.ircs.event_KillUser(u) self.removeUser(u) return scfg = getServiceConfig() # Report the change to Dtella. if u in self.chanusers: try: osm = self.getOnlineStateManager() except NotOnline: return infoindex = scfg.chan_umodes.getUserInfoIndex(u) chunks = [] osm.bsm.addChatChunk( chunks, cfg.irc_to_dc_bot, "%s is now known as %s" % (irc_to_dc(old_inick), irc_to_dc(new_inick))) osm.bsm.addNickChunk(chunks, irc_to_dc(old_inick), 0xFF) osm.bsm.addNickChunk(chunks, irc_to_dc(new_inick), infoindex) osm.bsm.sendBridgeChange(chunks) def isMyBot(self, inick): # Identify the dc_to_irc_bot, by either nick or uuid. return (inick.lower() == self.bot_user.inick.lower() or inick.lower() == self.bot_user.uuid.lower()) def joinChannel(self, u): if u in self.chanusers: LOG.error("joinChannel: %r already in channel." % u) return self.chanusers.add(u) u.chanmodes.clear() try: osm = self.getOnlineStateManager() except NotOnline: return scfg = getServiceConfig() infoindex = scfg.chan_umodes.getUserInfoIndex(u) chunks = [] osm.bsm.addNickChunk(chunks, irc_to_dc(u.inick), infoindex) osm.bsm.sendBridgeChange(chunks) def partChannel(self, u, message=None): # Remove user from the Dtella channel. Return True if successful. try: self.chanusers.remove(u) except KeyError: return False try: osm = self.getOnlineStateManager() except NotOnline: # Removal was successful, even if it's not broadcasted. return True chunks = [] if message: osm.bsm.addChatChunk(chunks, cfg.irc_to_dc_bot, message) osm.bsm.addNickChunk(chunks, irc_to_dc(u.inick), 0xFF) osm.bsm.sendBridgeChange(chunks) return True def findDtellaNode(self, inick=None, dnick=None): # Try to find a user on Dtella. # note: inick may also be a UUID. try: osm = self.getOnlineStateManager() except NotOnline: return None if inick: # First, try parsing inick as a UUID. if self.uuid_generator: try: return self.dt_uuids[inick.lower()] except KeyError: pass try: dnick = dc_from_irc(inick) except NickError: pass if not dnick: return None try: return osm.nkm.lookupNick(dnick) except KeyError: return None def kickDtellaNode(self, n, l33t_inick, reason, send_quit=True): # Handler for KICK/KILL of an existing Dtella user. # Caller should get 'n' from findDtellaNode() # Exception shouldn't happen here; don't catch. osm = self.getOnlineStateManager() # Send a kick message. chunks = [] osm.bsm.addKickChunk(chunks, n, irc_to_dc(l33t_inick), reason, rejoin=True, silent=False) osm.bsm.sendBridgeChange(chunks) # Forget this nick. if not send_quit: del n.inick osm.nkm.removeNode(n, "Kicked") n.setNoUser() def sendPrivateMessage(self, n, src_inick, text, flags): # Send a private message to a Dtella node. # Caller should get 'n' from findDtellaNode() # Exception shouldn't happen here; don't catch. osm = self.getOnlineStateManager() chunks = [] osm.bsm.addMessageChunk(chunks, irc_to_dc(src_inick), text, flags) osm.bsm.sendPrivateBridgeChange(n, chunks) def sendChannelMessage(self, src_inick, text, flags): # Send text to all Dtella nodes. try: osm = self.getOnlineStateManager() except NotOnline: return chunks = [] osm.bsm.addChatChunk(chunks, irc_to_dc(src_inick), text, flags) osm.bsm.sendBridgeChange(chunks) def setTopic(self, whoset, topic): try: # DC nick dnick = dc_from_irc(whoset) except NickError: # IRC nick dnick = irc_to_dc(whoset) self.topic = topic self.topic_whoset = dnick try: osm = self.getOnlineStateManager() except NotOnline: return chunks = [] osm.bsm.addTopicChunk(chunks, dnick, topic, changed=True) osm.bsm.sendBridgeChange(chunks) def setModerated(self, whoset, on_off): self.moderated = on_off try: osm = self.getOnlineStateManager() except NotOnline: return if on_off: action = "enabled" else: action = "disabled" chunks = [] osm.bsm.addModeratedChunk(chunks, on_off) osm.bsm.addChatChunk(chunks, cfg.irc_to_dc_bot, "%s %s moderation." % (irc_to_dc(whoset), action)) osm.bsm.sendBridgeChange(chunks) def setTopicLocked(self, whoset, on_off): self.topic_locked = on_off try: osm = self.getOnlineStateManager() except NotOnline: return if on_off: action = "locked" else: action = "unlocked" chunks = [] osm.bsm.addChatChunk(chunks, cfg.irc_to_dc_bot, "%s %s the topic." % (irc_to_dc(whoset), action)) osm.bsm.sendBridgeChange(chunks) def setChannelBan(self, whoset, on_off, banmask): if on_off: self.chanbans[banmask] = wild_to_regex(banmask) action = "added" else: self.chanbans.pop(banmask, None) action = "removed" LOG.debug("bans= %s" % self.chanbans.keys()) try: osm = self.getOnlineStateManager() except NotOnline: return chunks = [] osm.bsm.addChatChunk( chunks, cfg.irc_to_dc_bot, "%s %s ban: %s" % (irc_to_dc(whoset), action, banmask)) osm.bsm.sendBridgeChange(chunks) def setChannelUserModes(self, whoset, u, changes): # changes: dict of {mode -> on_off} if u not in self.chanusers: LOG.error("setChannelUserModes: %r not in channel." % u) return scfg = getServiceConfig() # Save old index, apply changes, and get new index. old_infoindex = scfg.chan_umodes.getUserInfoIndex(u) for mode, on_off in changes.iteritems(): if on_off: u.chanmodes.add(mode) else: u.chanmodes.discard(mode) new_infoindex = scfg.chan_umodes.getUserInfoIndex(u) try: osm = self.getOnlineStateManager() except NotOnline: return chunks = [] if new_infoindex == old_infoindex: friendly_change = "well that was pointless" else: friendly_change = "%s -> %s" % ( scfg.chan_umodes.friendly[old_infoindex], scfg.chan_umodes.friendly[new_infoindex]) osm.bsm.addNickChunk(chunks, irc_to_dc(u.inick), new_infoindex) osm.bsm.addChatChunk( chunks, cfg.irc_to_dc_bot, "%s set mode %s for %s: %s" % (irc_to_dc(whoset), self.formatChannelUserModes(changes), irc_to_dc(u.inick), friendly_change)) osm.bsm.sendBridgeChange(chunks) def addQLine(self, nickmask, reason): nick_re = wild_to_regex(nickmask) # After EOS, auto-remove any Q-lines which conflict with mine. # This may cause a conflicting bridge to abort. if self.syncd and nick_re.match(cfg.dc_to_irc_prefix): if self.ircs: self.ircs.pushRemoveQLine(nickmask) LOG.info("Conflicted Q-line: " + nickmask) return self.qlines[nickmask] = (nick_re, reason) LOG.info("Added Q-line: " + nickmask) def removeQLine(self, nickmask): self.qlines.pop(nickmask, None) LOG.info("Removed Q-line: " + nickmask) # If some other bridge removes our reservation, abort. if self.syncd and (nickmask == cfg.dc_to_irc_prefix + "*"): LOG.error("My own Q-line was removed! Terminating.") if self.ircs: self.ircs.transport.loseConnection() reactor.stop() def setNetworkBan(self, cidr, on_off): # See if this is a valid 1.2.3.4/5 CIDR string. try: ipmask = ipv4.CidrStringToIPMask(cidr) except ValueError, e: LOG.error("Bad CIDR string: %s") return # Convert back, to get a normalized string. cidr = ipv4.IPMaskToCidrString(ipmask) if on_off: if ipmask in self.bans: LOG.warning("Duplicate ban: %s" % cidr) return self.bans.add(ipmask) LOG.info("Added ban: %s" % cidr) else: try: self.bans.remove(ipmask) except KeyError: LOG.warning("Ban not found: %s" % cidr) return LOG.info("Removed ban: %s" % cidr) # If we're online, broadcast the ban. try: osm = self.getOnlineStateManager() except NotOnline: pass else: ip, mask = ipmask chunks = [] osm.bsm.addBanChunk(chunks, ip, mask, on_off) osm.bsm.sendBridgeChange(chunks) # If we're even sort-of online, update local bans. if self.main.osm: self.main.osm.banm.scheduleRebuildBans()
def cleanupOnExit(self): LOG.info("Reactor is shutting down. Doing cleanup.") self.shutdown(reconnect="no") self.state.saveState()
def connectionMade(self): scfg = getServiceConfig() LOG.info("Connected to IRC server.") self.sendLine("PASS :%s" % (scfg.sendpass,)) self.sendLine( "SERVER %s 1 :%s" % (scfg.my_host, scfg.my_name))
def showLoginStatus(self, text, counter=None): LOG.info(text)
def connectionMade(self): scfg = getServiceConfig() LOG.info("Connected to IRC server.") self.sendLine("PASS :%s" % (scfg.sendpass, )) self.sendLine("SERVER %s 1 :%s" % (scfg.my_host, scfg.my_name))
def cleanupOnExit(self): LOG.info("Reactor is shutting down. Doing cleanup.") if self.dch: self.dch.state = 'shutdown' self.shutdown(reconnect='no') self.state.saveState()