-
-
Notifications
You must be signed in to change notification settings - Fork 9
Description
When trying to pass a domain name like mc.advancius.net on Windows to the RakNet protocol, the library does not receive any response and times out. This can be reproduced with the example main function in raknet.py:
opengsq-python/opengsq/protocols/raknet.py
Lines 80 to 88 in 085a9b6
| if __name__ == "__main__": | |
| import asyncio | |
| async def main_async(): | |
| raknet = RakNet(host="mc.advancius.net", port=19132, timeout=5.0) | |
| status = await raknet.get_status() | |
| print(status) | |
| asyncio.run(main_async()) |
When running this module, the following traceback is printed:
(opengsq-python) C:\Users\home\Documents\GitHub\opengsq-python>py -m opengsq.protocols.raknet
<frozen runpy>:128: RuntimeWarning: 'opengsq.protocols.raknet' found in sys.modules after import of package 'opengsq.protocols', but prior to execution of 'opengsq.protocols.raknet'; this may result in unpredictable behaviour
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\tasks.py", line 488, in wait_for
return await fut
^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\queues.py", line 186, in get
await getter
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Users\home\Documents\GitHub\opengsq-python\opengsq\protocols\raknet.py", line 88, in <module>
asyncio.run(main_async())
~~~~~~~~~~~^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\runners.py", line 204, in run
return runner.run(main)
~~~~~~~~~~^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\runners.py", line 127, in run
return self._loop.run_until_complete(task)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\base_events.py", line 719, in run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File "C:\Users\home\Documents\GitHub\opengsq-python\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\Documents\GitHub\opengsq-python\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\Documents\GitHub\opengsq-python\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\Documents\GitHub\opengsq-python\opengsq\protocol_socket.py", line 24, in recv
return await asyncio.wait_for(self.__packets.get(), timeout=self.__timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\tasks.py", line 487, in wait_for
async with timeouts.timeout(timeout):
~~~~~~~~~~~~~~~~^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.14-64\Lib\asyncio\timeouts.py", line 114, in __aexit__
raise TimeoutError from exc_val
TimeoutErrorBut when I tested this on a Linux system, this issue was not present:
~$ uv run --with opengsq -m opengsq.protocols.raknet
Installed 11 packages in 8ms
<frozen runpy>:128: RuntimeWarning: 'opengsq.protocols.raknet' found in sys.modules after import of package 'opengsq.protocols', but prior to execution of 'opengsq.protocols.raknet'; this may result in unpredictable behaviour
Status(edition='MCPE', motd_line1='Advancius Network', protocol_version=844, version_name='1.21.111', num_players=161, max_players=500, server_unique_id='12947326039399818065', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)And if the IP address of mc.advancius.net is explicitly given (currently 142.44.218.185), it works fine on Windows:
# main.py
import asyncio
from opengsq import RakNet
async def main_async():
raknet = RakNet(host="142.44.218.185", port=19132, timeout=5.0)
status = await raknet.get_status()
print(status)
asyncio.run(main_async())(opengsq-python) C:\Users\home\Documents\GitHub\opengsq-python>py main.py
Status(edition='MCPE', motd_line1='Advancius Network', protocol_version=844, version_name='1.21.111', num_players=158, max_players=500, server_unique_id='12947326039399818065', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)From what I can tell after an hour of debugging, there's a quirk with the UdpClient.communicate() method which ignores the default Socket transport and always passes the local_addr= argument to loop.create_datagram_endpoint(), even when the static method is passed source_port=None and protocol._allow_broadcast is False:
opengsq-python/opengsq/protocol_socket.py
Lines 148 to 167 in 085a9b6
| class UdpClient(Socket): | |
| @staticmethod | |
| async def communicate(protocol: ProtocolBase, data: bytes, source_port: int = None): | |
| with UdpClient() as udpClient: | |
| if source_port: | |
| udpClient.bind_port(source_port) | |
| udpClient.settimeout(protocol._timeout) | |
| loop = asyncio.get_running_loop() | |
| transport, protocol_instance = await loop.create_datagram_endpoint( | |
| lambda: Socket.Protocol(protocol._timeout), # Use public Protocol class | |
| local_addr=('0.0.0.0', source_port if source_port else 0), | |
| allow_broadcast=protocol._allow_broadcast | |
| ) | |
| try: | |
| transport.sendto(data, (protocol._host, protocol._port)) | |
| return await protocol_instance.recv() | |
| finally: | |
| transport.close() |
If I change the source code to pass the remote_addr argument exclusively, then the hostname query works on Windows:
# opengsq/protocol_socket.py
transport, protocol_instance = await loop.create_datagram_endpoint(
lambda: Socket.Protocol(protocol._timeout), # Use public Protocol class
- local_addr=('0.0.0.0', source_port if source_port else 0),
+ remote_addr=(protocol._host, protocol._port),
allow_broadcast=protocol._allow_broadcast
)
try:
- transport.sendto(data, (protocol._host, protocol._port))
+ transport.sendto(data)
return await protocol_instance.recv()
finally:
transport.close()(opengsq-python) C:\Users\home\Documents\GitHub\opengsq-python>py -m opengsq.protocols.raknet
<frozen runpy>:128: RuntimeWarning: 'opengsq.protocols.raknet' found in sys.modules after import of package 'opengsq.protocols', but prior to execution of 'opengsq.protocols.raknet'; this may result in unpredictable behaviour
Status(edition='MCPE', motd_line1='Advancius Network', protocol_version=844, version_name='1.21.111', num_players=162, max_players=500, server_unique_id='12947326039399818065', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)