Currently in testing: the GitHub code will be opened once complete.

Transport Layer

ItemValue
TransportTCP (persistent connection)
Default port5225
Socket optionsTCP_NODELAY enabled — sends small packets immediately, without Nagle's coalescing delay
TLSOptional — if the server has a certificate configured, the whole stream is wrapped in one-way TLS (server auth)
EncodingFixed-width binary fields + UTF-8 keys. Integers are big-endian (network order)
Frame terminatorOne \n byte. No \r handling
Empty frameA bare \n (op position is \n) is silently ignored as a keep-alive
Max frame size192 bytes — including op, excluding \n (over the limit → E line_too_long, then connection closed)
PipeliningAllowed — responses may arrive in a different order than requests
Idle timeoutNone — the server never closes a quiet connection
Frame progress timeAt most 5 seconds from the first op byte through the fixed header and LF; partial sends cannot occupy a connection forever

Connection Establishment Order

  1. TCP connect
  2. TLS handshake, if the server has TLS enabled — connecting to a TLS server in plaintext gets disconnected at this step
  3. Auth handshake, once
  4. 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 ] \n

The 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=100A). The \n scan only applies to the trailing key/text segment.

DirectionopFixed header
Client → ServerA10 bytes (wait:u8 + lease:u8 + owner:u64 BE)
Client → ServerR8 bytes (token:u64 BE)
Server → ClientA16 bytes (token:u64 BE + owner:u64 BE)
Server → ClientT · B8 bytes (owner:u64 BE)
Server → ClientR · N8 bytes (token:u64 BE)
Server → ClientM · L · E0 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.