3
0
mirror of https://github.com/jlu5/PyLink.git synced 2025-01-11 12:42:34 +01:00

protocols: split things common between nefarious and ts6_common into a new ircs2s_common module

This commit is contained in:
James Lu 2016-07-05 00:24:23 -07:00
parent 26f4a9c276
commit bfa69815b4
3 changed files with 89 additions and 115 deletions

View File

@ -0,0 +1,82 @@
"""
ircs2s_common.py: Common base protocol class with functions shared by TS6 and P10-based protocols.
"""
from pylinkirc.classes import Protocol
from pylinkirc.log import log
class IRCS2SProtocol(Protocol):
def handle_kill(self, source, command, args):
"""Handles incoming KILLs."""
killed = args[0]
# Depending on whether the IRCd sends explicit QUIT messages for
# killed clients, the user may or may not have automatically been
# removed from our user list.
# If not, we have to assume that KILL = QUIT and remove them
# ourselves.
data = self.irc.users.get(killed)
if data:
self.removeClient(killed)
# TS6-style kills look something like this:
# <- :GL KILL 38QAAAAAA :hidden-1C620195!GL (test)
# What we actually want is to format a pretty kill message, in the form
# "Killed (killername (reason))".
if source in self.irc.users:
# Killer was a user (they're SO fired)
killer = self.irc.users[source].nick
elif source in self.irc.servers:
# Killer was a server (impossible, the machine is always right)
killer = self.irc.servers[source].name
else:
# Killer was... neither? We must have aliens or something. Fallback
# to the given "UID".
killer = source
# Get the reason, which is enclosed in brackets.
reason = ' '.join(args[1].split(" ")[1:])
killmsg = "Killed (%s %s)" % (killer, reason)
return {'target': killed, 'text': killmsg, 'userdata': data}
def handle_squit(self, numeric, command, args):
"""Handles incoming SQUITs."""
# <- ABAAE SQ nefarious.midnight.vpn 0 :test
split_server = self._getSid(args[0])
affected_users = []
log.debug('(%s) Splitting server %s (reason: %s)', self.irc.name, split_server, args[-1])
if split_server not in self.irc.servers:
log.warning("(%s) Tried to split a server (%s) that didn't exist!", self.irc.name, split_server)
return
# Prevent RuntimeError: dictionary changed size during iteration
old_servers = self.irc.servers.copy()
# Cycle through our list of servers. If any server's uplink is the one that is being SQUIT,
# remove them and all their users too.
for sid, data in old_servers.items():
if data.uplink == split_server:
log.debug('Server %s also hosts server %s, removing those users too...', split_server, sid)
# Recursively run SQUIT on any other hubs this server may have been connected to.
args = self.handle_squit(sid, 'SQUIT', [sid, "0",
"PyLink: Automatically splitting leaf servers of %s" % sid])
affected_users += args['users']
for user in self.irc.servers[split_server].users.copy():
affected_users.append(user)
log.debug('Removing client %s (%s)', user, self.irc.users[user].nick)
self.removeClient(user)
sname = self.irc.servers[split_server].name
uplink = self.irc.servers[split_server].uplink
del self.irc.servers[split_server]
log.debug('(%s) Netsplit affected users: %s', self.irc.name, affected_users)
return {'target': split_server, 'users': affected_users, 'name': sname,
'uplink': uplink}

View File

@ -2,15 +2,14 @@
nefarious.py: Nefarious IRCu protocol module for PyLink.
"""
import sys
import os
import base64
import struct
from ipaddress import ip_address
from pylinkirc import utils
from pylinkirc import utils, structures
from pylinkirc.classes import *
from pylinkirc.log import log
from pylinkirc.protocols.ircs2s_common import *
class P10UIDGenerator(utils.IncrementalUIDGenerator):
"""Implements an incremental P10 UID Generator."""
@ -59,7 +58,7 @@ class P10SIDGenerator():
self.currentnum += 1
return sid
class P10Protocol(Protocol):
class P10Protocol(IRCS2SProtocol):
def __init__(self, irc):
super().__init__(irc)
@ -504,8 +503,8 @@ class P10Protocol(Protocol):
# XXX: there HAS to be a better way of doing this
def access_sort(key):
prefixes, user = key
# This is some hocus pocus. Add the prefixes given for each userpair,
# giving each one a set value. This ensures that 'ohv' > 'oh' > 'ov' > 'o' > 'hv' > 'h' > 'v' > ''
# Add the prefixes given for each userpair, giving each one a set value. This ensures
# that 'ohv' > 'oh' > 'ov' > 'o' > 'hv' > 'h' > 'v' > ''
accesses = {'o': 100, 'h': 10, 'v': 1}
num = 0
@ -1181,44 +1180,6 @@ class P10Protocol(Protocol):
self.removeClient(killed)
return {'target': killed, 'text': args[1], 'userdata': data}
def handle_squit(self, numeric, command, args):
"""Handles incoming SQUITs."""
# <- ABAAE SQ nefarious.midnight.vpn 0 :test
split_server = self._getSid(args[0])
affected_users = []
log.debug('(%s) Splitting server %s (reason: %s)', self.irc.name, split_server, args[-1])
if split_server not in self.irc.servers:
log.warning("(%s) Tried to split a server (%s) that didn't exist!", self.irc.name, split_server)
return
# Prevent RuntimeError: dictionary changed size during iteration
old_servers = self.irc.servers.copy()
# Cycle through our list of servers. If any server's uplink is the one that is being SQUIT,
# remove them and all their users too.
for sid, data in old_servers.items():
if data.uplink == split_server:
log.debug('Server %s also hosts server %s, removing those users too...', split_server, sid)
# Recursively run SQUIT on any other hubs this server may have been connected to.
args = self.handle_squit(sid, 'SQUIT', [sid, "0",
"PyLink: Automatically splitting leaf servers of %s" % sid])
affected_users += args['users']
for user in self.irc.servers[split_server].users.copy():
affected_users.append(user)
log.debug('Removing client %s (%s)', user, self.irc.users[user].nick)
self.removeClient(user)
sname = self.irc.servers[split_server].name
uplink = self.irc.servers[split_server].uplink
del self.irc.servers[split_server]
log.debug('(%s) Netsplit affected users: %s', self.irc.name, affected_users)
return {'target': split_server, 'users': affected_users, 'name': sname,
'uplink': uplink}
def handle_topic(self, source, command, args):
"""Handles TOPIC changes."""
# <- ABAAA T #test GL!~gl@nefarious.midnight.vpn 1460852591 1460855795 :blah

View File

@ -2,13 +2,12 @@
ts6_common.py: Common base protocol class with functions shared by the UnrealIRCd, InspIRCd, and TS6 protocol modules.
"""
import sys
import os
import string
from pylinkirc import utils, structures
from pylinkirc.classes import *
from pylinkirc.log import log
from pylinkirc.protocols.ircs2s_common import *
class TS6SIDGenerator():
"""
@ -98,7 +97,7 @@ class TS6UIDGenerator(utils.IncrementalUIDGenerator):
self.length = 6
super().__init__(sid)
class TS6BaseProtocol(Protocol):
class TS6BaseProtocol(IRCS2SProtocol):
def __init__(self, irc):
super().__init__(irc)
@ -352,41 +351,6 @@ class TS6BaseProtocol(Protocol):
handle_notice = handle_privmsg
def handle_kill(self, source, command, args):
"""Handles incoming KILLs."""
killed = args[0]
# Depending on whether the IRCd sends explicit QUIT messages for
# killed clients, the user may or may not have automatically been
# removed from our user list.
# If not, we have to assume that KILL = QUIT and remove them
# ourselves.
data = self.irc.users.get(killed)
if data:
self.removeClient(killed)
# TS6-style kills look something like this:
# <- :GL KILL 38QAAAAAA :hidden-1C620195!GL (test)
# What we actually want is to format a pretty kill message, in the form
# "Killed (killername (reason))".
if source in self.irc.users:
# Killer was a user (they're SO fired)
killer = self.irc.users[source].nick
elif source in self.irc.servers:
# Killer was a server (impossible, the machine is always right)
killer = self.irc.servers[source].name
else:
# Killer was... neither? We must have aliens or something. Fallback
# to the given "UID".
killer = source
# Get the reason, which is enclosed in brackets.
reason = ' '.join(args[1].split(" ")[1:])
killmsg = "Killed (%s %s)" % (killer, reason)
return {'target': killed, 'text': killmsg, 'userdata': data}
def handle_kick(self, source, command, args):
"""Handles incoming KICKs."""
# :70MAAAAAA KICK #test 70MAAAAAA :some reason
@ -428,39 +392,6 @@ class TS6BaseProtocol(Protocol):
self.irc.users[user].nick = user
return {'target': user, 'ts': int(args[1]), 'oldnick': oldnick}
def handle_squit(self, numeric, command, args):
"""Handles incoming SQUITs (netsplits)."""
# :70M SQUIT 1ML :Server quit by GL!gl@0::1
log.debug('handle_squit args: %s', args)
split_server = args[0]
affected_users = []
log.debug('(%s) Splitting server %s (reason: %s)', self.irc.name, split_server, args[-1])
if split_server not in self.irc.servers:
log.warning("(%s) Tried to split a server (%s) that didn't exist!", self.irc.name, split_server)
return
uplink = self.irc.servers[split_server].uplink
# Prevent RuntimeError: dictionary changed size during iteration
old_servers = self.irc.servers.copy()
for sid, data in old_servers.items():
if data.uplink == split_server:
log.debug('Server %s also hosts server %s, removing those users too...', split_server, sid)
args = self.handle_squit(sid, 'SQUIT', [sid, "PyLink: Automatically splitting leaf servers of %s" % sid])
affected_users += args['users']
for user in self.irc.servers[split_server].users.copy():
affected_users.append(user)
log.debug('Removing client %s (%s)', user, self.irc.users[user].nick)
self.removeClient(user)
sname = self.irc.servers[split_server].name
del self.irc.servers[split_server]
log.debug('(%s) Netsplit affected users: %s', self.irc.name, affected_users)
return {'target': split_server, 'users': affected_users, 'name': sname,
'uplink': uplink}
def handle_topic(self, numeric, command, args):
"""Handles incoming TOPIC changes from clients. For topic bursts,
TB (TS6/charybdis) and FTOPIC (InspIRCd) are used instead."""