mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 22:48:18 +00:00
Merge pull request #1705 from nheir/tw_api
tw_api: fix getinfo returning None, add comments
This commit is contained in:
commit
fe57e857ea
|
@ -12,14 +12,14 @@ MASTERSERVER_PORT = 8283
|
||||||
|
|
||||||
TIMEOUT = 2
|
TIMEOUT = 2
|
||||||
|
|
||||||
SERVERTYPE_NORMAL = 0
|
# src/mastersrv/mastersrv.h
|
||||||
|
|
||||||
PACKET_GETLIST = b"\xff\xff\xff\xffreq2"
|
PACKET_GETLIST = b"\xff\xff\xff\xffreq2"
|
||||||
PACKET_LIST = b"\xff\xff\xff\xfflis2"
|
PACKET_LIST = b"\xff\xff\xff\xfflis2"
|
||||||
|
|
||||||
PACKET_GETINFO = b"\xff\xff\xff\xffgie3"
|
PACKET_GETINFO = b"\xff\xff\xff\xffgie3"
|
||||||
PACKET_INFO = b"\xff\xff\xff\xffinf3"
|
PACKET_INFO = b"\xff\xff\xff\xffinf3"
|
||||||
|
|
||||||
|
# see CNetBase::SendControlMsgWithToken
|
||||||
def pack_control_msg_with_token(token_srv,token_cl):
|
def pack_control_msg_with_token(token_srv,token_cl):
|
||||||
NET_PACKETFLAG_CONTROL = 1
|
NET_PACKETFLAG_CONTROL = 1
|
||||||
NET_CTRLMSG_TOKEN = 5
|
NET_CTRLMSG_TOKEN = 5
|
||||||
|
@ -45,6 +45,7 @@ def unpack_control_msg_with_token(msg):
|
||||||
token_srv = (b[8] << 24) + (b[9] << 16) + (b[10] << 8) + (b[11])
|
token_srv = (b[8] << 24) + (b[9] << 16) + (b[10] << 8) + (b[11])
|
||||||
return token_cl,token_srv
|
return token_cl,token_srv
|
||||||
|
|
||||||
|
# CNetBase::SendPacketConnless
|
||||||
def header_connless(token_srv, token_cl):
|
def header_connless(token_srv, token_cl):
|
||||||
NET_PACKETFLAG_CONNLESS = 8
|
NET_PACKETFLAG_CONNLESS = 8
|
||||||
NET_PACKETVERSION = 1
|
NET_PACKETVERSION = 1
|
||||||
|
@ -60,18 +61,7 @@ def header_connless(token_srv, token_cl):
|
||||||
b[8] = (token_cl) & 0xff
|
b[8] = (token_cl) & 0xff
|
||||||
return bytes(b)
|
return bytes(b)
|
||||||
|
|
||||||
class Server_Info(threading.Thread):
|
# CVariableInt::Unpack from src/engine/shared/compression.cpp
|
||||||
|
|
||||||
def __init__(self, address):
|
|
||||||
self.address = address
|
|
||||||
self.finished = False
|
|
||||||
threading.Thread.__init__(self, target = self.run)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.info = None
|
|
||||||
self.info = get_server_info(self.address)
|
|
||||||
self.finished = True
|
|
||||||
|
|
||||||
def unpack_int(b):
|
def unpack_int(b):
|
||||||
l = list(b[:5])
|
l = list(b[:5])
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -103,15 +93,31 @@ def unpack_int(b):
|
||||||
res ^= -Sign
|
res ^= -Sign
|
||||||
return res, b[i:]
|
return res, b[i:]
|
||||||
|
|
||||||
|
class Server_Info(threading.Thread):
|
||||||
|
|
||||||
|
def __init__(self, address):
|
||||||
|
self.address = address
|
||||||
|
self.finished = False
|
||||||
|
threading.Thread.__init__(self, target = self.run)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.info = None
|
||||||
|
self.info = get_server_info(self.address)
|
||||||
|
self.finished = True
|
||||||
|
|
||||||
def get_server_info(address):
|
def get_server_info(address):
|
||||||
try:
|
try:
|
||||||
sock = socket(AF_INET, SOCK_DGRAM)
|
sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
sock.settimeout(TIMEOUT)
|
sock.settimeout(TIMEOUT)
|
||||||
token = random.randrange(0x100000000)
|
token = random.randrange(0x100000000)
|
||||||
|
|
||||||
|
# Token request
|
||||||
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
token_cl, token_srv = unpack_control_msg_with_token(data)
|
token_cl, token_srv = unpack_control_msg_with_token(data)
|
||||||
assert token_cl == token, "Server %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
assert token_cl == token, "Server %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
||||||
|
|
||||||
|
# Get info request
|
||||||
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETINFO + b'\x00', address)
|
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETINFO + b'\x00', address)
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
head = header_connless(token_cl, token_srv) + PACKET_INFO + b'\x00'
|
head = header_connless(token_cl, token_srv) + PACKET_INFO + b'\x00'
|
||||||
|
@ -152,7 +158,7 @@ def get_server_info(address):
|
||||||
return server_info
|
return server_info
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
print(*e.args)
|
print(*e.args)
|
||||||
except OSError as e:
|
except OSError as e: # Timeout
|
||||||
print('> Server %s did not answer' % (address,))
|
print('> Server %s did not answer' % (address,))
|
||||||
except:
|
except:
|
||||||
# import traceback
|
# import traceback
|
||||||
|
@ -160,7 +166,7 @@ def get_server_info(address):
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Master_Server_Info(threading.Thread):
|
class Master_Server_Info(threading.Thread):
|
||||||
|
@ -183,23 +189,30 @@ def get_list(address):
|
||||||
sock.settimeout(TIMEOUT)
|
sock.settimeout(TIMEOUT)
|
||||||
|
|
||||||
token = random.randrange(0x100000000)
|
token = random.randrange(0x100000000)
|
||||||
|
|
||||||
|
# Token request
|
||||||
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
sock.sendto(pack_control_msg_with_token(-1,token),address)
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
token_cl, token_srv = unpack_control_msg_with_token(data)
|
token_cl, token_srv = unpack_control_msg_with_token(data)
|
||||||
assert token_cl == token, "Master %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
assert token_cl == token, "Master %s send wrong token: %d (%d expected)" % (address, token_cl, token)
|
||||||
|
|
||||||
|
# Get list request
|
||||||
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETLIST, addr)
|
sock.sendto(header_connless(token_srv, token_cl) + PACKET_GETLIST, addr)
|
||||||
head = header_connless(token_cl, token_srv) + PACKET_LIST
|
head = header_connless(token_cl, token_srv) + PACKET_LIST
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
data, addr = sock.recvfrom(1024)
|
data, addr = sock.recvfrom(1024)
|
||||||
|
# Header should keep consistent
|
||||||
assert data[:len(head)] == head, "Master %s list header mismatch: %r != %r (expected)" % (address, data[:len(head)], head)
|
assert data[:len(head)] == head, "Master %s list header mismatch: %r != %r (expected)" % (address, data[:len(head)], head)
|
||||||
|
|
||||||
data = data[len(head):]
|
data = data[len(head):]
|
||||||
num_servers = len(data) // 18
|
num_servers = len(data) // 18
|
||||||
|
|
||||||
for n in range(0, num_servers):
|
for n in range(0, num_servers):
|
||||||
|
# IPv4
|
||||||
if data[n*18:n*18+12] == b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff":
|
if data[n*18:n*18+12] == b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff":
|
||||||
ip = ".".join(map(str, data[n*18+12:n*18+16]))
|
ip = ".".join(map(str, data[n*18+12:n*18+16]))
|
||||||
|
# IPv6
|
||||||
else:
|
else:
|
||||||
ip = ":".join(map(str, data[n*18:n*18+16]))
|
ip = ":".join(map(str, data[n*18:n*18+16]))
|
||||||
port = ((data[n*18+16])<<8) + data[n*18+17]
|
port = ((data[n*18+16])<<8) + data[n*18+17]
|
||||||
|
@ -207,7 +220,7 @@ def get_list(address):
|
||||||
|
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
print(*e.args)
|
print(*e.args)
|
||||||
except OSError as e:
|
except OSError as e: # Timeout
|
||||||
if not servers:
|
if not servers:
|
||||||
print('> Master %s did not answer' % (address,))
|
print('> Master %s did not answer' % (address,))
|
||||||
except:
|
except:
|
||||||
|
@ -217,48 +230,45 @@ def get_list(address):
|
||||||
|
|
||||||
return servers
|
return servers
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
master_servers = []
|
||||||
|
|
||||||
|
for i in range(1, NUM_MASTERSERVERS+1):
|
||||||
|
m = Master_Server_Info(("master%d.teeworlds.com"%i, MASTERSERVER_PORT))
|
||||||
|
master_servers.append(m)
|
||||||
|
m.start()
|
||||||
|
time.sleep(0.001) # avoid issues
|
||||||
|
|
||||||
master_servers = []
|
servers = []
|
||||||
|
|
||||||
for i in range(1, NUM_MASTERSERVERS+1):
|
while len(master_servers) != 0:
|
||||||
m = Master_Server_Info(("master%d.teeworlds.com"%i, MASTERSERVER_PORT))
|
if master_servers[0].finished == True:
|
||||||
master_servers.append(m)
|
if master_servers[0].servers:
|
||||||
m.start()
|
servers += master_servers[0].servers
|
||||||
time.sleep(0.001) # avoid issues
|
del master_servers[0]
|
||||||
|
time.sleep(0.001) # be nice
|
||||||
|
|
||||||
servers = []
|
servers_info = []
|
||||||
|
|
||||||
while len(master_servers) != 0:
|
print(str(len(servers)) + " servers")
|
||||||
if master_servers[0].finished == True:
|
|
||||||
if master_servers[0].servers:
|
|
||||||
servers += master_servers[0].servers
|
|
||||||
del master_servers[0]
|
|
||||||
time.sleep(0.001) # be nice
|
|
||||||
|
|
||||||
servers_info = []
|
for server in servers:
|
||||||
|
s = Server_Info(server)
|
||||||
|
servers_info.append(s)
|
||||||
|
s.start()
|
||||||
|
time.sleep(0.001) # avoid issues
|
||||||
|
|
||||||
print(str(len(servers)) + " servers")
|
num_players = 0
|
||||||
|
num_clients = 0
|
||||||
|
|
||||||
for server in servers:
|
while len(servers_info) != 0:
|
||||||
s = Server_Info(server)
|
if servers_info[0].finished == True:
|
||||||
servers_info.append(s)
|
if servers_info[0].info:
|
||||||
s.start()
|
num_players += servers_info[0].info["num_players"]
|
||||||
time.sleep(0.001) # avoid issues
|
num_clients += servers_info[0].info["num_clients"]
|
||||||
|
|
||||||
num_players = 0
|
del servers_info[0]
|
||||||
num_clients = 0
|
|
||||||
|
|
||||||
player_names = []
|
time.sleep(0.001) # be nice
|
||||||
while len(servers_info) != 0:
|
|
||||||
if servers_info[0].finished == True:
|
|
||||||
|
|
||||||
if servers_info[0].info:
|
print(str(num_players) + " players and " + str(num_clients-num_players) + " spectators")
|
||||||
num_players += servers_info[0].info["num_players"]
|
|
||||||
num_clients += servers_info[0].info["num_clients"]
|
|
||||||
|
|
||||||
del servers_info[0]
|
|
||||||
|
|
||||||
time.sleep(0.001) # be nice
|
|
||||||
|
|
||||||
print(str(num_players) + " players and " + str(num_clients-num_players) + " spectators")
|
|
||||||
|
|
Loading…
Reference in a new issue