From 6d6606900e2df60eb8055da0e4452a560c7510b5 Mon Sep 17 00:00:00 2001 From: James Lu Date: Tue, 1 Sep 2015 09:56:28 -0700 Subject: [PATCH 1/3] relay: coerse "/" to "|" in nicks if "/" isn't present in the separator a.k.a. make J*anus* happy :) --- plugins/relay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/relay.py b/plugins/relay.py index 64ae956..f65ca15 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -40,7 +40,7 @@ def normalizeNick(irc, netname, nick, separator=None, uid=''): orig_nick = nick protoname = irc.proto.__name__ maxnicklen = irc.maxnicklen - if not protoname.startswith(('insp', 'unreal')): + if '/' not in separator or not protoname.startswith(('insp', 'unreal')): # Charybdis doesn't allow / in usernames, and will SQUIT with # a protocol violation if it sees one. separator = separator.replace('/', '|') From 8d44830d5c5b12abd6764038d7e9983998acdfc6 Mon Sep 17 00:00:00 2001 From: James Lu Date: Mon, 31 Aug 2015 15:04:06 -0700 Subject: [PATCH 2/3] relay.handle_kill: prevent yet another RuntimeError (cherry picked from commit 4525b8117ef2f872768d1b696484f3b55b133eb1) Conflicts: plugins/relay.py --- plugins/relay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/relay.py b/plugins/relay.py index f65ca15..2dc7cf1 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -632,7 +632,7 @@ def handle_kill(irc, numeric, command, args): # client and rejoin it to its channels. del relayusers[realuser][irc.name] remoteirc = utils.networkobjects[realuser[0]] - for remotechan in remoteirc.channels: + for remotechan in remoteirc.channels.copy(): localchan = findRemoteChan(remoteirc, irc, remotechan) if localchan: modes = getPrefixModes(remoteirc, irc, localchan, realuser[1]) From 708d94916477f53ddc79a90c4ff321f636c01348 Mon Sep 17 00:00:00 2001 From: James Lu Date: Wed, 2 Sep 2015 17:41:49 -0700 Subject: [PATCH 3/3] relay: join remote users before sending ours This fixes race conditions where modes can be set on our joining users (e.g. auto-op by ChanServ), but are promptly erased as relay joins remote users and resets the channel TS. Also, move relayModes() calls back into relayJoins(), with an optional "burst" argument. Closes #102. --- plugins/relay.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/plugins/relay.py b/plugins/relay.py index 2dc7cf1..c924f68 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -222,11 +222,6 @@ def initializeChannel(irc, channel): log.debug('(%s) initializeChannel: relay pair found to be %s', irc.name, relay) queued_users = [] if relay: - # Send our users and channel modes to the other nets - log.debug('(%s) initializeChannel: joining our users: %s', irc.name, c.users) - relayJoins(irc, channel, c.users, c.ts) - irc.proto.joinClient(irc, irc.pseudoclient.uid, channel) - all_links = db[relay]['links'].copy() all_links.update((relay,)) log.debug('(%s) initializeChannel: all_links: %s', irc.name, all_links) @@ -243,13 +238,15 @@ def initializeChannel(irc, channel): continue # They aren't connected, don't bother! # Join their (remote) users and set their modes. relayJoins(remoteirc, remotechan, rc.users, rc.ts) - relayModes(remoteirc, irc, remoteirc.sid, remotechan, rc.modes) - relayModes(irc, remoteirc, irc.sid, channel, c.modes) topic = remoteirc.channels[remotechan].topic # Only update the topic if it's different from what we already have, # and topic bursting is complete. if remoteirc.channels[remotechan].topicset and topic != irc.channels[channel].topic: irc.proto.topicServer(irc, irc.sid, channel, topic) + # Send our users and channel modes to the other nets + log.debug('(%s) initializeChannel: joining our users: %s', irc.name, c.users) + relayJoins(irc, channel, c.users, c.ts) + irc.proto.joinClient(irc, irc.pseudoclient.uid, channel) def handle_join(irc, numeric, command, args): channel = args['channel'] @@ -672,7 +669,7 @@ def isRelayClient(irc, user): pass return False -def relayJoins(irc, channel, users, ts): +def relayJoins(irc, channel, users, ts, burst=True): for name, remoteirc in utils.networkobjects.items(): queued_users = [] if name == irc.name or not remoteirc.connected.is_set(): @@ -704,7 +701,13 @@ def relayJoins(irc, channel, users, ts): log.debug('(%s) relayJoins: not joining %s to %s%s; they\'re already there!', irc.name, u, remoteirc.name, remotechan) if queued_users: - remoteirc.proto.sjoinServer(remoteirc, remoteirc.sid, remotechan, queued_users, ts=ts) + # Burst was explicitly given, or we're trying to join multiple + # users/someone with a prefix. + if burst or len(queued_users) > 1 or queued_users[0][0]: + remoteirc.proto.sjoinServer(remoteirc, remoteirc.sid, remotechan, queued_users, ts=ts) + relayModes(irc, remoteirc, remoteirc.sid, remotechan) + else: + remoteirc.proto.joinClient(remoteirc, queued_users[0][1], remotechan) def relayPart(irc, channel, user): for name, remoteirc in utils.networkobjects.items():