Closed illwieckz closed 7 years ago
Hi, I have a working proof of concept: :smiley:
query_status_t deal_with_teemaster_packet( struct qserver *server, char *pkt, int pktlen )
{
char last_char;
int num_server;
int len_address_packet = 6;
int len_address_packe2 = 18;
int i;
int shift;
unsigned int ipv4[4];
unsigned int port;
// get the last character
last_char = pkt[len_tee_masterlist_headerprefix];
// compare the response without the last character
if ((0 == memcmp( pkt, tee_masterlist_headerprefix, len_tee_masterlist_headerprefix)))
{
// compare if the last character is 't' or '2'
if (last_char == 't')
{
num_server = (pktlen - len_tee_masterlist_header) / (len_address_packet);
for (i = 0; i < num_server; i++)
{
shift = len_tee_masterlist_header + (len_address_packet * i);
ipv4[0] = (unsigned char) pkt[shift];
ipv4[1] = (unsigned char) pkt[shift + 1];
ipv4[2] = (unsigned char) pkt[shift + 2];
ipv4[3] = (unsigned char) pkt[shift + 3];
port = (unsigned char) pkt[shift + 4] + ((unsigned char) pkt[shift + 5] << 8);
printf("PoC, addr: %u.%u.%u.%u:%u\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3], port);
// stub
}
}
else if (last_char == '2')
{
num_server = (pktlen - len_tee_masterlist_header) / (len_address_packe2);
for (i = 0; i < num_server; i++)
{
// stub
}
}
}
return (query_status_t) NULL; // stub
}
If I do ./qstat -teem master2.teeworlds.com:8300
It prints:
PoC, addr: 77.82.62.69:8305
PoC, addr: 24.132.121.123:8333
PoC, addr: 24.132.121.123:8309
PoC, addr: 81.30.158.57:8308
PoC, addr: 24.132.121.123:8303
PoC, addr: 195.112.231.229:8312
PoC, addr: 81.30.158.57:8313
PoC, addr: 217.18.138.26:8304
PoC, addr: 81.30.158.57:6050
PoC, addr: 109.74.202.76:8404
PoC, addr: 81.30.158.57:8311
PoC, addr: 81.30.158.57:8888
PoC, addr: 24.132.121.123:8324
PoC, addr: 24.132.121.123:8328
PoC, addr: 81.30.158.57:6053
PoC, addr: 24.132.121.123:8322
PoC, addr: 24.132.121.123:8321
PoC, addr: 81.30.158.57:8314
PoC, addr: 24.132.121.123:8310
PoC, addr: 24.132.121.123:8327
PoC, addr: 109.74.202.76:8408
PoC, addr: 24.132.121.123:8308
PoC, addr: 24.132.121.123:8317
PoC, addr: 24.132.121.123:8320
PoC, addr: 195.112.231.229:8314
PoC, addr: 109.74.202.76:8406
PoC, addr: 24.132.121.123:8306
PoC, addr: 81.30.158.57:8332
PoC, addr: 46.18.200.203:8303
PoC, addr: 81.30.158.57:8373
PoC, addr: 24.132.121.123:8305
PoC, addr: 24.132.121.123:8302
PoC, addr: 195.112.231.229:8311
PoC, addr: 93.79.156.148:8303
PoC, addr: 24.132.121.123:8304
Which is the same than get_list(("master2.teeworlds.com", 8300))
from tw_api.py
.
How I populate the server list? What is the internal ip addr and port format in QStat?
Thanks in advance. :smile:
my deal_with_teemaster_packet
proof of concept now looks like that:
query_status_t deal_with_teemaster_packet(struct qserver *server, char *rawpkt, int rawpktlen)
{
int i;
int skip;
int num_server;
int len_address_packet = 6;
int len_address_packe2 = 18;
char last_char;
unsigned int ipv4[4];
unsigned int port;
if (len_teemaster_list_headerprefix > rawpktlen) {
return PKT_ERROR;
}
/* get the last character */
last_char = rawpkt[len_teemaster_list_headerprefix];
/* compare the response without the last character */
if ((memcmp(rawpkt, teemaster_list_headerprefix, len_teemaster_list_headerprefix)) != 0) {
return PKT_ERROR;
}
/* legacy server format, only ipv4 addresses */
if (last_char == 't') {
num_server = (rawpktlen - len_teemaster_list_header) / (len_address_packet);
for (i = 0; i < num_server; i++) {
skip = len_teemaster_list_header + (len_address_packet * i);
if (skip + len_address_packet > rawpktlen) {
return PKT_ERROR;
}
ipv4[0] = (unsigned char) rawpkt[skip];
ipv4[1] = (unsigned char) rawpkt[skip + 1];
ipv4[2] = (unsigned char) rawpkt[skip + 2];
ipv4[3] = (unsigned char) rawpkt[skip + 3];
port = (unsigned char) rawpkt[skip + 4] + ((unsigned char) rawpkt[skip + 5] << 8);
printf("PoC, addr: %u.%u.%u.%u:%u\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3], port);
/* stub */
}
}
/* normal server format */
else if (last_char == '2') {
num_server = (rawpktlen - len_teemaster_list_header) / (len_address_packe2);
for (i = 0; i < num_server; i++) {
skip = len_teemaster_list_header + (len_address_packe2 * i);
if (skip + len_address_packe2 > rawpktlen) {
return PKT_ERROR;
}
/* ipv4 address */
if ((0 == memcmp(rawpkt + skip, ipv4_header, len_ipv4_header))) {
skip = len_teemaster_list_header + (len_address_packe2 * i);
ipv4[0] = (unsigned char) rawpkt[skip + len_ipv4_header];
ipv4[1] = (unsigned char) rawpkt[skip + len_ipv4_header + 1];
ipv4[2] = (unsigned char) rawpkt[skip + len_ipv4_header + 2];
ipv4[3] = (unsigned char) rawpkt[skip + len_ipv4_header + 3];
port = ((unsigned char) rawpkt[skip + len_ipv4_header + 4] << 8) + (unsigned char) rawpkt[skip + len_ipv4_header + 5];
printf("PoC, addr: %u.%u.%u.%u:%u\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3], port);
/* stub */
}
/* ipv6 address */
else {
skip = len_teemaster_list_header + (len_address_packe2 * i);
/* stub */
}
else {
return PKT_ERROR;
}
}
}
/* unknown server format */
else {
return PKT_ERROR;
}
return (query_status_t) NULL; /* stub */
}
This proof of concept works for both legacy and normal servers, but I don't know how to populate the server list and what is the qstat internal ip format.
We can read https://github.com/teeworlds/teeworlds/blob/master/scripts/tw_api.py
There is two way to query master servers:
Then, the response format differs. We can read
get_list
andget_list2
functions to understand theses formats.We don't have to return
SERVERTYPE
, onlyip
andport
, since the-tees
qstat function I udpdated recognizes server types.Master servers can understand the two queries, in this case, they respond a different list of servers.