QMail Peek — Group 6, Code 73
Non-blocking inbox check. The client asks the recipient’s beacon RAIDA for all pending .tell2 notifications newer than a caller-supplied timestamp. The server returns immediately with a tell-list response, or an empty tell-list if there is no matching mail.
Quick reference
| Command Group | 6 (QMail) |
| Command Code | 73 (0x49) |
| Server function | cmd_qmail_peek2 in cmd_qmail.c |
| Request packet | 32-byte plaintext RAIDA header + encrypted body fields + plaintext 3E 3E terminator |
| Request body size | 54 bytes total: encrypted challenge(16) + qmail identity/auth(32) + since_timestamp(4), then plaintext terminator(2) |
| Response packet | 32-byte plaintext RAIDA response header + encrypted tell-list payload + plaintext 3E 3E terminator |
| Encryption | Required — AES-128-CTR, type 1, keyed by the caller’s selected coin AN for this RAIDA |
| Side effect on success | Each returned .tell2 file is queued for deletion after it is read into the response |
Purpose
peek is the non-blocking version of ping. It scans the recipient mailbox directory immediately, returns every .tell2 file whose filesystem modification time is greater than since_timestamp, and then closes the request. Pass 0 to return every tell currently in the inbox.
The server path is selected from the mailbox identity in the request body: QMAIL_MAILBOX_ROOT/{denom_hex}/{serial_number}/inbox/. The request must be sent to the recipient’s beacon RAIDA; other RAIDAs may not have that mailbox coin loaded.
Wire packet
The word header is used carefully on this page. The RAIDA packet header is the 32 plaintext bytes at the front of the TCP packet. The 16-byte challenge/CRC is encrypted with the rest of the request body. raidax groups that challenge with the QMail identity block and calls those first 48 decrypted body bytes qmail_preamble_t.
QMail Peek request packet, bytes on TCP
+-------------------------------+-----------------------------------------+----------------------+
| RAIDA request header | encrypted request body | plaintext terminator |
| 32 bytes | 52 bytes | 2 bytes |
+-------------------------------+-----------------------------------------+----------------------+
| command group=6, command=73 | challenge/CRC(16) | 3E 3E |
| encryption type=1 | QMail identity/auth block(32) | |
| body_size=54 | since_timestamp(4) | |
| nonce(8) | | |
+-------------------------------+-----------------------------------------+----------------------+
The header’s body_size field includes the encrypted body bytes and the terminator, so for peek it is always 54 (0x0036) in current rest_core.
Request header (32 bytes, plaintext)
| Offset | Size | Field | Peek value / meaning |
|---|---|---|---|
| 0 | 1 | Router version | 0x01 |
| 1 | 1 | Split ID | 0x00 for the standard single-frame request |
| 2 | 1 | RAIDA ID | Target beacon RAIDA index, 0–24 |
| 3 | 1 | Shard ID | Current rest_core sends shard 0x03 |
| 4 | 1 | Command Group | 0x06 (QMail) |
| 5 | 1 | Command Code | 0x49 (73, peek) |
| 6–7 | 2 | Coin ID | 00 06 CloudCoin network ID |
| 8 | 1 | Bitfield | 0x01 |
| 9–15 | 7 | Reserved | Zero-filled by rest_core |
| 16 | 1 | Encryption type | 0x01 AES-128-CTR with coin AN |
| 17 | 1 | Encryption key denomination | Denomination of the coin used for wire encryption |
| 18–21 | 4 | Encryption key SN | Serial number of the coin used for wire encryption, big-endian |
| 22–23 | 2 | Body size | 00 36 for peek (54 bytes) |
| 24–31 | 8 | Nonce | AES-CTR nonce used to encrypt/decrypt the request body |
Request body (54 bytes after the RAIDA header)
Decrypted request body layout
+-------------------+--------------------------+---------------------+----------------------+
| challenge/CRC | QMail identity/auth | since_timestamp | terminator |
| 16 bytes | 32 bytes | 4 bytes | 2 bytes |
| encrypted | encrypted | encrypted | plaintext |
+-------------------+--------------------------+---------------------+----------------------+
| body[0..15] | body[16..47] | body[48..51] | body[52..53] |
+-------------------+--------------------------+---------------------+----------------------+
| Body offset | Size | Encrypted? | Field | Description |
|---|---|---|---|---|
| 0–11 | 12 | Yes | Challenge random | Random bytes generated by the client. |
| 12–15 | 4 | Yes | Challenge CRC32 | Big-endian CRC32 of body bytes 0–11. The server verifies this after decrypting. |
| 16–23 | 8 | Yes | Session ID | All zeros for current QMail AES-128 requests. |
| 24–25 | 2 | Yes | Coin Type | 00 06. |
| 26 | 1 | Yes | Mailbox denomination | Recipient mailbox coin denomination. |
| 27–30 | 4 | Yes | Mailbox serial number | Recipient mailbox serial number, big-endian. |
| 31 | 1 | Yes | Reserved | Was Device ID. Current server ignores it; clients should write zero. |
| 32–47 | 16 | Yes | Authenticity Number | The mailbox coin AN for this RAIDA. After decryption, process_inbox_scan() compares it to the stored AN for the body’s denomination/SN. |
| 48–51 | 4 | Yes | since_timestamp | Big-endian Unix seconds. The server returns only .tell2 files with st_mtime > since_timestamp. |
| 52–53 | 2 | No | Terminator | Fixed 3E 3E. Included in body_size but not encrypted. |
raidax names body offsets 0–47 qmail_preamble_t. In the terminology above, the challenge is still body data because it is encrypted with the rest of the body fields.
Response packet
For encryption type 1, the response has the same legacy 32-byte RAIDA header size. If the command returns a tell-list payload, the server encrypts the payload bytes and appends an unencrypted 3E 3E terminator.
QMail Peek response packet, bytes on TCP
+-------------------------------+-----------------------------------------+----------------------+
| RAIDA response header | encrypted tell-list payload | plaintext terminator |
| 32 bytes | payload_len bytes | 2 bytes |
+-------------------------------+-----------------------------------------+----------------------+
| status, group, body_size | array header(8) | 3E 3E |
| execution time | record 1 | |
| challenge signature | record 2 | |
| | ... | |
+-------------------------------+-----------------------------------------+----------------------+
The response header’s 3-byte body size is payload_len + 2. For an empty successful peek, payload_len is 8 and the response body size is 10.
Response header (32 bytes, plaintext)
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | RAIDA ID | Responding RAIDA index. |
| 1 | 1 | Shard ID | Legacy response path writes zero. |
| 2 | 1 | Status | 0xFA on success, or an error code. |
| 3 | 1 | Command Group | 0x06. |
| 4–5 | 2 | Frame count | Legacy response writes 00 01. |
| 6–7 | 2 | Echo bytes | Echoes legacy request bytes 30–31. |
| 8 | 1 | Reserved | Zero. |
| 9–11 | 3 | Body size | Big-endian length of encrypted payload plus terminator. |
| 12–15 | 4 | Execution time | Server execution time in microseconds, big-endian. |
| 16–31 | 16 | Challenge signature | Legacy response signature used by the client to verify the response belongs to the request. |
Tell-list payload (encrypted)
Decrypted tell-list payload
+----------------------+--------------------------------------+--------------------------------+
| Array header | Tell record 1 | Tell record 2 ... |
| 8 bytes | 64 + (M * 32) + 18 bytes | variable |
+----------------------+--------------------------------------+--------------------------------+
| Payload offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | tell_count | Number of tell records following this array header. |
| 1–2 | 2 | total_tells | Currently zero-filled by the server. |
| 3–7 | 5 | reserved | Zero-filled. |
| 8... | Variable | tell records | tell_count records, each parsed using the record structure below. |
If the inbox directory does not exist or contains no matching files, the server returns STATUS_SUCCESS with an 8-byte all-zero payload (tell_count = 0). That is a successful empty peek.
Tell record structure
Each returned record is the full contents of one .tell2 file. The server does not add a per-record length field. The client must read byte 29 of the 64-byte file header (stripe_count, called M below) and compute the record size:
record_size = 64 + (M * 32) + 18
+-------------------------+-----------------------------+-----------------------------+
| QMail file header | server location entries | recipient footer |
| 64 bytes | M entries * 32 bytes | 18 bytes |
+-------------------------+-----------------------------+-----------------------------+
QMail file header (64 bytes)
| Record offset | Size | Field | Description |
|---|---|---|---|
| 0–15 | 16 | email_id | Message/file GUID. Used by download to fetch stored stripes. |
| 16–17 | 2 | sender_coin_id | 00 06. |
| 18 | 1 | sender_denomination | Sender mailbox denomination. |
| 19–22 | 4 | sender_serial_number | Sender mailbox serial number, big-endian. |
| 23 | 1 | sender_device_id | Device tag copied from the tell blob. Logged, not enforced. |
| 24–27 | 4 | timestamp | Sender timestamp, big-endian Unix seconds. |
| 28 | 1 | tell_type | Current QMail email tells use 0. |
| 29 | 1 | stripe_count (M) | Number of 32-byte server entries following this header. The tell sender validated this as 1–32. |
| 30–45 | 16 | locker_code | Locker/download key copied into the notification. The receiver passes this to download. |
| 46–49 | 4 | total_file_size | Original total file/group size, big-endian. |
| 50 | 1 | version | 0x02. |
| 51–63 | 13 | reserved | Pass-through reserved bytes. |
Server location entry (32 bytes each)
There are M entries immediately after the file header. This structure tells the recipient which RAIDA servers hold the stripes and how to connect to them for download.
| Entry offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | stripe_index | Stripe number within the file’s stripe set. |
| 1 | 1 | stripe_type | Current rest_core writes 0 for data and 1 for parity. |
| 2 | 1 | server_id | RAIDA index holding this stripe. This is stored in the first byte of the legacy stripe_id field. |
| 3–9 | 7 | stripe_id reserved | Currently zero-filled by rest_core. |
| 10–19 | 10 | IPv6 prefix | Zero-filled for IPv4-mapped addresses. |
| 20–21 | 2 | IPv4 marker | FF FF for IPv4-mapped address. |
| 22–25 | 4 | IPv4 address | Storage RAIDA IPv4 octets. |
| 26–27 | 2 | Port | Storage RAIDA TCP port, big-endian. |
| 28–31 | 4 | reserved | Zero-filled by rest_core. |
Recipient footer (18 bytes)
The beacon appends this footer when writing each recipient’s .tell2 file. A receiver must skip these 18 bytes before parsing the next tell record.
| Footer offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | tag | 0x50. |
| 1 | 1 | length | 16. |
| 2–17 | 16 | receiver_locker | Per-recipient locker/payment key copied from the tell address entry. |
Status codes
| Decimal | Hex | Symbol | Meaning |
|---|---|---|---|
| 250 | 0xFA | STATUS_SUCCESS | Inbox scanned. Response payload is the tell-list, possibly empty. |
| 8 | 0x08 | ERROR_COIN_NOT_FOUND | Mailbox (denom, SN) from the body is not loaded on this RAIDA. |
| 16 | 0x10 | ERROR_INVALID_PACKET_LENGTH | Request body is shorter than the required 48 + 4 + 2 bytes. |
| 33 | 0x21 | ERROR_INVALID_EOF | Protocol terminator was not 3E 3E. |
| 34 | 0x22 | ERROR_INVALID_ENCRYPTION | Server could not decrypt/validate the body before reaching cmd_qmail_peek2. |
| 37 | 0x25 | ERROR_INVALID_CRC | The decrypted challenge CRC did not match. |
| 194 | 0xC2 | ERROR_FILESYSTEM | Inbox opendir() failed for a reason other than ENOENT. |
| 200 | 0xC8 | ERROR_INVALID_AN | Body AN does not match the server’s stored AN for the body denomination/SN. |
| 254 | 0xFE | ERROR_MEMORY_ALLOC | Server response buffer allocation failed. |
The per-coin rate limiter can silently drop excessive requests by closing the connection without a status response.
Common mistakes
Confusing the packet header with qmail_preamble_t
The 32-byte RAIDA header is plaintext. The server’s 48-byte qmail_preamble_t is decrypted body data: challenge/CRC plus the QMail identity/auth block.
Forgetting that the terminator is not encrypted
The header body-size field includes the final 3E 3E, but AES-128-CTR is applied only to the bytes before it.
Parsing tell records without skipping the footer
Each record ends with an 18-byte recipient footer. Even if a client does not consume that footer, it must skip it before reading the next 64-byte file header.
Empty response is success
STATUS_SUCCESS with tell_count = 0 means the inbox was scanned and no matching tells were found.
Points of confusion
- Filter is mtime-based. The server compares each
.tell2file’sst_mtimetosince_timestamp. It does not compare the timestamp embedded in the tell file header. - Tells are deleted on read. A successful peek queues returned files for deletion after directory scanning. Multiple devices sharing one mailbox can race; only the first device receives a given tell.
- Records are variable length. There is no length prefix per record. Use
stripe_countfrom the file header to compute64 + M*32 + 18. - The response can be capped. The server stops growing the response at its maximum tell response size; remaining tell files stay in the inbox for a later call.
peek2is the active command. The suffix is historical. Group 6 code 73 dispatches tocmd_qmail_peek2.