diff --git a/opengsq/protocols/scum.py b/opengsq/protocols/scum.py index d98e564..722e03f 100644 --- a/opengsq/protocols/scum.py +++ b/opengsq/protocols/scum.py @@ -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 @@ -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__':