3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-12-26 04:32:51 +01:00

Merge branch 'wip/protocol-cleanup' into devel

This commit is contained in:
James Lu 2017-06-02 07:40:08 -07:00
commit a32d937b91
3 changed files with 89 additions and 150 deletions

View File

@ -6,14 +6,103 @@ import time
from pylinkirc.classes import Protocol from pylinkirc.classes import Protocol
from pylinkirc.log import log from pylinkirc.log import log
from pylinkirc import utils
class IRCS2SProtocol(Protocol): class IRCS2SProtocol(Protocol):
COMMAND_TOKENS = {}
def __init__(self, irc): def __init__(self, irc):
super().__init__(irc) super().__init__(irc)
self.protocol_caps = {'can-spawn-clients', 'has-ts', 'can-host-relay', self.protocol_caps = {'can-spawn-clients', 'has-ts', 'can-host-relay',
'can-track-servers'} 'can-track-servers'}
def handle_events(self, data):
"""Event handler for RFC1459-like protocols.
This passes most commands to the various handle_ABCD() functions
elsewhere defined protocol modules, coersing various sender prefixes
from nicks and server names to UIDs and SIDs respectively,
whenever possible.
Commands sent without an explicit sender prefix will have them set to
the SID of the uplink server.
"""
data = data.split(" ")
args = self.parseArgs(data)
sender = args[0]
sender = sender.lstrip(':')
# If the sender isn't in numeric format, try to convert it automatically.
sender_sid = self._getSid(sender)
sender_uid = self._getUid(sender)
if sender_sid in self.irc.servers:
# Sender is a server (converting from name to SID gave a valid result).
sender = sender_sid
elif sender_uid in self.irc.users:
# Sender is a user (converting from name to UID gave a valid result).
sender = sender_uid
else:
# No sender prefix; treat as coming from uplink IRCd.
sender = self.irc.uplink
args.insert(0, sender)
if self.irc.isInternalClient(sender) or self.irc.isInternalServer(sender):
log.warning("(%s) Received command %s being routed the wrong way!", self.irc.name, command)
return
raw_command = args[1].upper()
args = args[2:]
log.debug('(%s) Found message sender as %s', self.irc.name, sender)
# For P10, convert the command token into a regular command, if present.
command = self.COMMAND_TOKENS.get(raw_command, raw_command)
if command != raw_command:
log.debug('(%s) Translating token %s to command %s', self.irc.name, raw_command, command)
if command == 'ENCAP':
# Special case for TS6 encapsulated commands (ENCAP), in forms like this:
# <- :00A ENCAP * SU 42XAAAAAC :GLolol
command = args[1]
args = args[2:]
log.debug("(%s) Rewriting incoming ENCAP to command %s (args: %s)", self.irc.name, command, args)
try:
func = getattr(self, 'handle_'+command.lower())
except AttributeError: # Unhandled command
pass
else:
parsed_args = func(sender, command, args)
if parsed_args is not None:
return [sender, command, parsed_args]
def handle_privmsg(self, source, command, args):
"""Handles incoming PRIVMSG/NOTICE."""
# TS6:
# <- :70MAAAAAA PRIVMSG #dev :afasfsa
# <- :70MAAAAAA NOTICE 0ALAAAAAA :afasfsa
# P10:
# <- ABAAA P AyAAA :privmsg text
# <- ABAAA O AyAAA :notice text
target = args[0]
# Coerse =#channel from Charybdis op moderated +z to @#channel.
if target.startswith('='):
target = '@' + target[1:]
# We use lowercase channels internally, but uppercase UIDs.
# Strip the target of leading prefix modes (for targets like @#channel)
# before checking whether it's actually a channel.
stripped_target = target.lstrip(''.join(self.irc.prefixmodes.values()))
if utils.isChannel(stripped_target):
target = self.irc.toLower(target)
return {'target': target, 'text': args[1]}
handle_notice = handle_privmsg
def check_nick_collision(self, nick): def check_nick_collision(self, nick):
""" """
Nick collision checker. Nick collision checker.

View File

@ -824,63 +824,6 @@ class P10Protocol(IRCS2SProtocol):
self._send(sid, "EB") self._send(sid, "EB")
self.irc.connected.set() self.irc.connected.set()
def handle_events(self, data):
"""
Event handler for the P10 protocol.
This passes most commands to the various handle_ABCD() functions defined elsewhere in the
protocol modules, coersing various sender prefixes from nicks and server names to P10
"numeric nicks", whenever possible.
Commands sent without an explicit sender prefix are treated as originating from the uplink
server.
"""
data = data.split(" ")
args = self.parseArgs(data)
sender = args[0]
if sender.startswith(':'):
# From https://github.com/evilnet/nefarious2/blob/a29b63144/doc/p10.txt#L140:
# if source begins with a colon, it (except for the colon) is the name. otherwise, it is
# a numeric. a P10 implementation must only send lines with a numeric source prefix.
sender = sender[1:]
# If the sender isn't in numeric format, try to convert it automatically.
sender_sid = self._getSid(sender)
sender_uid = self._getUid(sender)
if sender_sid in self.irc.servers:
# Sender is a server (converting from name to SID gave a valid result).
sender = sender_sid
elif sender_uid in self.irc.users:
# Sender is a user (converting from name to UID gave a valid result).
sender = sender_uid
else:
# No sender prefix; treat as coming from uplink IRCd.
sender = self.irc.uplink
args.insert(0, sender)
command_token = args[1].upper()
args = args[2:]
log.debug('(%s) Found message sender as %s', self.irc.name, sender)
# Convert the token given into a regular command, if present.
command = self.COMMAND_TOKENS.get(command_token, command_token)
log.debug('(%s) Translating token %s to command %s', self.irc.name, command_token, command)
try:
func = getattr(self, 'handle_'+command.lower())
except AttributeError: # Unhandled command, ignore
return
else: # Send a hook with the hook arguments given by the handler function.
if self.irc.isInternalClient(sender) or self.irc.isInternalServer(sender):
log.warning("(%s) Received command %s being routed the wrong way!", self.irc.name, command)
return
parsed_args = func(sender, command, args)
if parsed_args is not None:
return [sender, command, parsed_args]
def handle_server(self, source, command, args): def handle_server(self, source, command, args):
"""Handles incoming server introductions.""" """Handles incoming server introductions."""
# <- SERVER nefarious.midnight.vpn 1 1460673022 1460673239 J10 ABP]] +h6 :Nefarious2 test server # <- SERVER nefarious.midnight.vpn 1 1460673022 1460673239 J10 ABP]] +h6 :Nefarious2 test server
@ -1168,22 +1111,6 @@ class P10Protocol(IRCS2SProtocol):
self.irc.channels[channel].modes, 'ts': ts or int(time.time())} self.irc.channels[channel].modes, 'ts': ts or int(time.time())}
handle_create = handle_join handle_create = handle_join
def handle_privmsg(self, source, command, args):
"""Handles incoming PRIVMSG/NOTICE."""
# <- ABAAA P AyAAA :privmsg text
# <- ABAAA O AyAAA :notice text
target = args[0]
# We use lower case channels internally, but mixed case UIDs.
stripped_target = target.lstrip(''.join(self.irc.prefixmodes.values()))
if utils.isChannel(stripped_target):
target = self.irc.toLower(target)
return {'target': target, 'text': args[1]}
handle_notice = handle_privmsg
def handle_end_of_burst(self, source, command, args): def handle_end_of_burst(self, source, command, args):
"""Handles end of burst from our uplink.""" """Handles end of burst from our uplink."""
# Send EOB acknowledgement; this is required by the P10 specification, # Send EOB acknowledgement; this is required by the P10 specification,

View File

@ -294,83 +294,6 @@ class TS6BaseProtocol(IRCS2SProtocol):
self.irc.users[source].away = text self.irc.users[source].away = text
### HANDLERS ### HANDLERS
def handle_events(self, data):
"""Event handler for TS6 protocols.
This passes most commands to the various handle_ABCD() functions
elsewhere defined protocol modules, coersing various sender prefixes
from nicks and server names to UIDs and SIDs respectively,
whenever possible.
Commands sent without an explicit sender prefix will have them set to
the SID of the uplink server.
"""
data = data.split(" ")
try: # Message starts with a SID/UID prefix.
args = self.parsePrefixedArgs(data)
sender = args[0]
command = args[1]
args = args[2:]
# If the sender isn't in UID format, try to convert it automatically.
# Unreal's protocol, for example, isn't quite consistent with this yet!
sender_server = self._getSid(sender)
if sender_server in self.irc.servers:
# Sender is a server when converted from name to SID.
numeric = sender_server
else:
# Sender is a user.
numeric = self._getUid(sender)
# parsePrefixedArgs() will raise IndexError if the TS6 sender prefix is missing.
except IndexError:
# Raw command without an explicit sender; assume it's being sent by our uplink.
args = self.parseArgs(data)
numeric = self.irc.uplink
command = args[0]
args = args[1:]
if self.irc.isInternalClient(numeric) or self.irc.isInternalServer(numeric):
log.warning("(%s) Received command %s being routed the wrong way!", self.irc.name, command)
return
if command == 'ENCAP':
# Special case for encapsulated commands (ENCAP), in forms like this:
# <- :00A ENCAP * SU 42XAAAAAC :GLolol
command = args[1]
args = args[2:]
log.debug("(%s) Rewriting incoming ENCAP to command %s (args: %s)", self.irc.name, command, args)
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_privmsg(self, source, command, args):
"""Handles incoming PRIVMSG/NOTICE."""
# <- :70MAAAAAA PRIVMSG #dev :afasfsa
# <- :70MAAAAAA NOTICE 0ALAAAAAA :afasfsa
target = args[0]
# Coerse =#channel from Charybdis op moderated +z to @#channel.
if target.startswith('='):
target = '@' + target[1:]
# We use lowercase channels internally, but uppercase UIDs.
# Strip the target of leading prefix modes (for targets like @#channel)
# before checking whether it's actually a channel.
stripped_target = target.lstrip(''.join(self.irc.prefixmodes.values()))
if utils.isChannel(stripped_target):
target = self.irc.toLower(target)
return {'target': target, 'text': args[1]}
handle_notice = handle_privmsg
def handle_kick(self, source, command, args): def handle_kick(self, source, command, args):
"""Handles incoming KICKs.""" """Handles incoming KICKs."""
# :70MAAAAAA KICK #test 70MAAAAAA :some reason # :70MAAAAAA KICK #test 70MAAAAAA :some reason