Author: Andrew Rose
Date: 6th November 2003
Status: Draft
The Diplomacy Centralisation Project Client-Server Protocol
Version 1
Revision 13
DRAFT COPY
This document specifies the protocol by which a Diplomacy AI (“client”) should communicate with the AIJudge (“server”). It should be read in conjunction with the AI Language Syntax. The remainder of this document is structured as follows.
The document is aimed at people who wish to…
The following issues have been identified with this protocol and are under investigation.
This section defines the transport mechanism to be used.
Client-server communications will be carried out over a TCP connection.
The server will publish an address and TCP port on which the server can be contacted. The method of publishing the address is outside the scope of this document.
The server will open a listening connection on the published TCP port. It is recommended that a backlog of at least 10 connections be used where available to prevent unnecessary client connection failure.
Following a connection from a client, the server will continue to listen for further connections from clients on the original socket.
When a client connects to the server, the server will set the SO_KEEPALIVE socket option on the newly created socket. This causes dead connections to be cleared by the server.
The server will run a 30 second initial message timer. If the server hasn’t received any data when the timer pops, the server will send and error message (see below) and terminate the connection.
If a client sends data over a connection with an invalid message structure (see chapter 3), the server will terminate the connection.
To communicate with a server, a client shall first establish a TCP connection to the address and port published by the server. The client may use any free local port.
The client will set the SO_KEEPALIVE socket option on the socket connected to the server.
Immediately following the establishment of a connection, the client shall send an Initial Message (see section 3.2).
Once a connection has been established, the two parties may transfer messages as described in this section. Both parties may send messages at any time except as limited below.
All message structures described in this section are shown in network byte order (big endian). Implementers of clients or servers for little endian machines (e.g. Intel) should take care in swapping the octets of multi-octet fields.
All messages sent between a client and a server will have the following message structure.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Pad | Remaining Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Optional Data |
| . |
| . |
| . |
Message Type: 8 bits
The type of message that follows. The messages and their type are described in the subsequent sections of this chapter.
Pad: 8 bits
This part of the message is not valid. i.e. It may contain any bit pattern. It is included so that the length field is naturally aligned.
Remaining Length: 16 bits
The number of octets in the message that follow the Remaining Length field. This may be zero if the message type alone completely defines the message.
Optional Data: Variable length
The data part of the message is described in the definitions for the individual messages. It is exactly the length specified in the Remaining Length field and is not padded.
This is a fixed length message.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Pad | Remaining Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version | Magic Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Message Type = 0
Remaining Length = 4
Version, as specified on the introductory page of this document.
Magic Number = 0xDA10
This message is sent from the client to the server as soon as the connection has been opened. If the server discovers incompatible version numbers, it will send the error message and close the connection. Note that a single instance of a server may be able to talk several different protocol versions over different connections.
The message contains a magic number that is designed to quickly catch connections that have (inadvertently or deliberately) been made to the server by a program other than a Diplomacy AI Client. Because the magic number’s bit pattern is not the same forwards and backwards, it will also catch clients who have failed to send in network byte order. The message is only ever sent from the client to the server and it is only sent once.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Pad | Remaining Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Representation Message |
| . |
| . |
| . |
Message Type = 1
This mandatory message is sent from the server to the client immediately on receipt of the IM. It is used to define additional power and province tokens that will be valid for the variant of the game that the server is set up to adjudicate for. It will also give a text representation of any such tokens. If there are no such tokens, the remaining length will be zero. If there are additional tokens, the remaining length will be a multiple of six. Each six-octet block will consist of the following.
If the RM has non-zero length then none of the powers or provinces defined in chapter 4 are valid. Instead, the powers and provinces defined in the RM are the only valid powers and provinces. Note that if a variant uses the standard powers on a variant board or variant powers on the standard board, both the provinces and the powers must be defined in the RM.
The same token must not appear in the RM more than once.
When defining provinces, the low-octet of the province tokens must be unique and form a sequence starting at 0 and incrementing by 1 up to the number of provinces less 1.
When defining powers, the low-octet of the power tokens must be unique and form a sequence starting at 0 and incrementing by 1 up to the number of powers less 1.
This message is only ever sent from the server to the client and it is always sent precisely once, immediately following the IM.
This is a variable length message.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Pad | Remaining Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Language Message |
| . |
| . |
| . |
Message Type = 2
Remaining Length is at least 2.
The optional data part contains a single “language message” as described in the Language Syntax. The language message is encoded as described in the chapter “Language Representation”. It can be sent by either party following the RM.
This is a fixed length message.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Pad | Remaining Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Message Type = 3
Remaining Length = 0
This message is sent immediately before the either party closes the TCP connection. It is not sent if an error message has been sent. On receipt, the receiving party will immediately close the connection without sending a final message or error message.
This is a fixed length message.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type | Pad | Remaining Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Error code |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Message Type = 4
Remaining Length = 2
This message indicates that the sending party has detected a protocol error. An EM may be sent at any time. The party sending this message will terminate the connection immediately after sending it. The error codes are defined in the following table.
Code |
Meaning |
Code |
Meaning |
0x01 |
IM timer popped |
0x02 |
IM was not the first message sent by the client |
0x03 |
IM indicated the wrong endian |
0x04 |
IM had an incorrect magic number |
0x05 |
Version incompatibility |
0x06 |
More than 1 IM sent |
0x07 |
IM sent by server |
0x08 |
Unknown message received |
0x09 |
Message shorter than expected |
0x0A |
DM sent before RM |
0x0B |
RM was not the first message sent by the server |
0x0C |
More than 1 RM sent |
0x0D |
RM sent by client |
0x0E |
Invalid token in DM |
Note that this message will not be sent due to a language error. Language errors are handled in the language itself (see Chapter 4).
On receipt of an error message, the receiving party will immediately close the connection without sending an error message or final message.
This section describes how a language message is encoded into the data part of a Diplomacy Message (see above).
Every language token will be represented by a 2-octet field.
The tokens are split into categories. Each category will have a 1-octet value associated with it. The tokens within each category will be numbered. The token value can be calculated by multiplying the category by 256 and adding the token number within the category.
This method means that the protocol is extensible and allows simple determination of a token category from the top octet.
The category space is divided as follows.
00xxxxxx ( 64) - Integers
0100xxxx ( 16) – Various individual categories
01010xxx ( 8) - Provinces
01011xxx ( 8) – Reserved for individual AI/Server use. Never transmitted.
011xxxxx ( 32) - Unassigned
1xxxxxxx (128) - Unassigned
Of the 256 possible categories, 88 are assigned and the remaining 168 are reserved for future use. In those 168, a full 128-category block remains as well as a 32-category block. These blocks may be further subdivided in the future if appropriate.
The remainder of this chapter defines the categories, their value and the token numbers within the category.
The representable range of integers is -8192 to +8191. They are coded as a 14-bit two’s-complement value. The top two bits of the category are always zero.
BRA 0x00 - The open bracket ‘(’
KET 0x01 - The close bracket ‘)’
AUS 0x00
ENG 0x01
FRA 0x02
GER 0x03
ITA 0x04
RUS 0x05
TUR 0x06
AMY 0x00
FLT 0x01
CTO 0x20
CVY 0x21
HLD 0x22
MTO 0x23
SUP 0x24
VIA 0x25
DSB 0x40
RTO 0x41
BLD 0x80
REM 0x81
WVE 0x82
Note that the high three bits can be used to determine which phase the order is valid in. The top bit is valid the adjustments phase, the next is valid in the retreats phase and the last is valid in the movement phase.
MBV 0x00
BPR 0x01
CST 0x02
ESC 0x03
FAR 0x04
HSC 0x05
NAS 0x06
NMB 0x07
NMR 0x08
NRN 0x09
NRS 0x0A
NSA 0x0B
NSC 0x0C
NSF 0x0D
NSP 0x0E
NST 0x0F
NSU 0x10
NVR 0x11
NYU 0x12
YSC 0x13
SUC 0x00
BNC 0x01
CUT 0x02
DSR 0x03
FLD 0x04
NSO 0x05
RET 0x06
NCS 0x00
NEC 0x02
ECS 0x04
SEC 0x06
SCS 0x08
SWC 0x0A
WCS 0x0C
NWC 0x0E
SPR 0x00
SUM 0x01
FAL 0x02
AUT 0x03
WIN 0x04
CCD 0x00
DRW 0x01
FRM 0x02
GOF 0x03
HLO 0x04
HST 0x05
HUH 0x06
IAM 0x07
LOD 0x08
MAP 0x09
MDF 0x0A
MIS 0x0B
NME 0x0C
NOT 0x0D
NOW 0x0E
OBS 0x0F
OFF 0x10
ORD 0x11
OUT 0x12
PRN 0x13
REJ 0x14
SCO 0x15
SLO 0x16
SND 0x17
SUB 0x18
SVE 0x19
THX 0x1A
TME 0x1B
YES 0x1C
ADM 0x1D
AOA 0x00
BTL 0x01
ERR 0x02
LVL 0x03
MRT 0x04
MTL 0x05
NPB 0x06
NPR 0x07
PDA 0x08
PTL 0x09
RTL 0x0A
UNO 0x0B
DSD 0x0D
ALY 0x00
AND 0x01
BWX 0x02
DMZ 0x03
ELS 0x04
EXP 0x05
FWD 0x06
FCT 0x07
FOR 0x08
HOW 0x09
IDK 0x0A
IFF 0x0B
INS 0x0C
IOU 0x0D
OCC 0x0E
ORR 0x0F
PCE 0x10
POB 0x11
PPT 0x12
PRP 0x13
QRY 0x14
SCD 0x15
SRY 0x16
SUG 0x17
THK 0x18
THN 0x19
TRY 0x1A
UOM 0x1B
VSS 0x1C
WHT 0x1D
WHY 0x1E
XDO 0x1F
XOY 0x20
YDO 0x21
WRT 0x22
The value is the ASCII code for a single letter. Strings are not delimited with quotation marks or anything else. There are no situations in the language where one string runs directly into another. Therefore, the end of a string can be identified when the first non-text token is received.
There are eight province categories as defined here.
Inland non-SC category = 0x50
BOH 0x00
BUR 0x01
GAL 0x02
RUH 0x03
SIL 0x04
TYR 0x05
UKR 0x06
Inland SC category = 0x51
BUD 0x07
MOS 0x08
MUN 0x09
PAR 0x0A
SER 0x0B
VIE 0x0C
WAR 0x0D
Sea non-SC category = 0x52
ADR 0x0E
AEG 0x0F
BAL 0x10
BAR 0x11
BLA 0x12
EAS 0x13
ECH 0x14
GOB 0x15
GOL 0x16
HEL 0x17
ION 0x18
IRI 0x19
MAO 0x1A
NAO 0x1B
NTH 0x1C
NWG 0x1D
SKA 0x1E
TYS 0x1F
WES 0x20
Sea SC category = 0x53
On the standard map there are no sea SCs.
Coastal non-SC category = 0x54
ALB 0x21
APU 0x22
ARM 0x23
CLY 0x24
FIN 0x25
GAS 0x26
LVN 0x27
NAF 0x28
PIC 0x29
PIE 0x2A
PRU 0x2B
SYR 0x2C
TUS 0x2D
WAL 0x2E
YOR 0x2F
Coastal SC category = 0x55
ANK 0x30
BEL 0x31
BER 0x32
BRE 0x33
CON 0x34
DEN 0x35
EDI 0x36
GRE 0x37
HOL 0x38
KIE 0x39
LON 0x3A
LVP 0x3B
MAR 0x3C
NAP 0x3D
NWY 0x3E
POR 0x3F
ROM 0x40
RUM 0x41
SEV 0x42
SMY 0x43
SWE 0x44
TRI 0x45
TUN 0x46
VEN 0x47
Bicoastal non-SC category = 0x56
On the standard map there are no non-SC bicoastal provinces.
Bicoastal SC category = 0x57
BUL 0x48
SPA 0x49
STP 0x4A
Note that the province values form a sequence starting at zero and leading up to 74 (giving 75 provinces in total). It will always be possible to use the bottom octet to index into a zero-based array. The low bit of the category determines if the province is a supply centre or not. The next two bits can be used to determine province type.
These categories will never be assigned another use. AI writers are free to use these categories as they see fit. However, they must never be sent over the wire.