Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ JSON is a self-delimiting format—a compliant parser can determine where one JS

To ensure file descriptors are correctly associated with their corresponding messages, a sending party MUST adhere to the following rules:

1. **File Descriptor Ordering:** All file descriptors referenced by a message MUST be sent (via ancillary data) before or with the final bytes of that message. The receiver dequeues FDs in order as complete messages are parsed; if the required FDs have not yet arrived, the connection is terminated with a Mismatched Count error.
1. **File Descriptor Ordering:** All file descriptors referenced by a message MUST be sent (via ancillary data) before any bytes of the next message are transmitted. Because FDs may be batched across multiple sendmsg() calls (see Section 4.1), the receiver's JSON parser may finish parsing a message before all of its FDs have arrived. The receiver MUST handle this by waiting for additional data; see Section 5, Step 4.

## 3. Message Format

Expand Down Expand Up @@ -71,7 +71,7 @@ Operating systems impose limits on the number of file descriptors that can be pa

When a message requires more file descriptors than can be sent in a single sendmsg() call, the additional FDs MUST be sent before any bytes of the next message. Since some systems require non-empty data for ancillary data delivery, these continuation calls MUST send a single whitespace byte (space, `0x20`) as payload. The receiver's JSON parser will ignore inter-message whitespace per RFC 8259.

This ensures the receiver can dispatch each message as soon as it is fully parsed, without buffering subsequent messages while waiting for FDs.
Because the JSON data for a message may arrive in a single recvmsg() call while its FDs are still in transit, the receiver MUST be prepared to buffer a parsed message and continue reading until the required FDs have arrived (see Section 5, Step 4).

Implementations SHOULD use a batch size in the range of 200-500 FDs and handle `EINVAL` (or equivalent) by reducing the batch size and retrying.

Expand All @@ -89,7 +89,7 @@ Because SOCK_STREAM does not preserve message boundaries, the receiver MUST impl
1. **Streaming Parse:** Attempt to parse a complete JSON object from the beginning of the byte buffer using a streaming JSON parser. If the buffer contains an incomplete JSON value (e.g., the parser encounters EOF mid-value), the processing loop terminates until more data is received.
2. **Handle Parse Result:** If parsing succeeds, record the number of bytes consumed. If parsing fails with a syntax error (not EOF), this is a fatal Framing Error (see Section 7), and the connection MUST be closed.
3. **Read FD Count:** Read the `fds` field from the parsed JSON message to determine the number of file descriptors (N) associated with this message. If the field is absent, N is 0.
4. **Check FD Queue:** Check if the file descriptor queue contains at least N FDs. If it contains fewer than N FDs, this is a fatal Mismatched Count error (see Section 7). The protocol state is desynchronized, and the connection MUST be closed.
4. **Check FD Queue:** Check if the file descriptor queue contains at least N FDs. If it contains fewer than N FDs, the receiver MUST buffer the parsed message and return to reading from the socket (outer Step 2) until enough FDs have been received. Between messages, the only bytes the sender may transmit are whitespace continuation bytes carrying additional FDs (see Section 4.1). After each read, if the byte buffer contains any non-whitespace byte (i.e. the start of the next JSON message) and the FD queue still has fewer than N FDs, this is a fatal Mismatched Count error (see Section 7) — the sender has violated the ordering rule in Section 2.3 by beginning the next message before delivering all FDs for the current one. If the connection is closed before all N FDs have arrived, this is also a fatal Mismatched Count error.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for detecting a Mismatched Count error is currently ambiguous. Since the consumed bytes of the current message are not removed from the buffer until Step 7, the buffer will still contain the non-whitespace JSON of the current message when the receiver returns to Step 2. Consequently, the check for 'any non-whitespace byte' will trigger a fatal error immediately after the next read, even if the sender is correctly sending whitespace. I suggest explicitly stating that the bytes should be removed before waiting, which also aligns with how the current Rust implementation is structured (draining the buffer immediately after a successful parse).

Suggested change
4. **Check FD Queue:** Check if the file descriptor queue contains at least N FDs. If it contains fewer than N FDs, the receiver MUST buffer the parsed message and return to reading from the socket (outer Step 2) until enough FDs have been received. Between messages, the only bytes the sender may transmit are whitespace continuation bytes carrying additional FDs (see Section 4.1). After each read, if the byte buffer contains any non-whitespace byte (i.e. the start of the next JSON message) and the FD queue still has fewer than N FDs, this is a fatal Mismatched Count error (see Section 7) — the sender has violated the ordering rule in Section 2.3 by beginning the next message before delivering all FDs for the current one. If the connection is closed before all N FDs have arrived, this is also a fatal Mismatched Count error.
4. **Check FD Queue:** Check if the file descriptor queue contains at least N FDs. If it contains fewer than N FDs, the receiver MUST remove the consumed bytes from the front of the byte buffer (as in Step 7), buffer the parsed message, and return to reading from the socket (outer Step 2) until enough FDs have been received. Between messages, the only bytes the sender may transmit are whitespace continuation bytes carrying additional FDs (see Section 4.1). After each read, if the byte buffer contains any non-whitespace byte (i.e. the start of the next JSON message) and the FD queue still has fewer than N FDs, this is a fatal Mismatched Count error (see Section 7) — the sender has violated the ordering rule in Section 2.3 by beginning the next message before delivering all FDs for the current one. If the connection is closed before all N FDs have arrived, this is also a fatal Mismatched Count error.

5. **Dequeue and Associate:** Dequeue the first N file descriptors from the front of the queue. These FDs correspond positionally (0 through N-1) to the file descriptors expected by the application for this message.
6. **Dispatch:** The fully-formed message (with FDs) is now ready and SHOULD be dispatched to the application logic for handling.
7. **Consume Bytes:** The consumed bytes MUST be removed from the front of the byte buffer.
Expand Down Expand Up @@ -134,7 +134,7 @@ The primary error code for these issues is:
**Conditions that MUST be treated as fatal errors:**

* **Framing Error:** The byte stream cannot be parsed as valid JSON (syntax error, not incomplete data).
* **Mismatched Count:** A parsed message's `fds` field specifies N file descriptors, but the receiver's file descriptor queue contains fewer than N available FDs at the time of processing.
* **Mismatched Count:** A parsed message's `fds` field specifies N file descriptors, but either the connection was closed or a non-continuation character was received before N FDs were received. This indicates that the sender failed to deliver the promised file descriptors.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with Section 5, Step 4, consider using the term 'non-whitespace byte' instead of 'non-continuation character'. This clarifies that any character not permitted by RFC 8259 as whitespace (and thus potentially the start of a new message) triggers the error.

Suggested change
* **Mismatched Count:** A parsed message's `fds` field specifies N file descriptors, but either the connection was closed or a non-continuation character was received before N FDs were received. This indicates that the sender failed to deliver the promised file descriptors.
* **Mismatched Count:** A parsed message's `fds` field specifies N file descriptors, but either the connection was closed or a non-whitespace byte was received before N FDs were received. This indicates that the sender failed to deliver the promised file descriptors.


## 8. Security Considerations

Expand Down
Loading