Skip to content

Commit

Permalink
Update scum.py
Browse files Browse the repository at this point in the history
Resolve the issue of non-functioning master_servers on the Scum server
  • Loading branch information
BattlefieldDuck committed Dec 1, 2023
1 parent bd7a8ee commit 699baf6
Showing 1 changed file with 52 additions and 39 deletions.
91 changes: 52 additions & 39 deletions opengsq/protocols/scum.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class Scum(ProtocolBase):
"""Scum Protocol"""
full_name = 'Scum Protocol'

_master_servers = [
("176.57.138.2", 1040),
("172.107.16.215", 1040),
("206.189.248.133", 1040)
]

async def get_status(self, master_servers: list = None) -> dict:
"""
Retrieves information about the server
Expand All @@ -28,48 +34,55 @@ async def get_status(self, master_servers: list = None) -> dict:
raise ServerNotFoundException()

@staticmethod
async def query_master_servers(host='172.107.16.215', port=1040) -> list:
async def query_master_servers() -> list:
"""
Query SCUM Master-Server list
"""
with SocketAsync(SocketKind.SOCK_STREAM) as sock:
sock.settimeout(5)
await sock.connect((host, port))
sock.send(b'\x04\x03\x00\x00')

total = -1
response = b''
servers = []

while total == -1 or len(servers) < total:
response += await sock.recv()
br = BinaryReader(response)

# first packet return the total number of servers
if total == -1:
total = br.read_short()

# server bytes length always 127
while br.length() >= 127:
server = {}
server['ip'] = '.'.join(map(str, reversed([br.read_byte(), br.read_byte(), br.read_byte(), br.read_byte()])))
server['port'] = br.read_short()
server['name'] = str(br.read_bytes(100).rstrip(b'\x00'), encoding='utf-8', errors='ignore')
br.read_byte() # skip
server['numplayers'] = br.read_byte()
server['maxplayers'] = br.read_byte()
server['time'] = br.read_byte()
br.read_byte() # skip
server['password'] = ((br.read_byte() >> 1) & 1) == 1
br.read_bytes(7) # skip
v = list(reversed([hex(br.read_byte())[2:].rjust(2, '0') for _ in range(8)]))
server['version'] = f'{int(v[0], 16)}.{int(v[1], 16)}.{int(v[2] + v[3], 16)}.{int(v[4] + v[5] + v[6] + v[7], 16)}'
servers.append(server)

# if the length is less than 127, save the unused bytes for next loop
response = br.read()

return servers

for host, port in Scum._master_servers:
try:
with SocketAsync(SocketKind.SOCK_STREAM) as sock:
sock.settimeout(5)
await sock.connect((host, port))
sock.send(b'\x04\x03\x00\x00')

total = -1
response = b''
servers = []

while total == -1 or len(servers) < total:
response += await sock.recv()
br = BinaryReader(response)

# first packet return the total number of servers
if total == -1:
total = br.read_short()

# server bytes length always 127
while br.length() >= 127:
server = {}
server['ip'] = '.'.join(map(str, reversed([br.read_byte(), br.read_byte(), br.read_byte(), br.read_byte()])))
server['port'] = br.read_short()
server['name'] = str(br.read_bytes(100).rstrip(b'\x00'), encoding='utf-8', errors='ignore')
br.read_byte() # skip
server['numplayers'] = br.read_byte()
server['maxplayers'] = br.read_byte()
server['time'] = br.read_byte()
br.read_byte() # skip
server['password'] = ((br.read_byte() >> 1) & 1) == 1
br.read_bytes(7) # skip
v = list(reversed([hex(br.read_byte())[2:].rjust(2, '0') for _ in range(8)]))
server['version'] = f'{int(v[0], 16)}.{int(v[1], 16)}.{int(v[2] + v[3], 16)}.{int(v[4] + v[5] + v[6] + v[7], 16)}'
servers.append(server)

# if the length is less than 127, save the unused bytes for next loop
response = br.read()

return servers
except TimeoutError:
pass

raise Exception('Failed to connect to any of the master servers')


if __name__ == '__main__':
Expand Down

0 comments on commit 699baf6

Please sign in to comment.