Skip to content

Commit

Permalink
Add Titanfall support
Browse files Browse the repository at this point in the history
Add custom protocol to provide initial Titanfall support.

Also fix build under windows caused by changes to utils.h.
  • Loading branch information
stevenh committed Jul 10, 2015
1 parent fb2e967 commit 3c77ec5
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 3c77ec5

Please sign in to comment.