RakNet times out when querying any hostname on Windows
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:
https://github.com/opengsq/opengsq-python/blob/085a9b66317e63069585cfbeeca954025b062c63/opengsq/protocols/raknet.py#L80-L88
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
TimeoutError
But 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:
https://github.com/opengsq/opengsq-python/blob/085a9b66317e63069585cfbeeca954025b062c63/opengsq/protocol_socket.py#L148-L167
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)
This is indeed a very weird behavior. Why should the hostname not be resolved in windows.
I got some questions for replicating the issue:
- Is the python version identical on windows and Linux?
- is the host you try to query publicly available for replicating the issue?
Hmm, the Python versions are indeed different - 3.14.0 on Windows and system 3.12.3 on Ubuntu 24.04. mc.advancius.net I'd assume is publicly available, as it is part of the repository.
I was able to repro this issue from 3.9-3.14 on Windows using CPython provided by the official pymanager, alongside uv to create the virtual environments:
pymanager install 3.9 3.10. 3.11 3.12 3.13 3.14 # previously installed
uv run --with opengsq==3.5.0 --python 3.9.13 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.10.11 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.11.9 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.12.10 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.13.9 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.14.0 -m opengsq.protocols.raknet
Full output, including tracebacks
C:\Users\home\Downloads>uv run --with opengsq==3.5.0 --python 3.9.13 -m opengsq.protocols.raknet
C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\runpy.py:127: 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
warn(RuntimeWarning(msg))
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\asyncio\queues.py", line 166, in get
await getter
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\asyncio\tasks.py", line 490, in wait_for
return fut.result()
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\O2nTfdq5-isIIdvTkLGW-\Lib\site-packages\opengsq\protocols\raknet.py", line 88, in <module>
asyncio.run(main_async())
File "C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Users\home\AppData\Local\Python\pythoncore-3.9-64\lib\asyncio\base_events.py", line 647, in run_until_complete
return future.result()
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\O2nTfdq5-isIIdvTkLGW-\Lib\site-packages\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\O2nTfdq5-isIIdvTkLGW-\Lib\site-packages\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\O2nTfdq5-isIIdvTkLGW-\Lib\site-packages\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\O2nTfdq5-isIIdvTkLGW-\Lib\site-packages\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.9-64\lib\asyncio\tasks.py", line 492, in wait_for
raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError
C:\Users\home\Downloads>uv run --with opengsq==3.5.0 --python 3.10.11 -m opengsq.protocols.raknet
C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\runpy.py:126: 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
warn(RuntimeWarning(msg))
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\asyncio\queues.py", line 159, in get
await getter
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\asyncio\tasks.py", line 456, in wait_for
return fut.result()
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\X9UJnEQ5D5pKWhEqPsY_w\Lib\site-packages\opengsq\protocols\raknet.py", line 88, in <module>
asyncio.run(main_async())
File "C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Users\home\AppData\Local\Python\pythoncore-3.10-64\lib\asyncio\base_events.py", line 649, in run_until_complete
return future.result()
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\X9UJnEQ5D5pKWhEqPsY_w\Lib\site-packages\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\X9UJnEQ5D5pKWhEqPsY_w\Lib\site-packages\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\X9UJnEQ5D5pKWhEqPsY_w\Lib\site-packages\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\X9UJnEQ5D5pKWhEqPsY_w\Lib\site-packages\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.10-64\lib\asyncio\tasks.py", line 458, in wait_for
raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError
C:\Users\home\Downloads>uv run --with opengsq==3.5.0 --python 3.11.9 -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.11-64\Lib\asyncio\tasks.py", line 500, in wait_for
return fut.result()
^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.11-64\Lib\asyncio\queues.py", line 158, 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\AppData\Local\uv\cache\archive-v0\y97CNW7WmGUzobAqTmu5u\Lib\site-packages\opengsq\protocols\raknet.py", line 88, in <module>
asyncio.run(main_async())
File "C:\Users\home\AppData\Local\Python\pythoncore-3.11-64\Lib\asyncio\runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.11-64\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.11-64\Lib\asyncio\base_events.py", line 654, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\y97CNW7WmGUzobAqTmu5u\Lib\site-packages\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\y97CNW7WmGUzobAqTmu5u\Lib\site-packages\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\y97CNW7WmGUzobAqTmu5u\Lib\site-packages\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\y97CNW7WmGUzobAqTmu5u\Lib\site-packages\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.11-64\Lib\asyncio\tasks.py", line 502, in wait_for
raise exceptions.TimeoutError() from exc
TimeoutError
C:\Users\home\Downloads>uv run --with opengsq==3.5.0 --python 3.12.10 -m opengsq.protocols.raknet
C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocols\cod1.py:114: SyntaxWarning: invalid escape sequence '\)'
CoD1 uses backslash (\) as delimiter between keys and values.
C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocols\cod4.py:114: SyntaxWarning: invalid escape sequence '\)'
CoD4 uses backslash (\) as delimiter between keys and values.
C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocols\cod5.py:114: SyntaxWarning: invalid escape sequence '\)'
CoD5 uses backslash (\) as delimiter between keys and values.
<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.12-64\Lib\asyncio\tasks.py", line 520, in wait_for
return await fut
^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.12-64\Lib\asyncio\queues.py", line 158, 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\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocols\raknet.py", line 88, in <module>
asyncio.run(main_async())
File "C:\Users\home\AppData\Local\Python\pythoncore-3.12-64\Lib\asyncio\runners.py", line 195, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.12-64\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.12-64\Lib\asyncio\base_events.py", line 691, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\-6OHqIarc6vORiCAC8zNd\Lib\site-packages\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.12-64\Lib\asyncio\tasks.py", line 519, in wait_for
async with timeouts.timeout(timeout):
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.12-64\Lib\asyncio\timeouts.py", line 115, in __aexit__
raise TimeoutError from exc_val
TimeoutError
C:\Users\home\Downloads>uv run --with opengsq==3.5.0 --python 3.13.9 -m opengsq.protocols.raknet
C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocols\cod1.py:114: SyntaxWarning: invalid escape sequence '\)'
CoD1 uses backslash (\) as delimiter between keys and values.
C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocols\cod4.py:114: SyntaxWarning: invalid escape sequence '\)'
CoD4 uses backslash (\) as delimiter between keys and values.
C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocols\cod5.py:114: SyntaxWarning: invalid escape sequence '\)'
CoD5 uses backslash (\) as delimiter between keys and values.
<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.13-64\Lib\asyncio\tasks.py", line 507, in wait_for
return await fut
^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.13-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\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocols\raknet.py", line 88, in <module>
asyncio.run(main_async())
~~~~~~~~~~~^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.13-64\Lib\asyncio\runners.py", line 195, in run
return runner.run(main)
~~~~~~~~~~^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.13-64\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.13-64\Lib\asyncio\base_events.py", line 725, in run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\byEm03QZ4HZlGf2tdXY-k\Lib\site-packages\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.13-64\Lib\asyncio\tasks.py", line 506, in wait_for
async with timeouts.timeout(timeout):
~~~~~~~~~~~~~~~~^^^^^^^^^
File "C:\Users\home\AppData\Local\Python\pythoncore-3.13-64\Lib\asyncio\timeouts.py", line 116, in __aexit__
raise TimeoutError from exc_val
TimeoutError
C:\Users\home\Downloads>uv run --with opengsq==3.5.0 --python 3.14.0 -m opengsq.protocols.raknet
C:\Users\home\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\opengsq\protocols\cod1.py:114: SyntaxWarning: "\)" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\)"? A raw string is also an option.
CoD1 uses backslash (\) as delimiter between keys and values.
C:\Users\home\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\opengsq\protocols\cod4.py:114: SyntaxWarning: "\)" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\)"? A raw string is also an option.
CoD4 uses backslash (\) as delimiter between keys and values.
C:\Users\home\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\opengsq\protocols\cod5.py:114: SyntaxWarning: "\)" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\)"? A raw string is also an option.
CoD5 uses backslash (\) as delimiter between keys and values.
<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\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\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\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\opengsq\protocols\raknet.py", line 85, in main_async
status = await raknet.get_status()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\opengsq\protocols\raknet.py", line 36, in get_status
response = await UdpClient.communicate(self, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\opengsq\protocol_socket.py", line 165, in communicate
return await protocol_instance.recv()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\home\AppData\Local\uv\cache\archive-v0\qf1PZV7gGMgn4ggLmH4Tk\Lib\site-packages\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
TimeoutError
Here's the same 3.9-3.14 tests succeeding on Ubuntu 24.04, using uv-managed Python installations:
uv python install 3.9 3.10 3.11 3.12 3.13 3.14
uv run --with opengsq==3.5.0 --python 3.9 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.10 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.11 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.12 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.13 -m opengsq.protocols.raknet
uv run --with opengsq==3.5.0 --python 3.14 -m opengsq.protocols.raknet
Full output
~$ uv python install 3.9 3.10 3.11 3.12 3.13 3.14
Installed 6 versions in 2.98s
+ cpython-3.9.24-linux-x86_64-gnu (python3.9)
+ cpython-3.10.19-linux-x86_64-gnu (python3.10)
+ cpython-3.11.14-linux-x86_64-gnu (python3.11)
+ cpython-3.12.12-linux-x86_64-gnu (python3.12)
+ cpython-3.13.9-linux-x86_64-gnu (python3.13)
+ cpython-3.14.0-linux-x86_64-gnu (python3.14)
~$ uv run --with opengsq==3.5.0 --python 3.9 -m opengsq.protocols.raknet
/home/ministatus/.local/share/uv/python/cpython-3.9.24-linux-x86_64-gnu/lib/python3.9/runpy.py:127: 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
warn(RuntimeWarning(msg))
Status(edition='MCPE', motd_line1='Advancius Network', protocol_version=859, version_name='1.21.120', num_players=169, max_players=500, server_unique_id='8643987271603006626', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)
~$ uv run --with opengsq==3.5.0 --python 3.10 -m opengsq.protocols.raknet
/home/ministatus/.local/share/uv/python/cpython-3.10.19-linux-x86_64-gnu/lib/python3.10/runpy.py:126: 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
warn(RuntimeWarning(msg))
Status(edition='MCPE', motd_line1='Advancius Network', protocol_version=859, version_name='1.21.120', num_players=169, max_players=500, server_unique_id='8643987271603006626', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)
~$ uv run --with opengsq==3.5.0 --python 3.11 -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=859, version_name='1.21.120', num_players=169, max_players=500, server_unique_id='8643987271603006626', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)
~$ uv run --with opengsq==3.5.0 --python 3.12 -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=859, version_name='1.21.120', num_players=169, max_players=500, server_unique_id='8643987271603006626', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)
~$ uv run --with opengsq==3.5.0 --python 3.13 -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=859, version_name='1.21.120', num_players=169, max_players=500, server_unique_id='8643987271603006626', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)
~$ uv run --with opengsq==3.5.0 --python 3.14 -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=859, version_name='1.21.120', num_players=169, max_players=500, server_unique_id='8643987271603006626', motd_line2='www.advancius.net', game_mode='Survival', game_mode_numeric=1, port_ipv4=19132, port_ipv6=19132)
My specific Windows version is Windows-11-10.0.26100-SP0 (py -m platform) if that helps.
This is indeed a very weird behavior. Why should the hostname not be resolved in windows.
I was able to accidentally reproduce this same bug while writing my own A2S library, and I think I've distilled it to this MRE, written for Python 3.11:
import asyncio, socket
dest_ipv4 = ("23.137.105.24", 16261)
dest_host = ("play.thegamecracks.xyz", 16261)
request = b"\xff\xff\xff\xffTSource Engine Query\x00\xff\xff\xff\xff"
local_addr = ("0.0.0.0", 0)
async def main():
await try_request(dest_ipv4, local_addr=None, remote_addr=None)
await try_request(dest_ipv4, local_addr=local_addr, remote_addr=None)
await try_request(dest_ipv4, local_addr=None, remote_addr=dest_ipv4)
await try_request(dest_ipv4, local_addr=local_addr, remote_addr=dest_ipv4)
await try_request(None, local_addr=None, remote_addr=dest_ipv4)
await try_request(None, local_addr=local_addr, remote_addr=dest_ipv4)
await try_request(dest_host, local_addr=None, remote_addr=None)
await try_request(dest_host, local_addr=local_addr, remote_addr=None)
await try_request(dest_host, local_addr=None, remote_addr=dest_host)
await try_request(dest_host, local_addr=local_addr, remote_addr=dest_host)
await try_request(None, local_addr=None, remote_addr=dest_host)
await try_request(None, local_addr=local_addr, remote_addr=dest_host)
async def try_request(addr, local_addr, remote_addr):
print(f" Sending to {addr}, {local_addr = }, {remote_addr = }")
loop = asyncio.get_running_loop()
try:
transport, protocol = await loop.create_datagram_endpoint(
MyProtocol,
local_addr=local_addr,
remote_addr=remote_addr,
family=socket.AF_INET,
)
except ValueError as e:
return print(f" {e}")
try:
async with protocol, asyncio.timeout(1):
transport.sendto(request, addr)
response = await asyncio.shield(protocol.received_fut)
print(f" {response.hex(':')}")
except TimeoutError:
print(" Timed out")
except ValueError as e:
print(f" {e}")
await asyncio.sleep(1) # avoid spamming requests
class MyProtocol(asyncio.DatagramProtocol):
def __init__(self):
loop = asyncio.get_running_loop()
self.received_fut = loop.create_future()
self.closed_fut = loop.create_future()
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
self.received_fut.set_result(data)
def connection_lost(self, exc) -> None:
self.closed_fut.set_result(None)
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc_val, tb):
self.transport.close()
await asyncio.shield(self.closed_fut)
print("With (implied) protactor event loop:")
asyncio.run(main())
print("With selector event loop:")
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())
I included the selector event loop after noticing this in the Python docs: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.create_datagram_endpoint
local_addr, if given, is a (local_host, local_port) tuple used to bind the socket locally. The local_host and local_port are looked up using getaddrinfo(). Note: On Windows, when using the proactor event loop with local_addr=None, an OSError with errno.WSAEINVAL will be raised when running it.
Anyway, here's the output of that MRE:
Output
With (implied) protactor event loop:
Sending to ('23.137.105.24', 16261), local_addr = None, remote_addr = None
Timed out
Sending to ('23.137.105.24', 16261), local_addr = ('0.0.0.0', 0), remote_addr = None
ff:ff:ff:ff:41:3e:74:af:c2
Sending to ('23.137.105.24', 16261), local_addr = None, remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:03:48:60:ef
Sending to ('23.137.105.24', 16261), local_addr = ('0.0.0.0', 0), remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:03:48:60:ef
Sending to None, local_addr = None, remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:03:48:60:ef
Sending to None, local_addr = ('0.0.0.0', 0), remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:03:48:60:ef
Sending to ('play.thegamecracks.xyz', 16261), local_addr = None, remote_addr = None
Timed out
Sending to ('play.thegamecracks.xyz', 16261), local_addr = ('0.0.0.0', 0), remote_addr = None
Timed out
Sending to ('play.thegamecracks.xyz', 16261), local_addr = None, remote_addr = ('play.thegamecracks.xyz', 16261)
Invalid address: must be None or ('23.137.105.24', 16261)
Sending to ('play.thegamecracks.xyz', 16261), local_addr = ('0.0.0.0', 0), remote_addr = ('play.thegamecracks.xyz', 16261)
can not get address information
Sending to None, local_addr = None, remote_addr = ('play.thegamecracks.xyz', 16261)
ff:ff:ff:ff:41:11:a6:88:7f
Sending to None, local_addr = ('0.0.0.0', 0), remote_addr = ('play.thegamecracks.xyz', 16261)
can not get address information
With selector event loop:
Sending to ('23.137.105.24', 16261), local_addr = None, remote_addr = None
ff:ff:ff:ff:41:11:a6:88:7f
Sending to ('23.137.105.24', 16261), local_addr = ('0.0.0.0', 0), remote_addr = None
ff:ff:ff:ff:41:11:a6:88:7f
Sending to ('23.137.105.24', 16261), local_addr = None, remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:11:a6:88:7f
Sending to ('23.137.105.24', 16261), local_addr = ('0.0.0.0', 0), remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:11:a6:88:7f
Sending to None, local_addr = None, remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:9e:b1:3b:23
Sending to None, local_addr = ('0.0.0.0', 0), remote_addr = ('23.137.105.24', 16261)
ff:ff:ff:ff:41:9e:b1:3b:23
Sending to ('play.thegamecracks.xyz', 16261), local_addr = None, remote_addr = None
ff:ff:ff:ff:41:9e:b1:3b:23
Sending to ('play.thegamecracks.xyz', 16261), local_addr = ('0.0.0.0', 0), remote_addr = None
ff:ff:ff:ff:41:9e:b1:3b:23
Sending to ('play.thegamecracks.xyz', 16261), local_addr = None, remote_addr = ('play.thegamecracks.xyz', 16261)
Invalid address: must be None or ('23.137.105.24', 16261)
Sending to ('play.thegamecracks.xyz', 16261), local_addr = ('0.0.0.0', 0), remote_addr = ('play.thegamecracks.xyz', 16261)
can not get address information
Sending to None, local_addr = None, remote_addr = ('play.thegamecracks.xyz', 16261)
ff:ff:ff:ff:41:33:c9:63:d9
Sending to None, local_addr = ('0.0.0.0', 0), remote_addr = ('play.thegamecracks.xyz', 16261)
can not get address information
More simply organized into this big matrix:
| Event Loop | Address | sendto(addr)? | local_addr? | remote_addr? | Responded? |
|---|---|---|---|---|---|
| Proactor | IPv4 | ✔️ | ❌ | ❌ | ❌ |
| Proactor | IPv4 | ✔️ | ✔️ | ❌ | ✅ |
| Proactor | IPv4 | ✔️ | ❌ | ✔️ | ✅ |
| Proactor | IPv4 | ✔️ | ✔️ | ✔️ | ✅ |
| Proactor | IPv4 | ❌ | ❌ | ✔️ | ✅ |
| Proactor | IPv4 | ❌ | ✔️ | ✔️ | ✅ |
| Proactor | Hostname | ✔️ | ❌ | ❌ | ❌ |
| Proactor | Hostname | ✔️ | ✔️ | ❌ | ❌ |
| Proactor | Hostname | ✔️ | ❌ | ✔️ | ⚠️ |
| Proactor | Hostname | ✔️ | ✔️ | ✔️ | ⚠️ |
| Proactor | Hostname | ❌ | ❌ | ✔️ | ✅ |
| Proactor | Hostname | ❌ | ✔️ | ✔️ | ⚠️ |
| Selector | IPv4 | ✔️ | ❌ | ❌ | ✅ |
| Selector | IPv4 | ✔️ | ✔️ | ❌ | ✅ |
| Selector | IPv4 | ✔️ | ❌ | ✔️ | ✅ |
| Selector | IPv4 | ✔️ | ✔️ | ✔️ | ✅ |
| Selector | IPv4 | ❌ | ❌ | ✔️ | ✅ |
| Selector | IPv4 | ❌ | ✔️ | ✔️ | ✅ |
| Selector | Hostname | ✔️ | ❌ | ❌ | ✅ |
| Selector | Hostname | ✔️ | ✔️ | ❌ | ✅ |
| Selector | Hostname | ✔️ | ❌ | ✔️ | ⚠️ |
| Selector | Hostname | ✔️ | ✔️ | ✔️ | ⚠️ |
| Selector | Hostname | ❌ | ❌ | ✔️ | ✅ |
| Selector | Hostname | ❌ | ✔️ | ✔️ | ⚠️ |
In the case of opengsq's UdpClient, it always sets sendto(addr) and local_addr, so these four rows apply:
| Event Loop | Address | sendto(addr)? | local_addr? | remote_addr? | Responded? |
|---|---|---|---|---|---|
| Proactor | IPv4 | ✔️ | ✔️ | ❌ | ✅ |
| Proactor | Hostname | ✔️ | ✔️ | ❌ | ❌ |
| Selector | IPv4 | ✔️ | ✔️ | ❌ | ✅ |
| Selector | Hostname | ✔️ | ✔️ | ❌ | ✅ |
While this test used A2S instead of RakNet, this seems to match everything I described in my first message, where opengsq timed out with "mc.advancius.net" on Windows, but worked with "142.44.218.185". As for why it fails only with the proactor event loop, I guess it has something to do with that local_addr= note? But I don't know, I'm not a network doctor >.<
It’s best practice to always resolve the hostname to an IP address before making any query with opengsq.
For example:
import socket
hostname = "play.thegamecracks.xyz"
ip = socket.gethostbyname(hostname)
print(f"Resolved {hostname} to {ip}")
# Use 'ip' instead of 'hostname' in your query call
Thanks for testing! Based on the testing results, queries using IPv4 always work perfectly and it clearly shows how inconsistent and messy the results can get when querying directly with the hostname 🫣🤣
I Agree, that it should be still best practice of giving the IP Address instead of the hostname. While I know a lot of networking stuff my knowledge about the OS specific Python querks are limited.