2014-10-29 08:02:03 +01:00
|
|
|
LICENSE: The Artistic License 2.0
|
|
|
|
|
|
|
|
/*
|
|
|
|
* qstat.h
|
|
|
|
* by Steve Jankowski
|
|
|
|
* steve@qstat.org
|
|
|
|
* http://www.qstat.org
|
|
|
|
*
|
|
|
|
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
unsigned char farcry_serverquery[] = {
|
|
|
|
0x08,0x80
|
|
|
|
};
|
|
|
|
|
|
|
|
{
|
|
|
|
/* FARCRY PROTOCOL */
|
|
|
|
FARCRY_SERVER, /* id */
|
|
|
|
"FCS", /* type_prefix */
|
|
|
|
"fcs", /* type_string */
|
|
|
|
"-fcs", /* type_option */
|
|
|
|
"FarCry", /* game_name */
|
|
|
|
0, /* master */
|
|
|
|
FARCRY_DEFAULT_PORT, /* default_port */
|
|
|
|
0, /* port_offset */
|
|
|
|
TF_QUERY_ARG, /* flags */
|
|
|
|
"gametype", /* game_rule */
|
|
|
|
"FARCRY", /* template_var */
|
|
|
|
(char*)farcry_serverquery, /* status_packet */
|
|
|
|
sizeof( savage_serverquery ) - 1, /* status_len */
|
|
|
|
NULL, /* player_packet */
|
|
|
|
0, /* player_len */
|
|
|
|
NULL, /* rule_packet */
|
|
|
|
0, /* rule_len */
|
|
|
|
NULL, /* master_packet */
|
|
|
|
0, /* master_len */
|
|
|
|
NULL, /* master_protocol */
|
|
|
|
NULL, /* master_query */
|
|
|
|
display_farcry_player_info, /* display_player_func */
|
|
|
|
display_server_rules, /* display_rule_func */
|
|
|
|
raw_display_farcry_player_info, /* display_raw_player_func */
|
|
|
|
raw_display_server_rules, /* display_raw_rule_func */
|
|
|
|
xml_display_farcry_player_info, /* display_xml_player_func */
|
|
|
|
xml_display_server_rules, /* display_xml_rule_func */
|
|
|
|
send_farcry_request_packet, /* status_query_func */
|
|
|
|
NULL, /* rule_query_func */
|
|
|
|
NULL, /* player_query_func */
|
|
|
|
deal_with_farcry_packet, /* packet_func */
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query_status_t send_farcry_request_packet(struct qserver *server)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *pkt;
|
|
|
|
|
|
|
|
if (get_player_info)
|
|
|
|
{
|
|
|
|
pkt = server->type->player_packet;
|
|
|
|
len = server->type->player_len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pkt = server->type->status_packet;
|
|
|
|
len = server->type->status_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return send_packet(server, pkt, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query_status_t deal_with_farcry_packet(struct qserver *server, char *rawpkt, int pktlen)
|
|
|
|
{
|
|
|
|
char *s, *key, *value, *end;
|
|
|
|
|
|
|
|
debug( 2, "deal_with_farcry_packet %p, %d", server, pktlen );
|
|
|
|
|
|
|
|
server->n_servers++;
|
|
|
|
if (NULL == server->server_name)
|
|
|
|
{
|
|
|
|
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gettimeofday(&server->packet_time1, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
rawpkt[pktlen] = '\0';
|
|
|
|
|
|
|
|
end = s = rawpkt;
|
|
|
|
end += pktlen;
|
|
|
|
while (*s)
|
|
|
|
{
|
|
|
|
// Find the seperator
|
|
|
|
while (s <= end && *s != '\xFF')
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s >= end)
|
|
|
|
{
|
|
|
|
// Hit the end no more
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// key start
|
|
|
|
key = ++s;
|
|
|
|
while (s < end && *s != '\xFE')
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (*s != '\xFE')
|
|
|
|
{
|
|
|
|
// malformed
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*s++ = '\0';
|
|
|
|
// key end
|
|
|
|
// value start
|
|
|
|
value = s;
|
|
|
|
|
|
|
|
while (s < end && *s != '\xFF')
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*s == '\xFF')
|
|
|
|
{
|
|
|
|
*s = '\0';
|
|
|
|
}
|
|
|
|
//fprintf( stderr, "'%s' = '%s'\n", key, value );
|
|
|
|
|
|
|
|
// Decode current key par
|
|
|
|
if (0 == strcmp("cmax", key))
|
|
|
|
{
|
|
|
|
// Max players
|
|
|
|
server->max_players = atoi(value);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("cnum", key))
|
|
|
|
{
|
|
|
|
// Current players
|
|
|
|
server->num_players = atoi(value);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("bal", key))
|
|
|
|
{
|
|
|
|
// Balance
|
|
|
|
add_rule(server, "Balance", value, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("world", key))
|
|
|
|
{
|
|
|
|
// Current map
|
|
|
|
server->map_name = strdup(value);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("gametype", key))
|
|
|
|
{
|
|
|
|
// Game type
|
|
|
|
server->game = find_savage_game(value);
|
|
|
|
add_rule(server, server->type->game_rule, server->game, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("pure", key))
|
|
|
|
{
|
|
|
|
// Pure
|
|
|
|
add_rule(server, "Pure", value, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("time", key))
|
|
|
|
{
|
|
|
|
// Current game time
|
|
|
|
add_rule(server, "Time", value, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("notes", key))
|
|
|
|
{
|
|
|
|
// Notes
|
|
|
|
add_rule(server, "Notes", value, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("needcmdr", key))
|
|
|
|
{
|
|
|
|
// Need Commander
|
|
|
|
add_rule(server, "Need Commander", value, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("name", key))
|
|
|
|
{
|
|
|
|
// Server name
|
|
|
|
server->server_name = strdup(value);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("fw", key))
|
|
|
|
{
|
|
|
|
// Firewalled
|
|
|
|
add_rule(server, "Firewalled", value, NO_FLAGS);
|
|
|
|
}
|
|
|
|
else if (0 == strcmp("players", key))
|
|
|
|
{
|
|
|
|
|
|
|
|
// Players names
|
|
|
|
int player_number = 0;
|
|
|
|
int team_number = 1;
|
|
|
|
char *team_name, *player_name, *n;
|
|
|
|
n = team_name = value;
|
|
|
|
|
|
|
|
// team name
|
|
|
|
n++;
|
|
|
|
while (*n && *n != '\x0a')
|
|
|
|
{
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*n != '\x0a')
|
|
|
|
{
|
|
|
|
// Broken data
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*n = '\0';
|
|
|
|
|
|
|
|
player_name = ++n;
|
|
|
|
while (*n)
|
|
|
|
{
|
|
|
|
while (*n && *n != '\x0a')
|
|
|
|
{
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*n != '\x0a')
|
|
|
|
{
|
|
|
|
// Broken data
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*n = '\0';
|
|
|
|
n++;
|
|
|
|
|
|
|
|
if (0 == strncmp("Team ", player_name, 5))
|
|
|
|
{
|
|
|
|
team_name = player_name;
|
|
|
|
team_number++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (0 != strlen(player_name))
|
|
|
|
{
|
|
|
|
struct player *player = add_player(server, player_number);
|
|
|
|
if (NULL != player)
|
|
|
|
{
|
|
|
|
player->name = strdup(player_name);
|
|
|
|
player->team = team_number;
|
|
|
|
player->team_name = strdup(team_name);
|
|
|
|
} player_number++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
player_name = n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*s = '\xFF';
|
|
|
|
}
|
|
|
|
|
|
|
|
return DONE_FORCE;
|
|
|
|
}
|
|
|
|
|