Skip to content

Commit 1a38170

Browse files
committed
Add retry counter to work around implementations repeatedly sending challenge responses
1 parent 2fbd78a commit 1a38170

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

a2s/defaults.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
DEFAULT_TIMEOUT = 3.0
22
DEFAULT_ENCODING = "utf-8"
3+
DEFAULT_RETRIES = 5

a2s/players.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
from typing import List
33

44
from a2s.exceptions import BrokenMessageError
5-
from a2s.defaults import DEFAULT_TIMEOUT, DEFAULT_ENCODING
5+
from a2s.defaults import DEFAULT_TIMEOUT, DEFAULT_ENCODING, \
6+
DEFAULT_RETRIES
67
from a2s.a2sstream import request
78
from a2s.byteio import ByteReader
89
from a2s.datacls import DataclsMeta
@@ -29,19 +30,20 @@ def players(address, timeout=DEFAULT_TIMEOUT,
2930
encoding=DEFAULT_ENCODING):
3031
return players_impl(address, timeout, encoding)
3132

32-
def players_impl(address, timeout, encoding, challenge=0):
33+
def players_impl(address, timeout, encoding, challenge=0, retries=0):
3334
resp_data = request(
3435
address, b"\x55" + challenge.to_bytes(4, "little"), timeout)
3536
reader = ByteReader(
3637
io.BytesIO(resp_data), endian="<", encoding=encoding)
3738

3839
response_type = reader.read_uint8()
3940
if response_type == A2S_CHALLENGE_RESPONSE:
40-
if challenge != 0:
41+
if retries >= DEFAULT_RETRIES:
4142
raise BrokenMessageError(
4243
"Server keeps sending challenge responses")
43-
challenge = reader.read_int32()
44-
return players_impl(address, timeout, encoding, challenge)
44+
challenge = reader.read_uint32()
45+
return players_impl(
46+
address, timeout, encoding, challenge, retries + 1)
4547

4648
if response_type != A2S_PLAYER_RESPONSE:
4749
raise BrokenMessageError(

a2s/rules.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import io
22

33
from a2s.exceptions import BrokenMessageError
4-
from a2s.defaults import DEFAULT_TIMEOUT, DEFAULT_ENCODING
4+
from a2s.defaults import DEFAULT_TIMEOUT, DEFAULT_ENCODING, \
5+
DEFAULT_RETRIES
56
from a2s.a2sstream import request
67
from a2s.byteio import ByteReader
78

@@ -13,7 +14,7 @@
1314
def rules(address, timeout=DEFAULT_TIMEOUT, encoding=DEFAULT_ENCODING):
1415
return rules_impl(address, timeout, encoding)
1516

16-
def rules_impl(address, timeout, encoding, challenge=0):
17+
def rules_impl(address, timeout, encoding, challenge=0, retries=0):
1718
resp_data = request(
1819
address, b"\x56" + challenge.to_bytes(4, "little"), timeout)
1920
reader = ByteReader(
@@ -31,11 +32,12 @@ def rules_impl(address, timeout, encoding, challenge=0):
3132

3233
response_type = reader.read_uint8()
3334
if response_type == A2S_CHALLENGE_RESPONSE:
34-
if challenge != 0:
35+
if retries >= DEFAULT_RETRIES:
3536
raise BrokenMessageError(
3637
"Server keeps sending challenge responses")
37-
challenge = reader.read_int32()
38-
return rules_impl(address, timeout, encoding, challenge)
38+
challenge = reader.read_uint32()
39+
return rules_impl(
40+
address, timeout, encoding, challenge, retries + 1)
3941

4042
if response_type != A2S_RULES_RESPONSE:
4143
raise BrokenMessageError(

0 commit comments

Comments
 (0)