Started to implement the server browser

This commit is contained in:
polaris
2014-04-01 06:04:06 -04:00
parent 5bf10bcdb4
commit 3ba94e1725
3 changed files with 139 additions and 7 deletions

3
.gitignore vendored
View File

@@ -221,4 +221,5 @@ pip-log.txt
.idea/vcs.xml
.idea/workspace.xml
gpcm.db
.idea/dictionaries/Nagato.xml
.idea/dictionaries/Nagato.xml
.idea/modules.xml

View File

@@ -67,4 +67,40 @@ def base32_decode(str, reverse = False):
# For server logging
def print_log(text):
print "[%s] %s" % (time.strftime("%c"), text)
print ""
print ""
# Number routines
# I'm not sure what the pythonic way to do this is, so I'm making the code explicit by giving myself functions to
# convert the bytes to ints.
def get_num_from_bytes(data, idx, bytes, bigEndian = False):
# Get only the bytes we want to work with
data = data[idx:idx+bytes]
if bigEndian == True:
data = data[::-1]
num = 0
i = 0
while i < bytes and i < len(data):
num |= (ord(data[i]) << (8 * i))
i += 1
return num
# Instead of passing slices, pass the buffer and index so we can calculate the length automatically.
def get_short(data, idx):
return get_num_from_bytes(data, idx, 2, False)
def get_short_be(data, idx):
return get_num_from_bytes(data, idx, 2, True)
def get_int(data, idx):
return get_num_from_bytes(data, idx, 4, False)
def get_int_be(data, idx):
return get_num_from_bytes(data, idx, 4, True)
def get_string(data, idx):
data = data[idx:]
end = data.index('\0')
return data[:end]

View File

@@ -24,11 +24,106 @@ s.listen(backlog)
utils.print_log("Server is now listening on %s:%s..." % (address[0], address[1]))
while 1:
client, address = s.accept()
client, addr = s.accept()
utils.print_log("Received connection from %s:%s" % (address[0], address[1]))
while 1:
receive_data = True
while receive_data:
utils.print_log("Waiting for data...")
accept_connection = True
data = client.recv(size).rstrip()
utils.print_log("RESPONSE: %s" % data)
data = client.recv(size)
# Didn't get a valid command.
# Player disconnected?
# Close connection
if not data:
break
# 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 data[2] == '\x00': # Server list request
utils.print_log("Received server list request from %s:%s..." % (addr[0], addr[1]))
# 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
ALTERNATE_SOURCE_IP = 0x08
LIMIT_RESULT_COUNT = 0x80
if (options & LIMIT_RESULT_COUNT):
max_servers = utils.get_int(data, idx)
elif (options & ALTERNATE_SOURCE_IP):
source_ip = utils.get_int(data, idx)
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)
# TODO: Handle query
elif data[2] == '\x02': # Send message request
dest_addr = '.'.join(["%d" % x for x in addr[3:7]])
dest_port = utils.get_short_be(addr, 7) # What's the pythonic way to do this? unpack?
dest = (dest_addr, dest_port)
# Wait for message data
msg_data = client.recv(size)
utils.print_log("Received send message request from %s:%s to %s:%d... %s" % (addr[0], addr[1], dest_addr, dest_port, msg_data))
# Create new connection to send to other user over UDP.
# Move this code somewhere else after testing has been finished.
user_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
user_s.bind(dest)
user_s.sendto(msg_data, dest)
utils.print_log("Sent message to %s:%d... %s" % (dest_addr, dest_port, msg_data))
elif data[2] == '\x03': # Keep alive reply
utils.print_log("Received keep alive from %s:%s..." % (addr[0], addr[1]))
else:
utils.print_log("Received unknown command (%02x) from %s:%s... %s" % (ord(data[2]), addr[0], addr[1], data))