From 6c4e3f2a20adf100afef26da1ab80bd370ab4a34 Mon Sep 17 00:00:00 2001 From: Akashdeep Dhar Date: Sun, 10 Nov 2024 17:24:36 +0530 Subject: [PATCH] Refine the docstrings and typing for server Signed-off-by: Akashdeep Dhar --- expedite/server/base.py | 17 +++++++++ expedite/server/conn.py | 77 +++++++++++++++++++++++++++++++++++++++++ expedite/server/main.py | 18 ++++++++-- expedite/server/meet.py | 5 +++ expedite/server/room.py | 9 ++++- 5 files changed, 122 insertions(+), 4 deletions(-) diff --git a/expedite/server/base.py b/expedite/server/base.py index 0d68c69..cc1b2e1 100644 --- a/expedite/server/base.py +++ b/expedite/server/base.py @@ -28,6 +28,14 @@ class ExpediteConnection: def __init__(self, iden: str = standard.client_iden, plan: str = standard.client_plan, scan: str = standard.client_endo, time: int = standard.client_time) -> None: + """ + Initialize the Expedite connection with the client identity, operation intent, target identity and waiting time + + :param iden: Identity provided by the exchange server to the connecting client to be recognized within the network + :param plan: Operation intent of the connecting client - This can be either SEND or RECV depending on the purpose + :param scan: Target client sought by the connecting client - This can be either empty string or hexadecimal string + :param time: Time for which a connecting client will stay connected to the network and wait for a pairing process + """ self.iden = iden self.plan = plan self.scan = scan if scan != "" else None @@ -36,5 +44,14 @@ def __init__(self, iden: str = standard.client_iden, plan: str = standard.client self.ptsc = None def pair_connection(self, ptid: str = standard.client_endo, ptsc: WebSocketServerProtocol = None) -> None: + """ + Configure the partner identity and partner sought when the pairing process with both the clients has completed + + These attributes belong to the pairmate and are populated for the client after the pairing process is complete + + :param ptid: Identity provided by the exchange server to the connecting client to be recognized within the network + :param ptsc: Websocket object belonging to the connecting client + :return: + """ self.ptid = ptid self.ptsc = ptsc diff --git a/expedite/server/conn.py b/expedite/server/conn.py index a5c4604..93d6499 100644 --- a/expedite/server/conn.py +++ b/expedite/server/conn.py @@ -32,6 +32,20 @@ async def exchange_insert(sock: WebSocketServerProtocol, plan: str = standard.client_plan, scan: str = standard.client_endo, time: int = standard.client_time) -> str | bool: + """ + Comply with the client request of joining the network + + If client ABC joins before client XYZ + - assuming that client ABC wants to connect to client XYZ + - client ABC does not need to provide any target identity + - client XYZ has to provide client ABC as target identity + + :param sock: Websocket object belonging to the connecting client + :param plan: Operation intent of the connecting client - This can be either SEND or RECV depending on the purpose + :param scan: Target client sought by the connecting client - This can be either empty string or hexadecimal string + :param time: Identity provided by the exchange server to the connecting client to be recognized within the network + :return: Confirmation of the action completion + """ if sock not in standard.connection_dict: if plan in ["SEND", "RECV"]: iden = uuid4().hex[0:8].upper() @@ -53,6 +67,24 @@ async def exchange_insert(sock: WebSocketServerProtocol, plan: str = standard.cl async def exchange_remove(sock: WebSocketServerProtocol) -> bool: + """ + Inform the client about them being booted off the network + + Here is how the logic works - + + Once participant ABC is flagged for removal either from client side or server side + - If participant ABC exists in the connection dictionary + - If participant ABC is paired with participant XYZ + - Participant XYZ is disconnected from the network and removed from the connection dictionary + - Participant ABC is disconnected from the network and removed from the connection dictionary + - If participant ABC is not paired with anyone else + - Participant ABC is disconnected from the network and removed from the connection dictionary + - If participant ABC does not exist in the connection dictionary + - Do nothing + + :param sock: Websocket object belonging to the disconnecting client + :return: Confirmation of the action completion + """ if sock in standard.connection_dict: if standard.connection_dict[sock].ptsc in standard.connection_dict and standard.connection_dict[sock].ptsc.state == 1: warning(f"{standard.connection_dict[sock].ptid} left.") @@ -67,6 +99,36 @@ async def exchange_remove(sock: WebSocketServerProtocol) -> bool: async def exchange_inform(sock: WebSocketServerProtocol, plan: str = standard.client_plan, scan: str = standard.client_endo, iden: str = standard.client_iden) -> int: + """ + Inform the client about them being able to join the network + + Here is how the logic works - + + After client ABC is able to join the network with operation intent P + - If client ABC has provided that they are looking for client XYZ for DEF seconds + - If client XYZ has not yet joined the network + - Client ABC will wait until the client XYZ will join the network [Code 3] + - Client ABC will disconnect after DEF seconds if the client XYZ does not turn up + - If client XYZ has been connected to the network for a while + - If client XYZ is not yet paired with anyone else + - If client XYZ has the operation intent Q (opposite of operation intent P of client ABC) + - Client ABC will be paired with client XYZ due to the positive operation intents [Code 0] + - Client XYZ will be paired with client ABC due to the positive operation intents [Code 0] + - If client XYZ has the operation intent P (selfsame of operation intent P of client ABC) + - Client ABC will be booted off the network due to the negative operation intents [Code 1] + - Client XYZ will be booted off the network due to the negative operation intents [Code 1] + - If client XYZ has already paired with anyone else + - Client ABC will be booted off the network as client XYZ is already paired [Code 2] + - If client ABC has provided that they are waiting for connection for DEF seconds + - Client ABC will wait until they are connected with some client [Code 3] + - Client ABC will disconnect after DEF seconds if they are not paired until then + + :param sock: Websocket object belonging to the connecting client + :param plan: Operation intent of the connecting client - This can be either SEND or RECV depending on the purpose + :param scan: Target client sought by the connecting client - This can be either empty string or hexadecimal string + :param iden: Identity provided by the exchange server to the connecting client to be recognized within the network + :return: Confirmation of the action completion + """ for indx in standard.connection_dict: if standard.connection_dict[indx].iden == scan: if not standard.connection_dict[indx].ptsc: @@ -90,6 +152,14 @@ async def exchange_inform(sock: WebSocketServerProtocol, plan: str = standard.cl async def exchange_json(sock: WebSocketServerProtocol, note: str = "", data: str = "") -> bool: + """ + Convey the JSON elements from delivering client to collecting client + + :param sock: Websocket object belonging to the delivering client + :param note: Action requested to be performed by the collecting client + :param data: Data elements that are to be conveyed across + :return: Confirmation of the action completion + """ general(standard.server_note[note].format(sj=standard.connection_dict[sock].iden, oj=standard.connection_dict[sock].ptid)) if sock in standard.connection_dict: if standard.connection_dict[sock].ptsc in standard.connection_dict and standard.connection_dict[sock].ptsc.state == 1: @@ -102,6 +172,13 @@ async def exchange_json(sock: WebSocketServerProtocol, note: str = "", data: str async def exchange_byte(sock: WebSocketServerProtocol, pack: bytes = b"") -> bool: + """ + Convey the file contents from delivering client to collecting client + + :param sock: Websocket object belonging to the delivering client + :param pack: File contents that are to be conveyed across + :return: Confirmation of the action completion + """ if sock in standard.connection_dict: if standard.connection_dict[sock].ptsc in standard.connection_dict and standard.connection_dict[sock].ptsc.state == 1: await standard.connection_dict[sock].ptsc.send(pack) diff --git a/expedite/server/main.py b/expedite/server/main.py index aa18e59..4d1011c 100644 --- a/expedite/server/main.py +++ b/expedite/server/main.py @@ -30,12 +30,17 @@ from expedite import __versdata__ from expedite.config import standard from expedite.server.meet import talk -from expedite.server.room import oper +from expedite.server.room import exchange from expedite.view import failure, general -def work(): - func = serve(oper, standard.server_addr, standard.server_port) +def work() -> None: + """ + Start the worker module to serve the exchange service + + :return: + """ + func = serve(exchange, standard.server_addr, standard.server_port) get_event_loop().run_until_complete(func) get_event_loop().run_forever() @@ -66,6 +71,13 @@ def work(): version=__versdata__, prog_name="Expedite Server by Akashdeep Dhar" ) def main(addr: str = standard.server_addr, port: int = standard.server_port) -> None: + """ + Configure the service particulars before starting it + + :param addr: Interface for the service endpoint + :param port: Port value for the service endpoint + :return: + """ try: standard.server_addr = addr standard.server_port = port diff --git a/expedite/server/meet.py b/expedite/server/meet.py index 120abd4..406a40e 100644 --- a/expedite/server/meet.py +++ b/expedite/server/meet.py @@ -27,6 +27,11 @@ def talk() -> None: + """ + Show information on the server side during startup + + :return: + """ success(f"Expedite Server v{__versdata__}") general(f"Addr. {standard.server_addr}") general(f"Port. {standard.server_port}") diff --git a/expedite/server/room.py b/expedite/server/room.py index ef28d63..e6834ea 100644 --- a/expedite/server/room.py +++ b/expedite/server/room.py @@ -24,6 +24,7 @@ from json import loads from websockets.exceptions import ConnectionClosed +from websockets.legacy.server import WebSocketServerProtocol from expedite.config import standard from expedite.server.conn import ( @@ -36,7 +37,13 @@ from expedite.view import failure, general, warning -async def oper(sock): +async def exchange(sock: WebSocketServerProtocol) -> None: + """ + Exchange data among connected clients depending on client identity, operation intent and target identity + + :param sock: Websocket object belonging to the client + :return: + """ try: async for mesgcont in sock: if isinstance(mesgcont, str):