mirror of
https://github.com/rocketsciencegg/qstat
synced 2026-08-18 12:23:04 -04:00
Due to the age of the qstat code base it had really varied style making it hard to maintain. This commit reformats the code to a common style using the uncrustify utility with the cmd: uncrustify -c uncrustify.cfg --no-backup
228 lines
4.1 KiB
C
228 lines
4.1 KiB
C
/*
|
|
* qstat
|
|
* by Steve Jankowski
|
|
*
|
|
* Cube 2 / Sauerbraten protocol
|
|
* Copyright 2011 NoisyB
|
|
*
|
|
* Licensed under the Artistic License, see LICENSE.txt for license terms
|
|
*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "debug.h"
|
|
#include "qstat.h"
|
|
#include "packet_manip.h"
|
|
|
|
struct offset {
|
|
unsigned char *d;
|
|
int pos;
|
|
int len;
|
|
};
|
|
|
|
//#define SB_MASTER_SERVER "http://sauerbraten.org/masterserver/retrieve.do?item=list"
|
|
#define SB_PROTOCOL 258
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#define MAX_ATTR 255
|
|
#define MAX_STRING 1024
|
|
|
|
static int
|
|
getint(struct offset *d)
|
|
{
|
|
int val = 0;
|
|
|
|
if (d->pos >= d->len) {
|
|
return (0);
|
|
}
|
|
|
|
val = d->d[d->pos++] & 0xff;// 8 bit value
|
|
|
|
// except...
|
|
if ((val == 0x80) && (d->pos < d->len - 2)) { // 16 bit value
|
|
val = (d->d[d->pos++] & 0xff);
|
|
val |= (d->d[d->pos++] & 0xff) << 8;
|
|
} else if ((val == 0x81) && (d->pos < d->len - 4)) { // 32 bit value
|
|
val = (d->d[d->pos++] & 0xff);
|
|
val |= (d->d[d->pos++] & 0xff) << 8;
|
|
val |= (d->d[d->pos++] & 0xff) << 16;
|
|
val |= (d->d[d->pos++] & 0xff) << 24;
|
|
}
|
|
|
|
return (val);
|
|
}
|
|
|
|
|
|
static char *
|
|
getstr(char *dest, int dest_len, struct offset *d)
|
|
{
|
|
int len = 0;
|
|
|
|
if (d->pos >= d->len) {
|
|
return (NULL);
|
|
}
|
|
|
|
len = MIN(dest_len, d->len - d->pos);
|
|
strncpy(dest, (const char *)d->d + d->pos, len)[len - 1] = 0;
|
|
d->pos += strlen(dest) + 1;
|
|
|
|
return (dest);
|
|
}
|
|
|
|
|
|
static char *
|
|
sb_getversion_s(int n)
|
|
{
|
|
static char *version_s[] =
|
|
{
|
|
"Justice",
|
|
"CTF",
|
|
"Assassin",
|
|
"Summer",
|
|
"Spring",
|
|
"Gui",
|
|
"Water",
|
|
"Normalmap",
|
|
"Sp",
|
|
"Occlusion",
|
|
"Shader",
|
|
"Physics",
|
|
"Mp",
|
|
"",
|
|
"Agc",
|
|
"Quakecon",
|
|
"Independence"
|
|
};
|
|
|
|
n = SB_PROTOCOL - n;
|
|
if ((n >= 0) && ((size_t)n < sizeof(version_s) / sizeof(version_s[0]))) {
|
|
return (version_s[n]);
|
|
}
|
|
return ("unknown");
|
|
}
|
|
|
|
|
|
static char *
|
|
sb_getmode_s(int n)
|
|
{
|
|
static char *mode_s[] =
|
|
{
|
|
"slowmo SP",
|
|
"slowmo DMSP",
|
|
"demo",
|
|
"SP",
|
|
"DMSP",
|
|
"ffa/default",
|
|
"coopedit",
|
|
"ffa/duel",
|
|
"teamplay",
|
|
"instagib",
|
|
"instagib team",
|
|
"efficiency",
|
|
"efficiency team",
|
|
"insta arena",
|
|
"insta clan arena",
|
|
"tactics arena",
|
|
"tactics clan arena",
|
|
"capture",
|
|
"insta capture",
|
|
"regen capture",
|
|
"assassin",
|
|
"insta assassin",
|
|
"ctf",
|
|
"insta ctf"
|
|
};
|
|
|
|
n += 6;
|
|
if ((n >= 0) && ((size_t)n < sizeof(mode_s) / sizeof(mode_s[0]))) {
|
|
return (mode_s[n]);
|
|
}
|
|
return ("unknown");
|
|
}
|
|
|
|
|
|
query_status_t
|
|
send_cube2_request_packet(struct qserver *server)
|
|
{
|
|
return (send_packet(server, server->type->status_packet, server->type->status_len));
|
|
}
|
|
|
|
|
|
query_status_t
|
|
deal_with_cube2_packet(struct qserver *server, char *rawpkt, int pktlen)
|
|
{
|
|
// skip unimplemented ack, crc, etc
|
|
int i;
|
|
int numattr;
|
|
int attr[MAX_ATTR];
|
|
char buf[MAX_STRING];
|
|
|
|
enum {
|
|
MM_OPEN = 0,
|
|
MM_VETO,
|
|
MM_LOCKED,
|
|
MM_PRIVATE
|
|
};
|
|
|
|
struct offset d;
|
|
d.d = (unsigned char *)rawpkt;
|
|
d.pos = 0;
|
|
d.len = pktlen;
|
|
|
|
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
|
|
getint(&d); // we have the ping already
|
|
server->num_players = getint(&d);
|
|
numattr = getint(&d);
|
|
for (i = 0; i < numattr && i < MAX_ATTR; i++) {
|
|
attr[i] = getint(&d);
|
|
}
|
|
|
|
server->protocol_version = attr[0];
|
|
|
|
sprintf(buf, "%d %s", attr[0], sb_getversion_s(attr[0]));
|
|
add_rule(server, "version", buf, NO_FLAGS);
|
|
|
|
sprintf(buf, "%d %s", attr[1], sb_getmode_s(attr[1]));
|
|
add_rule(server, "mode", buf, NO_FLAGS);
|
|
|
|
sprintf(buf, "%d", attr[2]);
|
|
add_rule(server, "seconds_left", buf, NO_FLAGS);
|
|
|
|
server->max_players = attr[3];
|
|
|
|
switch (attr[5]) {
|
|
case MM_OPEN:
|
|
sprintf(buf, "%d open", attr[5]);
|
|
break;
|
|
|
|
case MM_VETO:
|
|
sprintf(buf, "%d veto", attr[5]);
|
|
break;
|
|
|
|
case MM_LOCKED:
|
|
sprintf(buf, "%d locked", attr[5]);
|
|
break;
|
|
|
|
case MM_PRIVATE:
|
|
sprintf(buf, "%d private", attr[5]);
|
|
break;
|
|
|
|
default:
|
|
sprintf(buf, "%d unknown", attr[5]);
|
|
}
|
|
add_rule(server, "mm", buf, NO_FLAGS);
|
|
|
|
for (i = 0; i < numattr && i < MAX_ATTR; i++) {
|
|
char buf2[MAX_STRING];
|
|
sprintf(buf, "attr%d", i);
|
|
sprintf(buf2, "%d", attr[i]);
|
|
add_rule(server, buf, buf2, NO_FLAGS);
|
|
}
|
|
|
|
getstr(buf, MAX_STRING, &d);
|
|
server->map_name = strdup(buf);
|
|
getstr(buf, MAX_STRING, &d);
|
|
server->server_name = strdup(buf);
|
|
|
|
return (DONE_FORCE);
|
|
}
|