mirror of
https://github.com/tribufu/node-gamedig
synced 2026-06-01 09:42:41 +00:00
crlf -> ln conversion
This commit is contained in:
parent
50d3ef20a0
commit
f1467c5a04
94 changed files with 11388 additions and 11388 deletions
|
|
@ -1,77 +1,77 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of GameQ.
|
||||
*
|
||||
* GameQ is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GameQ is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Id: openttd.php,v 1.1 2009/10/24 18:45:16 evilpie Exp $
|
||||
*/
|
||||
|
||||
[openttd]
|
||||
status = "\x03\x00\x00"
|
||||
|
||||
|
||||
require_once GAMEQ_BASE . 'Protocol.php';
|
||||
|
||||
/**
|
||||
* OpenTTD Protocol, direct port from udp.cpp source from the game
|
||||
*
|
||||
* @author Tom Schuster <evilpie@users.sf.net>
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
class GameQ_Protocol_openttd extends GameQ_Protocol
|
||||
{
|
||||
public function status ()
|
||||
{
|
||||
$this->p->readInt16(); # packet size
|
||||
$this->p->readInt8(); # packet type
|
||||
|
||||
$protocol_version = $this->p->readInt8();
|
||||
$this->r->add('protocol_version', $protocol_version);
|
||||
switch ($protocol_version)
|
||||
{
|
||||
case 4:
|
||||
$num_grfs = $this->p->readInt8(); #number of grfs
|
||||
$this->r->add('num_grfs', $num_grfs);
|
||||
$this->p->skip ($num_grfs * 20); #skip id and md5 hash
|
||||
case 3:
|
||||
$this->r->add('game_date', $this->p->readInt32());
|
||||
$this->r->add('start_date', $this->p->readInt32());
|
||||
case 2:
|
||||
$this->r->add('companies_max', $this->p->readInt8());
|
||||
$this->r->add('companies_on', $this->p->readInt8());
|
||||
$this->r->add('spectators_max', $this->p->readInt8());
|
||||
case 1:
|
||||
$this->r->add('hostname', $this->p->readString());
|
||||
$this->r->add('version', $this->p->readString());
|
||||
$this->r->add('language', $this->p->readInt8());
|
||||
$this->r->add('password', $this->p->readInt8());
|
||||
$this->r->add('max_clients', $this->p->readInt8());
|
||||
$this->r->add('clients', $this->p->readInt8());
|
||||
$this->r->add('spectators', $this->p->readInt8());
|
||||
if ($protocol_version < 3)
|
||||
{
|
||||
$days = ( 365 * 1920 + 1920 / 4 - 1920 / 100 + 1920 / 400 );
|
||||
$this->r->add('game_date', $this->p->readInt16() + $days);
|
||||
$this->r->add('start_date', $this->p->readInt16() + $days);
|
||||
}
|
||||
$this->r->add('map', $this->p->readString());
|
||||
$this->r->add('map_width', $this->p->readInt16());
|
||||
$this->r->add('map_height', $this->p->readInt16());
|
||||
$this->r->add('map_type', $this->p->readInt8());
|
||||
$this->r->add('dedicated', $this->p->readInt8());
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* This file is part of GameQ.
|
||||
*
|
||||
* GameQ is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GameQ is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Id: openttd.php,v 1.1 2009/10/24 18:45:16 evilpie Exp $
|
||||
*/
|
||||
|
||||
[openttd]
|
||||
status = "\x03\x00\x00"
|
||||
|
||||
|
||||
require_once GAMEQ_BASE . 'Protocol.php';
|
||||
|
||||
/**
|
||||
* OpenTTD Protocol, direct port from udp.cpp source from the game
|
||||
*
|
||||
* @author Tom Schuster <evilpie@users.sf.net>
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
|
||||
class GameQ_Protocol_openttd extends GameQ_Protocol
|
||||
{
|
||||
public function status ()
|
||||
{
|
||||
$this->p->readInt16(); # packet size
|
||||
$this->p->readInt8(); # packet type
|
||||
|
||||
$protocol_version = $this->p->readInt8();
|
||||
$this->r->add('protocol_version', $protocol_version);
|
||||
switch ($protocol_version)
|
||||
{
|
||||
case 4:
|
||||
$num_grfs = $this->p->readInt8(); #number of grfs
|
||||
$this->r->add('num_grfs', $num_grfs);
|
||||
$this->p->skip ($num_grfs * 20); #skip id and md5 hash
|
||||
case 3:
|
||||
$this->r->add('game_date', $this->p->readInt32());
|
||||
$this->r->add('start_date', $this->p->readInt32());
|
||||
case 2:
|
||||
$this->r->add('companies_max', $this->p->readInt8());
|
||||
$this->r->add('companies_on', $this->p->readInt8());
|
||||
$this->r->add('spectators_max', $this->p->readInt8());
|
||||
case 1:
|
||||
$this->r->add('hostname', $this->p->readString());
|
||||
$this->r->add('version', $this->p->readString());
|
||||
$this->r->add('language', $this->p->readInt8());
|
||||
$this->r->add('password', $this->p->readInt8());
|
||||
$this->r->add('max_clients', $this->p->readInt8());
|
||||
$this->r->add('clients', $this->p->readInt8());
|
||||
$this->r->add('spectators', $this->p->readInt8());
|
||||
if ($protocol_version < 3)
|
||||
{
|
||||
$days = ( 365 * 1920 + 1920 / 4 - 1920 / 100 + 1920 / 400 );
|
||||
$this->r->add('game_date', $this->p->readInt16() + $days);
|
||||
$this->r->add('start_date', $this->p->readInt16() + $days);
|
||||
}
|
||||
$this->r->add('map', $this->p->readString());
|
||||
$this->r->add('map_width', $this->p->readInt16());
|
||||
$this->r->add('map_height', $this->p->readInt16());
|
||||
$this->r->add('map_type', $this->p->readInt8());
|
||||
$this->r->add('dedicated', $this->p->readInt8());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +1,64 @@
|
|||
|
||||
/*----------------------------------------------------------------------------------------------------------\
|
||||
| |
|
||||
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
|
||||
| |
|
||||
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
|
||||
| |
|
||||
\-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
function lgsl_query_22(&$server, &$lgsl_need, &$lgsl_fp)
|
||||
{
|
||||
//---------------------------------------------------------+
|
||||
|
||||
fwrite($lgsl_fp,"\x03\x00\x00");
|
||||
|
||||
$buffer = fread($lgsl_fp, 4096);
|
||||
$buffer = substr($buffer, 3); // REMOVE HEADER
|
||||
|
||||
if (!$buffer) { return FALSE; }
|
||||
|
||||
$response_type = ord(lgsl_cut_byte($buffer, 1)); // TYPE SHOULD BE 4
|
||||
|
||||
//---------------------------------------------------------+
|
||||
|
||||
$grf_count = ord(lgsl_cut_byte($buffer, 1));
|
||||
|
||||
for ($a=0; $a<$grf_count; $a++)
|
||||
{
|
||||
$server['e']['grf_'.$a.'_id'] = strtoupper(dechex(lgsl_unpack(lgsl_cut_byte($buffer, 4), "N")));
|
||||
|
||||
for ($b=0; $b<16; $b++)
|
||||
{
|
||||
$server['e']['grf_'.$a.'_md5'] .= strtoupper(dechex(ord(lgsl_cut_byte($buffer, 1))));
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------+
|
||||
|
||||
$server['e']['date_current'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "L");
|
||||
$server['e']['date_start'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "L");
|
||||
$server['e']['companies_max'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['companies'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['spectators_max'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['name'] = lgsl_cut_string($buffer);
|
||||
$server['e']['version'] = lgsl_cut_string($buffer);
|
||||
$server['e']['language'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['spectators'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['map'] = lgsl_cut_string($buffer);
|
||||
$server['e']['map_width'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
|
||||
$server['e']['map_height'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
|
||||
$server['e']['map_set'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['dedicated'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
|
||||
// DOES NOT RETURN PLAYER INFORMATION
|
||||
|
||||
//---------------------------------------------------------+
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------\
|
||||
| |
|
||||
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
|
||||
| |
|
||||
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
|
||||
| |
|
||||
\-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
function lgsl_query_22(&$server, &$lgsl_need, &$lgsl_fp)
|
||||
{
|
||||
//---------------------------------------------------------+
|
||||
|
||||
fwrite($lgsl_fp,"\x03\x00\x00");
|
||||
|
||||
$buffer = fread($lgsl_fp, 4096);
|
||||
$buffer = substr($buffer, 3); // REMOVE HEADER
|
||||
|
||||
if (!$buffer) { return FALSE; }
|
||||
|
||||
$response_type = ord(lgsl_cut_byte($buffer, 1)); // TYPE SHOULD BE 4
|
||||
|
||||
//---------------------------------------------------------+
|
||||
|
||||
$grf_count = ord(lgsl_cut_byte($buffer, 1));
|
||||
|
||||
for ($a=0; $a<$grf_count; $a++)
|
||||
{
|
||||
$server['e']['grf_'.$a.'_id'] = strtoupper(dechex(lgsl_unpack(lgsl_cut_byte($buffer, 4), "N")));
|
||||
|
||||
for ($b=0; $b<16; $b++)
|
||||
{
|
||||
$server['e']['grf_'.$a.'_md5'] .= strtoupper(dechex(ord(lgsl_cut_byte($buffer, 1))));
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------+
|
||||
|
||||
$server['e']['date_current'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "L");
|
||||
$server['e']['date_start'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "L");
|
||||
$server['e']['companies_max'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['companies'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['spectators_max'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['name'] = lgsl_cut_string($buffer);
|
||||
$server['e']['version'] = lgsl_cut_string($buffer);
|
||||
$server['e']['language'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['spectators'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['s']['map'] = lgsl_cut_string($buffer);
|
||||
$server['e']['map_width'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
|
||||
$server['e']['map_height'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
|
||||
$server['e']['map_set'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
$server['e']['dedicated'] = ord(lgsl_cut_byte($buffer, 1));
|
||||
|
||||
// DOES NOT RETURN PLAYER INFORMATION
|
||||
|
||||
//---------------------------------------------------------+
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,404 +1,404 @@
|
|||
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
|
||||
*/
|
||||
|
||||
|
||||
char ottd_serverinfo[] = {
|
||||
0x03, 0x00, // packet length
|
||||
0x00, // packet type
|
||||
};
|
||||
|
||||
char ottd_serverdetails[] = {
|
||||
0x03, 0x00, // packet length
|
||||
0x02, // packet type
|
||||
};
|
||||
|
||||
|
||||
{
|
||||
/* openTTD */
|
||||
OTTD_SERVER, /* id */
|
||||
"OTTDS", /* type_prefix */
|
||||
"ottds", /* type_string */
|
||||
"-ottds", /* type_option */
|
||||
"OpenTTD", /* game_name */
|
||||
0, /* master */
|
||||
3979, /* default_port */
|
||||
0, /* port_offset */
|
||||
0, /* flags */
|
||||
"", /* game_rule */
|
||||
"OPENTTD", /* template_var */
|
||||
(char*) &ottd_serverinfo, /* status_packet */
|
||||
sizeof( ottd_serverinfo), /* status_len */
|
||||
NULL, /* player_packet */
|
||||
0, /* player_len */
|
||||
(char*) &ottd_serverdetails,/* rule_packet */
|
||||
sizeof( ottd_serverdetails), /* rule_len */
|
||||
NULL, /* master_packet */
|
||||
0, /* master_len */
|
||||
NULL, /* master_protocol */
|
||||
NULL, /* master_query */
|
||||
display_q2_player_info, /* display_player_func */
|
||||
display_server_rules, /* display_rule_func */
|
||||
raw_display_q2_player_info, /* display_raw_player_func */
|
||||
raw_display_server_rules, /* display_raw_rule_func */
|
||||
xml_display_player_info,/* display_xml_player_func */
|
||||
xml_display_server_rules, /* display_xml_rule_func */
|
||||
send_ottd_request_packet, /* status_query_func */
|
||||
NULL, /* rule_query_func */
|
||||
NULL, /* player_query_func */
|
||||
deal_with_ottd_packet, /* packet_func */
|
||||
},
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* qstat 2.11
|
||||
*
|
||||
* opentTTD protocol
|
||||
* Copyright 2007 Ludwig Nussel
|
||||
*
|
||||
* Licensed under the Artistic License, see LICENSE.txt for license terms
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "qstat.h"
|
||||
#include "qserver.h"
|
||||
#include "debug.h"
|
||||
|
||||
enum { MAX_VEHICLE_TYPES = 5, MAX_STATION_TYPES = 5 };
|
||||
|
||||
static const char* vehicle_types[] = {
|
||||
"num_trains",
|
||||
"num_trucks",
|
||||
"num_busses",
|
||||
"num_aircrafts",
|
||||
"num_ships",
|
||||
};
|
||||
|
||||
static const char* station_types[] = {
|
||||
"num_stations",
|
||||
"num_truckbays",
|
||||
"num_busstations",
|
||||
"num_airports",
|
||||
"num_docks",
|
||||
};
|
||||
|
||||
query_status_t deal_with_ottdmaster_packet(struct qserver *server, char *rawpkt, int pktlen)
|
||||
{
|
||||
unsigned num;
|
||||
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
|
||||
server->server_name = MASTER;
|
||||
|
||||
if(swap_short_from_little(rawpkt) != pktlen)
|
||||
{
|
||||
malformed_packet( server, "invalid packet length" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
if(rawpkt[2] != 7)
|
||||
{
|
||||
malformed_packet( server, "invalid packet type" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
if(rawpkt[3] != 1)
|
||||
{
|
||||
malformed_packet( server, "invalid packet version" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
num = swap_short_from_little(&rawpkt[4]);
|
||||
rawpkt += 6;
|
||||
pktlen -= 6;
|
||||
if( num && num*6 <= pktlen )
|
||||
{
|
||||
unsigned i;
|
||||
server->master_pkt = (char*)realloc(server->master_pkt, server->master_pkt_len + pktlen );
|
||||
memset(server->master_pkt + server->master_pkt_len, 0, pktlen );
|
||||
server->master_pkt_len += pktlen;
|
||||
for( i = 0; i < num * 6; i += 6 )
|
||||
{
|
||||
memcpy(&server->master_pkt[i], &rawpkt[i], 4);
|
||||
server->master_pkt[i+4] = rawpkt[i+5];
|
||||
server->master_pkt[i+5] = rawpkt[i+4];
|
||||
}
|
||||
server->n_servers += num;
|
||||
}
|
||||
else
|
||||
{
|
||||
malformed_packet( server, "invalid packet" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
bind_sockets();
|
||||
|
||||
return DONE_AUTO;
|
||||
}
|
||||
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
#define GET_STRING do { \
|
||||
str = (char*)ptr; \
|
||||
ptr = memchr(ptr, '\0', end-ptr); \
|
||||
if ( !ptr ) \
|
||||
{ \
|
||||
malformed_packet( server, "%s:%s invalid packet", __FILE__, xstr(__LINE__) ); \
|
||||
return PKT_ERROR; \
|
||||
} \
|
||||
++ptr; \
|
||||
} while(0)
|
||||
|
||||
#define FAIL_IF(cond, msg) \
|
||||
if((cond)) { \
|
||||
malformed_packet( server, "%s:%s %s", __FILE__, xstr(__LINE__), msg ); \
|
||||
return PKT_ERROR; \
|
||||
}
|
||||
|
||||
#define INVALID_IF(cond) \
|
||||
FAIL_IF(cond, "invalid packet")
|
||||
|
||||
query_status_t deal_with_ottd_packet(struct qserver *server, char *rawpkt, int pktlen)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char*)rawpkt;
|
||||
unsigned char *end = (unsigned char*)(rawpkt + pktlen);
|
||||
unsigned char type;
|
||||
char* str;
|
||||
char buf[32];
|
||||
unsigned ver;
|
||||
|
||||
server->n_servers++;
|
||||
if ( server->server_name == NULL)
|
||||
{
|
||||
server->ping_total += time_delta( &packet_recv_time, &server->packet_time1);
|
||||
server->n_requests++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gettimeofday( &server->packet_time1, NULL);
|
||||
}
|
||||
|
||||
FAIL_IF(pktlen < 4 || swap_short_from_little(rawpkt) > pktlen, "invalid packet");
|
||||
|
||||
type = ptr[2];
|
||||
ver = ptr[3];
|
||||
ptr += 4;
|
||||
|
||||
debug(3, "len %hu type %hhu ver %hhu", swap_short_from_little(rawpkt), type, ver);
|
||||
|
||||
FAIL_IF(ver != 4 && ver != 5, "only version 4 and 5 servers are supported");
|
||||
|
||||
if(type == 1) // info packet
|
||||
{
|
||||
unsigned numgrf = *ptr;
|
||||
FAIL_IF(ptr + numgrf * 20 + 1 > end, "invalid newgrf number");
|
||||
ptr += numgrf * 20 + 1;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
|
||||
add_rule(server, "date_days", buf, NO_FLAGS);
|
||||
ptr += 4;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
|
||||
add_rule(server, "startdate_days", buf, NO_FLAGS);
|
||||
ptr += 4;
|
||||
|
||||
FAIL_IF(ptr + 3 > end, "invalid packet");
|
||||
|
||||
snprintf(buf, sizeof(buf), "%hhu", ptr[0]);
|
||||
add_rule(server, "maxcompanies", buf, NO_FLAGS);
|
||||
snprintf(buf, sizeof(buf), "%hhu", ptr[1]);
|
||||
add_rule(server, "numcompanies", buf, NO_FLAGS);
|
||||
server->max_spectators = ptr[2];
|
||||
ptr += 3;
|
||||
|
||||
GET_STRING;
|
||||
server->server_name = strdup(str);
|
||||
|
||||
GET_STRING;
|
||||
add_rule(server, "version", str, NO_FLAGS);
|
||||
|
||||
FAIL_IF(ptr + 7 > end, "invalid packet");
|
||||
|
||||
{
|
||||
static const char* langs[] = {
|
||||
"any",
|
||||
"English",
|
||||
"German",
|
||||
"French"
|
||||
};
|
||||
unsigned i = *ptr++;
|
||||
if(i > 3) i = 0;
|
||||
add_rule(server, "language", (char*)langs[i], NO_FLAGS);
|
||||
}
|
||||
|
||||
add_rule(server, "password", *ptr++ ? "1" : "0", NO_FLAGS);
|
||||
|
||||
server->max_players = *ptr++;
|
||||
server->num_players = *ptr++;
|
||||
server->num_spectators = *ptr++;
|
||||
|
||||
GET_STRING;
|
||||
|
||||
server->map_name = strdup(str);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
add_rule(server, "map_width", buf, NO_FLAGS);
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
add_rule(server, "map_height", buf, NO_FLAGS);
|
||||
|
||||
{
|
||||
static const char* sets[] = {
|
||||
"temperate",
|
||||
"arctic",
|
||||
"desert",
|
||||
"toyland"
|
||||
};
|
||||
unsigned i = *ptr++;
|
||||
if(i > 3) i = 0;
|
||||
add_rule(server, "map_set", (char*)sets[i], NO_FLAGS);
|
||||
}
|
||||
|
||||
add_rule(server, "dedicated", *ptr++ ? "1" : "0", NO_FLAGS);
|
||||
}
|
||||
else if(type == 3) // player packet
|
||||
{
|
||||
unsigned i, j;
|
||||
INVALID_IF(ptr + 2 > end);
|
||||
|
||||
server->num_players = *ptr++;
|
||||
|
||||
for(i = 0; i < server->num_players; ++i)
|
||||
{
|
||||
unsigned long long lli;
|
||||
struct player* player;
|
||||
unsigned char nr;
|
||||
|
||||
nr = *ptr++;
|
||||
|
||||
debug(3, "player number %d", nr);
|
||||
player = add_player(server, i);
|
||||
FAIL_IF(!player, "can't allocate player");
|
||||
|
||||
GET_STRING;
|
||||
player->name = strdup(str);
|
||||
debug(3, "name %s", str);
|
||||
player->frags = 0;
|
||||
|
||||
INVALID_IF(ptr + 4 + 3*8 + 2 + 1 + 2*MAX_VEHICLE_TYPES + 2*MAX_STATION_TYPES > end);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
|
||||
player_add_info(player, "startdate", buf, 0);
|
||||
ptr += 4;
|
||||
|
||||
lli = swap_long_from_little(ptr+4);
|
||||
lli <<= 32;
|
||||
lli += swap_long_from_little(ptr);
|
||||
snprintf(buf, sizeof(buf), "%lld", lli);
|
||||
player_add_info(player, "value", buf, 0);
|
||||
ptr += 8;
|
||||
|
||||
lli = swap_long_from_little(ptr+4);
|
||||
lli <<= 32;
|
||||
lli = swap_long_from_little(ptr);
|
||||
snprintf(buf, sizeof(buf), "%lld", lli);
|
||||
player_add_info(player, "money", buf, 0);
|
||||
ptr += 8;
|
||||
|
||||
lli = swap_long_from_little(ptr+4);
|
||||
lli <<= 32;
|
||||
lli += swap_long_from_little(ptr);
|
||||
snprintf(buf, sizeof(buf), "%lld", lli);
|
||||
player_add_info(player, "income", buf, 0);
|
||||
ptr += 8;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
player_add_info(player, "performance", buf, 0);
|
||||
ptr += 2;
|
||||
|
||||
player_add_info(player, "password", *ptr?"1":"0", 0);
|
||||
++ptr;
|
||||
|
||||
for (j = 0; j < MAX_VEHICLE_TYPES; ++j)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
player_add_info(player, (char*)vehicle_types[j], buf, 0);
|
||||
ptr += 2;
|
||||
}
|
||||
for (j = 0; j < MAX_STATION_TYPES; ++j)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
player_add_info(player, (char*)station_types[j], buf, 0);
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
if (ver != 5)
|
||||
{
|
||||
// connections
|
||||
while(ptr + 1 < end && *ptr)
|
||||
{
|
||||
++ptr;
|
||||
GET_STRING; // client name
|
||||
debug(3, "%s played by %s", str, player->name);
|
||||
GET_STRING; // id
|
||||
INVALID_IF(ptr + 4 > end);
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
++ptr; // record terminated by zero byte
|
||||
}
|
||||
}
|
||||
|
||||
// spectators
|
||||
while(ptr + 1 < end && *ptr)
|
||||
{
|
||||
++ptr;
|
||||
GET_STRING; // client name
|
||||
debug(3, "spectator %s", str);
|
||||
GET_STRING; // id
|
||||
INVALID_IF(ptr + 4 > end);
|
||||
ptr += 4;
|
||||
}
|
||||
++ptr; // record terminated by zero byte
|
||||
|
||||
server->next_rule = NO_SERVER_RULES; // we're done
|
||||
server->next_player_info = server->num_players; // we're done
|
||||
}
|
||||
else
|
||||
{
|
||||
malformed_packet( server, "invalid type" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
server->retry1 = n_retries; // we're done with this packet, reset retry counter
|
||||
|
||||
return DONE_AUTO;
|
||||
}
|
||||
|
||||
query_status_t send_ottdmaster_request_packet(struct qserver *server)
|
||||
{
|
||||
return qserver_send_initial(server, server->type->master_packet, server->type->master_len);
|
||||
}
|
||||
|
||||
query_status_t send_ottd_request_packet(struct qserver *server)
|
||||
{
|
||||
qserver_send_initial(server, server->type->status_packet, server->type->status_len);
|
||||
|
||||
if(get_server_rules || get_player_info)
|
||||
{
|
||||
server->next_rule = ""; // trigger calling send_a2s_rule_request_packet
|
||||
}
|
||||
|
||||
return INPROGRESS;
|
||||
}
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
char ottd_serverinfo[] = {
|
||||
0x03, 0x00, // packet length
|
||||
0x00, // packet type
|
||||
};
|
||||
|
||||
char ottd_serverdetails[] = {
|
||||
0x03, 0x00, // packet length
|
||||
0x02, // packet type
|
||||
};
|
||||
|
||||
|
||||
{
|
||||
/* openTTD */
|
||||
OTTD_SERVER, /* id */
|
||||
"OTTDS", /* type_prefix */
|
||||
"ottds", /* type_string */
|
||||
"-ottds", /* type_option */
|
||||
"OpenTTD", /* game_name */
|
||||
0, /* master */
|
||||
3979, /* default_port */
|
||||
0, /* port_offset */
|
||||
0, /* flags */
|
||||
"", /* game_rule */
|
||||
"OPENTTD", /* template_var */
|
||||
(char*) &ottd_serverinfo, /* status_packet */
|
||||
sizeof( ottd_serverinfo), /* status_len */
|
||||
NULL, /* player_packet */
|
||||
0, /* player_len */
|
||||
(char*) &ottd_serverdetails,/* rule_packet */
|
||||
sizeof( ottd_serverdetails), /* rule_len */
|
||||
NULL, /* master_packet */
|
||||
0, /* master_len */
|
||||
NULL, /* master_protocol */
|
||||
NULL, /* master_query */
|
||||
display_q2_player_info, /* display_player_func */
|
||||
display_server_rules, /* display_rule_func */
|
||||
raw_display_q2_player_info, /* display_raw_player_func */
|
||||
raw_display_server_rules, /* display_raw_rule_func */
|
||||
xml_display_player_info,/* display_xml_player_func */
|
||||
xml_display_server_rules, /* display_xml_rule_func */
|
||||
send_ottd_request_packet, /* status_query_func */
|
||||
NULL, /* rule_query_func */
|
||||
NULL, /* player_query_func */
|
||||
deal_with_ottd_packet, /* packet_func */
|
||||
},
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* qstat 2.11
|
||||
*
|
||||
* opentTTD protocol
|
||||
* Copyright 2007 Ludwig Nussel
|
||||
*
|
||||
* Licensed under the Artistic License, see LICENSE.txt for license terms
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "qstat.h"
|
||||
#include "qserver.h"
|
||||
#include "debug.h"
|
||||
|
||||
enum { MAX_VEHICLE_TYPES = 5, MAX_STATION_TYPES = 5 };
|
||||
|
||||
static const char* vehicle_types[] = {
|
||||
"num_trains",
|
||||
"num_trucks",
|
||||
"num_busses",
|
||||
"num_aircrafts",
|
||||
"num_ships",
|
||||
};
|
||||
|
||||
static const char* station_types[] = {
|
||||
"num_stations",
|
||||
"num_truckbays",
|
||||
"num_busstations",
|
||||
"num_airports",
|
||||
"num_docks",
|
||||
};
|
||||
|
||||
query_status_t deal_with_ottdmaster_packet(struct qserver *server, char *rawpkt, int pktlen)
|
||||
{
|
||||
unsigned num;
|
||||
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
|
||||
server->server_name = MASTER;
|
||||
|
||||
if(swap_short_from_little(rawpkt) != pktlen)
|
||||
{
|
||||
malformed_packet( server, "invalid packet length" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
if(rawpkt[2] != 7)
|
||||
{
|
||||
malformed_packet( server, "invalid packet type" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
if(rawpkt[3] != 1)
|
||||
{
|
||||
malformed_packet( server, "invalid packet version" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
num = swap_short_from_little(&rawpkt[4]);
|
||||
rawpkt += 6;
|
||||
pktlen -= 6;
|
||||
if( num && num*6 <= pktlen )
|
||||
{
|
||||
unsigned i;
|
||||
server->master_pkt = (char*)realloc(server->master_pkt, server->master_pkt_len + pktlen );
|
||||
memset(server->master_pkt + server->master_pkt_len, 0, pktlen );
|
||||
server->master_pkt_len += pktlen;
|
||||
for( i = 0; i < num * 6; i += 6 )
|
||||
{
|
||||
memcpy(&server->master_pkt[i], &rawpkt[i], 4);
|
||||
server->master_pkt[i+4] = rawpkt[i+5];
|
||||
server->master_pkt[i+5] = rawpkt[i+4];
|
||||
}
|
||||
server->n_servers += num;
|
||||
}
|
||||
else
|
||||
{
|
||||
malformed_packet( server, "invalid packet" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
bind_sockets();
|
||||
|
||||
return DONE_AUTO;
|
||||
}
|
||||
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
#define GET_STRING do { \
|
||||
str = (char*)ptr; \
|
||||
ptr = memchr(ptr, '\0', end-ptr); \
|
||||
if ( !ptr ) \
|
||||
{ \
|
||||
malformed_packet( server, "%s:%s invalid packet", __FILE__, xstr(__LINE__) ); \
|
||||
return PKT_ERROR; \
|
||||
} \
|
||||
++ptr; \
|
||||
} while(0)
|
||||
|
||||
#define FAIL_IF(cond, msg) \
|
||||
if((cond)) { \
|
||||
malformed_packet( server, "%s:%s %s", __FILE__, xstr(__LINE__), msg ); \
|
||||
return PKT_ERROR; \
|
||||
}
|
||||
|
||||
#define INVALID_IF(cond) \
|
||||
FAIL_IF(cond, "invalid packet")
|
||||
|
||||
query_status_t deal_with_ottd_packet(struct qserver *server, char *rawpkt, int pktlen)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char*)rawpkt;
|
||||
unsigned char *end = (unsigned char*)(rawpkt + pktlen);
|
||||
unsigned char type;
|
||||
char* str;
|
||||
char buf[32];
|
||||
unsigned ver;
|
||||
|
||||
server->n_servers++;
|
||||
if ( server->server_name == NULL)
|
||||
{
|
||||
server->ping_total += time_delta( &packet_recv_time, &server->packet_time1);
|
||||
server->n_requests++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gettimeofday( &server->packet_time1, NULL);
|
||||
}
|
||||
|
||||
FAIL_IF(pktlen < 4 || swap_short_from_little(rawpkt) > pktlen, "invalid packet");
|
||||
|
||||
type = ptr[2];
|
||||
ver = ptr[3];
|
||||
ptr += 4;
|
||||
|
||||
debug(3, "len %hu type %hhu ver %hhu", swap_short_from_little(rawpkt), type, ver);
|
||||
|
||||
FAIL_IF(ver != 4 && ver != 5, "only version 4 and 5 servers are supported");
|
||||
|
||||
if(type == 1) // info packet
|
||||
{
|
||||
unsigned numgrf = *ptr;
|
||||
FAIL_IF(ptr + numgrf * 20 + 1 > end, "invalid newgrf number");
|
||||
ptr += numgrf * 20 + 1;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
|
||||
add_rule(server, "date_days", buf, NO_FLAGS);
|
||||
ptr += 4;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
|
||||
add_rule(server, "startdate_days", buf, NO_FLAGS);
|
||||
ptr += 4;
|
||||
|
||||
FAIL_IF(ptr + 3 > end, "invalid packet");
|
||||
|
||||
snprintf(buf, sizeof(buf), "%hhu", ptr[0]);
|
||||
add_rule(server, "maxcompanies", buf, NO_FLAGS);
|
||||
snprintf(buf, sizeof(buf), "%hhu", ptr[1]);
|
||||
add_rule(server, "numcompanies", buf, NO_FLAGS);
|
||||
server->max_spectators = ptr[2];
|
||||
ptr += 3;
|
||||
|
||||
GET_STRING;
|
||||
server->server_name = strdup(str);
|
||||
|
||||
GET_STRING;
|
||||
add_rule(server, "version", str, NO_FLAGS);
|
||||
|
||||
FAIL_IF(ptr + 7 > end, "invalid packet");
|
||||
|
||||
{
|
||||
static const char* langs[] = {
|
||||
"any",
|
||||
"English",
|
||||
"German",
|
||||
"French"
|
||||
};
|
||||
unsigned i = *ptr++;
|
||||
if(i > 3) i = 0;
|
||||
add_rule(server, "language", (char*)langs[i], NO_FLAGS);
|
||||
}
|
||||
|
||||
add_rule(server, "password", *ptr++ ? "1" : "0", NO_FLAGS);
|
||||
|
||||
server->max_players = *ptr++;
|
||||
server->num_players = *ptr++;
|
||||
server->num_spectators = *ptr++;
|
||||
|
||||
GET_STRING;
|
||||
|
||||
server->map_name = strdup(str);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
add_rule(server, "map_width", buf, NO_FLAGS);
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
add_rule(server, "map_height", buf, NO_FLAGS);
|
||||
|
||||
{
|
||||
static const char* sets[] = {
|
||||
"temperate",
|
||||
"arctic",
|
||||
"desert",
|
||||
"toyland"
|
||||
};
|
||||
unsigned i = *ptr++;
|
||||
if(i > 3) i = 0;
|
||||
add_rule(server, "map_set", (char*)sets[i], NO_FLAGS);
|
||||
}
|
||||
|
||||
add_rule(server, "dedicated", *ptr++ ? "1" : "0", NO_FLAGS);
|
||||
}
|
||||
else if(type == 3) // player packet
|
||||
{
|
||||
unsigned i, j;
|
||||
INVALID_IF(ptr + 2 > end);
|
||||
|
||||
server->num_players = *ptr++;
|
||||
|
||||
for(i = 0; i < server->num_players; ++i)
|
||||
{
|
||||
unsigned long long lli;
|
||||
struct player* player;
|
||||
unsigned char nr;
|
||||
|
||||
nr = *ptr++;
|
||||
|
||||
debug(3, "player number %d", nr);
|
||||
player = add_player(server, i);
|
||||
FAIL_IF(!player, "can't allocate player");
|
||||
|
||||
GET_STRING;
|
||||
player->name = strdup(str);
|
||||
debug(3, "name %s", str);
|
||||
player->frags = 0;
|
||||
|
||||
INVALID_IF(ptr + 4 + 3*8 + 2 + 1 + 2*MAX_VEHICLE_TYPES + 2*MAX_STATION_TYPES > end);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
|
||||
player_add_info(player, "startdate", buf, 0);
|
||||
ptr += 4;
|
||||
|
||||
lli = swap_long_from_little(ptr+4);
|
||||
lli <<= 32;
|
||||
lli += swap_long_from_little(ptr);
|
||||
snprintf(buf, sizeof(buf), "%lld", lli);
|
||||
player_add_info(player, "value", buf, 0);
|
||||
ptr += 8;
|
||||
|
||||
lli = swap_long_from_little(ptr+4);
|
||||
lli <<= 32;
|
||||
lli = swap_long_from_little(ptr);
|
||||
snprintf(buf, sizeof(buf), "%lld", lli);
|
||||
player_add_info(player, "money", buf, 0);
|
||||
ptr += 8;
|
||||
|
||||
lli = swap_long_from_little(ptr+4);
|
||||
lli <<= 32;
|
||||
lli += swap_long_from_little(ptr);
|
||||
snprintf(buf, sizeof(buf), "%lld", lli);
|
||||
player_add_info(player, "income", buf, 0);
|
||||
ptr += 8;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
player_add_info(player, "performance", buf, 0);
|
||||
ptr += 2;
|
||||
|
||||
player_add_info(player, "password", *ptr?"1":"0", 0);
|
||||
++ptr;
|
||||
|
||||
for (j = 0; j < MAX_VEHICLE_TYPES; ++j)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
player_add_info(player, (char*)vehicle_types[j], buf, 0);
|
||||
ptr += 2;
|
||||
}
|
||||
for (j = 0; j < MAX_STATION_TYPES; ++j)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
|
||||
player_add_info(player, (char*)station_types[j], buf, 0);
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
if (ver != 5)
|
||||
{
|
||||
// connections
|
||||
while(ptr + 1 < end && *ptr)
|
||||
{
|
||||
++ptr;
|
||||
GET_STRING; // client name
|
||||
debug(3, "%s played by %s", str, player->name);
|
||||
GET_STRING; // id
|
||||
INVALID_IF(ptr + 4 > end);
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
++ptr; // record terminated by zero byte
|
||||
}
|
||||
}
|
||||
|
||||
// spectators
|
||||
while(ptr + 1 < end && *ptr)
|
||||
{
|
||||
++ptr;
|
||||
GET_STRING; // client name
|
||||
debug(3, "spectator %s", str);
|
||||
GET_STRING; // id
|
||||
INVALID_IF(ptr + 4 > end);
|
||||
ptr += 4;
|
||||
}
|
||||
++ptr; // record terminated by zero byte
|
||||
|
||||
server->next_rule = NO_SERVER_RULES; // we're done
|
||||
server->next_player_info = server->num_players; // we're done
|
||||
}
|
||||
else
|
||||
{
|
||||
malformed_packet( server, "invalid type" );
|
||||
return PKT_ERROR;
|
||||
}
|
||||
|
||||
server->retry1 = n_retries; // we're done with this packet, reset retry counter
|
||||
|
||||
return DONE_AUTO;
|
||||
}
|
||||
|
||||
query_status_t send_ottdmaster_request_packet(struct qserver *server)
|
||||
{
|
||||
return qserver_send_initial(server, server->type->master_packet, server->type->master_len);
|
||||
}
|
||||
|
||||
query_status_t send_ottd_request_packet(struct qserver *server)
|
||||
{
|
||||
qserver_send_initial(server, server->type->status_packet, server->type->status_len);
|
||||
|
||||
if(get_server_rules || get_player_info)
|
||||
{
|
||||
server->next_rule = ""; // trigger calling send_a2s_rule_request_packet
|
||||
}
|
||||
|
||||
return INPROGRESS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue