diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 160b8a9..c4f77e3 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -6,61 +6,27 @@ import re class AuthenticationError: pass -class InspircdHandler(threading.Thread): +def authenticate(irc): + f = irc.send + f('CAPAB START 1202') + f('CAPAB CAPABILITIES :NICKMAX=32 HALFOP=0 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255 PROTOCOL=1203') + f('CAPAB END') + f('SERVER %s %s 0 %s :PyLink Service' % (irc.serverdata["hostname"], + irc.serverdata["sendpass"], irc.sid)) + f(':%s BURST %s' % (irc.sid, int(time.time()))) + # :751 UID 751AAAAAA 1220196319 Brain brainwave.brainbox.cc netadmin.chatspike.net brain 192.168.1.10 1220196324 +Siosw +ACKNOQcdfgklnoqtx :Craig Edwards + f(":{sid} UID {sid}AAAAAA {ts} PyLink {host} {host} pylink 127.0.0.1 {ts} +o + :PyLink Client".format(sid=irc.sid, + ts=int(time.time()), host=irc.serverdata["hostname"])) + f(':%s ENDBURST' % (irc.sid)) - def __init__(self, name, serverdata): - threading.Thread.__init__(self) - self.name = name - self.authenticated = False - self.connected = False - self.serverdata = serverdata - ip = self.serverdata["ip"] - port = self.serverdata["port"] - self.sid = self.serverdata["sid"] - self.socket = socket.socket() - self.socket.connect((ip, port)) - print("[+] New thread started for %s:%s" % (ip, port)) - self.authenticate(serverdata) - self.listen() +# :7NU PING 7NU 0AL +def handle_ping(irc, data): + m = re.search('\:(\d[A-Z0-9]{1,2}) PING (\d[A-Z0-9]{1,2}) %s' % irc.sid, data) + if m: + irc.send(':%s PONG %s' % (irc.sid, m.group(0))) - def send(self, data): - data = data.encode("utf-8") + b"\n" - print("-> {}".format(data.decode("utf-8").strip("\n"))) - self.socket.send(data) +def handle_events(irc, data): + handle_ping(irc, data) - def authenticate(self, serverdata): - f = self.send - f('CAPAB START 1202') - f('CAPAB CAPABILITIES :NICKMAX=32 HALFOP=0 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=255 PROTOCOL=1203') - f('CAPAB END') - f('SERVER %s %s 0 %s :PyLink Service' % (self.serverdata["hostname"], - serverdata["sendpass"], self.sid)) - f(':%s BURST %s' % (self.sid, int(time.time()))) - # :751 UID 751AAAAAA 1220196319 Brain brainwave.brainbox.cc netadmin.chatspike.net brain 192.168.1.10 1220196324 +Siosw +ACKNOQcdfgklnoqtx :Craig Edwards - f(":{sid} UID {sid}AAAAAA {ts} PyLink {host} {host} pylink 127.0.0.1 {ts} +o + :PyLink Client".format(sid=self.sid, - ts=int(time.time()), host=self.serverdata["hostname"])) - f(':%s ENDBURST' % (self.sid)) - # :7NU PING 7NU 0AL - def handle_ping(self, data): - m = re.search('\:(\d[A-Z0-9]{1,2}) PING (\d[A-Z0-9]{1,2}) %s' % self.sid, data) - if m: - self.send(':%s PONG %s' % (self.sid, m.group(0))) - - def listen(self): - while True: - data = self.socket.recv(2048) - if not data: - print("Connection reset.") - break - try: - buf = data.decode("utf-8") - for line in buf.split("\n"): - print("<- {}".format(line)) - self.handle_ping(line) - except socket.error as e: - print("%s: Received socket error: '%s', aborting! =X=" % (self.name, e)) - break - -def connect(name, serverdata): - s = InspircdHandler(name, serverdata) - s.start() +def connect(irc): + authenticate(irc) diff --git a/protocols/stub.py b/protocols/stub.py index a2d1905..017b9d8 100644 --- a/protocols/stub.py +++ b/protocols/stub.py @@ -1,5 +1,8 @@ -def connect(name, networkdata): - print('%s: Using PyLink stub/testing protocol.' % name) - print('Send password: %s' % networkdata['sendpass']) - print('Receive password: %s' % networkdata['recvpass']) - print('Server: %s:%s' % (networkdata['ip'], networkdata['port'])) +def connect(irc): + print('%s: Using PyLink stub/testing protocol.' % irc.name) + print('Send password: %s' % irc.serverdata['sendpass']) + print('Receive password: %s' % irc.serverdata['recvpass']) + print('Server: %s:%s' % (irc.serverdata["ip"], irc.serverdata["port"])) + +def handle_events(irc, data): + print('%s: Received event: %s' % (irc.name, data)) diff --git a/pylink-main.py b/pylink-main.py index e5fc6a4..c7c6618 100755 --- a/pylink-main.py +++ b/pylink-main.py @@ -3,6 +3,9 @@ import yaml import imp import os +import threading +import socket +import asyncio print('PyLink starting...') @@ -15,12 +18,22 @@ with open("config.yml", 'r') as f: global networkobjects networkobjects = {} -class irc: - def __init__(self, network): +class irc(asyncio.Protocol): + def __init__(self, network, loop): + asyncio.Protocol.__init__(self) + self.authenticated = False self.connected = False - self.netname = network - self.networkdata = conf['networks'][network] - protoname = self.networkdata['protocol'] + self.socket = socket.socket() + self.loop = loop + + self.serverdata = conf['networks'][network] + ip = self.serverdata["ip"] + port = self.serverdata["port"] + self.sid = self.serverdata["sid"] + print("[+] New thread started for %s:%s" % (ip, port)) + + self.name = network + protoname = self.serverdata['protocol'] # With the introduction of Python 3, relative imports are no longer # allowed from normal applications ran from the command line. Instead, # these imported libraries must be installed as a package using distutils @@ -28,19 +41,32 @@ class irc: # # But I don't want that! Where PyLink is at right now (a total WIP), it is # a lot more convenient to run the program directly from the source folder. - protocols_folder = [os.path.join(os.getcwd(), 'protocols')] # Here, we override the module lookup and import the protocol module # dynamically depending on which module was configured. moduleinfo = imp.find_module(protoname, protocols_folder) self.proto = imp.load_source(protoname, moduleinfo[1]) - self.connect() - - def connect(self): - self.proto.connect(self.netname, self.networkdata) + self.socket = socket.socket() + self.socket.connect((ip, port)) + self.proto.connect(self) + + # def collect_incoming_data(self, data): + + @asyncio.coroutine + def handle_read(self): + data = self.socket.recv(2048) + buf = data.decode("utf-8") + for line in buf.split("\n"): + print("<- {}".format(line)) + self.proto.handle_events(self, line) + + def send(self, data): + data = data.encode("utf-8") + b"\n" + print("-> {}".format(data.decode("utf-8").strip("\n"))) + self.socket.send(data) for network in conf['networks']: print('Creating IRC Object for: %s' % network) networkobjects[network] = irc(network) - - + loop = asyncio.get_event_loop() + loop.run_forever(networkobjects[network].handle_read())