Response Headers
A fixed 32-byte frame. The first sixteen bytes are the same for every encryption type; the last sixteen are how the server proves the response is genuine, and those differ by type.
Bytes 0–15: the same for every type
| Bytes | Field | Meaning |
|---|---|---|
| 0 | RI | The responding RAIDA's index, or a Content Server's node ID echoed back under type 9. |
| 1 | SH | Shard ID. Zero. |
| 2 | ST | Status code. The single most important byte in the response. 250 is success; everything else is documented on the command's own page. |
| 3 | CG | Command group, echoed from the request. |
| 4–5 | FC | Frame count. Always 1. |
| 6–7 | EC | Client echo, returned from request bytes 30–31. Types 8 and 9 always send zero here — the echo is deferred in both specifications. |
| 8 | RS | Reserved, zero. The object transfer commands (6/76–84) overload this as a framing version. |
| 9–11 | BL | Response body length, 24-bit big-endian. Note this is a different width from any request length field. |
| 12–15 | ET | Server execution time, 32-bit big-endian microseconds. The object transfer commands repurpose these bytes as part of a 32-bit body length. |
Types 0, 1, 2 — bytes 16–31 carry a challenge proof
The server returns a 16-byte value derived from the challenge the client sent in its request body. Under type 0 this is the challenge echoed back; under types 1 and 2 it is a proof combining the challenge with the key coin's authenticity number — something only a server that genuinely holds that AN could produce.
This is the older authentication model: the header proves the responder is genuine, while the body's integrity rests on the challenge CRC32. It is not authenticated encryption, and it does not detect tampering with the response body itself.
Types 8 and 9 — bytes 16–31 carry a GCM tag
The same sixteen bytes now hold the response's AES-256-GCM authentication tag. This is a genuine upgrade rather than a relabelling: the tag covers both the header and the response body, so a client that verifies it knows the entire response is untampered, not merely that the responder knew a secret.
| Property | Value |
|---|---|
| Response AAD | Response header bytes 0–15 |
| Tag position | Bytes 16–31, full 16 bytes |
| Key | Same key as the request |
| Nonce | Not transmitted. Derived locally from the request nonce. |
Why the response nonce is not on the wire
The response nonce is the request nonce with its direction bit set: requests have the most significant bit of the nonce's first byte at 0, responses at 1. This partitions the nonce space so a request nonce and a response nonce can never collide under the same key — which is the property GCM requires.
The practical consequence for a client: keep the request nonce until the response has been verified. You cannot recover it from the response.
Reusing the 32-byte legacy frame for a modern AEAD cipher was deliberate. It meant type 8 could ship without changing the transport layer or any response parser — the frame is the same size and shape, and only the meaning of the last sixteen bytes changed.
The unauthenticated failure frame
A zero tag means the server could not authenticate you
When a type 8 or type 9 request cannot be authenticated at all — the key coin is unknown, the session handle does not resolve, or the GCM tag fails to verify — the server has no shared key, and therefore cannot produce a valid tag. It returns a fixed 32-byte frame with bytes 16–31 all zero and a zero body length.
Clients MUST handle this case explicitly. Do not treat a failed tag verification as a network error or a corrupt packet: check for the all-zero tag with a zero body length first, and read the status byte, which carries the real reason.
Type 9 defines named statuses for these conditions, including unknown handle (102), counter replay (103), capacity (104), authentication failed (105) and malformed (106).
Refused before any command: ERROR_SERVER_BUSY (251)
A RAIDA caps how many TCP connections one source address may hold open at once. When a source
is over the cap the connection is refused at accept time — before the header is
parsed, before any command is dispatched, and before any memory is allocated for the request.
The reply is a bare 32-byte header carrying status 251
(ERROR_SERVER_BUSY) with a zero body length and no command echo, and the socket is
then closed.
251 means “try again shortly”, not “this server is broken”
The cap counts connections per source address, and many independent clients share one address behind NAT or a carrier gateway, so a perfectly healthy client on a busy network can meet it. Back off and retry the same node. Do not mark the server failed, do not show it as down, and do not fail over to another RAIDA on a 251 alone.
The per-source cap is 128 concurrent TCP connections while the node is idle. When the node is
under pressure — open TCP above half its file-descriptor budget — the cap for
new connections drops to 8, and the node frees sockets before refusing anyone: it ends
the oldest parked long-poll PINGs with STATUS_TIMEOUT (245). A 245 on a parked PING
is routine under load and carries no meaning beyond “re-issue the PING”. Loopback and
the other RAIDAs in the fleet are exempt from the cap. UDP is unaffected, having no connection to
limit.
Parsing pitfalls
| Trap | What to do |
|---|---|
| Assuming the body length is 16-bit because request lengths often are | The response length is 24-bit, at bytes 9–11. It matches no request length field in the protocol. |
| Expecting your echo bytes back under type 8 or 9 | They are always zero. Match requests to responses by connection, not by echo. |
| Discarding the request nonce after sending | You need it to derive the response nonce. Keep it until verification completes. |
| Treating a zero tag as corruption | It is a defined failure frame. Read the status byte. |
| Reading bytes 8 and 12–15 as reserved and execution time for object transfer commands | Commands 6/76–84 repurpose them for extended framing. See the object transfer pages. |