mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-24 11:42:51 +01:00
relay: only allow one thread to run initialize_channel at a time
Closes #529.
This commit is contained in:
parent
113bfcba9d
commit
b667bed1e6
@ -17,6 +17,7 @@ relayusers = defaultdict(dict)
|
||||
relayservers = defaultdict(dict)
|
||||
spawnlocks = defaultdict(threading.RLock)
|
||||
spawnlocks_servers = defaultdict(threading.RLock)
|
||||
channels_init_in_progress = defaultdict(threading.Event)
|
||||
|
||||
dbname = conf.getDatabaseName('pylinkrelay')
|
||||
datastore = structures.PickleDataStore('pylinkrelay', dbname)
|
||||
@ -458,6 +459,7 @@ def get_remote_channel(irc, remoteirc, channel):
|
||||
|
||||
def initialize_channel(irc, channel):
|
||||
"""Initializes a relay channel (merge local/remote users, set modes, etc.)."""
|
||||
|
||||
# We're initializing a relay that already exists. This can be done at
|
||||
# ENDBURST, or on the LINK command.
|
||||
relay = get_relay(irc, channel)
|
||||
@ -465,41 +467,49 @@ def initialize_channel(irc, channel):
|
||||
log.debug('(%s) relay.initialize_channel: relay pair found to be %s', irc.name, relay)
|
||||
queued_users = []
|
||||
if relay:
|
||||
all_links = db[relay]['links'].copy()
|
||||
all_links.update((relay,))
|
||||
log.debug('(%s) relay.initialize_channel: all_links: %s', irc.name, all_links)
|
||||
if relay in channels_init_in_progress and channels_init_in_progress[relay].is_set():
|
||||
log.debug('(%s) relay.initialize_channel: skipping init of %s since another one is in progress', irc.name, relay)
|
||||
return
|
||||
|
||||
# Iterate over all the remote channels linked in this relay.
|
||||
for link in all_links:
|
||||
remotenet, remotechan = link
|
||||
if remotenet == irc.name: # If the network is us, skip.
|
||||
continue
|
||||
remoteirc = world.networkobjects.get(remotenet)
|
||||
channels_init_in_progress[relay].set()
|
||||
try:
|
||||
all_links = db[relay]['links'].copy()
|
||||
all_links.update((relay,))
|
||||
log.debug('(%s) relay.initialize_channel: all_links: %s', irc.name, all_links)
|
||||
|
||||
if remoteirc is None:
|
||||
# Remote network doesn't have an IRC object; e.g. it was removed
|
||||
# from the config. Skip this.
|
||||
continue
|
||||
# Iterate over all the remote channels linked in this relay.
|
||||
for link in all_links:
|
||||
remotenet, remotechan = link
|
||||
if remotenet == irc.name: # If the network is us, skip.
|
||||
continue
|
||||
remoteirc = world.networkobjects.get(remotenet)
|
||||
|
||||
if not (remoteirc.connected.is_set() and get_remote_channel(remoteirc, irc, remotechan)):
|
||||
continue # Remote network isn't connected.
|
||||
if remoteirc is None:
|
||||
# Remote network doesn't have an IRC object; e.g. it was removed
|
||||
# from the config. Skip this.
|
||||
continue
|
||||
|
||||
# Join their (remote) users and set their modes, if applicable.
|
||||
if remotechan in remoteirc.channels:
|
||||
rc = remoteirc.channels[remotechan]
|
||||
relay_joins(remoteirc, remotechan, rc.users, rc.ts)
|
||||
if not (remoteirc.connected.is_set() and get_remote_channel(remoteirc, irc, remotechan)):
|
||||
continue # Remote network isn't connected.
|
||||
|
||||
# Only update the topic if it's different from what we already have,
|
||||
# and topic bursting is complete.
|
||||
if rc.topicset and rc.topic != irc.channels[channel].topic:
|
||||
irc.topic_burst(irc.sid, channel, rc.topic)
|
||||
# Join their (remote) users and set their modes, if applicable.
|
||||
if remotechan in remoteirc.channels:
|
||||
rc = remoteirc.channels[remotechan]
|
||||
relay_joins(remoteirc, remotechan, rc.users, rc.ts)
|
||||
|
||||
# Send our users and channel modes to the other nets
|
||||
if channel in irc.channels:
|
||||
relay_joins(irc, channel, irc.channels[channel].users, irc.channels[channel].ts)
|
||||
# Only update the topic if it's different from what we already have,
|
||||
# and topic bursting is complete.
|
||||
if rc.topicset and rc.topic != irc.channels[channel].topic:
|
||||
irc.topic_burst(irc.sid, channel, rc.topic)
|
||||
|
||||
if 'pylink' in world.services:
|
||||
world.services['pylink'].join(irc, channel)
|
||||
# Send our users and channel modes to the other nets
|
||||
if channel in irc.channels:
|
||||
relay_joins(irc, channel, irc.channels[channel].users, irc.channels[channel].ts)
|
||||
|
||||
if 'pylink' in world.services:
|
||||
world.services['pylink'].join(irc, channel)
|
||||
finally:
|
||||
channels_init_in_progress[relay].clear()
|
||||
|
||||
def remove_channel(irc, channel):
|
||||
"""Destroys a relay channel by parting all of its users."""
|
||||
|
Loading…
Reference in New Issue
Block a user