2.2 KiB
2.2 KiB
Architecture and Design
This project follows a strict Object-Oriented approach to manage the complexity of the OpenTTD network protocol.
Component Overview
1. OpenTTDProtocol (Low-Level)
Inherits from openttd_protocol.wire.tcp.TCPProtocol.
- Responsibility: Binary serialization/deserialization and stream encryption.
- Encryption Layer: It overrides
send_packetandreceive_packetto wrap/unwrap AEAD (XChaCha20-Poly1305) payloads. - Manual Dispatch: Uses a manual dispatch mechanism to ensure that even encrypted packets are correctly mapped to their high-level handlers.
2. OpenTTDClient (High-Level)
The primary API for developers.
- Responsibility: Handshake orchestration, state management, and keep-alive.
- Event-Driven: Uses
asyncio.Event(likeself.joined) to signal state changes to the calling code. - Callback System: Provides hooks like
on_chatto allow users to react to game events without modifying the core library.
Handshake Flow
- Connection: TCP connection established to Port 3979.
- Information:
ClientGameInfosent to verify server version. - Join:
ClientJoinsent with the specific JGRPP revision string. - Authentication: Server sends
ServerAuthenticationRequest(Type 1: PAKE). - PAKE Exchange:
- Shared Secret derived via X25519.
- Session Keys derived via Blake2b hashing of (SharedSecret + ServerPub + OurPub + Password).
- Encrypted challenge sent back via
ClientAuthenticationResponse.
- Encryption: Server sends
ServerEnableEncryption. The Protocol layer activates the AEAD stream. - Identification:
ClientIdentifysent (now encrypted). - Map Synchronization:
ServerWelcomereceived ->ClientGetMapsent -> Map segments received ->ClientMapOksent. - Active State:
client.joinedis set. The client responds toServerFramewithClientAckto prevent timeouts.
Error Handling
- Shutdown Event: Every fatal error or manual quit triggers a
shutdown_event. - Graceful Exit: The
quit()method sends aClientQuitpacket before closing the transport. - Fallback: Unknown packets are caught and mapped to
receive_ServerUnusedto prevent the simulation loop from crashing.