Files
openttd-client/docs/PROTOCOL.md
kovagoadi 0a8271d57c
All checks were successful
Continuous Integration / lint-and-security (pull_request) Successful in 31s
Continuous Integration / tests-and-coverage (pull_request) Successful in 25s
Add vehicle listing support to admin client
The Admin Network has no native packet for listing individual vehicles,
so list_vehicles() sends a "list_vehicles" command over the existing
GameScript JSON channel and relies on a companion server-side script to
reply with vehicle data via ServerGamescript. Requires subscribing to
Gamescript updates (documented in docs/PROTOCOL.md) to receive the reply.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 20:44:44 +02:00

3.5 KiB

Protocol Internals

This client supports the modern OpenTTD Game Port protocol (TCP 3979), specifically as implemented in JGRPP.

X25519 PAKE Authentication

OpenTTD 14+ and JGRPP use a Password-Authenticated Key Exchange to prevent plaintext password leakage.

Key Derivation (KDF)

We use Blake2b (64-byte digest) to derive two 32-byte session keys.

  • Input: SharedSecret (32) + ServerPublicKey (32) + ClientPublicKey (32) + Password (string)
  • Output:
    • 0..31: Client-to-Server Key
    • 32..63: Server-to-Client Key

Handshake Nonces

The server provides a 24-byte nonce in the ServerAuthenticationRequest. This nonce is used for the AEAD challenge during the auth response and for the initial stream encryption setup.

Admin Network (TCP 3977)

The Admin Network allows external applications to monitor and control the server. It supports both unsecured and secure (X25519 PAKE) authentication.

Secure Authentication

Similar to the Game Port, the Admin Network uses X25519 PAKE for secure authentication.

  • Packet: AdminJoinSecure starts the handshake.
  • Encryption: Once enabled via ServerEnableEncryption, all subsequent traffic is encrypted using XChaCha20-Poly1305.

Update Frequencies

Admins can subscribe to various updates (Date, Client Info, Company Info, etc.) at different frequencies (Poll, Daily, Weekly, Monthly, Quarterly, Annually, Automatic).

Vehicle Listing

The Admin Network has no native packet or AdminUpdateType for listing individual vehicles — ServerCompanyStats only reports aggregate per-company vehicle counts (trains/lorries/buses/planes/ships). To retrieve an actual vehicle list, this client sends a list_vehicles command over the GameScript JSON channel (AdminGamescript/ServerGamescript) via list_vehicles(). This requires a companion GameScript running server-side that understands the list_vehicles command and replies with vehicle data through ServerGamescript.

Important: the server only forwards ServerGamescript packets to admins that have subscribed with update_frequency(AdminUpdateType.Gamescript, AdminUpdateFrequency.Automatic) (enforced server-side in NetworkAdminGameScript, which checks update_frequency[ADMIN_UPDATE_GAMESCRIPT]). Call update_frequency() for Gamescript before list_vehicles(), or the response is silently dropped.

Stream Encryption (AEAD)

Once ServerEnableEncryption is received, all subsequent packets use XChaCha20-Poly1305 (Authenticated Encryption with Associated Data).

Encrypted Packet Format

On the wire, encrypted packets have the following structure:

  1. Length (2 bytes): Big-endian uint16 of the entire remaining packet.
  2. MAC (16 bytes): The Poly1305 authentication tag.
  3. Ciphertext (variable): The encrypted payload.

Decryption Logic

The OpenTTDProtocol layer uses an IncrementalAuthenticatedEncryption state from the Monocypher library. It maintains the nonce state internally. If a MAC check fails (indicating corruption or a wrong key), the client immediately closes the connection (SocketClosed).

Keep-Alive (Simulation Synchronization)

OpenTTD is a lockstep simulation. The server sends ServerFrame packets periodically.

  • Client Requirement: You must respond with a ClientAck containing the frame number and a one-time token provided in the frame packet.
  • Timeout: If the server does not receive an ACK for several in-game days, it will disconnect the client with error code 17 (TimeoutComputer).