Repository navigation
Gateway connections
The login and world connections: the read loop and writer they share, how their keys switch, and what each connection takes and answers. Sign-on is on Gateway sign-on, the checks every message passes on Gateway gate, and how the gateway fits together on Gateway.
The login and world connections share one base: a read loop and a single writer.
- The read loop takes one frame at a time: a 32-bit length that counts itself, a 16-bit opcode, then the body. A frame shorter than its own header or longer than
MaxClientFrameBytesends the connection, judged before the body arrives. - A transport ping, opcode 0 with a one-byte body, is answered with opcode 1 carrying the same byte.
- Every other frame goes through the gate, then the rate limit, then the connection's handler. The next frame isn't decoded until the handler returns.
- An owner or the connection sends a message; one below
Fieldscan't be sent at all. - It joins the session's bounded outbound queue without waiting. A full queue ends the connection.
- The one writer drains the queue in order, wraps each message in its envelope under the session's current key, and flushes every 64 messages and when the queue empties.
Keys switch between messages. A key change takes effect on the receive side at once, and on the send side exactly between the messages queued before and after it. Both connections start under the key the build fixes. The world connection switches to the session key as soon as it reads WorldHello (0x058F), so the client's next message, even in the same read, is decoded under the new key.
| Connection | Takes | Answers |
|---|---|---|
| Login | A bare ServerHello (0x0003) greeting from the server, then one LoginRequest (0x0592), whose game token it redeems with the account owner |
On a grant, LoginAccepted (0x0591) and RealmHandoff (0x03DB): the world's address and port, an echo value, the realm's details and the session key. A wrong build, a database that's unreachable or too many attempts get LoginDenied (0x063D) with the general result. A second LoginRequest ends the connection |
| World | A greeting inside the world envelope, then WorldHello before anything else, whose session key it switches to and redeems |
Character select's requests, handed to the realm owner. Closing the connection takes the account offline |
- A logged-in connection has no idle limit yet.
- The world connection takes pregame rows only; messages the client sends tagged wait for in-world routing (Gateway design).
| Piece | Path |
|---|---|
| Frames, envelopes and the packet cipher | Source/NexusTomorrow.Transport/ |
| The connection base, its outbound queue, and the login and world connections | Source/NexusTomorrow.Gateway/Connections/ |
| The listeners that hand each connection to its class | Source/NexusTomorrow.Gateway/Kestrel/ |
| Tests |
Tests/NexusTomorrow.Transport.Tests/, Tests/NexusTomorrow.Gateway.Tests/
|
Start here
How the server works
- Server core design
- Host
- Gateway
- Owners
- Persistence
- Command layer
- Harness
- Map scheduler design
- Timer wheel design
The protocol
Working on it