El Muerte/GQP
GQP stands for Gameserver Query Protocol (working title)
Purpose
This document serves as a working draft for a RFC to be written later.
At the moment, there's only one protocol that can be considered a standard: the GameSpy protocol. But this protocol is not well defined and has some design flaws.
Hopefully, game developers and server query programs (like [qstat] or [ASE]) will adopt this specification once it's complete.
Authors
If you are going to work on the design of this protocol, please add your name here for later reference.
- Michiel Hendriks <elmuerte@drunksnipers.com>
- Guillaume Cocatre-Zilgien, a.k.a. "skamp" - http://www.skamp.net/
Design features
- the protocol should be as basic and serve as many purposes as possible, so it can be implemented in every game;
- authentication, possibility to protect data (through encryption/encoding?);
- easily extensible with new query commands;
...
Grammar
Client request
QUERY ::= ( ENCODED )? COMMAND ( GS COMMAND )* EOT ENCODED ::= SOH STRING ACK COMMAND ::= STRING ( RS ARGUMENT-LIST )? ARGUMENT-LIST ::= STRING ( US STRING )*
Server response
RESPONSE ::= ( ENCODED )? COMMAND-REPLY ( GS COMMAND-REPLY )* EOT COMMAND-REPLY ::= STATUS-CODE COMMAND-NAME RS DATA COMMAND-NAME ::= STRING STATUS-CODE ::= DIGIT DIGIT DATA ::= ACK | RECORD ( RS RECORD )* RECORD ::= DC1 STRING // a simple string | DC2 STRING US STRING // name = value | DC3 STRING ( US STRING )* // array | DC4 STRING ( US STRING )* // labeled array (first element is the label) SOH ::= <SOH> EOT ::= <EOT> GS ::= <GS> RS ::= <RS> US ::= <US> STRING ::= ( <printable> )* DIGIT ::= '0' ... '9' ACK ::= <ACK> DC1 ::= <DC1> DC2 ::= <DC2> DC3 ::= <DC3> DC4 ::= <DC4>
Server reponse data
The server respons data (the rules DATA and RECORD) can be one of the following format:
- empty reply
- only an <ACK>
- text
- just a single string as reply
"single item"
- name/value
- both a name and value
"label" => "single item"
- array
- an array of value
Array ("item one", "item two", "item three")
- labeled array
- an array with a label
"label" => Array ("item one", "item two", "item three")
<DLE>, <EOT>, <ETB>, <GS>, <RS>, <US>, <ACK>, <SOH>, <STX> and <ETX> are ASCII control codes (the first 32 symbols in the ASCII table).
<printable> is every non-control code in the ASCII table.
Skamp: When needed, transmissions shall be split into blocks ending with <ETB>, <EOT> indicating overall completion.
El Muerte TDS: you don't need to split transmission into blocks, UDP is pretty much a constant stream of data so just start with reading until you get an <EOT>
Skamp: Mmm-kay.
Encoding
When a Query or Command starts with <SOH>, the data is encoded up to <EOT>.
The <SOH> control character is followed by a string containing encoding information terminated by <ACK>. The choice of encoding is up to the implementor.
Skamp: I believe that <DLE> is more suitable for type definition; besides, one might want to specify more than one kind of encoding: for instance, "bzip2" + "UTF-8"...
El Muerte TDS: the string is just a identification string, so if you want "bzip2" + "utf-8" you can just use "bzip2+utf-8" as string, or even "MySpecialEncoding". It really doesn't matter.
Skamp: I'm just affraid of implementations to use different syntaxes. One would use standard notations, and another one would use "zip/english" because it's just more convenient. You're right, it doesn't really matter, as long as we specify a standard - or use an existing - ASCII notation.
El Muerte TDS: we could say use a mime string, application/gzip for example, or application/x-gamespy
Status Codes
Returned codes per command:
Code | Meaning | |
10 | OK | The command returned succesfully |
20 | Unknown command | |
21 | Unsupported feature | The requested feature is not supported, can be returned in case of encoding or authentication |
22 | Incorrect number of arguments | Command requires more or fewer arguments; in the latter case, this status code may be ignored |
23 | Invalid argument | One ore more arguments aren't correctly formated |
30 | Disabled | This command has been disabled by the admin |
31 | Temporarily unavailable | This service or command is temporarily unavailable |
32 | Unauthorised | Not authorised to use this command or invalid credentials |
40 | Unsupported encoding | The used encoding isn't supported |
41 | Decode error | An error occured while decoding |
Required commands
The following commands should be supported by every implementation:
- identify
- return game identification info
input: none
output: gamename = tag; gamever = version; netver = minimal net version
- echo
- return the argument
input: any number of arguments
output: return each input argument
- auth
- return challenge info to be used with the challenge command in order to access protected commands, or to be supplied with encoded data.
input: login; password;
output: challenge string
- challenge
- validate the client after an authentication
input: challenge string
output: none
- extensions
- return the list of accepted extensions to the protocol
input: none
output: list
...
Example queries
Note: in the following examples, data sent to or received from the server is not real, but has been adapted to a more readable format.
- Query
"identify" <EOT>
- Response
10 "identify" <RS> "gamename" <US> "ut" <RS> "gamever" <US> "432" <RS> "netver" <US> "432" <EOT>
- Query
"unknown command" <EOT>
- Response
20 "unknown command" <RS> <STX> "error: unknown command" <EOT>
or
20 <RS> <ACK> <EOT>
- Query
"echo" <RS> "this text" <GS> "echo" <RS> "more text" <EOT>
- Response
10 "echo" <RS> <STX> "this text" <GS> 10 "echo" <RS> <STX> "more text" <EOT>
A test page: http://unreal.elmuerte.com/GQP/
Reference
ASCII Table
Notation | Meaning | Hex. code | Dec. code |
<SOH> | Start Of Header | 01 | 1 |
<STX> | Start of TeXt | 02 | 2 |
<ETX> | End of TeXt | 03 | 3 |
<EOT> | End Of Transmission | 04 | 4 |
<ACK> | Acknowledge | 06 | 6 |
<DLE> | Data Link Escape | 10 | 16 |
<DC1> | Device Control 1 | 11 | 17 |
<DC2> | Device Control 2 | 12 | 18 |
<DC3> | Device Control 3 | 13 | 19 |
<DC4> | Device Control 4 | 14 | 20 |
<ETB> | End of Transmission Block | 23 | 17 |
<GS> | Group Separator | 1d | 29 |
<RS> | Record Separator | 1e | 30 |
<US> | Unit Separator | 1f | 31 |
Sources:
- http://www.cs.tut.fi/~jkorpela/chars/c0.html
- http://www.evergreen.edu/biophysics/technotes/program/ascii_ctrl.htm
- http://www.beaunet.force9.co.uk/IT4IT/glossary/CtrlCods.htm
Discussion
El Muerte TDS: Everything on this page is subject for changing, this my initial concept.
Skamp: Good start! I think that in the future, technical specifications won't be enough: we will also need implementation guidelines.
Skamp: I've made some spelling and phrasing corrections, I hope you don't mind.
Skamp: Added some suggestions; I'm going to bed now
Skamp:
About TYPE:
The added TYPE would allow the specification of the item's type (hexadecimal, decimal, 16 bits or 32 bits integer, signed / unsigned, etc...). I think it is important to include such information; besides, as a single char it wouldn't take much space.
The default type would apply by default to every item in the list, if not specified otherwise on a case by case basis (specific type).
El Muerte TDS: I think it's best to simple use plain 8bit ASCII for everything. And if the data is transmitted in UNICODE you would just add <SOH> "UNICODE" <ACK> in front of your transmission. I want to prevent binary data as much as possible. (unless you use an encoding)
Skamp: I didn't realize that. You should specify it somewhere, although I'm not sure to agree with that. Binary mixes quite well with ASCII, while being very suitable for numbers, and lightweight. Type enforcement is a big concern to me, since existing implementations of the GameSpy protocol have shown to be very inconsistent. I believe we need a stricter protocol.
On another subject: your redefined RECORD is much simpler and clearer than mine, sometimes I probably should go to bed earlier By the way, EBNF standard notation for comments encloses them in (* *); although it doesn't matter now that you used C-like notation, it will matter when writing the RFC.
El Muerte TDS: The problem with binary data is that it will introduce endian problems (sure it's a single line in the definition that everything is big endian), But i just want to make sure we don't have to deal with 0x00.
EBNF has a format for comments ?! Didn't know that.