Network protocol: Difference between revisions

From OuroDev
(Created page with "Most of the servers use a common network protocol. It is a packet-oriented protocol, with each packet having a command number and some body fields. Packets are encoded as bit...")
 
No edit summary
Line 52: Line 52:


=== COMMCONTROL_IDLE (0) ===
=== COMMCONTROL_IDLE (0) ===
This packet is empty and is ignored.


=== COMMCONTROL_CONNECT (1) ===
=== COMMCONTROL_CONNECT (1) ===
Line 60: Line 62:
If *requested_version* is not present, the version is 0.
If *requested_version* is not present, the version is 0.


The protocol version is set to *requested_version*. This must be the first command send on a link. The server will respond to this message by sending back a command:
The protocol version is set to *requested_version*. This must be the first command send on a link. The server will respond to this message by sending back a COMMCONTROL_CONNECT_SERVER_ACK command.
 
=== COMMCONTROL_CONNECT_SERVER_ACK (2) ===


COMMCONTROL_CONNECT_SERVER_ACK
  packint(1) encrypted
  packint(1) encrypted
  optional alignedbits(512) public_key
  optional alignedbits(512) public_key
Line 68: Line 71:
If *encrypted* is 1, then a public key will be sent and link encryption will be used. If *encrypted* is 0, the packet ends here and the link is not encrypted.
If *encrypted* is 1, then a public key will be sent and link encryption will be used. If *encrypted* is 0, the packet ends here and the link is not encrypted.


=== COMMCONTROL_CONNECT_SERVER_ACK (2) ===
The server will respond to this message by sending back a COMMCONTROL_CONNECT_CLIENT_ACK command.


=== COMMCONTROL_CONNECT_CLIENT_ACK (3) ===
=== COMMCONTROL_CONNECT_CLIENT_ACK (3) ===
packint(1) encrypted
optional alignedbits(512) public_key
If *encrypted* is 1, then a public key will be sent and link encryption will be used. If *encrypted* is 0, the packet ends here and the link is not encrypted.
When it is received, the link is connected and future packets will be encrypted (if encryption is enabled).


=== COMMCONTROL_CONNECT_SERVER_ACK_ACK (4) ===
=== COMMCONTROL_CONNECT_SERVER_ACK_ACK (4) ===
This packet is empty. When it is received, the link is connected and future packets will be encrypted (if encryption is enabled).


=== COMMCONTROL_DISCONNECT (5) ===
=== COMMCONTROL_DISCONNECT (5) ===
This packet is empty. When it is received, the server will send back a COMMCONTROL_DISCONNECT_ACK and then immediately close the connection.


=== COMMCONTROL_DISCONNECT_ACK (6) ===
=== COMMCONTROL_DISCONNECT_ACK (6) ===
This packet is empty and is ignored.


=== COMMCONTROL_BUFFER_RESIZE (7) ===
=== COMMCONTROL_BUFFER_RESIZE (7) ===
bits(32) buffer_size
If *buffer_size* is not too large, then the buffer of the underlying OS socket is adjusted to this size.


== User commands ==
== User commands ==

Revision as of 19:06, 2 May 2019

Most of the servers use a common network protocol. It is a packet-oriented protocol, with each packet having a command number and some body fields.

Packets are encoded as bitstreams, implemented by [1] and accessed via the functions in [2].

Packets are sent over links, which are represented by the NetLink type. A link is a connection to a single endpoint, and can use TCP or UDP transport. Connections between servers are usually TCP, while connections to the game client may be UDP. In the case of UDP transport, packets are sent in a single datagram.

There are several versions of the network protocol, which have different encodings on the wire. After being deserialised into a packet, they all behave the same. As part of the network encoding, the packet may also be compressed and encrypted.

The wire format of a packet is framed with a struct PacketHeader at the start, containing a length and checksum. The length will be padded for blowfish block sizes if the link is encrypted; after this, the packet must be the size indicated.

After this, the packet is encoded as a bitstream.

Bitstreams

Bitstreams encode a series of values. There are several data types for these values, which determine their encoding in the bitstream.

Type name Implementation function Description Wire format
bits(N) pktSendBits / pktGetBits N bits, up to 32 Precisely N bits, unmodified
alignedbits(N) pktSendBitsArray / pktGetBitsArray N bits, up to maximum packet size The stream is padded with zeros to the next byte boundary, and the number of bits sent is rounded up to a whole byte, then those bits are send unmodified.
packint(N) pktSendBitsPack / pktGetBitsPack An unsigned int, packed with a variable-length encoding A sequence of bit strings, starting with one of length N, and then doubling in size each time until enough bits are used. All bits in all fields other than the last will be set to 1. With each field, the value of the bitstring is subtracted from the integer being sent, until the integer is small enough to fit into the final field.
string pktSendString / pktGetStringAndLength A null-terminated string The raw string, terminated with a zero byte. The string is not byte-aligned or padded, in the output, but will always be a multiple of 8 bits in length.
alignedstring pktSendStringAligned / pktGetStringTemp A null-terminated string The raw string, terminated with a zero byte. The stream will be padded with zeros to the next byte boundary before the string begins.
float32 pktSendF32 / pktGetF32 A 32-bit float An IEEE-754 32-bit float, in x86 byte ordering. The stream is not padded or aligned.

Packet format

The body of a packet begins with:

packint(1) cmd

In protocol versions 4 and 5, when cmd == 0 then this is a control command, and the next value in the packet is:

packint(1) controlcmd

In protocol versions 0, 1, and 2, values of cmd from 0 through 6 are controlcmd values, and other command values are increased by 5 to make room.

If this is not a control command, then cmd is adjusted as necessary for older protocol versions, and the rest of this packet is a user command.

Control commands

The content of a control command depends on the command number

COMMCONTROL_IDLE (0)

This packet is empty and is ignored.

COMMCONTROL_CONNECT (1)

packint(1) connect_id
optional packint(1) requested_version

If *requested_version* is not present, the version is 0.

The protocol version is set to *requested_version*. This must be the first command send on a link. The server will respond to this message by sending back a COMMCONTROL_CONNECT_SERVER_ACK command.

COMMCONTROL_CONNECT_SERVER_ACK (2)

packint(1) encrypted
optional alignedbits(512) public_key

If *encrypted* is 1, then a public key will be sent and link encryption will be used. If *encrypted* is 0, the packet ends here and the link is not encrypted.

The server will respond to this message by sending back a COMMCONTROL_CONNECT_CLIENT_ACK command.

COMMCONTROL_CONNECT_CLIENT_ACK (3)

packint(1) encrypted
optional alignedbits(512) public_key

If *encrypted* is 1, then a public key will be sent and link encryption will be used. If *encrypted* is 0, the packet ends here and the link is not encrypted.

When it is received, the link is connected and future packets will be encrypted (if encryption is enabled).

COMMCONTROL_CONNECT_SERVER_ACK_ACK (4)

This packet is empty. When it is received, the link is connected and future packets will be encrypted (if encryption is enabled).

COMMCONTROL_DISCONNECT (5)

This packet is empty. When it is received, the server will send back a COMMCONTROL_DISCONNECT_ACK and then immediately close the connection.

COMMCONTROL_DISCONNECT_ACK (6)

This packet is empty and is ignored.

COMMCONTROL_BUFFER_RESIZE (7)

bits(32) buffer_size

If *buffer_size* is not too large, then the buffer of the underlying OS socket is adjusted to this size.

User commands

If the link has cookies enabled, the next values will be:

bits(32) cookie
bits(32) cookie_echo

(Cookies??? Still to figure out how these work, but they're sent back and forth to identify positions in the stream somehow)

The rest of the bitstream is delivered to the command handler as the body of the packet