mirror of
https://github.com/barronwaffles/dwc_network_server_emulator.git
synced 2026-08-27 13:24:03 -05:00
Console endianness, natneg report command fix
- Added endianness based on console. This allows the Wii to connect. - Fixed a bug where the report command was returning the wrong buffer in natneg.
This commit is contained in:
@@ -55,6 +55,9 @@ class GameSpyBackendServer(object):
|
|||||||
address = ("127.0.0.1", 27500)
|
address = ("127.0.0.1", 27500)
|
||||||
password = ""
|
password = ""
|
||||||
|
|
||||||
|
#self.server_list['mariokartwii'] = []
|
||||||
|
#self.server_list['mariokartwii'].append({'__session__': 1113766873, 'eb': '5000', 'ev': '5000', 'publicport': '61784', 'localip1': '190.190.190.190', 'gamename': 'mariokartwii', 'maxplayers': '11', 'dwc_mtype': '0', 'publicip': '167772642', 'dwc_mver': '90', 'rk': 'vs_123', 'natneg': '1', 'dwc_groupid': '0', 'localip0': '10.0.1.226', 'dwc_pid': '1', 'localport': '61784', 'statechanged': '1', 'dwc_suspend': '1', 'dwc_eval': '1', 'numplayers': '0', 'dwc_hoststate': '0', 'p': '0'})
|
||||||
|
|
||||||
logger.log(logging.INFO, "Started server on %s:%d..." % (address[0], address[1]))
|
logger.log(logging.INFO, "Started server on %s:%d..." % (address[0], address[1]))
|
||||||
|
|
||||||
manager = GameSpyServerDatabase(address = address, authkey = password)
|
manager = GameSpyServerDatabase(address = address, authkey = password)
|
||||||
@@ -293,13 +296,13 @@ class GameSpyBackendServer(object):
|
|||||||
values.append({ 'value': int(lval & rval), 'type': TokenType.NUMBER})
|
values.append({ 'value': int(lval & rval), 'type': TokenType.NUMBER})
|
||||||
|
|
||||||
if match == True:
|
if match == True:
|
||||||
#print "Matched: %s %s %s" % (l['value'], op, r['value'])
|
print "Matched: %s %s %s" % (l['value'], op, r['value'])
|
||||||
matched_filters += 1
|
matched_filters += 1
|
||||||
elif op != "&": # & doesn't need to be matched, so don't display a message for it
|
elif op != "&": # & doesn't need to be matched, so don't display a message for it
|
||||||
#print "Not matched: %s %s %s" % (l['value'], op, r['value'])
|
print "Not matched: %s %s %s" % (l['value'], op, r['value'])
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#print "Matched %d/%d" % (matched_filters, filter_count)
|
print "Matched %d/%d" % (matched_filters, filter_count)
|
||||||
|
|
||||||
# Add the server if everything was matched
|
# Add the server if everything was matched
|
||||||
if matched_filters == filter_count:
|
if matched_filters == filter_count:
|
||||||
@@ -344,7 +347,7 @@ class GameSpyBackendServer(object):
|
|||||||
|
|
||||||
return servers
|
return servers
|
||||||
|
|
||||||
def update_server_list(self, gameid, session, value):
|
def update_server_list(self, gameid, session, value, console):
|
||||||
# Make sure the user isn't hosting multiple servers or there isn't some left over server information that
|
# Make sure the user isn't hosting multiple servers or there isn't some left over server information that
|
||||||
# never got handled properly (game crashed, etc).
|
# never got handled properly (game crashed, etc).
|
||||||
self.delete_server(gameid, session)
|
self.delete_server(gameid, session)
|
||||||
@@ -355,6 +358,7 @@ class GameSpyBackendServer(object):
|
|||||||
|
|
||||||
# Add new server
|
# Add new server
|
||||||
value['__session__'] = session
|
value['__session__'] = session
|
||||||
|
value['__console__'] = console
|
||||||
|
|
||||||
logger.log(logging.DEBUG, "Added %s to the server list for %s" % (value, gameid))
|
logger.log(logging.DEBUG, "Added %s to the server list for %s" % (value, gameid))
|
||||||
self.server_list[gameid].append(value)
|
self.server_list[gameid].append(value)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class GameSpyNatNegServer(object):
|
|||||||
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
# Start QR server
|
# Start natneg server
|
||||||
address = ('0.0.0.0', 27901) # accessible to outside connections (use this if you don't know what you're doing)
|
address = ('0.0.0.0', 27901) # accessible to outside connections (use this if you don't know what you're doing)
|
||||||
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
@@ -32,6 +32,7 @@ class GameSpyNatNegServer(object):
|
|||||||
recv_data, addr = s.recvfrom(2048)
|
recv_data, addr = s.recvfrom(2048)
|
||||||
|
|
||||||
logger.log(logging.DEBUG, "Connection from %s:%d..." % (addr[0], addr[1]))
|
logger.log(logging.DEBUG, "Connection from %s:%d..." % (addr[0], addr[1]))
|
||||||
|
logger.log(logging.DEBUG, utils.pretty_print_hex(recv_data))
|
||||||
|
|
||||||
# Make sure it's a legal packet
|
# Make sure it's a legal packet
|
||||||
if recv_data[0:6] != bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]):
|
if recv_data[0:6] != bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]):
|
||||||
@@ -44,6 +45,12 @@ class GameSpyNatNegServer(object):
|
|||||||
if recv_data[7] == '\x00':
|
if recv_data[7] == '\x00':
|
||||||
logger.log(logging.DEBUG, "Received initialization from %s:%s..." % (addr[0], addr[1]))
|
logger.log(logging.DEBUG, "Received initialization from %s:%s..." % (addr[0], addr[1]))
|
||||||
|
|
||||||
|
output = bytearray(recv_data[0:14])
|
||||||
|
output += bytearray([0xff, 0xff, 0x6d, 0x16, 0xb5, 0x7d, 0xea ]) # Checked with Tetris DS, Mario Kart DS, and Metroid Prime Hunters, and this seems to be the standard response to 0x00
|
||||||
|
output[7] = 0x01 # Initialization response
|
||||||
|
s.sendto(output, addr)
|
||||||
|
|
||||||
|
# Try to connect to the server
|
||||||
gameid = utils.get_string(recv_data, 0x16)
|
gameid = utils.get_string(recv_data, 0x16)
|
||||||
client_id = "%02x" % ord(recv_data[13])
|
client_id = "%02x" % ord(recv_data[13])
|
||||||
|
|
||||||
@@ -56,8 +63,6 @@ class GameSpyNatNegServer(object):
|
|||||||
|
|
||||||
self.session_list[gameid][session_id][client_id]['addr'] = addr
|
self.session_list[gameid][session_id][client_id]['addr'] = addr
|
||||||
clients = len(self.session_list[gameid][session_id])
|
clients = len(self.session_list[gameid][session_id])
|
||||||
#if client_id in session_list[gameid][session_id]:
|
|
||||||
# clients -= 1
|
|
||||||
|
|
||||||
if clients > 0:
|
if clients > 0:
|
||||||
# Someone else is waiting to connect, send message
|
# Someone else is waiting to connect, send message
|
||||||
@@ -81,11 +86,6 @@ class GameSpyNatNegServer(object):
|
|||||||
logger.log(logging.DEBUG, "")
|
logger.log(logging.DEBUG, "")
|
||||||
#session_list[gameid][session_id][client_id]['connected'] = True
|
#session_list[gameid][session_id][client_id]['connected'] = True
|
||||||
|
|
||||||
output = bytearray(recv_data[0:14])
|
|
||||||
output += bytearray([0xff, 0xff, 0x6d, 0x16, 0xb5, 0x7d, 0xea ]) # Checked with Tetris DS, Mario Kart DS, and Metroid Prime Hunters, and this seems to be the standard response to 0x00
|
|
||||||
output[7] = 0x01 # Initialization response
|
|
||||||
s.sendto(output, addr)
|
|
||||||
|
|
||||||
elif recv_data[7] == '\x06': # Was able to connect
|
elif recv_data[7] == '\x06': # Was able to connect
|
||||||
client_id = "%02x" % ord(recv_data[13])
|
client_id = "%02x" % ord(recv_data[13])
|
||||||
logger.log(logging.DEBUG, "Received connected command from %s:%s..." % (addr[0], addr[1]))
|
logger.log(logging.DEBUG, "Received connected command from %s:%s..." % (addr[0], addr[1]))
|
||||||
@@ -97,15 +97,15 @@ class GameSpyNatNegServer(object):
|
|||||||
if client_id not in self.session_list[gameid][session_id]:
|
if client_id not in self.session_list[gameid][session_id]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#session_list[gameid][session_id][client_id]['connected'] = True
|
#self.session_list[gameid][session_id][client_id]['connected'] = True
|
||||||
|
|
||||||
elif recv_data[7] == '\x0d':
|
elif recv_data[7] == '\x0d':
|
||||||
client_id = "%02x" % ord(recv_data[13])
|
client_id = "%02x" % ord(recv_data[13])
|
||||||
logger.log(logging.DEBUG, "Received report command from %s:%s..." % (addr[0], addr[1]))
|
logger.log(logging.DEBUG, "Received report command from %s:%s..." % (addr[0], addr[1]))
|
||||||
logger.log(logging.DEBUG, utils.pretty_print_hex(recv_data))
|
logger.log(logging.DEBUG, utils.pretty_print_hex(recv_data))
|
||||||
|
|
||||||
output[7] = 0x0e # Report response
|
recv_data[7] = 0x0e # Report response
|
||||||
s.sendto(output, addr)
|
s.sendto(recv_data, addr)
|
||||||
|
|
||||||
else: # Was able to connect
|
else: # Was able to connect
|
||||||
logger.log(logging.DEBUG, "Received unknown command %02x from %s:%s..." % (ord(recv_data[7]), addr[0], addr[1]))
|
logger.log(logging.DEBUG, "Received unknown command %02x from %s:%s..." % (ord(recv_data[7]), addr[0], addr[1]))
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import logging
|
|||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import gamespy.gs_utility as gs_utils
|
import gamespy.gs_utility as gs_utils
|
||||||
|
import gamespy.gs_database as gs_database
|
||||||
import other.utils as utils
|
import other.utils as utils
|
||||||
|
|
||||||
from multiprocessing.managers import BaseManager
|
from multiprocessing.managers import BaseManager
|
||||||
@@ -27,6 +28,8 @@ class GameSpyQRServer(object):
|
|||||||
self.secretkey = "" # Parse gslist.cfg later
|
self.secretkey = "" # Parse gslist.cfg later
|
||||||
self.sent_challenge = False
|
self.sent_challenge = False
|
||||||
self.address = address
|
self.address = address
|
||||||
|
self.console = 0
|
||||||
|
self.playerid= 0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sessions = {}
|
self.sessions = {}
|
||||||
@@ -36,6 +39,8 @@ class GameSpyQRServer(object):
|
|||||||
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
||||||
#self.log(logging.DEBUG, address, "Generated list of secret game keys...")
|
#self.log(logging.DEBUG, address, "Generated list of secret game keys...")
|
||||||
|
|
||||||
|
self.db = gs_database.GamespyDatabase()
|
||||||
|
|
||||||
GameSpyServerDatabase.register("update_server_list")
|
GameSpyServerDatabase.register("update_server_list")
|
||||||
GameSpyServerDatabase.register("delete_server")
|
GameSpyServerDatabase.register("delete_server")
|
||||||
|
|
||||||
@@ -193,6 +198,17 @@ class GameSpyQRServer(object):
|
|||||||
self.sessions[session_id].secretkey = self.secret_key_list[k['gamename']]
|
self.sessions[session_id].secretkey = self.secret_key_list[k['gamename']]
|
||||||
#print "Got secret key %s for %s" % (self.sessions[session_id].secretkey, k['gamename'])
|
#print "Got secret key %s for %s" % (self.sessions[session_id].secretkey, k['gamename'])
|
||||||
|
|
||||||
|
if self.sessions[session_id].playerid == 0 and "dwc_pid" in k:
|
||||||
|
# Get the player's id and then query the profile to figure out what console they are on.
|
||||||
|
# The endianness of some server data depends on the endianness of the console, so we must be able
|
||||||
|
# to account for that.
|
||||||
|
self.sessions[session_id].playerid = int(k['dwc_pid'])
|
||||||
|
profile = self.db.get_profile_from_profileid(self.sessions[session_id].playerid)
|
||||||
|
|
||||||
|
if "console" in profile:
|
||||||
|
self.sessions[session_id].console = profile['console']
|
||||||
|
|
||||||
|
|
||||||
if self.sessions[session_id].sent_challenge == False:
|
if self.sessions[session_id].sent_challenge == False:
|
||||||
addr_hex = ''.join(["%02X" % int(x) for x in address[0].split('.')])
|
addr_hex = ''.join(["%02X" % int(x) for x in address[0].split('.')])
|
||||||
port_hex = "%04X" % int(address[1])
|
port_hex = "%04X" % int(address[1])
|
||||||
@@ -218,7 +234,7 @@ class GameSpyQRServer(object):
|
|||||||
# dwc_mtype = 3 is used when looking for a friends only game (possibly other uses too).
|
# dwc_mtype = 3 is used when looking for a friends only game (possibly other uses too).
|
||||||
|
|
||||||
# Some memory could be saved by clearing out any unwanted fields from k before sending.
|
# Some memory could be saved by clearing out any unwanted fields from k before sending.
|
||||||
self.server_manager.update_server_list(k['gamename'] , session_id, k)
|
self.server_manager.update_server_list(k['gamename'] , session_id, k, self.sessions[session_id].console)
|
||||||
elif k['statechanged'] == "2": # Close server
|
elif k['statechanged'] == "2": # Close server
|
||||||
self.server_manager.delete_server(k['gamename'] , session_id)
|
self.server_manager.delete_server(k['gamename'] , session_id)
|
||||||
#self.sessions.pop(session_id)
|
#self.sessions.pop(session_id)
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class Session(LineReceiver):
|
|||||||
self.forward_to_client = False
|
self.forward_to_client = False
|
||||||
self.forward_client = ()
|
self.forward_client = ()
|
||||||
self.secret_key_list = secret_key_list # Don't waste time parsing every session, so just accept it from the parent
|
self.secret_key_list = secret_key_list # Don't waste time parsing every session, so just accept it from the parent
|
||||||
|
self.console = 0
|
||||||
|
|
||||||
manager_address = ("127.0.0.1", 27500)
|
manager_address = ("127.0.0.1", 27500)
|
||||||
manager_password = ""
|
manager_password = ""
|
||||||
@@ -101,18 +102,22 @@ class Session(LineReceiver):
|
|||||||
# Find session id of server
|
# Find session id of server
|
||||||
# Iterate through the list of servers sent to the client and match by IP and port.
|
# 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?
|
# Is there a better way to determine this information?
|
||||||
ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in self.forward_client[0].split('.')]), 0)).value)
|
if self.console != 0:
|
||||||
|
ip = str(ctypes.c_int32(utils.get_int_be(bytearray([int(x) for x in self.forward_client[0].split('.')]), 0)).value) # Wii
|
||||||
|
else:
|
||||||
|
ip = str(ctypes.c_int32(utils.get_int(bytearray([int(x) for x in self.forward_client[0].split('.')]), 0)).value) # DS
|
||||||
|
|
||||||
logger.log(logging.DEBUG, "Trying to send message to %s:%d..." % (self.forward_client[0], self.forward_client[1]))
|
logger.log(logging.DEBUG, "Trying to send message to %s:%d..." % (self.forward_client[0], self.forward_client[1]))
|
||||||
logger.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
|
logger.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
|
||||||
|
|
||||||
# Get server based on ip/port
|
# Get server based on ip/port
|
||||||
server = self.server_manager.find_server_by_address(ip, self.forward_client[1])._getvalue()
|
server = self.server_manager.find_server_by_address(ip, self.forward_client[1])._getvalue()
|
||||||
logger.log(logging.DEBUG, server)
|
logger.log(logging.DEBUG, "find_server_by_address returned: %s" % server)
|
||||||
|
|
||||||
if server == None:
|
if server == None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#print "%s %s" % (ip, server['publicip'])
|
logger.log(logging.DEBUG, "%s %s" % (ip, server['publicip']))
|
||||||
if server['publicip'] == ip and server['publicport'] == str(self.forward_client[1]):
|
if server['publicip'] == ip and server['publicport'] == str(self.forward_client[1]):
|
||||||
# Send command to server to get it to connect to natneg
|
# 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 late.r
|
||||||
@@ -254,7 +259,10 @@ class Session(LineReceiver):
|
|||||||
if "natneg" in server_info:
|
if "natneg" in server_info:
|
||||||
flags |= ServerListFlags.CONNECT_NEGOTIATE_FLAG
|
flags |= ServerListFlags.CONNECT_NEGOTIATE_FLAG
|
||||||
|
|
||||||
flags_buffer += utils.get_bytes_from_int(int(server_info['publicip']))
|
if self.console != 0:
|
||||||
|
flags_buffer += utils.get_bytes_from_int_be(int(server_info['publicip'])) # Wii
|
||||||
|
else:
|
||||||
|
flags_buffer += utils.get_bytes_from_int(int(server_info['publicip'])) # DS
|
||||||
|
|
||||||
flags |= ServerListFlags.NONSTANDARD_PORT_FLAG
|
flags |= ServerListFlags.NONSTANDARD_PORT_FLAG
|
||||||
flags_buffer += utils.get_bytes_from_short_be(int(server_info['publicport']))
|
flags_buffer += utils.get_bytes_from_short_be(int(server_info['publicport']))
|
||||||
@@ -303,6 +311,9 @@ class Session(LineReceiver):
|
|||||||
#print "Requested was empty"
|
#print "Requested was empty"
|
||||||
server = {}
|
server = {}
|
||||||
|
|
||||||
|
if "__console__" in server:
|
||||||
|
self.console = int(server['__console__'])
|
||||||
|
|
||||||
# Generate binary server list data
|
# Generate binary server list data
|
||||||
data = self.generate_server_list_data(self.address, fields, server)
|
data = self.generate_server_list_data(self.address, fields, server)
|
||||||
logger.log(logging.DEBUG, utils.pretty_print_hex(data))
|
logger.log(logging.DEBUG, utils.pretty_print_hex(data))
|
||||||
|
|||||||
Reference in New Issue
Block a user