Added some exception catching for debugging

This commit is contained in:
polaris 2014-05-28 11:26:58 -04:00
parent 7ff0467d2a
commit 5a2bca3a57
7 changed files with 467 additions and 427 deletions

View File

@ -1,5 +1,6 @@
import logging
import time
import traceback
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import serverFromString
@ -75,52 +76,58 @@ class Gamestats(LineReceiver):
logger.log(level, "[%s:%d | %s | %s] %s", self.address.host, self.address.port, self.session, self.gameid, message)
def connectionMade(self):
self.log(logging.INFO, "Received connection from %s:%d" % (self.address.host, self.address.port))
try:
self.log(logging.INFO, "Received connection from %s:%d" % (self.address.host, self.address.port))
# Generate a random challenge string
self.challenge = utils.generate_random_str(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
# Generate a random challenge string
self.challenge = utils.generate_random_str(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
# The first command sent to the client is always a login challenge containing the server challenge key.
msg = gs_query.create_gamespy_message([
('__cmd__', "lc"),
('__cmd_val__', "1"),
('challenge', self.challenge),
('id', "1"),
])
# The first command sent to the client is always a login challenge containing the server challenge key.
msg = gs_query.create_gamespy_message([
('__cmd__', "lc"),
('__cmd_val__', "1"),
('challenge', self.challenge),
('id', "1"),
])
self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
msg = self.crypt(msg)
self.transport.write(bytes(msg))
msg = self.crypt(msg)
self.transport.write(bytes(msg))
except:
self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def connectionLost(self, reason):
return
def rawDataReceived(self, data):
# Decrypt packet
msg = self.remaining_message + str(self.crypt(data))
self.data = msg
try:
# Decrypt packet
msg = self.remaining_message + str(self.crypt(data))
self.data = msg
commands, self.remaining_message = gs_query.parse_gamespy_message(msg)
#logger.log(logging.DEBUG, "STATS RESPONSE: %s" % msg)
commands, self.remaining_message = gs_query.parse_gamespy_message(msg)
#logger.log(logging.DEBUG, "STATS RESPONSE: %s" % msg)
cmds = {
"auth": self.perform_auth,
"authp": self.perform_authp,
"ka": self.perform_ka,
"setpd": self.perform_setpd,
"getpd": self.perform_getpd,
"newgame": self.perform_newgame,
"updgame": self.perform_updgame,
}
cmds = {
"auth": self.perform_auth,
"authp": self.perform_authp,
"ka": self.perform_ka,
"setpd": self.perform_setpd,
"getpd": self.perform_getpd,
"newgame": self.perform_newgame,
"updgame": self.perform_updgame,
}
def cmd_err(data_parsed):
logger.log(logging.DEBUG, "Found unknown command, don't know how to handle '%s'.", data_parsed['__cmd__'])
def cmd_err(data_parsed):
logger.log(logging.DEBUG, "Found unknown command, don't know how to handle '%s'.", data_parsed['__cmd__'])
for data_parsed in commands:
print(data_parsed)
for data_parsed in commands:
print(data_parsed)
cmds.get(data_parsed['__cmd__'], cmd_err)(data_parsed)
cmds.get(data_parsed['__cmd__'], cmd_err)(data_parsed)
except:
self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def perform_auth(self, data_parsed):
self.log(logging.DEBUG, "Parsing 'auth'...")

View File

@ -10,6 +10,7 @@ import time
import Queue
import gamespy.gs_utility as gs_utils
import other.utils as utils
import traceback
from multiprocessing.managers import BaseManager
@ -43,21 +44,24 @@ class GameSpyNatNegServer(object):
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)
try:
# Start natneg server
address = ('0.0.0.0', 27901) # accessible to outside connections (use this if you don't know what you're doing)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.bind(address)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.bind(address)
self.write_queue = Queue.Queue();
self.write_queue = Queue.Queue();
logger.log(logging.INFO, "Server is now listening on %s:%s..." % (address[0], address[1]))
threading.Thread(target=self.write_queue_worker).start()
logger.log(logging.INFO, "Server is now listening on %s:%s..." % (address[0], address[1]))
threading.Thread(target=self.write_queue_worker).start()
while 1:
recv_data, addr = self.socket.recvfrom(2048)
while 1:
recv_data, addr = self.socket.recvfrom(2048)
self.handle_packet(recv_data, addr)
self.handle_packet(recv_data, addr)
except:
logger.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def write_queue_send(self, data, address):
time.sleep(0.05)

View File

@ -1,4 +1,5 @@
import logging
import traceback
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import serverFromString
@ -57,18 +58,21 @@ class PlayerSearch(LineReceiver):
pass
def rawDataReceived(self, data):
logger.log(logging.DEBUG, "SEARCH RESPONSE: %s" % data)
try:
logger.log(logging.DEBUG, "SEARCH RESPONSE: %s" % data)
data = self.leftover + data
commands, self.leftover = gs_query.parse_gamespy_message(data)
data = self.leftover + data
commands, self.leftover = gs_query.parse_gamespy_message(data)
for data_parsed in commands:
print data_parsed
for data_parsed in commands:
print data_parsed
if data_parsed['__cmd__'] == "otherslist":
self.perform_otherslist(data_parsed)
else:
logger.log(logging.DEBUG, "Found unknown search command, don't know how to handle '%s'." % data_parsed['__cmd__'])
if data_parsed['__cmd__'] == "otherslist":
self.perform_otherslist(data_parsed)
else:
logger.log(logging.DEBUG, "Found unknown search command, don't know how to handle '%s'." % data_parsed['__cmd__'])
except:
logger.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def perform_otherslist(self, data_parsed):
# Reference: http://wiki.tockdom.com/wiki/MKWii_Network_Protocol/Server/gpsp.gs.nintendowifi.net

View File

@ -1,5 +1,6 @@
import logging
import time
import traceback
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import serverFromString
@ -89,79 +90,88 @@ class PlayerSession(LineReceiver):
return ipaddress
def connectionMade(self):
self.transport.setTcpKeepAlive(1)
try:
self.transport.setTcpKeepAlive(1)
self.log(logging.INFO, "Received connection from %s:%d" % (self.address.host, self.address.port))
self.log(logging.INFO, "Received connection from %s:%d" % (self.address.host, self.address.port))
# Create new session id
self.session = ""
# Create new session id
self.session = ""
# Generate a random challenge string
self.challenge = utils.generate_random_str(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
# Generate a random challenge string
self.challenge = utils.generate_random_str(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
# The first command sent to the client is always a login challenge containing the server challenge key.
msg = gs_query.create_gamespy_message([
('__cmd__', "lc"),
('__cmd_val__', "1"),
('challenge', self.challenge),
('id', "1"),
])
# The first command sent to the client is always a login challenge containing the server challenge key.
msg = gs_query.create_gamespy_message([
('__cmd__', "lc"),
('__cmd_val__', "1"),
('challenge', self.challenge),
('id', "1"),
])
self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
self.transport.write(bytes(msg))
self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
self.transport.write(bytes(msg))
except:
self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def connectionLost(self, reason):
self.log(logging.INFO, "Client disconnected")
try:
self.log(logging.INFO, "Client disconnected")
self.status = "0"
self.statstring = "Offline"
self.locstring = ""
self.send_status_to_friends()
self.status = "0"
self.statstring = "Offline"
self.locstring = ""
self.send_status_to_friends()
if self.profileid in self.sessions:
del self.sessions[self.profileid]
if self.profileid in self.sessions:
del self.sessions[self.profileid]
self.db.delete_session(self.session)
self.log(logging.INFO, "Deleted session " + self.session)
self.db.delete_session(self.session)
self.log(logging.INFO, "Deleted session " + self.session)
except:
self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def rawDataReceived(self, data):
self.log(logging.DEBUG, "RESPONSE: '%s'..." % data)
try:
self.log(logging.DEBUG, "RESPONSE: '%s'..." % data)
# In the case where command string is too big to fit into one read, any parts that could not be successfully
# parsed are stored in the variable remaining_message. On the next rawDataReceived command, the remaining
# message and the data are combined to create a full command.
data = self.remaining_message + data
# In the case where command string is too big to fit into one read, any parts that could not be successfully
# parsed are stored in the variable remaining_message. On the next rawDataReceived command, the remaining
# message and the data are combined to create a full command.
data = self.remaining_message + data
# Check to make sure the data buffer starts with a valid command.
if len(data) > 0 and data[0] != '\\':
# There is data in the buffer but it doesn't start with a \ so there's no chance of it being valid.
# Look for the first instance of \final\ and remove everything before it.
# If \final\ is not in the command string then ignore it.
final = "\\final\\"
data = data[data.index(final) + len(final):] if final in data else ""
# Check to make sure the data buffer starts with a valid command.
if len(data) > 0 and data[0] != '\\':
# There is data in the buffer but it doesn't start with a \ so there's no chance of it being valid.
# Look for the first instance of \final\ and remove everything before it.
# If \final\ is not in the command string then ignore it.
final = "\\final\\"
data = data[data.index(final) + len(final):] if final in data else ""
commands, self.remaining_message = gs_query.parse_gamespy_message(data)
commands, self.remaining_message = gs_query.parse_gamespy_message(data)
cmds = {
"login": self.perform_login,
"logout": self.perform_logout,
"getprofile": self.perform_getprofile,
"updatepro": self.perform_updatepro,
"ka": self.perform_ka,
"status": self.perform_status,
"bm": self.perform_bm,
"addbuddy": self.perform_addbuddy,
"delbuddy": self.perform_delbuddy,
"authadd": self.perform_authadd,
}
def cmd_err(data_parsed):
# Maybe write unknown commands to a separate file later so new data can be collected more easily?
self.log(logging.ERROR, "Found unknown command, don't know how to handle '%s'." % data_parsed['__cmd__'])
cmds = {
"login": self.perform_login,
"logout": self.perform_logout,
"getprofile": self.perform_getprofile,
"updatepro": self.perform_updatepro,
"ka": self.perform_ka,
"status": self.perform_status,
"bm": self.perform_bm,
"addbuddy": self.perform_addbuddy,
"delbuddy": self.perform_delbuddy,
"authadd": self.perform_authadd,
}
def cmd_err(data_parsed):
# Maybe write unknown commands to a separate file later so new data can be collected more easily?
self.log(logging.ERROR, "Found unknown command, don't know how to handle '%s'." % data_parsed['__cmd__'])
for data_parsed in commands:
#self.log(-1, data_parsed)
self.log(logging.DEBUG, data_parsed)
cmds.get(data_parsed['__cmd__'], cmd_err)(data_parsed)
for data_parsed in commands:
#self.log(-1, data_parsed)
self.log(logging.DEBUG, data_parsed)
cmds.get(data_parsed['__cmd__'], cmd_err)(data_parsed)
except:
self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def perform_login(self, data_parsed):
authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db)

View File

@ -9,6 +9,7 @@ import threading
import time
import ctypes
import Queue
import traceback
from multiprocessing.managers import BaseManager
@ -60,38 +61,41 @@ class GameSpyQRServer(object):
logger.log(level, "[%s:%d] %s", address[0], address[1], message)
def start(self):
manager_address = ("127.0.0.1", 27500)
manager_password = ""
try:
manager_address = ("127.0.0.1", 27500)
manager_password = ""
self.server_manager = GameSpyServerDatabase(address = manager_address, authkey= manager_password)
self.server_manager.connect()
self.server_manager = GameSpyServerDatabase(address = manager_address, authkey= manager_password)
self.server_manager.connect()
# Start QR server
address = ('0.0.0.0', 27900) # accessible to outside connections (use this if you don't know what you're doing)
# Start QR server
address = ('0.0.0.0', 27900) # accessible to outside connections (use this if you don't know what you're doing)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.bind(address)
self.socket.setblocking(0)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.bind(address)
self.socket.setblocking(0)
logger.log(logging.INFO, "Server is now listening on %s:%s..." % (address[0], address[1]))
logger.log(logging.INFO, "Server is now listening on %s:%s..." % (address[0], address[1]))
# Dependencies! I don't really like this solution but it's easier than trying to manage it another way.
server_browser_server = GameSpyServerBrowserServer(self)
server_browser_server_thread = threading.Thread(target=server_browser_server.start)
server_browser_server_thread.start()
# Dependencies! I don't really like this solution but it's easier than trying to manage it another way.
server_browser_server = GameSpyServerBrowserServer(self)
server_browser_server_thread = threading.Thread(target=server_browser_server.start)
server_browser_server_thread.start()
self.write_queue = Queue.Queue();
self.db = gs_database.GamespyDatabase()
threading.Thread(target=self.write_queue_worker).start()
self.write_queue = Queue.Queue()
self.db = gs_database.GamespyDatabase()
threading.Thread(target=self.write_queue_worker).start()
while 1:
ready = select.select([self.socket], [], [], 15)
while 1:
ready = select.select([self.socket], [], [], 15)
if ready[0]:
recv_data, address = self.socket.recvfrom(2048)
self.handle_packet(self.socket, recv_data, address)
if ready[0]:
recv_data, address = self.socket.recvfrom(2048)
self.handle_packet(self.socket, recv_data, address)
self.keepalive_check()
self.keepalive_check()
except:
logger.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def write_queue_send(self, data, address):
time.sleep(0.05)

View File

@ -4,6 +4,7 @@
import logging
import socket
import ctypes
import traceback
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import serverFromString
@ -97,143 +98,146 @@ class Session(LineReceiver):
logger.log(level, "[%s:%d] %s", self.address.host, self.address.port,message)
def rawDataReceived(self, data):
# First 2 bytes are the packet size.
#
# Third byte is the command byte.
# According to Openspy-Core:
# 0x00 - Server list request
# 0x01 - Server info request
# 0x02 - Send message request
# 0x03 - Keep alive reply
# 0x04 - Map loop request (?)
# 0x05 - Player search request
#
# For Tetris DS, at the very least 0x00 and 0x02 need to be implemented.
if self.forward_to_client:
if self.forward_packet == None:
self.forward_packet = data
try:
# First 2 bytes are the packet size.
#
# Third byte is the command byte.
# According to Openspy-Core:
# 0x00 - Server list request
# 0x01 - Server info request
# 0x02 - Send message request
# 0x03 - Keep alive reply
# 0x04 - Map loop request (?)
# 0x05 - Player search request
#
# For Tetris DS, at the very least 0x00 and 0x02 need to be implemented.
if self.forward_to_client:
if self.forward_packet == None:
self.forward_packet = data
else:
self.forward_packet += data
if self.header_length + len(self.forward_packet) >= self.expected_packet_length:
# Is it possible that multiple packets will need to be waited for?
# Is it possible that more data will be in the last packet than expected?
self.forward_data_to_client(self.forward_packet, self.forward_client)
self.forward_to_client = False
self.forward_client = None
self.header_length = 0
self.expected_packet_length = 0
self.forward_packet = None
return
if data[2] == '\x00': # Server list request
self.log(logging.DEBUG, "Received server list request from %s:%s..." % (self.address.host, self.address.port))
# This code is so... not python. The C programmer in me is coming out strong.
# TODO: Rewrite this section later?
idx = 3
list_version = ord(data[idx])
idx += 1
encoding_version = ord(data[idx])
idx += 1
game_version = utils.get_int(data, idx)
idx += 4
query_game = utils.get_string(data, idx)
idx += len(query_game) + 1
game_name = utils.get_string(data, idx)
idx += len(game_name) + 1
challenge = data[idx:idx+8]
idx += 8
filter = utils.get_string(data, idx)
idx += len(filter) + 1
fields = utils.get_string(data, idx)
idx += len(fields) + 1
options = utils.get_int_be(data, idx)
idx += 4
source_ip = 0
max_servers = 0
NO_SERVER_LIST = 0x02
ALTERNATE_SOURCE_IP = 0x08
LIMIT_RESULT_COUNT = 0x80
send_ip = False
if (options & LIMIT_RESULT_COUNT):
max_servers = utils.get_int(data, idx)
elif (options & ALTERNATE_SOURCE_IP):
source_ip = utils.get_int(data, idx)
elif (options & NO_SERVER_LIST):
send_ip = True
if '\\' in fields:
fields = [x for x in fields.split('\\') if x and not x.isspace()]
#print "%02x %02x %08x" % (list_version, encoding_version, game_version)
#print "%s" % query_game
#print "%s" % game_name
#print "%s" % challenge
#print "%s" % filter
#print "%s" % fields
#print "%08x" % options
#print "%d %08x" % (max_servers, source_ip)
self.log(logging.DEBUG, "list version: %02x / encoding version: %02x / game version: %08x / query game: %s / game name: %s / challenge: %s / filter: %s / fields: %s / options: %08x / max servers: %d / source ip: %08x" % (list_version, encoding_version, game_version, query_game, game_name, challenge, filter, fields, options, max_servers, source_ip))
# Requesting ip and port of client, not server
if filter == "" or fields == "" or send_ip == True:
output = bytearray([int(x) for x in self.address.host.split('.')])
output += utils.get_bytes_from_short_be(6500) # Does this ever change?
enc = gs_utils.EncTypeX()
output_enc = enc.encrypt(self.secret_key_list[game_name], challenge, output)
self.transport.write(bytes(output_enc))
self.log(logging.DEBUG, "Responding with own IP and game port...")
self.log(logging.DEBUG, utils.pretty_print_hex(output))
else:
self.find_server(query_game, filter, fields, max_servers, game_name, challenge)
elif data[2] == '\x02': # Send message request
packet_len = utils.get_short_be(data, 0)
dest_addr = '.'.join(["%d" % ord(x) for x in data[3:7]])
dest_port = utils.get_short_be(data, 7) # What's the pythonic way to do this? unpack?
dest = (dest_addr, dest_port)
self.log(logging.DEBUG, "Received send message request from %s:%s to %s:%d... expecting %d byte packet." % (self.address.host, self.address.port, dest_addr, dest_port, packet_len))
self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
if packet_len == len(data):
# Contains entire packet, send immediately.
self.forward_data_to_client(data[3:], dest)
self.forward_to_client = False
self.forward_client = None
self.header_length = 0
self.expected_packet_length = 0
self.forward_packet = None
else:
self.forward_to_client = True
self.forward_client = dest
self.header_length = len(data)
self.expected_packet_length = packet_len
elif data[2] == '\x03': # Keep alive reply
self.log(logging.DEBUG, "Received keep alive from %s:%s..." % (self.address.host, self.address.port))
else:
self.forward_packet += data
if self.header_length + len(self.forward_packet) >= self.expected_packet_length:
# Is it possible that multiple packets will need to be waited for?
# Is it possible that more data will be in the last packet than expected?
self.forward_data_to_client(self.forward_packet, self.forward_client)
self.forward_to_client = False
self.forward_client = None
self.header_length = 0
self.expected_packet_length = 0
self.forward_packet = None
return
if data[2] == '\x00': # Server list request
self.log(logging.DEBUG, "Received server list request from %s:%s..." % (self.address.host, self.address.port))
# This code is so... not python. The C programmer in me is coming out strong.
# TODO: Rewrite this section later?
idx = 3
list_version = ord(data[idx])
idx += 1
encoding_version = ord(data[idx])
idx += 1
game_version = utils.get_int(data, idx)
idx += 4
query_game = utils.get_string(data, idx)
idx += len(query_game) + 1
game_name = utils.get_string(data, idx)
idx += len(game_name) + 1
challenge = data[idx:idx+8]
idx += 8
filter = utils.get_string(data, idx)
idx += len(filter) + 1
fields = utils.get_string(data, idx)
idx += len(fields) + 1
options = utils.get_int_be(data, idx)
idx += 4
source_ip = 0
max_servers = 0
NO_SERVER_LIST = 0x02
ALTERNATE_SOURCE_IP = 0x08
LIMIT_RESULT_COUNT = 0x80
send_ip = False
if (options & LIMIT_RESULT_COUNT):
max_servers = utils.get_int(data, idx)
elif (options & ALTERNATE_SOURCE_IP):
source_ip = utils.get_int(data, idx)
elif (options & NO_SERVER_LIST):
send_ip = True
if '\\' in fields:
fields = [x for x in fields.split('\\') if x and not x.isspace()]
#print "%02x %02x %08x" % (list_version, encoding_version, game_version)
#print "%s" % query_game
#print "%s" % game_name
#print "%s" % challenge
#print "%s" % filter
#print "%s" % fields
#print "%08x" % options
#print "%d %08x" % (max_servers, source_ip)
self.log(logging.DEBUG, "list version: %02x / encoding version: %02x / game version: %08x / query game: %s / game name: %s / challenge: %s / filter: %s / fields: %s / options: %08x / max servers: %d / source ip: %08x" % (list_version, encoding_version, game_version, query_game, game_name, challenge, filter, fields, options, max_servers, source_ip))
# Requesting ip and port of client, not server
if filter == "" or fields == "" or send_ip == True:
output = bytearray([int(x) for x in self.address.host.split('.')])
output += utils.get_bytes_from_short_be(6500) # Does this ever change?
enc = gs_utils.EncTypeX()
output_enc = enc.encrypt(self.secret_key_list[game_name], challenge, output)
self.transport.write(bytes(output_enc))
self.log(logging.DEBUG, "Responding with own IP and game port...")
self.log(logging.DEBUG, utils.pretty_print_hex(output))
else:
self.find_server(query_game, filter, fields, max_servers, game_name, challenge)
elif data[2] == '\x02': # Send message request
packet_len = utils.get_short_be(data, 0)
dest_addr = '.'.join(["%d" % ord(x) for x in data[3:7]])
dest_port = utils.get_short_be(data, 7) # What's the pythonic way to do this? unpack?
dest = (dest_addr, dest_port)
self.log(logging.DEBUG, "Received send message request from %s:%s to %s:%d... expecting %d byte packet." % (self.address.host, self.address.port, dest_addr, dest_port, packet_len))
self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
if packet_len == len(data):
# Contains entire packet, send immediately.
self.forward_data_to_client(data[3:], dest)
self.forward_to_client = False
self.forward_client = None
self.header_length = 0
self.expected_packet_length = 0
self.forward_packet = None
else:
self.forward_to_client = True
self.forward_client = dest
self.header_length = len(data)
self.expected_packet_length = packet_len
elif data[2] == '\x03': # Keep alive reply
self.log(logging.DEBUG, "Received keep alive from %s:%s..." % (self.address.host, self.address.port))
else:
self.log(logging.DEBUG, "Received unknown command (%02x) from %s:%s..." % (ord(data[2]), self.address.host, self.address.port))
self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
self.log(logging.DEBUG, utils.pretty_print_hex(data))
self.log(logging.DEBUG, "Received unknown command (%02x) from %s:%s..." % (ord(data[2]), self.address.host, self.address.port))
self.log(logging.DEBUG, utils.pretty_print_hex(bytearray(data)))
self.log(logging.DEBUG, utils.pretty_print_hex(data))
except:
self.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def get_game_id(self, data):
game_id = data[5: -1]

View File

@ -6,6 +6,7 @@ import urlparse
import BaseHTTPServer
import os
import random
import traceback
import gamespy.gs_database as gs_database
import gamespy.gs_utility as gs_utils
@ -40,208 +41,214 @@ class NasHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
return "Nintendo Wii (http)"
def do_GET(self):
# conntest server
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("X-Organization", "Nintendo")
self.send_header("Server", "BigIP")
self.end_headers()
self.wfile.write("ok")
try:
# conntest server
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("X-Organization", "Nintendo")
self.send_header("Server", "BigIP")
self.end_headers()
self.wfile.write("ok")
except:
logger.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def do_POST(self):
length = int(self.headers['content-length'])
post = self.str_to_dict(self.rfile.read(length))
ret = ''
try:
length = int(self.headers['content-length'])
post = self.str_to_dict(self.rfile.read(length))
ret = ''
if self.path == "/ac":
logger.log(logging.DEBUG, "Request to %s from %s", self.path, self.client_address)
logger.log(logging.DEBUG, post)
ret = {}
ret["datetime"] = time.strftime("%Y%m%d%H%M%S")
ret["retry"] = "0"
action = post["action"]
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("NODE", "wifiappe1")
if self.path == "/ac":
logger.log(logging.DEBUG, "Request to %s from %s", self.path, self.client_address)
logger.log(logging.DEBUG, post)
ret = {}
ret["datetime"] = time.strftime("%Y%m%d%H%M%S")
ret["retry"] = "0"
action = post["action"]
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("NODE", "wifiappe1")
if action == "acctcreate":
# TODO: test for duplicate accounts
ret["returncd"] = "002"
if action == "acctcreate":
# TODO: test for duplicate accounts
ret["returncd"] = "002"
logger.log(logging.DEBUG, "acctcreate response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
logger.log(logging.DEBUG, "acctcreate response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
ret = self.dict_to_str(ret)
ret = self.dict_to_str(ret)
elif action == "login":
ret["returncd"] = "001"
ret["locator"] = "gamespy.com"
challenge = utils.generate_random_str(8)
ret["challenge"] = challenge
post["challenge"] = challenge
authtoken = self.server.db.generate_authtoken(post["userid"], post)
ret["token"] = authtoken
elif action == "login":
ret["returncd"] = "001"
ret["locator"] = "gamespy.com"
challenge = utils.generate_random_str(8)
ret["challenge"] = challenge
post["challenge"] = challenge
authtoken = self.server.db.generate_authtoken(post["userid"], post)
ret["token"] = authtoken
logger.log(logging.DEBUG, "login response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
logger.log(logging.DEBUG, "login response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
ret = self.dict_to_str(ret)
ret = self.dict_to_str(ret)
elif action == "SVCLOC" or action == "svcloc": # Get service based on service id number
ret["returncd"] = "007"
ret["statusdata"] = "Y"
authtoken = self.server.db.generate_authtoken(post["userid"], post)
elif action == "SVCLOC" or action == "svcloc": # Get service based on service id number
ret["returncd"] = "007"
ret["statusdata"] = "Y"
authtoken = self.server.db.generate_authtoken(post["userid"], post)
if 'svc' in post:
if post["svc"] in ("9000", "9001"): # DLC host = 9000
ret["svchost"] = self.headers['host'] # in case the client's DNS isn't redirecting dls1.nintendowifi.net
if 'svc' in post:
if post["svc"] in ("9000", "9001"): # DLC host = 9000
ret["svchost"] = self.headers['host'] # in case the client's DNS isn't redirecting dls1.nintendowifi.net
# Brawl has 2 host headers which Apache chokes on, so only return the first one or else it won't work
ret["svchost"] = ret["svchost"].split(',')[0]
# Brawl has 2 host headers which Apache chokes on, so only return the first one or else it won't work
ret["svchost"] = ret["svchost"].split(',')[0]
if post["svc"] == 9000:
ret["token"] = authtoken
else:
if post["svc"] == 9000:
ret["token"] = authtoken
else:
ret["servicetoken"] = authtoken
elif post["svc"] == "0000": # Pokemon requests this for some things
ret["servicetoken"] = authtoken
elif post["svc"] == "0000": # Pokemon requests this for some things
ret["servicetoken"] = authtoken
ret["svchost"] = "n/a"
ret["svchost"] = "n/a"
logger.log(logging.DEBUG, "svcloc response to %s", self.client_address)
logger.log(logging.DEBUG, "svcloc response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
ret = self.dict_to_str(ret)
else:
logger.log(logging.WARNING, "Unknown action request %s from %s!", self.path, self.client_address)
ret = ''
elif self.path == "/pr":
logger.log(logging.DEBUG, "Request to %s from %s", self.path, self.client_address)
logger.log(logging.DEBUG, post)
ret = {}
words = len(post["words"].split('\t'))
wordsret = "0" * words
ret["prwords"] = wordsret
ret["prwordsA"] = wordsret
ret["prwordsC"] = wordsret
ret["prwordsE"] = wordsret
ret["prwordsJ"] = wordsret
ret["prwordsK"] = wordsret
ret["prwordsP"] = wordsret
ret["returncd"] = "000"
ret["datetime"] = time.strftime("%Y%m%d%H%M%S")
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("NODE", "wifiappe1")
logger.log(logging.DEBUG, "pr response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
ret = self.dict_to_str(ret)
else:
logger.log(logging.WARNING, "Unknown action request %s from %s!", self.path, self.client_address)
ret = ''
elif self.path == "/download":
logger.log(logging.DEBUG, "Request to %s from %s", self.path, self.client_address)
logger.log(logging.DEBUG, post)
elif self.path == "/pr":
logger.log(logging.DEBUG, "Request to %s from %s", self.path, self.client_address)
logger.log(logging.DEBUG, post)
ret = {}
action = post["action"]
words = len(post["words"].split('\t'))
wordsret = "0" * words
ret["prwords"] = wordsret
ret["prwordsA"] = wordsret
ret["prwordsC"] = wordsret
ret["prwordsE"] = wordsret
ret["prwordsJ"] = wordsret
ret["prwordsK"] = wordsret
ret["prwordsP"] = wordsret
ret["returncd"] = "000"
ret["datetime"] = time.strftime("%Y%m%d%H%M%S")
ret = ""
dlcdir = os.path.abspath('dlc')
dlcpath = os.path.abspath("dlc/" + post["gamecd"])
dlc_contenttype = False
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("NODE", "wifiappe1")
if os.path.commonprefix([dlcdir, dlcpath]) != dlcdir:
logging.log(logging.WARNING, 'Attempted directory traversal attack "%s", cancelling.', dlcpath)
self.send_response(403)
return
logger.log(logging.DEBUG, "pr response to %s", self.client_address)
logger.log(logging.DEBUG, ret)
def safeloadfi(fn, mode='rb'):
'''
safeloadfi : string -> string
ret = self.dict_to_str(ret)
Safely load contents of a file, given a filename, and closing the file afterward
'''
with open(os.path.join(dlcpath, fn), mode) as fi:
return fi.read()
elif self.path == "/download":
logger.log(logging.DEBUG, "Request to %s from %s", self.path, self.client_address)
logger.log(logging.DEBUG, post)
if action == "count":
if post["gamecd"] in gamecodes_return_random_file:
ret = "1"
else:
count = 0
action = post["action"]
if os.path.exists(dlcpath):
count = len(os.listdir(dlcpath))
ret = ""
dlcdir = os.path.abspath('dlc')
dlcpath = os.path.abspath("dlc/" + post["gamecd"])
dlc_contenttype = False
if os.path.commonprefix([dlcdir, dlcpath]) != dlcdir:
logging.log(logging.WARNING, 'Attempted directory traversal attack "%s", cancelling.', dlcpath)
self.send_response(403)
return
if os.path.isfile(dlcpath + "/_list.txt"):
attr1 = None
if "attr1" in post:
attr1 = post["attr1"]
attr2 = None
if "attr2" in post:
attr2 = post["attr2"]
attr3 = None
if "attr3" in post:
attr3 = post["attr3"]
def safeloadfi(fn, mode='rb'):
'''
safeloadfi : string -> string
dlcfi = safeloadfi("_list.txt")
lst = self.filter_list(dlcfi, attr1, attr2, attr3)
count = self.get_file_count(lst)
Safely load contents of a file, given a filename, and closing the file afterward
'''
with open(os.path.join(dlcpath, fn), mode) as fi:
return fi.read()
ret = "%d" % count
if action == "count":
if post["gamecd"] in gamecodes_return_random_file:
ret = "1"
else:
count = 0
if action == "list":
num = int(post["num"])
offset = int(post["offset"])
attr1 = None
if "attr1" in post:
attr1 = post["attr1"]
attr2 = None
if "attr2" in post:
attr2 = post["attr2"]
attr3 = None
if "attr3" in post:
attr3 = post["attr3"]
if os.path.exists(dlcpath):
count = len(os.listdir(dlcpath))
# Look for a list file first.
# If the list file exists, send the entire thing back to the client.
if os.path.isfile(os.path.join(dlcpath, "_list.txt")):
ret = self.filter_list(safeloadfi("_list.txt"), attr1, attr2, attr3)
if os.path.isfile(dlcpath + "/_list.txt"):
attr1 = None
if "attr1" in post:
attr1 = post["attr1"]
attr2 = None
if "attr2" in post:
attr2 = post["attr2"]
attr3 = None
if "attr3" in post:
attr3 = post["attr3"]
if post["gamecd"] in gamecodes_return_random_file:
ret = self.filter_list_random_files(ret, 1)
dlcfi = safeloadfi("_list.txt")
lst = self.filter_list(dlcfi, attr1, attr2, attr3)
count = self.get_file_count(lst)
if action == "contents":
# Get only the base filename just in case there is a path involved somewhere in the filename string.
dlc_contenttype = True
contents = os.path.basename(post["contents"])
ret = safeloadfi(contents)
ret = "%d" % count
self.send_response(200)
if action == "list":
num = int(post["num"])
offset = int(post["offset"])
if dlc_contenttype == True:
self.send_header("Content-type", "application/x-dsdl")
self.send_header("Content-Disposition", "attachment; filename=\"" + post["contents"] + "\"")
else:
self.send_header("Content-type", "text/plain")
attr1 = None
if "attr1" in post:
attr1 = post["attr1"]
attr2 = None
if "attr2" in post:
attr2 = post["attr2"]
attr3 = None
if "attr3" in post:
attr3 = post["attr3"]
self.send_header("X-DLS-Host", "http://127.0.0.1/")
if os.path.exists(dlcpath):
# Look for a list file first.
# If the list file exists, send the entire thing back to the client.
if os.path.isfile(os.path.join(dlcpath, "_list.txt")):
ret = self.filter_list(safeloadfi("_list.txt"), attr1, attr2, attr3)
logger.log(logging.DEBUG, "download response to %s", self.client_address)
if post["gamecd"] in gamecodes_return_random_file:
ret = self.filter_list_random_files(ret, 1)
if action == "contents":
# Get only the base filename just in case there is a path involved somewhere in the filename string.
dlc_contenttype = True
contents = os.path.basename(post["contents"])
ret = safeloadfi(contents)
self.send_response(200)
if dlc_contenttype == True:
self.send_header("Content-type", "application/x-dsdl")
self.send_header("Content-Disposition", "attachment; filename=\"" + post["contents"] + "\"")
#if dlc_contenttype == False:
# logger.log(logging.DEBUG, ret)
else:
self.send_header("Content-type", "text/plain")
logger.log(logging.WARNING, "Unknown path request %s from %s!", self.path, self.client_address)
self.send_header("X-DLS-Host", "http://127.0.0.1/")
logger.log(logging.DEBUG, "download response to %s", self.client_address)
#if dlc_contenttype == False:
# logger.log(logging.DEBUG, ret)
else:
logger.log(logging.WARNING, "Unknown path request %s from %s!", self.path, self.client_address)
self.send_header("Content-Length", str(len(ret)))
self.end_headers()
self.wfile.write(ret)
self.send_header("Content-Length", str(len(ret)))
self.end_headers()
self.wfile.write(ret)
except:
logger.log(logging.ERROR, "Unknown exception: %s" % traceback.format_exc())
def str_to_dict(self, str):
ret = urlparse.parse_qs(str)