From 3d853e8fe9c989633aa33cd87b314b0b1acbfe24 Mon Sep 17 00:00:00 2001 From: Sunpy Date: Mon, 29 Jul 2019 21:20:54 +0200 Subject: [PATCH] Initial commit --- .gitignore | 2 + __init__.py | 0 config.json | 19 +++ handlers/__init__.py | 0 handlers/mainHandler.py | 261 ++++++++++++++++++++++++++++++++++++++++ main.py | 43 +++++++ objects/__init__.py | 0 objects/glob.py | 31 +++++ requirements.txt | 1 + test.html | 42 +++++++ 10 files changed, 399 insertions(+) create mode 100644 __init__.py create mode 100644 config.json create mode 100644 handlers/__init__.py create mode 100644 handlers/mainHandler.py create mode 100644 main.py create mode 100644 objects/__init__.py create mode 100644 objects/glob.py create mode 100644 requirements.txt create mode 100644 test.html diff --git a/.gitignore b/.gitignore index 6a18ad4..186f86a 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,5 @@ ENV/ # Rope project settings .ropeproject +.data/ +certs/ diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/config.json b/config.json new file mode 100644 index 0000000..163988d --- /dev/null +++ b/config.json @@ -0,0 +1,19 @@ +{ + "save_path": ".data", + "log_file": "", + "socket": { + "ip": "0.0.0.0", + "port": 7766 + }, + "ws": { + "ip": "0.0.0.0", + "port": 7767, + "cert": "", + "key": "" + }, + "logging": { + "level": "DEBUG", + "format": "%(asctime)s.%(msecs)03d %(name)s - %(levelname)s - %(message)s", + "datefmt": "%d-%b-%y %H:%M:%S" + } +} \ No newline at end of file diff --git a/handlers/__init__.py b/handlers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/handlers/mainHandler.py b/handlers/mainHandler.py new file mode 100644 index 0000000..573e44f --- /dev/null +++ b/handlers/mainHandler.py @@ -0,0 +1,261 @@ +import asyncio +import logging +import struct + +from time import time + +from objects import glob + +flights = {} +#flight_data_cache = b"" +clients = set() + +STRUCTS = { + "start": b"IB24s", + "end": b"", + "flight_data": b"?BHhHff", + "server_open": b"", + "server_close": b"" +} + +class Client: + def __init__(self, ws): + self.ws = ws + self.subscriptions = set() + self.get_flight_changes = False + +async def broadcast_flight_change(uuid, active): + logging.info("[%d] Broadcasting flight running: %r" % (uuid, active)) + for cli in [cli for cli in clients if cli.get_flight_changes or uuid in cli.subscriptions]: + await cli.ws.send(struct.pack(b" Connected." % (*ws.remote_address, path)) + + async def send_error(msg): + logging.debug(" -> ERROR: %s" % (*ws.remote_address, path, msg.decode())) + await cli.ws.send(struct.pack(b" -> All active flights" % (*ws.remote_address, path)) + await cli.ws.send(struct.pack(b"<2B%dI" % len(flights), + 0, # packet_id + len(flights), + *flights + )) + + async def subscribe_flight_changes(data): + if not len(data): + return await send_error(b"Invalid data") + + (cli.get_flight_changes,) = struct.unpack(b" -> %subscribed to all flight changes" % (*ws.remote_address, path, cli.get_flight_changes and "S" or "Uns")) + await cli.ws.send(struct.pack(b" -> %subscribed to %d" % (*ws.remote_address, path, uuid in cli.subscriptions and "S" or "Uns", uuid)) + await cli.ws.send(struct.pack(b" Disconnected." % (*ws.remote_address, path)) + +class Flight: + def __init__(self, data): + (self.uuid, self.playername_len, self.playername) = struct.unpack(b"<" + STRUCTS["start"], data[:29]) + self.active = True + + self.last_timeline_values = [None] * 7 + self.timeline = b"" + + logging.info("[%d] Flight started" % self.uuid) + asyncio.ensure_future( broadcast_flight_change(self.uuid, self.active) ) + + def get_all(self): + return struct.pack(b"<" + STRUCTS["start"], + self.uuid, + self.playername_len, + self.playername, + ) + self.timeline + + def add(self, data): + data = [*struct.unpack(b"<" + STRUCTS["flight_data"], data[:16])] + for i in range(len(data)): + if data[i] == self.last_timeline_values[i]: + data[i] = None + else: + self.last_timeline_values[i] = data[i] + + frame = self.format_flight_data(data) + if not frame: + logging.debug("[%d] Empty frame (skipping)" % self.uuid) + return + + logging.debug("[%d] New frame: %s" % (self.uuid, frame)) + asyncio.ensure_future( broadcast_flight_data(self.uuid, frame) ) + + self.timeline += frame + + @staticmethod + def format_flight_data(data): + ret = b"" + flag = 0 + for i in range(len(data)): + if data[i] != None: + flag |= 1< 5: + logging.error("Invalid packet header: %b" % data[:4]) + return + + switch = { + 0: self.unimplemented, # ping? + 1: self.handle_start, + 2: self.handle_flight_data, + 3: self.handle_end, + 4: self.handle_server_open, + 5: self.handle_server_close + } + switch.get(packet_id, self.unimplemented)(data[4:]) + + @staticmethod + def unimplemented(data): + logging.warning("Unimplemented: %b" % data) + + @staticmethod + def handle_start(data): + flight = Flight(data) + flights[flight.uuid] = flight + logging.debug("Added %d into flights dict" % flight.uuid) + + @staticmethod + def handle_end(data): + (uuid, data) = (*struct.unpack(b" + + + WebSocket test + + + + + \ No newline at end of file