Standard Server Queries

v0.31

The aim of this document is to provide a starting point for the standardisation of server query request and response formats for gaming engines. There is a focus on FPS style games, but with input hopefully this specification can be general enough to encompass other gaming styles.

Intent

It is the goal of this document to provide an extensible system for querying gaming servers, while remaining efficient and simple to implement.

Contents


Packet Format

Query packets (both request and response) SHALL be transmitted within a UDP packet or series of packets. The port used by this query service SHALL be26999. Each UDP packet will contain a header of 2 bytes, which consist of:

Unique ID
Number of packets in SEQ
Packet Number
8 bits
4 bits              4 bits
                            
The Unique ID is set initially by the query request packet, and the response SHALL use this same Unique ID in its header. The allows for easy identification of different request sessions from the same host. The first 4 bits of the second byte represent the number of packets present in this sequence. A zero value (binary 0000) means only one packet exists. This would be the common value for request packets. The last 4 bits represent the position of this particular packet within the packet sequence. A zero value means that this is the first packet and so on. For a single packet both of these values will be zero.


01011101 (0x5D)
0000 (0x0)
0000 (0x0)
Example 1: an example header for a single packet.


01011111 (0x5F)
0010 (0x2)
0001 (0x1)
Example 2: an example header for a multi packet sequence (3 packets in the sequence, this is packet 1, the "middle" packet)

Note that all counters start from zero (C style). Note that the Unique ID need not be unique, this is a choice for the client not the server.

Data Response format ( CSV)

The basic query result format SHALL be a CSV style table. Every row SHALL contain the same number of zero delimited elements (with the exception of the header row, discussed below)..  Rows are delimited by "\n\0" pairs (ascii code 10 then ascii code 0), cells within the row are delimited by '\0' (ascii code 0). The content of the cell is ALWAYS a string.


hostname\0ip\0port\0map\0game\0x-secure\0\n\0
My Server\01.2.3.4\027015\0de_dust\0cstrike\01\0\n\0
Example 3: Sample CSV format.

If you wish to have a newline within your cell, escape it with the '\' character (ascii code 92). To have the '\' character in the cell, simply use it twice in a row.

John\nBob\0Joe,Bob\0\n\0
\\Player\\\0\n\0
Example 4: Special character escaping.

Emtpy cells are denoted by two consectutive zero values (i.e '\0\0').

Headers

The query format described in Query Format describes a protocol where the client requests certain column names from the server. As this standard is aimed towards computer-to-computer communications (rather than human interaction) it would be expected that for the majority of the time the query will be in the correct format with the correct column names. To help minimise traffic various options have been provided with respect to returning the header row.
Normal
The default behaviour should be for the server to simply insert a header row in each response, where every cell contains the column name it represents.

Query:
SELECT hostname,ip,port,map,game,x-secure
Response:
hostname\0ip\0port\0map\0game\0x-secure\0\n\0
My Server\01.2.3.4\027015\0de_dust\0cstrike\01\0\n\0
Example 5: Sample "Normal" headers

Compact
This format is used to reduce bandwidth when not all of the requested columns can be returned (either due to a bad name or lack of authentication). Rather than the full column names a simple "1" (ascii 49)  is used to denote the column is present and a "0" (ascii 48) that it is absent. Note that you MUST still return the column names in the order requested, you can just skip the unavailable columns.

Query:
SELECT hostname,ip,port,map,game,x-secure
Response:
1\00\01\01\01\00\0\n\0
My Server\027015\0de_dust\0cstrike\0\n\0
Example 5: Sample "Normal" headers
Null
When the column names asked for in the query are all available and returned in the order requested you can further reduce the length of the header row by simply returning "\0\n\0" as the first row. This character sequence is known as the Null Header, and simply means the data returned follows the number and ordering of columns requested.

Query:
SELECT hostname,ip,port,map,game,x-secure
Response:
\0\n\0
My Server\01.2.3.4\027015\0de_dust\0cstrike\01\0\n\0
Example 6: Sample "Null" header

Time

    Two basic time formats SHALL be used when returning time values. The basic time types will be ISO 8601 and Unix Epoch time.
    ISO 8601 has the format "YYYYMMDDTHHMMSS", where each field is a fixed width (i.e minutes will always consist of two characters), and fields to the left can be dropped if not important (i.e to indicated 1 hour and 20 minutes, you can write 012000). A timezone can be represented by appending direction of the timezone change (with respect to GMT) and the value, for example +02.
    Unix Epoch time is the number of seconds since 00:00:00 GMT, January 1, 1970. To use this format simply append a string representation of the number of seconds with the letter "E" (i.e E1027728720).

Query Format

Authentication

A server contains two forms of data, publically available information (such as player names and pings) and private (or sensitive) information such as client IP addresses. To retrieve sensitive information from a server the client must first get an authentication token from a server. This is handled by the AUTH query.
 The format is:
AUTH [password]

A client sends an AUTH query to a server and the response is an authentication token. The authentication token is a null terminated string, with a zero length string denoting an authentication error (possibly due to a bad password). The token is returned in the CSV format describe in the Data Response Format section, with a single column name of "token". This returned token is then used in the SELECT query below to access private data.

AUTH john
Example 7: An example AUTH request

token\0\n\0
dfklj67fhjsdf98s6y\0\n\0
Example 8: An example AUTH response.

token\0\n\0
\0\n\0
Example 9: An example AUTH response due to a bad password.

Data Selection

To retrieve information from a server you send it a "query". The query format is based upon the SELECT statement from the SQL language. The information that a game server contains is abstracted into a database format (with fields for information, and tables grouping like information). The client can then query the information they require, thereby allowing them to either get a rich information source or minimise the bandwidth used when querying a server.
The basic lexical makup of a query is:
SELECT [fields] WHERE [expressions] IDENTIFIED [password]

The query string is case INSENSITIVE. The SELECT tag is required, the WHERE and IDENTIFIED tags are optional. Note that there is no FROM tag, as coloumn names are unique (explained below), so this entry is not required.

[fields] is a comma delimited list of column names to return in this query. Commas are NOT allowed in column names.  Each coloumn name MUST be unique within the database. This uniqueness requirement removes the need to qualify the table from which a column name is sourced, simplifying both the SELECT syntax and the parser. As the column names are either defined in this document or by the developer, maintaining this requirement is not onerous.

name,ping,frags
Example 10: An example [fields] entry

When answering a request, if the column name is not available (either it doesn't exist or the user isn't authenticated) then that column can be left out of the response packet. If ALL fields are not present in the response (i.e no data is to be returned) then a simple null row is returned, which consists of "\n\0" (note that differs from the NULL header which is "\0\n\0").

[expressions] are a list of arithmetic expressions applied to each row of the returned data set. The logical meaning of each expression should be maintained across different data types. For example, ping > 100 should be an integer compare where as name > "bob" should be a string compare. The comparison type to use should be context sensitive, based upon the field name.
The valid expressions are:

Symbol Meaning
= equal to
!= not equal to
> greater than
< less than
and
logical and
or
logical or


ping > 10 and name != "bob"
Example 11: example expression string

[password] is the method by which clients can identify themselves to the server. An authenticated client will have access to sensitive data fields, such as client IP address. The password is a string token returned from the AUTHquery. If private data is requested but the token is invalid then the private columns will not be returned.


Stored Procedures

A small subset of queries will be commonly used. To minimise bandwidth it is possible to have pre-defined queries which can be access by a simple key. The query format to access a stored procedure is:
SP [name]

where [name] is the name of the "hardcoded" stored procedure.
There are several default stored procedures that all servers must implement.

name resulting query string
players SELECT playername,ping,frags,deaths
rules SELECT rulename,rulevalue
info SELECT hostname,hostip,numplayers,maxplayers,map

Developers can specifixy more store procedures for commonly used query strings, the only requirement is that the name is appended with "x-" to denote it as an extended feature.

SP players
Example 12: An example use of a stored procedure

Columns

This command returns the complete list of the columns that the server can return.The query format to get the list is:
CL [LONG]

This will return the list of columns and the virtual table the columns belong to, in the CSV format defined above. The option "LONG" can also be sent to get a short descriptive string about each field (if available).

CL LONG
Example 13: Example of the long CL command.


playername\0hostname\0frags\0pings\0rulename\0\n\0
player\0server\0player\0player\0rules\0\n\0
name of the player\0the name of this server\0the number of frags a player has\0the players latency\0Server Variable names\0\n\0
Example 14: Example return format of the CL LONG command (this is only a small subset of the MINIMUM set of columns).

Version

This command is used to query the protocol version this server supports. It also returns the "game" or "mod" version of this server. The format of this command is:
VERSION

and the return format is two columns, PROTO, GAME and SERVER. PROTOis the protocol version supported by the server. For servers that completely implement the standard describe by this document is SHALL be "1". GAMEis the game or mod name for this server. SERVER is the server game type, or the gaming engine name.

PROTO\0GAME\0SERVER\n\0
1\0Counter-Strike\0HalfLife\0\n\0
Example 15:  Example return values for the VERSION command



Basic Query Tables

There are 4 basic tables that a server SHALL conceptually implement. Each table contains a representation of a certain data source that the engine contains. The definitions in this document contain the minimum coloumn names that SHALL be implemented.

Each response SHALL contain CSV formatted data, as defined in Data Format. Extra column can be added to the table, with the condition that the column names are appended with the "x-" character. The "x-" tag denotes them as an extended feature. Column names MUST be unique across the complete database of names, and the names "0", "1" or "j" are reserved for other uses.

The basic tables are:

Table Name
Query Purpose
info
information about the server, such as current map and mod name
players
information about the players on each server
rules
information about the rules (settings,variables) in use on the server
ping
a short, quick response packet used to determine the server ping time


Info

This table contains information about the server. The minimum columns are:

Column Name
Meaning
hostip the internet address (numeric or DNS) and port of this server
numplayers the current number of players on the server
maxplayers the maximum number of players allowed on the server
map the current map being played


hostip\0players\0max\0map\0\n\0
192.168.1.66:27015\010\020\0datacore\0\n\0
Example 16: Minimum "info" response

Extra fields that could be included are:

Players

The players table is used to encapsulate information about the current players on the server. The minimum columns are:

Column Name Meaning
playername the name of this player
frags the number of kills this player has
deaths the number of deaths this player has
playerping the ping this player has to the server
playertime the time this player has been connected



playername\0frags\0deaths\0playerping\0playertime\0\n\0
Bob\020\010\0200\03321\0\n\0
Example 17: Minimum "players" response

Optional column names include:

Rules

This table contains the list of rules (or variables) being used by the server. It has only two columns:

Column Name Meaning
rulename the name of this rule
rulevalue the value of this rule

An optional column name is "source" (from which addon the variable was registered).
rulename\0rulevalue\0\n\0
mp_timelimit\010\0\n\0
Example 18: Minimum "rules" response

Ping

This query type is purely used by clients to determine the ping (more properly known as latency) between itself and the server. The response in this packet is simply a "j\0\n" (ascii code 106) with no other data.

NOTE - does the ping query need to be standardised? Is this definition enough?


Contributors

Andrew Chen, Divo Networks
Alfred Reynolds, Valve Software
Chuck Larson
Florian, Admin Mod
HoundDawg, UnitedAdmins
Simon Garner
Terry
VALVe Software

Changelog

v0.31
   - Fixed typo's. Added "server" field to VERSION response. Added "table" field to CL response. Added new header options to response format.

v0.3
   - Added VERSION and CL commands, added time definition.

v0.21
   - Updated query definitons.

v0.20
   - Added SQL type query format, introduced virtual database concept

v0.10
    - Defined basic CSV format. Defined basic information sources.



By Alfred Reynolds, alfred@valvesoftware.com, 26th July 2002