diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6f1c6b5 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "hbd", + "console": "integratedTerminal", + "args": ["-f"] + + } + ] +} \ No newline at end of file diff --git a/hbd b/hbd index 3a74038..706db9c 100755 --- a/hbd +++ b/hbd @@ -28,6 +28,9 @@ import json import zlib import codecs +import asyncio +import websockets + from subprocess import Popen, STDOUT, PIPE #from hbdclass import * @@ -55,6 +58,7 @@ msgs = [] PORT = 50003 TPORT = 50004 THOST = "" +WSPORT = 50005 verbose = False @@ -374,12 +378,14 @@ def log(host, m, service=None): else: hst = "" - msg = "%s: %s%s%s\n" % (ts, hst, srv, m) - msgs.append(msg) + msg = "%s: %s%s%s" % (ts, hst, srv, m) + msgs.append(msg+'\n') + msg_to_websockets('message', msg) + if logfmt == "msg": m2 = "%d|%s|%s\n" % (now, hst, m) else: - m2 = msg + m2 = msg+'\n' logf.write(m2) logf.flush() pickleit() @@ -536,6 +542,7 @@ def readsock(sock): if verbose: print(("sendto2: %s (%s) %s %s" % (addr, len(opkt), op, str(rmsg)[:50]))) if DEBUG > 2: print(("msg from %s,%s, sent %s bytes back" % (addr[0], addr[1], ss))) + msg_to_websockets('host', host.stateinfo()) def updatecode(ucode, uname): @@ -801,6 +808,34 @@ def pickleit(): pick.dump(lastfm) pickf.close() +ws_connections = {} + +async def ws_serve(websocket, path): + + ws_connections[websocket] = path + while True: + try: + name = await websocket.recv() + except ( + websockets.exceptions.ConnectionClosedOK, + websockets.exceptions.ConnectionClosedError) as e: + print(f'ws closed: {e}') + break + print(f"< {name} at {path}") + for h in hbdclass.Host.hosts: + jmsg = json.dumps({'type': 'host', 'data': hbdclass.Host.hosts[h].stateinfo() }) + await websocket.send(jmsg) + + del ws_connections[websocket] + +def websocketupdater(): + loop.run_forever() + + +def msg_to_websockets(typ: str, msg: str): + jmsg = json.dumps({'type': typ, 'data': msg}) + for ws in ws_connections: + asyncio.run(ws.send(jmsg)) # # Main @@ -1033,6 +1068,10 @@ except: print(("failed to start server on %s:%s" % (hbd_host, hbd_port))) sys.exit(1) + +ws_start_server = websockets.serve(ws_serve, hbd_host, WSPORT) +asyncio.get_event_loop().run_until_complete(ws_start_server) + servthread = threading.Thread(target=serv.serve_forever) servthread.daemon = True servthread.start() @@ -1042,6 +1081,11 @@ dnsT = threading.Thread(target=dnsupdatethread) dnsT.daemon = True dnsT.start() +loop = asyncio.get_event_loop() +wsT = threading.Thread(target=websocketupdater) +wsT.daemon = True +wsT.start() + running = True sig = 0 signal.signal(signal.SIGTERM, handler) diff --git a/hbdclass.py b/hbdclass.py index 93d392b..e7ce70e 100644 --- a/hbdclass.py +++ b/hbdclass.py @@ -208,7 +208,7 @@ class Host: for af in self.connections: self.connections[af].registerDns() - def jsons(self): + def stateinfo(self): ddict = {} for d in self.__dict__: if d == "connections": @@ -221,7 +221,10 @@ class Host: ddict[d] = cl else: ddict[d] = self.__dict__[d] - return json.dumps(ddict) + return ddict + + def jsons(self): + return json.dumps(self.stateinfo()) def setcver(self, cver): self.cver = cver diff --git a/wstest.py b/wstest.py new file mode 100644 index 0000000..4b7743b --- /dev/null +++ b/wstest.py @@ -0,0 +1,20 @@ +import asyncio +import websockets + +async def hello(): + uri = "ws://localhost:50005/messages" + async with websockets.connect(uri) as websocket: + name = "Andreas" + + await websocket.send(name) + print(f"> {name}") + + while True: + greeting = await websocket.recv() + print(f"< {greeting}") + if greeting == "bye": + break + + print('out of here') + +asyncio.get_event_loop().run_until_complete(hello())