mirror of
https://github.com/barronwaffles/dwc_network_server_emulator.git
synced 2026-07-19 08:41:23 -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:
parent
25ff93469b
commit
f64b1e1c60
|
|
@ -55,6 +55,9 @@ class GameSpyBackendServer(object):
|
|||
address = ("127.0.0.1", 27500)
|
||||
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]))
|
||||
|
||||
manager = GameSpyServerDatabase(address = address, authkey = password)
|
||||
|
|
@ -293,13 +296,13 @@ class GameSpyBackendServer(object):
|
|||
values.append({ 'value': int(lval & rval), 'type': TokenType.NUMBER})
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
#print "Matched %d/%d" % (matched_filters, filter_count)
|
||||
print "Matched %d/%d" % (matched_filters, filter_count)
|
||||
|
||||
# Add the server if everything was matched
|
||||
if matched_filters == filter_count:
|
||||
|
|
@ -344,7 +347,7 @@ class GameSpyBackendServer(object):
|
|||
|
||||
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
|
||||
# never got handled properly (game crashed, etc).
|
||||
self.delete_server(gameid, session)
|
||||
|
|
@ -355,6 +358,7 @@ class GameSpyBackendServer(object):
|
|||
|
||||
# Add new server
|
||||
value['__session__'] = session
|
||||
value['__console__'] = console
|
||||
|
||||
logger.log(logging.DEBUG, "Added %s to the server list for %s" % (value, gameid))
|
||||
self.server_list[gameid].append(value)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class GameSpyNatNegServer(object):
|
|||
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
||||
|
||||
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)
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
|
@ -32,6 +32,7 @@ class GameSpyNatNegServer(object):
|
|||
recv_data, addr = s.recvfrom(2048)
|
||||
|
||||
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
|
||||
if recv_data[0:6] != bytearray([0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2]):
|
||||
|
|
@ -44,6 +45,12 @@ class GameSpyNatNegServer(object):
|
|||
if recv_data[7] == '\x00':
|
||||
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)
|
||||
client_id = "%02x" % ord(recv_data[13])
|
||||
|
||||
|
|
@ -56,8 +63,6 @@ class GameSpyNatNegServer(object):
|
|||
|
||||
self.session_list[gameid][session_id][client_id]['addr'] = addr
|
||||
clients = len(self.session_list[gameid][session_id])
|
||||
#if client_id in session_list[gameid][session_id]:
|
||||
# clients -= 1
|
||||
|
||||
if clients > 0:
|
||||
# Someone else is waiting to connect, send message
|
||||
|
|
@ -81,11 +86,6 @@ class GameSpyNatNegServer(object):
|
|||
logger.log(logging.DEBUG, "")
|
||||
#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
|
||||
client_id = "%02x" % ord(recv_data[13])
|
||||
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]:
|
||||
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':
|
||||
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, utils.pretty_print_hex(recv_data))
|
||||
|
||||
output[7] = 0x0e # Report response
|
||||
s.sendto(output, addr)
|
||||
recv_data[7] = 0x0e # Report response
|
||||
s.sendto(recv_data, addr)
|
||||
|
||||
else: # Was able to connect
|
||||
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 struct
|
||||
import gamespy.gs_utility as gs_utils
|
||||
import gamespy.gs_database as gs_database
|
||||
import other.utils as utils
|
||||
|
||||
from multiprocessing.managers import BaseManager
|
||||
|
|
@ -27,6 +28,8 @@ class GameSpyQRServer(object):
|
|||
self.secretkey = "" # Parse gslist.cfg later
|
||||
self.sent_challenge = False
|
||||
self.address = address
|
||||
self.console = 0
|
||||
self.playerid= 0
|
||||
|
||||
def __init__(self):
|
||||
self.sessions = {}
|
||||
|
|
@ -36,6 +39,8 @@ class GameSpyQRServer(object):
|
|||
self.secret_key_list = gs_utils.generate_secret_keys("gslist.cfg")
|
||||
#self.log(logging.DEBUG, address, "Generated list of secret game keys...")
|
||||
|
||||
self.db = gs_database.GamespyDatabase()
|
||||
|
||||
GameSpyServerDatabase.register("update_server_list")
|
||||
GameSpyServerDatabase.register("delete_server")
|
||||
|
||||
|
|
@ -193,6 +198,17 @@ class GameSpyQRServer(object):
|
|||
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'])
|
||||
|
||||
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:
|
||||
addr_hex = ''.join(["%02X" % int(x) for x in address[0].split('.')])
|
||||
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).
|
||||
|
||||
# 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
|
||||
self.server_manager.delete_server(k['gamename'] , session_id)
|
||||
#self.sessions.pop(session_id)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class Session(LineReceiver):
|
|||
self.forward_to_client = False
|
||||
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.console = 0
|
||||
|
||||
manager_address = ("127.0.0.1", 27500)
|
||||
manager_password = ""
|
||||
|
|
@ -101,18 +102,22 @@ 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?
|
||||
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, utils.pretty_print_hex(bytearray(data)))
|
||||
|
||||
# Get server based on ip/port
|
||||
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:
|
||||
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]):
|
||||
# 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
|
||||
|
|
@ -254,7 +259,10 @@ class Session(LineReceiver):
|
|||
if "natneg" in server_info:
|
||||
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_buffer += utils.get_bytes_from_short_be(int(server_info['publicport']))
|
||||
|
|
@ -303,6 +311,9 @@ class Session(LineReceiver):
|
|||
#print "Requested was empty"
|
||||
server = {}
|
||||
|
||||
if "__console__" in server:
|
||||
self.console = int(server['__console__'])
|
||||
|
||||
# Generate binary server list data
|
||||
data = self.generate_server_list_data(self.address, fields, server)
|
||||
logger.log(logging.DEBUG, utils.pretty_print_hex(data))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user