mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-24 19:52:53 +01:00
ts6: use new-style module design (#156)
This commit is contained in:
parent
a220659eaf
commit
814ebc9fe0
152
protocols/ts6.py
152
protocols/ts6.py
@ -25,6 +25,8 @@ class TS6Protocol(TS6BaseProtocol):
|
||||
self.sidgen = utils.TS6SIDGenerator(self.irc)
|
||||
self.uidgen = {}
|
||||
|
||||
### OUTGOING COMMANDS
|
||||
|
||||
def spawnClient(self, nick, ident='null', host='null', realhost=None, modes=set(),
|
||||
server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None,
|
||||
manipulatable=False):
|
||||
@ -235,6 +237,8 @@ class TS6Protocol(TS6BaseProtocol):
|
||||
else:
|
||||
self._send(source, 'PING %s' % source)
|
||||
|
||||
### Core / handlers
|
||||
|
||||
def connect(self):
|
||||
"""Initializes a connection to a server."""
|
||||
ts = self.irc.start_ts
|
||||
@ -329,88 +333,60 @@ class TS6Protocol(TS6BaseProtocol):
|
||||
f('SERVER %s 0 :%s' % (self.irc.serverdata["hostname"],
|
||||
self.irc.serverdata.get('serverdesc') or self.irc.botdata['serverdesc']))
|
||||
|
||||
def handle_events(self, data):
|
||||
"""Generic event handler for the TS6 protocol: does protocol negotation
|
||||
and passes commands to handle_ABCD() functions elsewhere in this module."""
|
||||
# TS6 messages:
|
||||
# :42X COMMAND arg1 arg2 :final long arg
|
||||
# :42XAAAAAA PRIVMSG #somewhere :hello!
|
||||
args = data.split(" ")
|
||||
if not args:
|
||||
# No data??
|
||||
return
|
||||
if args[0] == 'PASS':
|
||||
# <- PASS $somepassword TS 6 :42X
|
||||
if args[1] != self.irc.serverdata['recvpass']:
|
||||
# Check if recvpass is correct
|
||||
raise ProtocolError('Error: recvpass from uplink server %s does not match configuration!' % servername)
|
||||
if 'TS 6' not in data:
|
||||
raise ProtocolError("Remote protocol version is too old! Is this even TS6?")
|
||||
# Server name and SID are sent in different messages, grr
|
||||
numeric = data.rsplit(':', 1)[1]
|
||||
log.debug('(%s) Found uplink SID as %r', self.irc.name, numeric)
|
||||
self.irc.servers[numeric] = IrcServer(None, 'unknown')
|
||||
self.irc.uplink = numeric
|
||||
return
|
||||
elif args[0] == 'SERVER':
|
||||
# <- SERVER charybdis.midnight.vpn 1 :charybdis test server
|
||||
sname = args[1].lower()
|
||||
log.debug('(%s) Found uplink server name as %r', self.irc.name, sname)
|
||||
self.irc.servers[self.irc.uplink].name = sname
|
||||
self.irc.servers[self.irc.uplink].desc = ' '.join(args).split(':', 1)[1]
|
||||
# According to the TS6 protocol documentation, we should send SVINFO
|
||||
# when we get our uplink's SERVER command.
|
||||
self.irc.send('SVINFO 6 6 0 :%s' % int(time.time()))
|
||||
elif args[0] == 'SQUIT':
|
||||
# What? Charybdis send this in a different format!
|
||||
# <- SQUIT 00A :Remote host closed the connection
|
||||
split_server = args[1]
|
||||
res = self.handle_squit(split_server, 'SQUIT', [split_server])
|
||||
self.irc.callHooks([split_server, 'SQUIT', res])
|
||||
elif args[0] == 'CAPAB':
|
||||
# We only get a list of keywords here. Charybdis obviously assumes that
|
||||
# we know what modes it supports (indeed, this is a standard list).
|
||||
# <- CAPAB :BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SAVE SERVICES TB UNKLN
|
||||
self.irc.caps = caps = data.split(':', 1)[1].split()
|
||||
for required_cap in ('EUID', 'SAVE', 'TB', 'ENCAP', 'QS'):
|
||||
if required_cap not in caps:
|
||||
raise ProtocolError('%s not found in TS6 capabilities list; this is required! (got %r)' % (required_cap, caps))
|
||||
def handle_pass(self, numeric, command, args):
|
||||
"""
|
||||
Handles the PASS command, used to send the server's SID and negotiate
|
||||
passwords on connect.
|
||||
"""
|
||||
# <- PASS $somepassword TS 6 :42X
|
||||
|
||||
if 'EX' in caps:
|
||||
self.irc.cmodes['banexception'] = 'e'
|
||||
if 'IE' in caps:
|
||||
self.irc.cmodes['invex'] = 'I'
|
||||
if 'SERVICES' in caps:
|
||||
self.irc.cmodes['regonly'] = 'r'
|
||||
if args[0] != self.irc.serverdata['recvpass']:
|
||||
# Check if recvpass is correct
|
||||
raise ProtocolError('Recvpass from uplink server %s does not match configuration!' % servername)
|
||||
|
||||
log.debug('(%s) self.irc.connected set!', self.irc.name)
|
||||
self.irc.connected.set()
|
||||
if args[1] != 'TS' and args[2] != '6':
|
||||
raise ProtocolError("Remote protocol version is too old! Is this even TS6?")
|
||||
|
||||
# Charybdis doesn't have the idea of an explicit endburst; but some plugins
|
||||
# like relay require it to know that the network's connected.
|
||||
# We'll set a timer to manually call endburst. It's not beautiful,
|
||||
# but it's the best we can do.
|
||||
endburst_timer = threading.Timer(1, self.irc.callHooks, args=([self.irc.uplink, 'ENDBURST', {}],))
|
||||
log.debug('(%s) Starting delay to send ENDBURST', self.irc.name)
|
||||
endburst_timer.start()
|
||||
try:
|
||||
args = self.parseTS6Args(args)
|
||||
numeric = args[-1]
|
||||
log.debug('(%s) Found uplink SID as %r', self.irc.name, numeric)
|
||||
|
||||
numeric = args[0]
|
||||
command = args[1]
|
||||
args = args[2:]
|
||||
except IndexError:
|
||||
return
|
||||
# Server name and SID are sent in different messages, so we fill this
|
||||
# with dummy information until we get the actual sid.
|
||||
self.irc.servers[numeric] = IrcServer(None, '')
|
||||
self.irc.uplink = numeric
|
||||
|
||||
# We will do wildcard command handling here. Unhandled commands are just ignored.
|
||||
try:
|
||||
func = getattr(self, 'handle_'+command.lower())
|
||||
except AttributeError: # Unhandled command
|
||||
pass
|
||||
else:
|
||||
parsed_args = func(numeric, command, args)
|
||||
if parsed_args is not None:
|
||||
return [numeric, command, parsed_args]
|
||||
def handle_capab(self, numeric, command, args):
|
||||
"""
|
||||
Handles the CAPAB command, used for TS6 capability negotiation.
|
||||
"""
|
||||
# We only get a list of keywords here. Charybdis obviously assumes that
|
||||
# we know what modes it supports (indeed, this is a standard list).
|
||||
# <- CAPAB :BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SAVE SERVICES TB UNKLN
|
||||
self.irc.caps = caps = args[0].split()
|
||||
|
||||
for required_cap in ('EUID', 'SAVE', 'TB', 'ENCAP', 'QS'):
|
||||
if required_cap not in caps:
|
||||
raise ProtocolError('%s not found in TS6 capabilities list; this is required! (got %r)' % (required_cap, caps))
|
||||
|
||||
if 'EX' in caps:
|
||||
self.irc.cmodes['banexception'] = 'e'
|
||||
if 'IE' in caps:
|
||||
self.irc.cmodes['invex'] = 'I'
|
||||
if 'SERVICES' in caps:
|
||||
self.irc.cmodes['regonly'] = 'r'
|
||||
|
||||
log.debug('(%s) self.irc.connected set!', self.irc.name)
|
||||
self.irc.connected.set()
|
||||
|
||||
# Charybdis doesn't have the idea of an explicit endburst; but some plugins
|
||||
# like relay require it to know that the network's connected.
|
||||
# We'll set a timer to manually call endburst. It's not beautiful,
|
||||
# but it's the best we can do.
|
||||
endburst_timer = threading.Timer(1, self.irc.callHooks,
|
||||
args=([self.irc.uplink, 'ENDBURST', {}],))
|
||||
|
||||
log.debug('(%s) Starting delay to send ENDBURST', self.irc.name)
|
||||
endburst_timer.start()
|
||||
|
||||
def handle_ping(self, source, command, args):
|
||||
"""Handles incoming PING commands."""
|
||||
@ -529,10 +505,26 @@ class TS6Protocol(TS6BaseProtocol):
|
||||
self.irc.servers[sid] = IrcServer(numeric, servername, desc=sdesc)
|
||||
return {'name': servername, 'sid': sid, 'text': sdesc}
|
||||
|
||||
def handle_server(self, sender, command, args):
|
||||
"""Handles incoming legacy (no SID) server introductions."""
|
||||
def handle_server(self, numeric, command, args):
|
||||
"""
|
||||
Handles 1) incoming legacy (no SID) server introductions,
|
||||
2) Sending server data in initial connection.
|
||||
"""
|
||||
if numeric == self.irc.uplink and not self.irc.servers[numeric].name:
|
||||
# <- SERVER charybdis.midnight.vpn 1 :charybdis test server
|
||||
sname = args[0].lower()
|
||||
|
||||
log.debug('(%s) Found uplink server name as %r', self.irc.name, sname)
|
||||
self.irc.servers[numeric].name = sname
|
||||
self.irc.servers[numeric].desc = args[-1]
|
||||
|
||||
# According to the TS6 protocol documentation, we should send SVINFO
|
||||
# when we get our uplink's SERVER command.
|
||||
self.irc.send('SVINFO 6 6 0 :%s' % int(time.time()))
|
||||
|
||||
return
|
||||
|
||||
# <- :services.int SERVER a.bc 2 :(H) [GL] a
|
||||
numeric = self._getSid(sender) # Convert the server name prefix to a SID.
|
||||
servername = args[0].lower()
|
||||
sdesc = args[-1]
|
||||
self.irc.servers[servername] = IrcServer(numeric, servername, desc=sdesc)
|
||||
|
Loading…
Reference in New Issue
Block a user