3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-01 01:09:22 +01:00

updateTS: Fix mode tracking again

It looks like we actually do need to track whether we're sending or receiving modes. This time, do so /properly/.
This commit is contained in:
James Lu 2016-07-10 21:35:17 -07:00
parent fa59e2bded
commit c1cd6f42a0
5 changed files with 26 additions and 18 deletions

View File

@ -1157,7 +1157,7 @@ class Protocol():
log.debug('Removing client %s from self.irc.servers[%s].users', numeric, sid)
self.irc.servers[sid].users.discard(numeric)
def updateTS(self, channel, their_ts, modes=[]):
def updateTS(self, sender, channel, their_ts, modes=[]):
"""
Merges modes of a channel given the remote TS and a list of modes.
"""
@ -1179,12 +1179,17 @@ class Protocol():
assert type(our_ts) == int, "Wrong type for our_ts (expected int, got %s)" % type(our_ts)
assert type(their_ts) == int, "Wrong type for their_ts (expected int, got %s)" % type(their_ts)
# Check if we're the mode sender based on the UID / SID given.
our_mode = self.irc.isInternalClient(sender) or self.irc.isInternalServer(sender)
log.debug("(%s/%s) is the mode origin us? %s",
self.irc.name, channel, our_mode)
if their_ts < our_ts:
# Their TS is older than ours. We should clear our stored modes for the channel and
# apply the ones in the queue to be set. This is regardless of whether we're sending
# outgoing modes or receiving some - both are handled the same with a "received" TS,
# and comparing it with the one we have.
log.debug("(%s/%s) received TS of %s is lower than ours %s; setting modes %s",
log.debug("(%s/%s) received TS of %s is lower than our %s; mode query %s",
self.irc.name, channel, their_ts, our_ts, modes)
# Update the channel TS to theirs regardless of whether the mode setting passes.
@ -1193,21 +1198,24 @@ class Protocol():
self.irc.channels[channel].ts = their_ts
_clear()
_apply()
if not our_mode:
_apply()
elif their_ts == our_ts:
log.debug("(%s/%s) remote TS of %s is equal to ours %s; setting modes %s",
log.debug("(%s/%s) remote TS of %s is equal to our %s; mode query %s",
self.irc.name, channel, their_ts, our_ts, modes)
# Their TS is equal to ours. Merge modes.
_apply()
elif their_ts > our_ts:
log.debug("(%s/%s) remote TS of %s is higher than ours %s; setting modes %s",
log.debug("(%s/%s) remote TS of %s is higher than our %s; mode query %s",
self.irc.name, channel, their_ts, our_ts, modes)
# Their TS is younger than ours. Clear the state and replace the modes for the channel
# with the ones being set.
# with the ones being set, if we're the one setting modes.
_clear()
_apply()
if our_mode:
_apply()
def _getSid(self, sname):
"""Returns the SID of a server with the given name, if present."""

View File

@ -150,7 +150,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
self._send(server, "FMODE {channel} {ts} {modes} ".format(
ts=ts, channel=channel, modes=self.irc.joinModes(banmodes)))
self.updateTS(channel, ts, changedmodes)
self.updateTS(server, channel, ts, changedmodes)
def _operUp(self, target, opertype=None):
"""Opers a client up (internal function specific to InspIRCd).
@ -535,7 +535,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
# Statekeeping with timestamps
their_ts = int(args[1])
our_ts = self.irc.channels[channel].ts
self.updateTS(channel, their_ts, changedmodes)
self.updateTS(servernumeric, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts}

View File

@ -569,7 +569,7 @@ class P10Protocol(IRCS2SProtocol):
self.irc.channels[channel].users.update(changedusers)
self.updateTS(channel, ts, changedmodes)
self.updateTS(server, channel, ts, changedmodes)
def spawnServer(self, name, sid=None, uplink=None, desc=None, endburst_delay=0):
"""
@ -1055,7 +1055,7 @@ class P10Protocol(IRCS2SProtocol):
# Statekeeping with timestamps
their_ts = int(args[1])
our_ts = self.irc.channels[channel].ts
self.updateTS(channel, their_ts, changedmodes)
self.updateTS(source, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts}
@ -1084,7 +1084,7 @@ class P10Protocol(IRCS2SProtocol):
else:
channel = self.irc.toLower(args[0])
if ts: # Only update TS if one was sent.
self.updateTS(channel, ts)
self.updateTS(source, channel, ts)
self.irc.users[source].channels.add(channel)
self.irc.channels[channel].users.add(source)

View File

@ -158,7 +158,7 @@ class TS6Protocol(TS6BaseProtocol):
channel=channel, bmode=bmode, bans=' '.join(bans[:12])))
bans = bans[12:]
self.updateTS(channel, ts, changedmodes)
self.updateTS(server, channel, ts, changedmodes)
def mode(self, numeric, target, modes, ts=None):
"""Sends mode changes from a PyLink client/server."""
@ -464,7 +464,7 @@ class TS6Protocol(TS6BaseProtocol):
# Statekeeping with timestamps
their_ts = int(args[0])
our_ts = self.irc.channels[channel].ts
self.updateTS(channel, their_ts, changedmodes)
self.updateTS(servernumeric, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': parsedmodes, 'ts': their_ts}
@ -484,7 +484,7 @@ class TS6Protocol(TS6BaseProtocol):
return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'}
else:
channel = self.irc.toLower(args[1])
self.updateTS(channel, ts)
self.updateTS(numeric, channel, ts)
self.irc.users[numeric].channels.add(channel)
self.irc.channels[channel].users.add(numeric)

View File

@ -186,7 +186,7 @@ class UnrealProtocol(TS6BaseProtocol):
self.irc.channels[channel].users.update(uids)
self.updateTS(channel, ts, changedmodes)
self.updateTS(server, channel, ts, changedmodes)
def ping(self, source=None, target=None):
"""Sends a PING to a target server. Periodic PINGs are sent to our uplink
@ -577,7 +577,7 @@ class UnrealProtocol(TS6BaseProtocol):
our_ts = self.irc.channels[channel].ts
their_ts = int(args[0])
self.updateTS(channel, their_ts, changedmodes)
self.updateTS(numeric, channel, their_ts, changedmodes)
return {'channel': channel, 'users': namelist, 'modes': self.irc.channels[channel].modes, 'ts': their_ts}
@ -657,7 +657,7 @@ class UnrealProtocol(TS6BaseProtocol):
# Sender is a server AND last arg is number. Perform TS updates.
their_ts = int(args[-1])
if their_ts > 0:
self.updateTS(channel, their_ts)
self.updateTS(numeric, channel, their_ts)
return {'target': channel, 'modes': parsedmodes, 'oldchan': oldobj}
else:
log.warning("(%s) received MODE for non-channel target: %r",