3. Session¶
A session is a player's stay on the server. It starts with a login over TCP, which gives the client a session token; the client then binds its UDP endpoint to the session with that token, and the game runs over UDP. This section specifies the TCP messages and the binding. The framing of TCP messages is in section 1.3, the UDP header in section 2.
3.1 Overview¶
sequenceDiagram
participant C as Client
participant S as Server
C->>S: TCP connect
C->>S: LoginRequest (version, name)
alt accepted
S->>C: LoginAccepted (token, player, UDP port)
loop every 250 ms until Accept
C->>S: UDP Connect (session = token)
end
S->>C: UDP Accept
Note over C,S: game over UDP, TCP stays open and silent
C->>S: Logout (or TCP close)
else rejected
S->>C: LoginRejected (reason)
S--xC: TCP close
end
3.2 TCP messages¶
Every TCP message, inside its length prefix, starts with its kind on one u8; the fields
of that kind follow. Fields are encoded as in section 1.4.
| Kind | Name | Direction | Fields |
|---|---|---|---|
| 1 | LoginRequest |
client → server | version (u8), name (string) |
| 2 | LoginAccepted |
server → client | session (u32), player (u8), udp_port (u16) |
| 3 | LoginRejected |
server → client | reason (u8) |
| 4 | Logout |
both | reason (u8) |
Kinds 0 and 5 to 255 are reserved.
LoginRequest¶
The first and only message a client sends to log in.
versionis the protocol version, the same as in the UDP header:1.nameis the player's name: 1 to 16 bytes of UTF-8, without control characters (code points below0x20, and0x7F). It is shown to the other players.
LoginAccepted¶
The login succeeded: the session exists.
sessionis the session token. The server MUST NOT issue0, MUST NOT give the same token to two sessions at once, and SHOULD draw it at random, so that a third party cannot guess the token of another player's session.playeris the player's number in the game,0to3: it picks the player's ship and color.udp_portis the UDP port of the server, to which the client sends its datagrams.
LoginRejected¶
The login failed. The server MUST close the connection right after sending it.
reason |
Name | Meaning |
|---|---|---|
| 1 | ServerFull |
The game already has 4 players |
| 2 | BadVersion |
The server does not speak this version |
| 3 | BadName |
The name is empty, too long, not UTF-8 or has control characters |
| 4 | NameTaken |
Another player of the game has this name |
| 5 | GameStarted |
The game is running and does not take new players |
A client MUST treat an unknown reason like any other rejection.
Logout¶
The sender ends the session; it MUST close the connection right after sending it.
reason |
Name | Sent by | Meaning |
|---|---|---|---|
| 0 | Left |
client | The player quit |
| 1 | Shutdown |
server | The server is stopping |
| 2 | TimedOut |
server | No valid datagram for too long (section 5.5) |
| 3 | ProtocolError |
server | The client sent something invalid over UDP |
A receiver MUST treat an unknown reason as Left coming from a client, and as Shutdown
coming from the server.
3.3 Rules of the TCP connection¶
- The client MUST send
LoginRequestas its first message. The server MUST close a connection that sends anything else first, or nothing within 5 seconds of being accepted. - After the login, the client MUST NOT send anything but
Logout; the server MUST NOT send anything butLogout. A peer MUST close the connection on a secondLoginRequest, on a message of an unknown or unexpected kind, or on a malformed message: a field past its end, bytes left after the last field, or an invalid value. A TCP stream cannot be trusted after a bad message, so there is no rejection message in that case. - The session ends when either side sends
Logout, when the connection closes, or when UDP times out (section 5.5). In every case the server forgets the token, closes the connection if it is still open, and tells the other players (section 4.4).
3.4 Binding the UDP endpoint¶
Once logged in, the client tells the server which UDP endpoint (address and port) it plays from:
- The client sends a
Connectdatagram (type1) toudp_port, itssessionfield set to the token and its payload empty. Itssequencestarts the numbering of the client's datagrams (section 2.2). - On a
Connectwhose token belongs to a session with no endpoint yet, the server binds the datagram's source endpoint to the session and answers with anAcceptdatagram (type2, empty payload) to that endpoint. Gameplay traffic may then start in both directions. - The client sends
Connectagain every 250 ms until anAcceptarrives. Without anAcceptwithin 5 seconds ofLoginAccepted, it gives up: it sendsLogoutand reports that the server cannot be reached over UDP (a firewall, usually).
The server MUST:
- drop a
Connectwhose token is not the one of a current session; - answer a
Connectagain with anAcceptwhen it comes from the endpoint already bound to the session (the firstAcceptwas lost); - drop a
Connectfor a session already bound to another endpoint, so a third party who learned a token cannot take over the session; - drop every other datagram whose source endpoint is not bound, or whose token is not the one of the session bound to its endpoint (section 2.2).
The client MUST drop every datagram that does not come from the server's udp_port, or
whose token is not its own, and every datagram but Accept before the first Accept.
3.5 Example¶
A client logs in as R9 and gets session 0xDEADBEEF, player 2, UDP port 4242
(0x1092). Each message is shown with its length prefix:
06 00 01 01 02 00 52 39 LoginRequest
len kind ver name: len "R9"
08 00 02 EF BE AD DE 02 92 10 LoginAccepted
len kind session pl udp_port
Its first UDP datagram is then a Connect in that session, with sequence 0 and nothing
acknowledged yet (section 5.1):
52 54 59 50 01 01 00 00 FF FF 00 00 00 00 EF BE AD DE
magic ver typ seq ack ack_bits session