Skip to content

Commit

Permalink
Merge pull request Unity-Technologies#30 from stevenh/master
Browse files Browse the repository at this point in the history
Add Titanfall support
  • Loading branch information
stevenh committed Jul 10, 2015
2 parents fb2e967 + 3c77ec5 commit 2a95a5d
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 4 deletions.
3 changes: 2 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ qstat_SOURCES = \
dirtybomb.c dirtybomb.h \
starmade.c starmade.h \
farmsim.c farmsim.h \
ksp.c ksp.h
ksp.c ksp.h \
tf.c tf.h

dist_configfiles_DATA = qstat.cfg
configfilesdir = $(sysconfdir)
Expand Down
2 changes: 1 addition & 1 deletion Makefile.noauto
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ CFLAGS = -DDEBUG=1 -DENABLE_DUMP=1
## NOTE: if you get errors when linking qstat (missing symbols or
## libraries), then modify LDFLAGS or LDLIBS

SRC = utils.c xform.c config.c debug.c hcache.c md5.c qserver.c qstat.c template.c ut2004.c a2s.c packet_manip.c gs3.c gs2.c gps.c ts2.c doom3.c tm.c haze.c wic.c ottd.c fl.c tee.c ts3.c bfbc2.c ventrilo.c cube2.c mumble.c terraria.c crysis.c dirtybomb.c starmade.c farmsim.c ksp.c
SRC = utils.c xform.c config.c debug.c hcache.c md5.c qserver.c qstat.c template.c ut2004.c a2s.c packet_manip.c gs3.c gs2.c gps.c ts2.c doom3.c tm.c haze.c wic.c ottd.c fl.c tee.c ts3.c bfbc2.c ventrilo.c cube2.c mumble.c terraria.c crysis.c dirtybomb.c starmade.c farmsim.c ksp.c tf.c
OBJ = $(SRC:.c=.obj)
O = $(SRC:.c=.o)

Expand Down
4 changes: 3 additions & 1 deletion qstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@
#define INADDR_NONE ~0
#endif
#define sockerr() errno
#endif /* _WIN32 */
#else /* _WIN32 */
#include "utils.h"
#endif /* !_WIN32 */

#ifdef __OS2__
#include <sys/socket.h>
Expand Down
39 changes: 38 additions & 1 deletion qstat.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ typedef query_status_t (*PacketFunc)( struct qserver *, char *rawpkt, int pktlen
#include "starmade.h"
#include "farmsim.h"
#include "ksp.h"
#include "tf.h"

/*
* Various magic numbers.
Expand Down Expand Up @@ -170,6 +171,7 @@ typedef query_status_t (*PacketFunc)( struct qserver *, char *rawpkt, int pktlen
#define STARMADE_DEFAULT_PORT 4242
#define FARMSIM_DEFAULT_PORT 10828
#define KSP_DEFAULT_PORT 6702
#define TF_DEFAULT_PORT 37016


#define Q_UNKNOWN_TYPE 0
Expand Down Expand Up @@ -253,8 +255,9 @@ typedef query_status_t (*PacketFunc)( struct qserver *, char *rawpkt, int pktlen
#define STARMADE_PROTOCOL_SERVER 75
#define FARMSIM_PROTOCOL_SERVER 76
#define KSP_PROTOCOL_SERVER 77
#define TF_PROTOCOL_SERVER 78

#define LAST_BUILTIN_SERVER 77
#define LAST_BUILTIN_SERVER 78

#define TF_SINGLE_QUERY (1<<1)
#define TF_OUTFILE (1<<2)
Expand Down Expand Up @@ -3477,6 +3480,40 @@ server_type builtin_types[] = {
NULL, /* player_query_func */
deal_with_ksp_packet, /* packet_func */
},
{
/* TF PROTOCOL */
TF_PROTOCOL_SERVER, /* id */
"TF", /* type_prefix */
"tf", /* type_string */
"-tf", /* type_option */
"Titanfall", /* game_name */
0, /* master */
0, /* default_port */
0, /* port_offset */
0, /* flags */
"gamerules", /* game_rule */
"TFPROTOCOL", /* template_var */
NULL, /* status_packet */
0, /* 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 */
NULL, /* display_player_func */
display_server_rules, /* display_rule_func */
NULL, /* 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_tf_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_tf_packet, /* packet_func */
},
{
Q_UNKNOWN_TYPE, /* id */
"", /* type_prefix */
Expand Down
207 changes: 207 additions & 0 deletions tf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* qstat
*
* Titanfall Protocol
* Copyright 2015 Steven Hartland
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*
*/

#include "debug.h"
#include "qstat.h"
#include "utils.h"

#include <stdio.h>

#define SERVERINFO_REQUEST 79
#define SERVERINFO_VERSION 1
#define SERVERINFO_RESPONSE 80

static char serverinfo_pkt[] = {0xFF, 0xFF, 0xFF, 0xFF, SERVERINFO_REQUEST, SERVERINFO_VERSION};

static void
pkt_inc(char **pkt, int *rem, int inc)
{
*pkt += inc;
*rem -= inc;
}

static query_status_t
pkt_string(struct qserver *server, char **pkt, char **str, int *rem)
{
size_t len;

if (*rem <= 0) {
malformed_packet(server, "short packet");
return (PKT_ERROR);
}

*str = strndup(*pkt, *rem);
if (*str == NULL) {
malformed_packet(server, "out of memory");
return (MEM_ERROR);
}

len = strlen(*str) + 1;
pkt_inc(pkt, rem, (int)len);

return (INPROGRESS);
}

static query_status_t
pkt_rule(struct qserver *server, char *rule, char **pkt, int *rem)
{
char *str;
query_status_t ret;

ret = pkt_string(server, pkt, &str, rem);
if (ret < 0) {
return (ret);
}

// TODO: check return when it doesn't exit on failure
add_rule(server, rule, str, NO_VALUE_COPY);

return (INPROGRESS);
}

query_status_t
send_tf_request_packet(struct qserver *server)
{
return qserver_send_initial(server, serverinfo_pkt, sizeof(serverinfo_pkt));
}

query_status_t
deal_with_tf_packet(struct qserver *server, char *rawpkt, int pktlen)
{
char *pkt, *str, buf[16];
query_status_t ret;
uint16_t port;
int rem, i;
int32_t num;

rem = pktlen;
pkt = rawpkt;

if (server->server_name == NULL) {
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
server->n_requests++;
}

if (pktlen < 26) {
malformed_packet(server, "packet too short");
return (PKT_ERROR);
}

// Header (int32)
if (memcmp(serverinfo_pkt, pkt, sizeof(int32_t)) != 0) {
malformed_packet(server, "missing / invalid header");
return (PKT_ERROR);
}
pkt_inc(&pkt, &rem, sizeof(int32_t));

// Command (int8)
debug(2, "TF type = %hhu", *pkt);
if (*pkt != SERVERINFO_RESPONSE) {
malformed_packet(server, "unknown type");
return (PKT_ERROR);
}
pkt_inc(&pkt, &rem, sizeof(int8_t));

// Version (int8)
sprintf(buf, "%hhd", *pkt);
add_rule(server, "version", buf, 0);
pkt_inc(&pkt, &rem, sizeof(int8_t));

// Port (uint16)
port = (uint16_t)((unsigned char)pkt[0] | (unsigned char)pkt[1] << 8);
sprintf(buf, "%hu", port);
add_rule(server, "port", buf, 0);
change_server_port(server, port, 0);
pkt_inc(&pkt, &rem, sizeof(uint16_t));

// Platform (string)
ret = pkt_rule(server, "version", &pkt, &rem);
if (ret < 0) {
return (ret);
}

// Playlist Version (string)
ret = pkt_rule(server, "playlist_version", &pkt, &rem);
if (ret < 0) {
return (ret);
}

// Playlist Num (int32)
num = (int32_t)(
(unsigned char)pkt[0] |
(unsigned char)pkt[1] << 8 |
(unsigned char)pkt[2] << 16 |
(unsigned char)pkt[3] << 24
);
sprintf(buf, "%d", num);
add_rule(server, "playlist_num", buf, 0);
pkt_inc(&pkt, &rem, sizeof(int32_t));

// Playlist Name (string)
ret = pkt_rule(server, "playlist_name", &pkt, &rem);
if (ret < 0) {
return (ret);
}

// Num Clients (uint8)
server->num_players = (uint8_t)pkt[0];

// Max Clients (uint8)
server->max_players = (uint8_t)pkt[1];
pkt_inc(&pkt, &rem, sizeof(uint8_t) * 2);

// Map (string)
ret = pkt_string(server, &pkt, &str, &rem);
if (ret < 0) {
return (ret);
}
server->map_name = str;

// Clients
for (i = 0; i < server->num_players; i++) {
struct player *p;

p = add_player(server, server->n_player_info);
if (p == NULL) {
// Should never happen
return (SYS_ERROR);
}

// Client ID (int64)
pkt_inc(&pkt, &rem, sizeof(int64_t));

// Client Name (string)
ret = pkt_string(server, &pkt, &p->name, &rem);
if (ret < 0) {
return (ret);
}

// Client Team ID (uint8)
p->team = (uint8_t)*pkt;
pkt_inc(&pkt, &rem, sizeof(uint8_t));

}

// EOP (int64)
if (rem != 8) {
malformed_packet(server, "packet too short");
return (PKT_ERROR);
}

// Protocol doesn't support server name
server->server_name = strdup("unknown");

// Protocol doesn't support a specific rule request
server->next_rule = NULL;

return (DONE_AUTO);
}

// vim: sw=4 ts=4 noet
17 changes: 17 additions & 0 deletions tf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* qstat
*
* Titafall protocol
* Copyright 2015 Steven Hartland
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*/
#ifndef QSTAT_TF_H
#define QSTAT_TF_H

#include "qserver.h"

query_status_t send_tf_request_packet(struct qserver *server);
query_status_t deal_with_tf_packet(struct qserver *server, char *rawpkt, int pktlen);

#endif
3 changes: 3 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
*/
#ifndef QSTAT_UTILS_H
#define QSTAT_UTILS_H

#ifndef _WIN32
#include "gnuconfig.h"
#endif

// BSD has strnstr
#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__OpenBSD__)
Expand Down

0 comments on commit 2a95a5d

Please sign in to comment.