diff --git a/winerp/client.py b/winerp/client.py index 6be7e73..4bb4ef7 100644 --- a/winerp/client.py +++ b/winerp/client.py @@ -384,6 +384,40 @@ async def request( else: raise ClientNotReadyError("The client has not been started or has disconnected") + async def get_clients(self, timeout: int = 60) -> list: + """|coro| + + Gets all the connected clients. + + Raises + ------- + ClientNotReadyError + The client is currently not ready to send or accept requests. + UnauthorizedError + The client isn't authorized by the server. + + Returns + -------- + :class:`list` + A list of connected clients. + """ + if self._on_hold or self.websocket is None or not self.websocket.open: + raise ClientNotReadyError("The client is currently not ready to send or accept requests.") + if not self._authorized: + raise UnauthorizedError("Client is not authorized!") + + logger.debug("Getting all connected clients") + _uuid = str(uuid.uuid4()) + payload = MessagePayload( + type=Payloads.client_count, + id=self.local_name, + uuid=_uuid + ) + await self.send_message(payload) + resp = await self.__get_response(_uuid, asyncio.get_event_loop(), timeout=timeout) + return resp + + async def inform( self, data: Any, @@ -558,6 +592,10 @@ async def __on_message(self): logger.debug("Received an information bit from client: %s", message.id) self.__events.dispatch_event('winerp_information', message.data, message.id) + elif message.type.client_count: + logger.debug("Received the response of the client_count from server") + asyncio.create_task(self._dispatch(message)) + elif message.type.function_call: logger.debug("Received an object function call.") logger.debug(message.data) diff --git a/winerp/lib/payload.py b/winerp/lib/payload.py index a9b10ca..3b8793d 100644 --- a/winerp/lib/payload.py +++ b/winerp/lib/payload.py @@ -15,6 +15,8 @@ class Payloads: ping = 5 information = 6 function_call = 7 + client_count = 9 + class PayloadTypes: ''' @@ -25,6 +27,7 @@ class PayloadTypes: | ``response``: Response to a request. | ``error``: Error response. | ``ping``: Ping message. + | ``question``: Question message. ''' def __init__(self, type: int) -> None: self._type = type @@ -81,10 +84,17 @@ def information(self) -> bool: ''' return self._type == Payloads.information + @property + def client_count(self) -> bool: + ''' + :class:`bool`: Returns ``True`` if the message is a client_count message. + ''' + return self._type == Payloads.client_count + @property def function_call(self) -> bool: ''' - :class:`bool`: Returns ``True`` if the message is an information message. + :class:`bool`: Returns ``True`` if the message is a function call message. ''' return self._type == Payloads.function_call diff --git a/winerp/server.py b/winerp/server.py index 00cb4b2..761f004 100644 --- a/winerp/server.py +++ b/winerp/server.py @@ -103,6 +103,7 @@ def __send_error(self, client, payload): def __on_message(self, client, _, msg): msg = WsMessage(orjson.loads(msg)) payload = MessagePayload().from_message(msg) + if msg.type.verification: if msg.id in self.active_clients: logger.info("Connection from duplicate client has benn put on hold connection id %s and local id %s" % (client['address'][1], msg.id)) @@ -180,6 +181,17 @@ def __on_message(self, client, _, msg): ) logger.debug("Request Message Forwarded to %s" % self.active_clients[msg.destination]["client"]['address'][1]) + if msg.type.client_count: + logger.debug("Received Client_count Message from client %s" % client['address'][1]) + payload.type = Payloads.client_count + + payload.data = list(self.active_clients.keys()) + + self.__send_message( + client, + payload + ) + if msg.type.response or msg.type.error or msg.type.function_call: logger.debug("Received Response Message from client %s" % client['address'][1]) if msg.destination not in self.active_clients: