From d0209f720a9a2226dc5f33486e332106bb363771 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sun, 25 Jun 2017 01:12:22 -0700 Subject: [PATCH] Rewrite network intitialization bits - Move protocols.connect -> protocols.post_connect to fix namespace conflict - Starting an IRC connection is now explicit (via irc.connect instead of __init__) --- classes.py | 26 +++++++++++++------------- protocols/clientbot.py | 6 +++--- protocols/hybrid.py | 8 ++++---- protocols/inspircd.py | 6 +++--- protocols/ircs2s_common.py | 6 +++--- protocols/nefarious.py | 4 ++-- protocols/p10.py | 8 ++++---- protocols/ratbox.py | 7 +++---- protocols/ts6.py | 6 +++--- protocols/ts6_common.py | 7 +++---- protocols/unreal.py | 6 +++--- pylink | 8 ++++++-- 12 files changed, 50 insertions(+), 48 deletions(-) diff --git a/classes.py b/classes.py index 3f65ea8..96d6de5 100644 --- a/classes.py +++ b/classes.py @@ -1130,17 +1130,6 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore): _getUid = _get_UID class IRCNetwork(PyLinkNetworkCoreWithUtils): - def __init__(self, *args): - super().__init__(*args) - if world.testing: - # HACK: Don't thread if we're running tests. - self.connect() - else: - self.connection_thread = threading.Thread(target=self.connect, - name="Listener for %s" % - self.name) - self.connection_thread.start() - def schedule_ping(self): """Schedules periodic pings in a loop.""" self.proto.ping() @@ -1152,7 +1141,7 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils): log.debug('(%s) Ping scheduled at %s', self.name, time.time()) - def connect(self): + def _connect(self): """ Runs the connect loop for the IRC object. This is usually called by __init__ in a separate thread to allow multiple concurrent connections. @@ -1265,7 +1254,7 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils): self.sid = self.serverdata.get("sid") # All our checks passed, get the protocol module to connect and run the listen # loop. This also updates any SID values should the protocol module do so. - self.proto.connect() + self.post_connect() log.info('(%s) Enumerating our own SID %s', self.name, self.sid) host = self.hostname() @@ -1296,6 +1285,17 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils): if not self._run_autoconnect(): return + def connect(self): + log.debug('(%s) calling _connect() (world.testing=%s)', self.name, world.testing) + if world.testing: + # HACK: Don't thread if we're running tests. + self._connect() + else: + self.connection_thread = threading.Thread(target=self._connect, + name="Listener for %s" % + self.name) + self.connection_thread.start() + def disconnect(self): """Handle disconnects from the remote server.""" self._pre_disconnect() diff --git a/protocols/clientbot.py b/protocols/clientbot.py index 5db94e7..59ba253 100644 --- a/protocols/clientbot.py +++ b/protocols/clientbot.py @@ -11,8 +11,8 @@ COMMON_PREFIXMODES = [('h', 'halfop'), ('a', 'admin'), ('q', 'owner'), ('y', 'ow IRCV3_CAPABILITIES = {'multi-prefix', 'sasl'} class ClientbotWrapperProtocol(IRCCommonProtocol): - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.protocol_caps = {'clear-channels-on-leave', 'slash-in-nicks', 'slash-in-hosts', 'underscore-in-hosts'} @@ -51,7 +51,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol): return nick return uid - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" # (Re)initialize counter-based pseudo UID generators self.uidgen = utils.PUIDGenerator('PUID') diff --git a/protocols/hybrid.py b/protocols/hybrid.py index 8fdae6a..193d527 100644 --- a/protocols/hybrid.py +++ b/protocols/hybrid.py @@ -5,10 +5,10 @@ from pylinkirc.log import log from pylinkirc.classes import * from pylinkirc.protocols.ts6 import * +# This protocol module inherits from the TS6 protocol. class HybridProtocol(TS6Protocol): - def __init__(self, irc): - # This protocol module inherits from the TS6 protocol. - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.casemapping = 'ascii' self.caps = {} @@ -16,7 +16,7 @@ class HybridProtocol(TS6Protocol): self.has_eob = False self.protocol_caps -= {'slash-in-hosts'} - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" ts = self.irc.start_ts self.has_eob = False diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 83ce4e6..be27777 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -11,8 +11,8 @@ from pylinkirc.log import log from pylinkirc.protocols.ts6_common import * class InspIRCdProtocol(TS6BaseProtocol): - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.protocol_caps |= {'slash-in-nicks', 'slash-in-hosts', 'underscore-in-hosts'} @@ -392,7 +392,7 @@ class InspIRCdProtocol(TS6BaseProtocol): ### Core / command handlers - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" ts = self.irc.start_ts diff --git a/protocols/ircs2s_common.py b/protocols/ircs2s_common.py index fa0d7bf..a459183 100644 --- a/protocols/ircs2s_common.py +++ b/protocols/ircs2s_common.py @@ -11,7 +11,7 @@ from pylinkirc.log import log from pylinkirc import utils class IRCCommonProtocol(IRCNetwork): - def validateServerConf(self): + def validate_server_conf(self): """Validates that the server block given contains the required keys.""" for k in self.conf_keys: assert k in self.irc.serverdata, "Missing option %r in server block for network %s." % (k, self.irc.name) @@ -142,8 +142,8 @@ class IRCCommonProtocol(IRCNetwork): class IRCS2SProtocol(IRCCommonProtocol): COMMAND_TOKENS = {} - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.protocol_caps = {'can-spawn-clients', 'has-ts', 'can-host-relay', 'can-track-servers'} diff --git a/protocols/nefarious.py b/protocols/nefarious.py index 9966745..93267ee 100644 --- a/protocols/nefarious.py +++ b/protocols/nefarious.py @@ -6,8 +6,8 @@ from pylinkirc.log import log from pylinkirc.protocols.p10 import * class NefariousProtocol(P10Protocol): - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) log.warning("(%s) protocols/nefarious.py has been renamed to protocols/p10.py, which " "now also supports other IRCu variants. Please update your configuration, " "as this migration stub will be removed in a future version.", diff --git a/protocols/p10.py b/protocols/p10.py index e7f1ba1..339faff 100644 --- a/protocols/p10.py +++ b/protocols/p10.py @@ -151,14 +151,14 @@ class P10Protocol(IRCS2SProtocol): 'FA': 'FAKE' } - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Dictionary of UID generators (one for each server). self.uidgen = structures.KeyedDefaultdict(P10UIDGenerator) # SID generator for P10. - self.sidgen = P10SIDGenerator(irc) + self.sidgen = P10SIDGenerator(self) self.hook_map = {'END_OF_BURST': 'ENDBURST', 'OPMODE': 'MODE', 'CLEARMODE': 'MODE', 'BURST': 'JOIN'} @@ -754,7 +754,7 @@ class P10Protocol(IRCS2SProtocol): ### HANDLERS - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" ts = self.irc.start_ts diff --git a/protocols/ratbox.py b/protocols/ratbox.py index fbf73cd..394b14b 100644 --- a/protocols/ratbox.py +++ b/protocols/ratbox.py @@ -7,17 +7,16 @@ from pylinkirc.protocols.ts6 import * class RatboxProtocol(TS6Protocol): - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Don't require EUID for Ratbox self.required_caps.discard('EUID') self.hook_map['LOGIN'] = 'CLIENT_SERVICES_LOGIN' self.protocol_caps -= {'slash-in-hosts'} - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" - super().connect() # Note: +r, +e, and +I support will be negotiated on link self.irc.cmodes = {'op': 'o', 'secret': 's', 'private': 'p', 'noextmsg': 'n', 'moderated': 'm', diff --git a/protocols/ts6.py b/protocols/ts6.py index c498ee5..b49a9ae 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -13,8 +13,8 @@ from pylinkirc.protocols.ts6_common import * S2S_BUFSIZE = 510 class TS6Protocol(TS6BaseProtocol): - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.protocol_caps |= {'slash-in-hosts'} self.casemapping = 'rfc1459' self.hook_map = {'SJOIN': 'JOIN', 'TB': 'TOPIC', 'TMODE': 'MODE', 'BMASK': 'MODE', @@ -255,7 +255,7 @@ class TS6Protocol(TS6BaseProtocol): ### Core / handlers - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" ts = self.irc.start_ts self.has_eob = False diff --git a/protocols/ts6_common.py b/protocols/ts6_common.py index a002fb6..c6714d6 100644 --- a/protocols/ts6_common.py +++ b/protocols/ts6_common.py @@ -99,15 +99,14 @@ class TS6UIDGenerator(utils.IncrementalUIDGenerator): super().__init__(sid) class TS6BaseProtocol(IRCS2SProtocol): - - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) # Dictionary of UID generators (one for each server). self.uidgen = structures.KeyedDefaultdict(TS6UIDGenerator) # SID generator for TS6. - self.sidgen = TS6SIDGenerator(irc) + self.sidgen = TS6SIDGenerator(self) def _send_with_prefix(self, source, msg, **kwargs): """Sends a TS6-style raw command from a source numeric to the self.irc connection given.""" diff --git a/protocols/unreal.py b/protocols/unreal.py index fece249..fa0972e 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -21,8 +21,8 @@ SJOIN_PREFIXES = {'q': '*', 'a': '~', 'o': '@', 'h': '%', 'v': '+', 'b': '&', 'e S2S_BUFSIZE = 427 class UnrealProtocol(TS6BaseProtocol): - def __init__(self, irc): - super().__init__(irc) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) self.protocol_caps |= {'slash-in-nicks', 'underscore-in-hosts'} # Set our case mapping (rfc1459 maps "\" and "|" together, for example) self.casemapping = 'ascii' @@ -335,7 +335,7 @@ class UnrealProtocol(TS6BaseProtocol): ### HANDLERS - def connect(self): + def post_connect(self): """Initializes a connection to a server.""" ts = self.irc.start_ts self.irc.prefixmodes = {'q': '~', 'a': '&', 'o': '@', 'h': '%', 'v': '+'} diff --git a/pylink b/pylink index 2cc8956..30a48f1 100755 --- a/pylink +++ b/pylink @@ -83,9 +83,13 @@ if __name__ == '__main__': except (KeyError, TypeError): log.error("(%s) Configuration error: No protocol module specified, aborting.", network) else: - # Fetch the correct protocol module + # Fetch the correct protocol module. proto = utils.getProtocolModule(protoname) - world.networkobjects[network] = proto.Class(network) + + # Create and connect the network. + world.networkobjects[network] = irc = proto.Class(network) + log.debug('Connecting to network %r', network) + irc.connect() world.started.set() log.info("Loaded plugins: %s", ', '.join(sorted(world.plugins.keys())))