2021-06-17 16:02:50 +02:00
|
|
|
import websockets
|
|
|
|
import asyncio
|
|
|
|
import json
|
|
|
|
import logging
|
|
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
|
|
class JsonWebsocketConnection(object):
|
|
|
|
|
|
|
|
def __init__(self,
|
|
|
|
websocket: websockets.WebSocketServerProtocol):
|
|
|
|
|
|
|
|
logging.info("incoming connection")
|
|
|
|
self._websocket = websocket
|
|
|
|
self._is_closed = False;
|
|
|
|
|
|
|
|
def is_closed(self):
|
|
|
|
return self._is_closed
|
|
|
|
|
|
|
|
async def close(self):
|
|
|
|
logging.info("closing connection")
|
|
|
|
try:
|
|
|
|
if self._is_closed:
|
|
|
|
return
|
|
|
|
self._websocket.close()
|
|
|
|
self._is_closed = True
|
|
|
|
except Exception as e:
|
|
|
|
logging.warning("error closing connection: %s", str(e))
|
|
|
|
|
|
|
|
async def send(self, message: dict):
|
|
|
|
string_message = json.dumps(message)
|
|
|
|
logging.debug("sending message: %s", string_message)
|
|
|
|
try:
|
|
|
|
await self._websocket.send(string_message)
|
|
|
|
except Exception as e:
|
|
|
|
logging.warning("error sending message: %s", str(e))
|
|
|
|
|
|
|
|
async def handle_message(self, message: dict):
|
|
|
|
pass # override this function
|
|
|
|
|
|
|
|
async def run(self):
|
|
|
|
try:
|
|
|
|
async for message in self._websocket:
|
|
|
|
try:
|
|
|
|
json_message = json.loads(message)
|
|
|
|
await self.handle_message(json_message)
|
|
|
|
except ValueError as e:
|
|
|
|
logging.warning("received unprocessable message %s", str(e))
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
logging.warning("error in websocket connection: %s", str(e))
|
|
|
|
self._is_closed = True
|
|
|
|
finally:
|
|
|
|
self._is_closed = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class JsonWebsocketServer(object):
|
2021-06-17 16:12:16 +02:00
|
|
|
def __init__(self, handler_class: JsonWebsocketConnection, host:str = 'localhost', port:int = 8765, ssl_context = None):
|
2021-06-17 16:02:50 +02:00
|
|
|
self._host = host
|
|
|
|
self._port = port
|
|
|
|
self._handler_class = handler_class
|
2021-06-17 16:12:16 +02:00
|
|
|
self._ssl_context = ssl_context
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
async def main(websocket: websockets.WebSocketServerProtocol,
|
|
|
|
path: str):
|
|
|
|
|
|
|
|
connection = self._handler_class(websocket)
|
|
|
|
|
|
|
|
await connection.run()
|
2021-06-17 16:12:16 +02:00
|
|
|
|
|
|
|
if (self._ssl_context is not None):
|
|
|
|
start_server = websockets.serve(main, self._host, self._port, ssl=self._ssl_context)
|
|
|
|
else:
|
|
|
|
start_server = websockets.serve(main, self._host, self._port)
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
asyncio.get_event_loop().run_until_complete(start_server)
|
|
|
|
asyncio.get_event_loop().run_forever()
|
|
|
|
|
|
|
|
|