mirror of
https://github.com/barronwaffles/dwc_network_server_emulator.git
synced 2026-08-25 03:55:53 -05:00
Started to implement the server browser
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -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
|
||||
@@ -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]
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user