Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transport

A server and a client exchange messages over UDP, carried by ENet 1.2.5 with the header each range’s definitions give.

Layering

Four layers carry a message to a socket.

  1. UDP moves datagrams.
  2. ENet turns datagrams into ordered, acknowledged deliveries on numbered channels.
  3. A cipher covers each channel payload.
  4. A message occupies the deciphered payload, opening with the header its family carries, as Messages defines.

This chapter covers layers 1 to 3.

Stock ENet

This document does not restate ENet. Connection setup, acknowledgement, sequence numbers, retransmission, throttling, and fragmentation behave as ENet 1.2.5 defines them.

In 1.0.0.25–1.0.0.126

Stock ENet 1.2.5 serves a client as it stands: the header, the constants and the commands are the release’s own, and the verify connect stock ENet sends states what the client’s connect asked for.

In 1.0.0.127–1.0.0.129

Stock ENet 1.2.5 serves a client once its transmission unit is clamped (see below). The header and the commands are the release’s own.

The packet header

Each range has its own header, below with the constants it is read under. A server MUST use the layout of the version it serves, because a client establishes no connection under any other layout.

Packet headers and constants

In 1.0.0.25–1.0.0.110

ENet 1.2.5 beneath; little-endian fields. Blowfish in ECB mode over 8-byte blocks, each read big-endian, under a 16-byte key given as text. A client pads what it sends to whole blocks.

FieldTypePresent whenWhat it is
sessionIdbytes, 4The four bytes the client put in its connect command, carried unchanged on every packet. A client drops a packet carrying any other four.
peer2-byte bits
peer.peerIdbit 0 to 1432767 marks an unassigned peer, which is what a connecting client sends. A server gives the client peer 0.
peer.sentTimeFlagbit 15Set when the header carries a sent time.
sentTimeu16, big-endianpeer.sentTimeFlag setMilliseconds since the connection opened.
ConstantValueStock ENetWhat it is
maximumPeerId3276732767Follows from the peer id occupying fifteen bits.
maximumTransmissionUnit40964096A client asks for 1400 in its connect command, and takes datagrams up to 4096 bytes.
minimumDatagram88A client discards any datagram shorter than this many bytes.

In 1.0.0.111–1.0.0.115

ENet 1.2.5 beneath; little-endian fields. Blowfish in ECB mode over 8-byte blocks, each read big-endian, under a 16-byte key given in base64. A client pads what it sends to whole blocks.

FieldTypePresent whenWhat it is
sessionIdbytes, 4The four bytes the client put in its connect command, carried unchanged on every packet. A client drops a packet carrying any other four.
peer2-byte bits
peer.peerIdbit 0 to 1432767 marks an unassigned peer, which is what a connecting client sends. A server gives the client peer 0.
peer.sentTimeFlagbit 15Set when the header carries a sent time.
sentTimeu16, big-endianpeer.sentTimeFlag setMilliseconds since the connection opened.
ConstantValueStock ENetWhat it is
maximumPeerId3276732767Follows from the peer id occupying fifteen bits.
maximumTransmissionUnit40964096A client asks for 1400 in its connect command, and takes datagrams up to 4096 bytes.
minimumDatagram88A client discards any datagram shorter than this many bytes.

In 1.0.0.116–1.0.0.126

ENet 1.2.5 beneath; little-endian fields. Blowfish in ECB mode over 8-byte blocks, each read big-endian, under a 16-byte key given in base64. Neither end pads.

FieldTypePresent whenWhat it is
sessionIdbytes, 4The four bytes the client put in its connect command, carried unchanged on every packet. A client drops a packet carrying any other four.
peer2-byte bits
peer.peerIdbit 0 to 1432767 marks an unassigned peer, which is what a connecting client sends. A server gives the client peer 0.
peer.sentTimeFlagbit 15Set when the header carries a sent time.
sentTimeu16, big-endianpeer.sentTimeFlag setMilliseconds since the connection opened.
ConstantValueStock ENetWhat it is
maximumPeerId3276732767Follows from the peer id occupying fifteen bits.
maximumTransmissionUnit40964096A client asks for 1400 in its connect command, and takes datagrams up to 4096 bytes.
minimumDatagram88A client discards any datagram shorter than this many bytes.

In 1.0.0.127–1.0.0.129

ENet 1.2.5 beneath; little-endian fields. Blowfish in ECB mode over 8-byte blocks, each read big-endian, under a 16-byte key given in base64. Neither end pads.

FieldTypePresent whenWhat it is
sessionIdbytes, 4The four bytes the client put in its connect command, carried unchanged on every packet. A client drops a packet carrying any other four.
peer2-byte bits
peer.peerIdbit 0 to 1432767 marks an unassigned peer, which is what a connecting client sends. A server gives the client peer 0.
peer.sentTimeFlagbit 15Set when the header carries a sent time.
sentTimeu16, big-endianpeer.sentTimeFlag setMilliseconds since the connection opened.
ConstantValueStock ENetWhat it is
maximumPeerId3276732767Follows from the peer id occupying fifteen bits.
maximumTransmissionUnit9964096A client asks for 1400 in its connect command, and takes no datagram larger than 996 bytes.
minimumDatagram88A client discards any datagram shorter than this many bytes.

A header built from the schema is necessary to reach a client, and not sufficient on its own. Where a field’s content is free rather than fixed, its note in the schema says so.

conformance/vectors/transport holds a header with a sent time and one without.

A client discards any datagram shorter than the minimumDatagram constant of its range. A server MUST NOT send a shorter datagram.

The connect command

A server’s verify connect MUST state the channel count, and the throttle interval, acceleration and deceleration, the connect command carried: a client abandons a connection whose verify connect states anything else.

A client asks for 7 channels.

Maximum transmission unit

A client asks for a transmission unit of 1400 bytes, and discards any datagram whose UDP payload, packet header included, exceeds the maximumTransmissionUnit constant of its range. A server MUST NOT send a larger datagram.

In 1.0.0.25–1.0.0.126

That constant is above what a client asks for, so a server needs no clamp.

In 1.0.0.127–1.0.0.129

That constant is below what a client asks for. A server MUST accept a connection at a transmission unit no greater than the constant, by clamping the value the client asks for. Capping its own sending without clamping the negotiated value is not sufficient, because ENet derives fragment sizes from the negotiated value and still emits datagrams above the limit.

The cipher

Whether a payload is enciphered follows from the state of the connection rather than from the channel it travels on. A connection begins with no cipher state, and the request that establishes it travels in the clear apart from one field it carries enciphered as proof. Everything after that is enciphered, on every channel and in both directions, the answer to that request included.

schema/protocol.json records which cipher, in which mode, and the shape of a block. A server MUST use that cipher; a client accepts no other. A standard implementation of Blowfish interoperates with a client.

What a server sends carries no padding. Trailing bytes that do not fill a block travel unchanged, so a payload shorter than one block travels in the clear.

In 1.0.0.25–1.0.0.115

A client pads what it sends to a whole number of blocks and enciphers all of it. The bytes it adds follow the message’s own fields to the end of the payload and hold nothing in particular.

In 1.0.0.116–1.0.0.129

What a client sends carries no padding either.

conformance/vectors/cipher covers a whole block, a payload with a tail too short to fill one, and a payload shorter than a block.

The key

Both ends hold the key before a connection opens. Nothing on the wire negotiates it, and no exchange derives it. A client receives it as a launch argument.

In 1.0.0.25–1.0.0.110

A client decodes nothing: its key is the first sixteen characters of the argument, as they stand. A key both this and later builds take alike is sixteen characters of text.

In 1.0.0.111–1.0.0.125

The argument holds the key in base64.

In 1.0.0.126–1.0.0.129

An argument longer than sixteen characters holds the key in base64, and the key is the first sixteen bytes it decodes to. An argument of sixteen characters or fewer is the key as it stands.

Registration associates the key with a connection. Register travels in the clear apart from one field enciphered under the key, and a server MUST refuse a connection whose deciphered field is not what it expects, since that field is all that shows the client holds the key. schema/messages records the exchange, as Register and Registered.

Channels

In every range of this book

ChannelNameFamily
0registrationregistration
1requestsgame
2clockgame
3eventsgame
4transientgame
5chatchat
6rostersession