mirror of
https://github.com/barronwaffles/dwc_network_server_emulator.git
synced 2026-08-20 17:45:23 -05:00
Fixes to matchmaking
This commit is contained in:
committed by
Admiral H. Curtiss
parent
43076f35af
commit
359f4eb3e8
@@ -50,6 +50,7 @@ class GameSpyBackendServer(object):
|
||||
GameSpyServerDatabase.register("get_server_list", callable=lambda:self.server_list)
|
||||
GameSpyServerDatabase.register("find_servers", callable=self.find_servers)
|
||||
GameSpyServerDatabase.register("find_server_by_address", callable=self.find_server_by_address)
|
||||
GameSpyServerDatabase.register("find_server_by_local_address", callable=self.find_server_by_local_address)
|
||||
GameSpyServerDatabase.register("update_server_list", callable=self.update_server_list)
|
||||
GameSpyServerDatabase.register("delete_server", callable=self.delete_server)
|
||||
|
||||
@@ -390,6 +391,29 @@ class GameSpyBackendServer(object):
|
||||
|
||||
return None
|
||||
|
||||
def find_server_by_local_address(self, publicip, localip, localport, gameid = None):
|
||||
if gameid == None:
|
||||
# Search all servers
|
||||
for gameid in self.server_list:
|
||||
for server in self.server_list[gameid]:
|
||||
logger.log(logging.DEBUG, "publicip: %s == %s ? %d" % (server['publicip'], publicip, server['publicip'] == publicip))
|
||||
if server['publicip'] == publicip and server['localport'] == str(localport):
|
||||
for x in range(0, 10):
|
||||
s = 'localip%d' % x
|
||||
if s in server:
|
||||
if server[s] == localip:
|
||||
return server
|
||||
else:
|
||||
for server in self.server_list[gameid]:
|
||||
logger.log(logging.DEBUG, "publicip: %s == %s ? %d" % (server['publicip'], publicip, server['publicip'] == publicip))
|
||||
if server['publicip'] == publicip and server['localport'] == str(localport):
|
||||
for x in range(0, 10):
|
||||
s = 'localip%d' % x
|
||||
if s in server:
|
||||
if server[s] == localip:
|
||||
return server
|
||||
return None
|
||||
|
||||
if __name__ == '__main__':
|
||||
freeze_support()
|
||||
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
|
||||
import logging
|
||||
import socket
|
||||
import ctypes
|
||||
import struct
|
||||
import gamespy.gs_utility as gs_utils
|
||||
import other.utils as utils
|
||||
|
||||
from multiprocessing.managers import BaseManager
|
||||
|
||||
# Logger settings
|
||||
logger_output_to_console = True
|
||||
logger_output_to_file = True
|
||||
@@ -14,11 +17,25 @@ logger_name = "GameSpyNatNegServer"
|
||||
logger_filename = "gamespy_natneg_server.log"
|
||||
logger = utils.create_logger(logger_name, logger_filename, -1, logger_output_to_console, logger_output_to_file)
|
||||
|
||||
class GameSpyServerDatabase(BaseManager):
|
||||
pass
|
||||
|
||||
GameSpyServerDatabase.register("get_server_list")
|
||||
GameSpyServerDatabase.register("modify_server_list")
|
||||
GameSpyServerDatabase.register("find_servers")
|
||||
GameSpyServerDatabase.register("find_server_by_address")
|
||||
GameSpyServerDatabase.register("find_server_by_local_address")
|
||||
|
||||
class GameSpyNatNegServer(object):
|
||||
def __init__(self):
|
||||
self.session_list = {}
|
||||
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
||||
|
||||
manager_address = ("127.0.0.1", 27500)
|
||||
manager_password = ""
|
||||
self.server_manager = GameSpyServerDatabase(address = manager_address, authkey= manager_password)
|
||||
self.server_manager.connect()
|
||||
|
||||
def start(self):
|
||||
# Start natneg server
|
||||
address = ('0.0.0.0', 27901) # accessible to outside connections (use this if you don't know what you're doing)
|
||||
@@ -54,46 +71,72 @@ class GameSpyNatNegServer(object):
|
||||
gameid = utils.get_string(recv_data, 0x16)
|
||||
client_id = "%02x" % ord(recv_data[13])
|
||||
|
||||
localip_raw = recv_data[15:19]
|
||||
localip = '.'.join(["%d" % ord(x) for x in localip_raw])
|
||||
localport_raw = recv_data[19:21]
|
||||
localport = utils.get_short_be(localport_raw, 0)
|
||||
localaddr = (localip, localport)
|
||||
|
||||
if gameid not in self.session_list:
|
||||
self.session_list[gameid] = {}
|
||||
if session_id not in self.session_list[gameid]:
|
||||
self.session_list[gameid][session_id] = {}
|
||||
if client_id not in self.session_list[gameid][session_id]:
|
||||
self.session_list[gameid][session_id][client_id] = { 'connected': False, 'addr': '' }
|
||||
self.session_list[gameid][session_id][client_id] = { 'connected': False, 'addr': '', 'localaddr': None, 'serveraddr': None, 'gameid': None }
|
||||
|
||||
self.session_list[gameid][session_id][client_id]['gameid'] = utils.get_string(recv_data[21:], 0)
|
||||
self.session_list[gameid][session_id][client_id]['addr'] = addr
|
||||
self.session_list[gameid][session_id][client_id]['localaddr'] = localaddr
|
||||
clients = len(self.session_list[gameid][session_id])
|
||||
|
||||
for client in self.session_list[gameid][session_id]:
|
||||
if self.session_list[gameid][session_id][client]['connected'] == False:
|
||||
if self.session_list[gameid][session_id][client]['connected'] == False and self.session_list[gameid][session_id][client]['localaddr'][1] != 0:
|
||||
if client == client_id:
|
||||
continue
|
||||
|
||||
if self.session_list[gameid][session_id][client]['serveraddr'] == None:
|
||||
serveraddr = self.get_server_info(gameid, session_id, client)
|
||||
self.session_list[gameid][session_id][client]['serveraddr'] = serveraddr
|
||||
logger.log(logging.DEBUG, "Found server from local ip/port: %s" % serveraddr)
|
||||
|
||||
publicport = 0
|
||||
if self.session_list[gameid][session_id][client]['serveraddr'] != None:
|
||||
publicport = int(self.session_list[gameid][session_id][client]['serveraddr']['publicport'])
|
||||
|
||||
# Send to requesting client
|
||||
output = bytearray(recv_data[0:12])
|
||||
output += bytearray([int(x) for x in self.session_list[gameid][session_id][client]['addr'][0].split('.')])
|
||||
output += utils.get_bytes_from_short_be(self.session_list[gameid][session_id][client]['addr'][1])
|
||||
output += utils.get_bytes_from_short_be(publicport)
|
||||
|
||||
output += bytearray([0x42, 0x00]) # Unknown, always seems to be \x42\x00
|
||||
output[7] = 0x05
|
||||
s.sendto(output, (self.session_list[gameid][session_id][client_id]['addr']))
|
||||
#s.sendto(output, (self.session_list[gameid][session_id][client_id]['addr']))
|
||||
s.sendto(output, (self.session_list[gameid][session_id][client_id]['addr'][0], self.session_list[gameid][session_id][client_id]['addr'][1]))
|
||||
|
||||
logger.log(logging.DEBUG, "Sent connection request to %s:%d..." % (self.session_list[gameid][session_id][client_id]['addr'][0], self.session_list[gameid][session_id][client_id]['addr'][1]))
|
||||
logger.log(logging.DEBUG, utils.pretty_print_hex(output))
|
||||
logger.log(logging.DEBUG, "")
|
||||
|
||||
# Send to other client
|
||||
if self.session_list[gameid][session_id][client_id]['serveraddr'] == None:
|
||||
serveraddr = self.get_server_info(gameid, session_id, client_id)
|
||||
self.session_list[gameid][session_id][client_id]['serveraddr'] = serveraddr
|
||||
logger.log(logging.DEBUG, "Found server 2 from local ip/port: %s" % serveraddr)
|
||||
|
||||
publicport = 0
|
||||
if self.session_list[gameid][session_id][client_id]['serveraddr'] != None:
|
||||
publicport = int(self.session_list[gameid][session_id][client_id]['serveraddr']['publicport'])
|
||||
|
||||
output = bytearray(recv_data[0:12])
|
||||
output += bytearray([int(x) for x in self.session_list[gameid][session_id][client_id]['addr'][0].split('.')])
|
||||
output += utils.get_bytes_from_short_be(self.session_list[gameid][session_id][client_id]['addr'][1])
|
||||
output += utils.get_bytes_from_short_be(publicport)
|
||||
|
||||
output += bytearray([0x42, 0x00]) # Unknown, always seems to be \x42\x00
|
||||
output[7] = 0x05
|
||||
s.sendto(output, (self.session_list[gameid][session_id][client]['addr']))
|
||||
#s.sendto(output, (self.session_list[gameid][session_id][client]['addr']))
|
||||
s.sendto(output, (self.session_list[gameid][session_id][client]['addr'][0], self.session_list[gameid][session_id][client]['addr'][1]))
|
||||
|
||||
logger.log(logging.DEBUG, "Sent connection request to %s:%d..." % (self.session_list[gameid][session_id][client]['addr'][0], self.session_list[gameid][session_id][client]['addr'][1]))
|
||||
logger.log(logging.DEBUG, utils.pretty_print_hex(output))
|
||||
logger.log(logging.DEBUG, "")
|
||||
|
||||
elif recv_data[7] == '\x06': # Was able to connect
|
||||
client_id = "%02x" % ord(recv_data[13])
|
||||
@@ -106,7 +149,7 @@ class GameSpyNatNegServer(object):
|
||||
if client_id not in self.session_list[gameid][session_id]:
|
||||
pass
|
||||
|
||||
#self.session_list[gameid][session_id][client_id]['connected'] = True
|
||||
self.session_list[gameid][session_id][client_id]['connected'] = True
|
||||
|
||||
elif recv_data[7] == '\x0a': # Address check. Note: UNTESTED!
|
||||
client_id = "%02x" % ord(recv_data[13])
|
||||
@@ -135,6 +178,31 @@ class GameSpyNatNegServer(object):
|
||||
else: # Was able to connect
|
||||
logger.log(logging.DEBUG, "Received unknown command %02x from %s:%s..." % (ord(recv_data[7]), addr[0], addr[1]))
|
||||
|
||||
def get_server_info(self, gameid, session_id, client_id):
|
||||
console = 0
|
||||
ipstr = self.session_list[gameid][session_id][client_id]['addr'][0]
|
||||
|
||||
if console != 0:
|
||||
ip = str(ctypes.c_int32(utils.get_int_be(bytearray([int(x) for x in ipstr.split('.')]), 0)).value) # Wii
|
||||
console = 0
|
||||
else:
|
||||
ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in ipstr.split('.')]), 0)).value) # DS
|
||||
console = 1
|
||||
|
||||
serveraddr = self.server_manager.find_server_by_local_address(ip, self.session_list[gameid][session_id][client_id]['localaddr'][0], self.session_list[gameid][session_id][client_id]['localaddr'][1], self.session_list[gameid][session_id][client_id]['gameid'])._getvalue()
|
||||
|
||||
if serveraddr == None:
|
||||
if console != 0:
|
||||
ip = str(ctypes.c_int32(utils.get_int_be(bytearray([int(x) for x in ipstr.split('.')]), 0)).value) # Wii
|
||||
console = 0
|
||||
else:
|
||||
ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in ipstr.split('.')]), 0)).value) # DS
|
||||
console = 1
|
||||
|
||||
serveraddr = self.server_manager.find_server_by_local_address(ip, self.session_list[gameid][session_id][client_id]['localaddr'][0], self.session_list[gameid][session_id][client_id]['localaddr'][1], self.session_list[gameid][session_id][client_id]['gameid'])._getvalue()
|
||||
|
||||
return serveraddr
|
||||
|
||||
if __name__ == "__main__":
|
||||
natneg_server = GameSpyNatNegServer()
|
||||
natneg_server.start()
|
||||
@@ -364,6 +364,7 @@ class Session(LineReceiver):
|
||||
# #self.server_cache.pop((publicip + str(self.forward_client[1])))
|
||||
|
||||
server = self.server_manager.find_server_by_address(ip, self.forward_client[1])._getvalue()
|
||||
self.log(logging.DEBUG, "find_server_in_cache is returning: %s %s" % (server, ip))
|
||||
|
||||
return server, ip
|
||||
|
||||
@@ -371,6 +372,9 @@ class Session(LineReceiver):
|
||||
# Find session id of server
|
||||
# Iterate through the list of servers sent to the client and match by IP and port.
|
||||
# Is there a better way to determine this information?
|
||||
if self.forward_client == None or len(self.forward_client) != 2:
|
||||
return
|
||||
|
||||
server, ip = self.find_server_in_cache(self.forward_client[0], self.forward_client[1], self.console)
|
||||
|
||||
if server == None:
|
||||
@@ -389,7 +393,7 @@ class Session(LineReceiver):
|
||||
self.log(logging.DEBUG, "%s %s" % (ip, server['publicip']))
|
||||
if server['publicip'] == ip and server['publicport'] == str(self.forward_client[1]):
|
||||
# Send command to server to get it to connect to natneg
|
||||
natneg_session = int(utils.generate_random_hex_str(8), 16) # Quick and lazy way to get a random 32bit integer. Replace with something else late.r
|
||||
natneg_session = int(utils.generate_random_hex_str(8), 16) # Quick and lazy way to get a random 32bit integer. Replace with something else later
|
||||
|
||||
output = bytearray([0xfe, 0xfd, 0x06])
|
||||
output += utils.get_bytes_from_int(server['__session__'])
|
||||
|
||||
Reference in New Issue
Block a user