Transport Layer
| Item | Value |
|---|---|
| Transport | TCP (persistent connection) |
| Default port | 5225 |
| Socket options | TCP_NODELAY enabled — sends small packets immediately, without Nagle's coalescing delay |
| TLS | Optional — if the server has a certificate configured, the whole stream is wrapped in one-way TLS (server auth) |
| Encoding | Fixed-width binary fields + UTF-8 keys. Integers are big-endian (network order) |
| Frame terminator | One \n byte. No \r handling |
| Empty frame | A bare \n (op position is \n) is silently ignored as a keep-alive |
| Max frame size | 192 bytes — including op, excluding \n (over the limit → E line_too_long, then connection closed) |
| Pipelining | Allowed — responses may arrive in a different order than requests |
| Idle timeout | None — the server never closes a quiet connection |
| Frame progress time | At most 5 seconds from the first op byte through the fixed header and LF; partial sends cannot occupy a connection forever |
Connection Establishment Order
- TCP connect
- TLS handshake, if the server has TLS enabled — connecting to a TLS server in plaintext gets disconnected at this step
- Auth handshake, once
- Lock protocol frame exchange from then on
Framing Rules
Every message is one frame = one line.
[ op: 1 byte ][ op-specific fixed header ][ variable body ] \nThe receiver must look at the op and read the fixed header by its byte count first, only scanning for \n afterward. That's because the fixed header is binary and can contain 0x0A (\n) as a value (e.g. lease=10 → 0A). The \n scan only applies to the trailing key/text segment.
| Direction | op | Fixed header |
|---|---|---|
| Client → Server | A | 10 bytes (wait:u8 + lease:u8 + owner:u64 BE) |
| Client → Server | R | 8 bytes (token:u64 BE) |
| Server → Client | A | 16 bytes (token:u64 BE + owner:u64 BE) |
| Server → Client | T · B | 8 bytes (owner:u64 BE) |
| Server → Client | R · N | 8 bytes (token:u64 BE) |
| Server → Client | M · L · E | 0 bytes (address/reason is UTF-8 text) |
If a frame is malformed or exceeds 192 bytes, the server flushes E when possible and then closes the connection. Clients likewise treat malformed, oversized, unknown-op, or uncorrelatable E frames as connection-fatal. An acquire for which at least one byte was sent is not retried automatically and ends as Indeterminate if no definitive response was observed.
Terminology
- Frame — the unit a continuous byte stream (TCP) is cut into to mean "one message." In this protocol, one
\n-terminated line is one frame. - Big-endian — the byte order that writes an integer's most significant byte first. It's the standard for network protocols, so it's also called network order.
- Pipelining — sending the next request without waiting for the previous response. Overlapping round-trip latency this way increases throughput.
- Keep-alive — a meaningless signal sent periodically to announce a connection is still alive. Here, an empty frame (
\n) plays that role.