#!/usr/bin/env python3 # -*- coding: utf-8 -*- from typing import Any, Self, Sequence, Optional from websockets.sync.server import serve as server_serve from websockets import ServerConnection as WebSocketServer, ClientConnection as WebSocketClient from Application.Event import Event from Interfaces.Application.AnPInterface import AnPInterface class WebSocketServerDriver: def __init__(self:Self, anp:AnPInterface, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None: self.anp:AnPInterface = anp self.on_new_client:Event = Event() self.on_message:Event = Event() self.on_close:Event = Event() self.on_error:Event = Event() self.__server:WebSocketServer self.__clients:dict[str, WebSocketClient] = {} self.__host:str = anp.settings.get(("web_socket_server_host", "host"), inputs, "") self.__port:int = anp.settings.get(("web_socket_server_port", "port"), inputs, 8765) with server_serve(self.__handler, self.__host, self.__port) as self.__server: self.__server.serve_forever() def close(self:Self) -> None: id:str for id in tuple(self.__clients.keys()): self.close_client(id) self.__server.close() def close_client(self:Self, id:str, show_exception:bool = True) -> None: if id in self.__clients: try: self.__clients[id].close() except Exception as exception: show_exception and self.anp.exception(exception, "web_socket_server_client_close_exception", { "client": id, "port": self.__port, "host": self.__host }) del self.__clients[id] def __handler(self:Self, client:WebSocketClient) -> None: id:str = str(id(client)) self.__clients[id] = client self.on_new_client.execute(client, id) self.anp.print("info", "web_socket_server_client_connected", { "client": id, "port": self.__port, "host": self.__host, "client_host" : client.remote_address[0], "client_port" : client.remote_address[1] }) try: while self.anp.working(): message:str = client.recv() if message is None: break self.on_message.execute(client, message) except Exception as exception: self.anp.exception(exception, "web_socket_server_client_exception", { "client": id, "port": self.__port, "host": self.__host }) self.on_error.execute(client, exception) finally: self.close_client(id, False) self.on_close.execute(client) self.anp.print("info", "web_socket_server_client_disconnected", { "client": id, "port": self.__port, "host": self.__host })