mirror of
https://github.com/barronwaffles/dwc_network_server_emulator.git
synced 2026-07-09 13:56:02 -05:00
Documentation, tidying up
- Moved some gamespy-related utility functions to where they should've been. - Added more documentation.
This commit is contained in:
parent
63a173cf1f
commit
74df6f1ea7
|
|
@ -3,7 +3,6 @@ import hashlib
|
|||
import itertools
|
||||
import other.utils as utils
|
||||
|
||||
|
||||
class GamespyDatabase(object):
|
||||
def __init__(self, filename='gpcm.db'):
|
||||
self.conn = sqlite3.connect(filename)
|
||||
|
|
@ -35,7 +34,7 @@ class GamespyDatabase(object):
|
|||
c = self.conn.cursor()
|
||||
c.execute("SELECT max(profileid) FROM users")
|
||||
|
||||
r = c.fetchone()
|
||||
r = self.get_dict(c.fetchone())
|
||||
|
||||
profileid = 476639431 #100000000
|
||||
if r != None and r['max(profileid)'] != None:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from ctypes import c_uint
|
||||
import sys
|
||||
import base64
|
||||
import hashlib
|
||||
import other.utils as utils
|
||||
|
||||
# GameSpy uses a slightly modified version of base64 which replaces +/= with []_
|
||||
def base64_encode(input):
|
||||
|
|
@ -64,4 +63,24 @@ def generate_proof(challenge, ac_challenge, secretkey, authtoken):
|
|||
md5_2.update(output)
|
||||
|
||||
return md5_2.hexdigest()
|
||||
|
||||
|
||||
# Code: Tetris DS @ 02057A14
|
||||
def get_friendcode_from_profileid(profileid, gameid):
|
||||
friendcode = 0
|
||||
|
||||
# Combine the profileid and gameid into one buffer
|
||||
buffer = [(profileid >> (8 * i)) & 0xff for i in range(4)]
|
||||
buffer += [ord(c) for c in gameid]
|
||||
|
||||
crc = utils.calculate_crc8(buffer)
|
||||
|
||||
# The upper 32 bits is the crc8 of the combined buffer.
|
||||
# The lower 32 bits of the friend code is the profileid.
|
||||
friendcode = ((crc & 0x7f) << 32) | profileid
|
||||
|
||||
return friendcode
|
||||
|
||||
def get_profileid_from_friendcode(friendcode):
|
||||
# Get the lower 32 bits as the profile id
|
||||
profileid = friendcode & 0xffffffff
|
||||
return profileid
|
||||
|
|
@ -45,8 +45,6 @@ while 1:
|
|||
commands = gs_query.parse_gamespy_message(data)
|
||||
|
||||
for data_parsed in commands:
|
||||
msg_d = []
|
||||
|
||||
print data_parsed
|
||||
|
||||
if data_parsed['__cmd__'] == "login":
|
||||
|
|
@ -79,6 +77,7 @@ while 1:
|
|||
|
||||
sesskey = db.create_session(profileid)
|
||||
|
||||
msg_d = []
|
||||
msg_d.append(('__cmd__', "lc"))
|
||||
msg_d.append(('__cmd_val__', "2"))
|
||||
msg_d.append(('sesskey', sesskey))
|
||||
|
|
@ -91,9 +90,9 @@ while 1:
|
|||
msg = gs_query.create_gamespy_message(msg_d)
|
||||
|
||||
elif data_parsed['__cmd__'] == "getprofile":
|
||||
msg_d = []
|
||||
|
||||
profile = db.get_profile_from_session_key(data_parsed.append(('sesskey')))
|
||||
|
||||
msg_d = []
|
||||
msg_d.append(('__cmd__', "pi"))
|
||||
msg_d.append(('__cmd_val__', ""))
|
||||
msg_d.append(('profileid', profile['profileid']))
|
||||
|
|
@ -112,7 +111,11 @@ while 1:
|
|||
|
||||
elif data_parsed['__cmd__'] == "updatepro":
|
||||
# Handle properly later
|
||||
# Assume that there will be other parameters besides lastname, so make it a loop or something along those lines later
|
||||
# Assume that there will be other parameters besides lastname, so make it a loop or something along those lines later.
|
||||
#
|
||||
# Idea: Make user's actual profile data a dictionary, and serialize that and store it in the database
|
||||
# instead of making each possible field a column in the table? Such a setup would make the the profile
|
||||
# more robust.
|
||||
db.update_profile(data_parsed['sesskey'], [("lastname", data_parsed['lastname'])])
|
||||
|
||||
elif data_parsed['__cmd__'] == "status":
|
||||
|
|
@ -120,8 +123,7 @@ while 1:
|
|||
msg = ""
|
||||
|
||||
elif data_parsed['__cmd__'] == "ka":
|
||||
# Unknown
|
||||
|
||||
# Keep alive
|
||||
msg = ""
|
||||
|
||||
elif data_parsed['__cmd__'] == "bm":
|
||||
|
|
@ -151,6 +153,19 @@ while 1:
|
|||
# (CLIENT) \status\2\sesskey\233209064\statstring\\locstring\JZoAAAAAAAAAAAAA-wA*\final\
|
||||
# (SERVER) \bm\100\f\217936895\msg\|s|6|ss|/SCM/2/SCN/2/VER/3|ls|97YBAAAAAAAAAAAA-wA*|ip|-1405615422|p|0|qm|0\final\
|
||||
# (SERVER) \bm\100\f\217936895\msg\|s|6|ss|/SCM/2/SCN/1/VER/3|ls|97YBAAAAAAAAAAAA-wA*|ip|-1405615422|p|0|qm|0\final\
|
||||
#
|
||||
# Notes:
|
||||
# \bm\1 = Message
|
||||
# \bm\100 = Status
|
||||
# Check out OpenSpy to find out more \bm request codes: https://github.com/sfcspanky/Openspy-Core/blob/playerspy/gp.h
|
||||
#
|
||||
# msg field:
|
||||
# s = status
|
||||
# ss = status string
|
||||
# ls = location string
|
||||
# ip = signed ip (convert back into hex, take each byte to build x.x.x.x)
|
||||
# p = port
|
||||
# qm = ? (According to OpenSpy, "quietflags". See above linked gp.h to get GP_SILENCE_* flags)
|
||||
msg = ""
|
||||
|
||||
elif data_parsed['__cmd__'] == "logout":
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
# Server emulator for *.available.gs.nintendowifi.net and *.master.gs.nintendowifi.net
|
||||
import socket
|
||||
import time
|
||||
import other.utils as utils
|
||||
|
||||
|
||||
def get_game_id(data):
|
||||
game_id = data[5: -1]
|
||||
return game_id
|
||||
|
|
@ -25,19 +23,42 @@ while 1:
|
|||
# - Bytes 2 - 5 from the client is some kind of ID. This will have to be inspected later. I believe it's a
|
||||
# session-like ID because the number changes between connections. Copying the client's ID might be enough.
|
||||
#
|
||||
# The above was as guessed.
|
||||
# The code in Tetris DS (overlay 10) @ 0216E974 handles the network command creation.
|
||||
# R1 contains the command to be sent to the server.
|
||||
# R2 contains a pointer to some unknown integer that gets written after the command.
|
||||
#
|
||||
# - Commands
|
||||
# Commands range from 0x00 to 0x09 (for client only at least?) (Tetris DS overlay 10 @ 0216DDCC)
|
||||
#
|
||||
# CLIENT:
|
||||
# 0x01 - Unknown
|
||||
# 0x03 - Send client state?
|
||||
# 0x01 - Unknown (Tetris DS overlay 10 @ 216DCA4)
|
||||
# 0x03 - Send client state? (Tetris DS overlay 10 @ 216DA30)
|
||||
# Data sent:
|
||||
# 1) Loop for each localip available on the system, write as localip%d\x00(local ip)
|
||||
# 2) localport\x00(local port)
|
||||
# 3) natneg (either 0 or 1)
|
||||
# 4) ONLY IF STATE CHANGED: statechanged\x00(state) (Possible values: 0, 1, 2, 3)
|
||||
# 5) gamename\x00(game name)
|
||||
# 6) ONLY IF PUBLIC IP AND PORT ARE AVAILABLE: publicip\x00(public ip)
|
||||
# 7) ONLY IF PUBLIC IP AND PORT ARE AVAILABLE: publicport\x00(public port)
|
||||
#
|
||||
# if statechanged != 2:
|
||||
# Write various other data described here: http://docs.poweredbygamespy.com/wiki/Query_and_Reporting_Implementation
|
||||
#
|
||||
# 0x07 - Unknown, related to server's 0x06 (returns value sent from server)
|
||||
#
|
||||
#
|
||||
# 0x08 - Keep alive?
|
||||
# 0x09 - Availability check
|
||||
#
|
||||
# SERVER:
|
||||
# 0x01 - Unknown
|
||||
# 0x06 - Unknown
|
||||
# 0x0a - Unknown
|
||||
#
|
||||
# - \xfd\xfc commands get passed directly between the other player(s)?
|
||||
#
|
||||
|
||||
if [ord(x) for x in recv_data[0:5]] == [0x09, 0x00, 0x00, 0x00, 0x00]:
|
||||
utils.print_log("Received request for '%s' from %s:%s... %s" % (
|
||||
|
|
|
|||
|
|
@ -64,28 +64,6 @@ def base32_decode(str, reverse = False):
|
|||
|
||||
return orig
|
||||
|
||||
# Code: Tetris DS @ 02057A14
|
||||
def get_friendcode_from_profileid(profileid, gameid):
|
||||
friendcode = 0
|
||||
|
||||
# Combine the profileid and gameid into one buffer
|
||||
buffer = [(profileid >> (8 * i)) & 0xff for i in range(4)]
|
||||
buffer += [ord(c) for c in gameid]
|
||||
|
||||
crc = calculate_crc8(buffer)
|
||||
|
||||
# The upper 32 bits is the crc8 of the combined buffer.
|
||||
# The lower 32 bits of the friend code is the profileid.
|
||||
friendcode = ((crc & 0x7f) << 32) | profileid
|
||||
|
||||
return friendcode
|
||||
|
||||
def get_profileid_from_friendcode(friendcode):
|
||||
# Get the lower 32 bits as the profile id
|
||||
profileid = friendcode & 0xffffffff
|
||||
return profileid
|
||||
|
||||
|
||||
# For server logging
|
||||
def print_log(text):
|
||||
print "[%s] %s" % (time.strftime("%c"), text)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user