From 9e2c77ddff5fb6a80118f63b51bf4dd9ffa24b00 Mon Sep 17 00:00:00 2001 From: polaris Date: Tue, 29 Jul 2014 12:48:36 -0400 Subject: [PATCH] More bugfixes. Server browser server should work --- gamespy_server_browser_server.py | 21 +++++++++------------ other/utils.py | 22 +++++++++++++++++++--- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/gamespy_server_browser_server.py b/gamespy_server_browser_server.py index 1e693d5..ac32080 100644 --- a/gamespy_server_browser_server.py +++ b/gamespy_server_browser_server.py @@ -128,12 +128,12 @@ class Session(LineReceiver): self.buffer += data - while True: + while len(self.buffer) > 0: packet_len = utils.get_short(self.buffer, 0, True) packet = None - if len(data) >= packet_len: - packet = data[:packet_len] + if len(self.buffer) >= packet_len: + packet = self.buffer[:packet_len] self.buffer = self.buffer[packet_len:] if packet == None: @@ -158,7 +158,7 @@ class Session(LineReceiver): game_name = utils.get_string(packet, idx) idx += len(game_name) + 1 - challenge = packet[idx:idx+8] + challenge = ''.join(packet[idx:idx+8]) idx += 8 filter = utils.get_string(packet, idx) @@ -225,7 +225,7 @@ class Session(LineReceiver): if packet_len == len(packet): # Contains entire packet, send immediately. - self.forward_data_to_client(packet[3:], dest) + self.forward_data_to_client(packet[9:], dest) else: self.log(logging.ERROR, "ERROR: Could not find entire packet.") @@ -235,7 +235,6 @@ class Session(LineReceiver): else: self.log(logging.DEBUG, "Received unknown command (%02x) from %s:%s..." % (ord(packet[2]), self.address.host, self.address.port)) self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(packet))) - self.log(logging.DEBUG, utils.pretty_print_hex(packet)) except: self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc()) @@ -284,7 +283,7 @@ class Session(LineReceiver): if "natneg" in server_info: flags |= ServerListFlags.CONNECT_NEGOTIATE_FLAG - ip = utils.get_bytes_from_int(int(server_info['publicip']), self.console) + ip = utils.get_bytes_from_int_signed(int(server_info['publicip']), self.console) flags_buffer += ip flags |= ServerListFlags.NONSTANDARD_PORT_FLAG @@ -366,13 +365,11 @@ class Session(LineReceiver): # self.server_cache[str(server['publicip']) + str(server['publicport'])] = server data += '\0' - data += utils.get_bytes_from_int(-1) + data += utils.get_bytes_from_int(0xffffffff) send_encrypted_data(self, challenge, data) def find_server_in_cache(self, addr, port, console): - ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in addr.split('.')]), 0)).value, console) - self.log(logging.DEBUG, "IP: %s, Port: %d, Console: %d" % (ip, port, console)) - + ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in addr.split('.')]), 0, console)).value) server = self.server_manager.find_server_by_address(ip, port)._getvalue() self.log(logging.DEBUG, "find_server_in_cache is returning: %s %s" % (server, ip)) @@ -431,7 +428,7 @@ class Session(LineReceiver): elif len(data) == 10 and bytearray(data)[0:6] == bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]): - natneg_session = utils.get_int(data,6) + natneg_session = utils.get_int_signed(data,6) self.log(logging.DEBUG, "Adding %d to natneg server list: %s" % (natneg_session, server)) self.server_manager.add_natneg_server(natneg_session, server) # Store info in backend so we can get it later in natneg diff --git a/other/utils.py b/other/utils.py index 0baccc0..3778be7 100644 --- a/other/utils.py +++ b/other/utils.py @@ -91,34 +91,50 @@ def base32_decode(s, reverse=False): # Number routines def get_num_from_bytes(data, idx, fmt, bigEndian=False): - return struct.unpack_from("<>"[bigEndian] + fmt, str(data), idx)[0] + return struct.unpack_from("<>"[bigEndian] + fmt, buffer(bytearray(data)), idx)[0] # Instead of passing slices, pass the buffer and index so we can calculate # the length automatically. +def get_short_signed(data, idx, be=False): + return get_num_from_bytes(data, idx, 'h', be) + + def get_short(data, idx, be=False): return get_num_from_bytes(data, idx, 'H', be) +def get_int_signed(data, idx, be=False): + return get_num_from_bytes(data, idx, 'i', be) + + def get_int(data, idx, be=False): return get_num_from_bytes(data, idx, 'I', be) def get_string(data, idx): data = data[idx:] - end = data.index('\0') - return str(data[:end]) + end = data.index('\x00') + return str(''.join(data[:end])) def get_bytes_from_num(num, fmt, bigEndian=False): return struct.pack("<>"[bigEndian] + fmt, num) +def get_bytes_from_short_signed(num, be=False): + return get_bytes_from_num(num, 'h', be) + + def get_bytes_from_short(num, be=False): return get_bytes_from_num(num, 'H', be) +def get_bytes_from_int_signed(num, be=False): + return get_bytes_from_num(num, 'i', be) + + def get_bytes_from_int(num, be=False): return get_bytes_from_num(num, 'I', be)