GameSpy Protocol

From BF2 Technical Information Wiki
Jump to navigation Jump to search

Basics

These are the protocols used to communicate with the server using the sv.gameSpyPort port in order to retrieve one or more of the following available information type:

Server Data

  • This is general information about the game in progress (i.e., the map that is being played, the type of game, and any specific game settings that would be of interest to players before they joined).

Player Data

  • This is information about a specific player that is in the current game (i.e., the player's name, their current score, what team they are on, and the latency to the game server).

Team Data

  • This is information about a specific team in the current game (i.e., the name of the team and the team score. If your game does not support team play you do not need to report any team information).
Data is reported in a "key-value" format: player keys always end in an "_" character (such as "score_") and team keys always end in a "_t" (such as score_t). Server keys can end in anything other than an "_" or "_t"

Almost every protocol starts the same way:

0xFE 0xFD YY XX XX XX XX 
Header uint16 Always 0xFE 0xFD
Protocol ID byte
TimeStamp uint32 Always retuned in the messages, may be used as an identifier distinguish between multiple packets from the same server

App packages sent by the server are limited to 1400 bytes and all communication is handled in UDP

Battlefield 2 uses the Gamespy SDK to handle these requests.

Protocol 00: Server information

Sub-Protocol A

Only replies with 1 message, even if means responding with incomplete information

Request

0xFE 0xFD 0x00 XX XX XX XX HH PP TT 0x00

HH, PP and TT are a individual flags to request to the server its headers, players and team information, respectively.

These flags need to set to FF to be considered enabled and multiple combinations can be made, eg: asking headers and team information will be ( FF 00 FF )

Reply

Same as "Sub-Protocol B"'s reply but limited to 1 reply, 1400 bytes and some fields might be omitted, depending on the flags.

Sub-Protocol B

The most complete protocol; it always reply all 3 information fields (server, players, team) using one or more packages (of 1400 bytes).

Request

0xFE 0xFD 0x00 XX XX XX XX HH PP TT 0x01

HH, PP and TT will be ignored not matter the value.

It's the last byte, 0x01, that matters. More specifically the last byte only needs to have the least significant bit set to 1.

Reply

The server may reply with one or more messages if the information is bigger than the 1400 bytes limit.

These messages will always start with:

00 XX XX XX XX splitnum 00 YY PAYLOAD
Protocol ID byte Always zero
Timestamp uint32 The value sent in the request
"splitnum" string Always "splitnum"
splitnum byte Only seen 00 probably indicates how the strings are terminated[1]
Message Number byte The most significant bit indicates if its the last message, all others are used for the message number

The payload 1st byte indicates the type: 00, 01 and 02 for Server Headers, Player information and Team Information, respectively.

Server Headers

key/value pairs.

00 <key 1> 00 <value 1> 00 ... <key N> 00 <value N> 00  00

Example:

\00hostname\00[PR v1.4.6.0] =]H[= HARDCORE GAMING - NA\00gamename\00battlefield2\00gamever\001.5.3153-802.0\00password\000\00

Which is:

hostname: "[PR v1.4.6.0] =]H[= HARDCORE GAMING - NA"
gamename: "battlefield2"
gamever: "1.5.3153-802.0"
password: "0" (false)

Player information and Team information

Player and Team informations are stored into <key>:<array of values>.

With the actual format being

QQ <key 1> 00 <offset> <value 1 + offset> 00 ... <value NN> 00 00 00

QQ is the type. With 0x01 indicating its Player information and 0x02 representing Team information.

Since the message may end before the array ends, the first value after each key is the <offset> that defines the index to start from.


An example of the player information's section with 3 players is:

\01 player_\00\00 =MD=shilijia\00>11< WangXi\00 a365476093\00\00score_\00\00191\00159\000\00\00ping_\00\0050\0033\0018\00\00\00

Which is:

player_: [" =MD=shilijia", ">11< WangXi", " a365476093"]
score_: ["191", "159", "0"]
ping_: ["50", "33", "18"]

Sub-Protocol C

The 3rd of our sub-protocols to request information about the server allows you to indicate which headers and how many you want to know about.

Request

0xFE 0xFD 0x00 XX XX XX XX YY KK0 ... KKYY-1 0x00 0x00

The 8th byte (YY) informs the server how many headers you're asking for, meaning the number of bytes that follows afterwards (plus 2 terminal ones). These following bytes, excluding the last 2, define the header's indexes that you're querying about. See next table to see the mapping between index and header.

Offset Header
01 hostname
02 gamename
03 gamever
04 hostport
05 mapname
06 gametype
07 gamevariant
08 numplayers
09 ??
0a maxplayers
0b gamemode
0c ??
0d ??
0e ??
0f ??
10 timelimit
11 roundtime?
12 ??
13 ??

Reply

The sub-protocol C replies with the usual protocol ID followed by the provided timestamp, the payload and the null byte to terminate the message.

0x00 XX XX XX XX PAYLOAD 0x00

The payload consists in all header's value requested separated by 0x00. The header's values maintains the same order as in the request.

Example: Requesting the number of players and server name

0xFE 0xFD 0x00 0x20 0x21 0x21 0x20 0x02 0x08 0x01 0x00 0x00

The reply will be, 84 players and 'My Server':

0x00 0x20 0x21 0x21 0x20 0x84 0x00 [PR v1.4.17.0] My Server 0x00

Protocol 02: Echo

An echo protocol. The server always returns the data sent after the protocol ID (up to 32 bytes) prefixed with the Echo Response Identifier (0x05).

Request

FE FD 02 XX0 ... XX31

Reply

05 XX0 ... XX31

Protocol 03: HEARTBEAT

Packet sent by the game server to the Master Server every 60s with the server's information.

Request

There is no request. Servers send this information every 60s so they can be considered 'alive' and thus displayed in the server browser.

Reply

0x03 XX XX XX XX <localIPs> <port> <natneg> <stateChanged> <gamename> <publicInfo> <serverKeys>

localIPs

Present when there's at least one local IP available.

A list composed by strings. Each string starts with 'localip' followed by a (sequential) number, a null character, and the the IP in IPv4 dotted-decimal notation, eg:

localip0 0x00 192.168.1.3 0x00 localip1 0x00 192.168.1.4 0x00 (42 bytes)

port

Always available.

String literal localport folowed by the string representation of the integer that represents the port, eg:

 localport 0x00 29900 (15 bytes)

natneg

stateChanged

gamename

publicInfo

serverKeys

Protocol 08: Keep Alive

Sent by the master server to the server to report it knows about it

Request

FE FD 08

Reply

No reply

Protocol 09: Echo Alternative

According to game-spy specifications this should be used to generate a 4 bytes value for us to send in the following replies as the TimeStamp, therefore allowing an IP verification.
Battlefield 2 however just returns 4 bytes of what we send with 2 more hardcoded bytes appended.

Request

FE FD 09 XX XX XX XX

Reply

09 XX XX XX XX 30 00