summaryrefslogtreecommitdiff
path: root/docs/design.md
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-14 14:10:28 -0300
committerGabriel Schneider <[email protected]>2026-09-14 14:20:25 -0300
commit5f24c4a2284a0af84fb9d116f7a39f6a58e42ae9 (patch)
tree8679763439492361fe99ea01f5190e5204fa590c /docs/design.md
downloadcloud9-5f24c4a2284a0af84fb9d116f7a39f6a58e42ae9.tar.gz
cloud9-5f24c4a2284a0af84fb9d116f7a39f6a58e42ae9.zip
Implement base 9P2000 sessions, shared transports, and conformance probes
Diffstat (limited to 'docs/design.md')
-rw-r--r--docs/design.md73
1 files changed, 73 insertions, 0 deletions
diff --git a/docs/design.md b/docs/design.md
new file mode 100644
index 0000000..ed9a66e
--- /dev/null
+++ b/docs/design.md
@@ -0,0 +1,73 @@
+# API and ownership
+
+The public entry point is `src/root.zig`. `Msg` covers every base request and
+response, excluding the reserved, nonexistent Terror. Decode returns borrowed
+strings/data. Encode checks complete output size before writing; input payloads
+may already occupy their exact final position in the output frame, but arbitrary
+input/output overlap is not supported. Stat uses the protocol's inner length;
+Rstat and Twstat add and validate the outer length separately.
+
+`Client` supports 16 ordinary outstanding requests and one additional flush.
+Replies can arrive out of order. Tags remain reserved while flushes are pending,
+even when the original request has already completed. Multiple flushes and
+flushing a flush are accounted for. A completed result's slices remain valid
+until the next `take()` or `hangup()`. `push()` only appends and never compacts.
+Submit copies request payloads into the output buffer. An iounit returned by an
+open/create is per fid; the caller must apply it when selecting atomic I/O sizes.
+`maxRead()` and `maxWrite()` describe frame limits, not that per-fid guarantee.
+Renegotiation requires an empty client request window.
+
+`Server` supports 64 ordinary outstanding requests and one additional flush.
+Receive errors terminate the connection. A full request table produces NoTags;
+output backpressure instead returns null without consuming the next request.
+`receive()` yields at most one frame. `release()` ends its borrow and advances
+input. A backend retaining any request data must copy it before release.
+A successful reply copies output and frees the request tag. An output-capacity
+error leaves that tag pending so the backend can drain and retry.
+
+The server validates transaction structure, not filesystem policy. Backends
+own fid maps, authentication state, file handles, access modes, complete directory
+records, atomic wstat, and cancellations. They must retire canceled work before
+reusing its tag; a tag alone cannot distinguish a stale backend completion from a
+new request. A version event requires backend cancellation and fid cleanup before
+`negotiate()`. A partially sent response drains before a new version is accepted.
+An Rflush promises no later reply to oldtag. Replying Rerror to a flush is refused.
+
+Caller-provided input/output buffers must be disjoint and remain stable for the
+session. No protocol API takes an allocator. Server and client request tables are
+fixed-size. Copies and work per frame are bounded by buffer size and fixed table
+capacities; transports and application backends can have their own allocations.
+
+# Transports
+
+`transport.readFrame` and `writeFrame` adapt `std.Io.Reader` and `std.Io.Writer`.
+The writer remains buffered until its owner flushes it. Reader errors leave the
+stream unsuitable for further frame processing; close the connection.
+
+`transport.connect` and `listen` use `std.Io.net` for TCP and Unix streams. The
+POSIX `connectFd`, `listenFd`, `acceptFd`, `read`, `write`, and `wait` APIs fit
+caller-owned poll loops. They configure nonblocking descriptors and close-on-exec;
+read/write return null for retry, and read returns zero for EOF. `wait` takes an
+absolute monotonic deadline. The application closes descriptors, limits its
+connections, selects addresses and deadlines, and manages Unix path permissions
+and removal. No mounting or namespace policy is performed.
+
+`Quic(OpenSSL, alpn)` is an optional OpenSSL 3.6+ adapter with a single ordered
+bidirectional stream per connection. It preserves the previous Pardes transport:
+ephemeral self-signed certificates, no peer authentication. Applications needing
+identity verification must provide that policy before using it across a trust
+boundary. OpenSSL allocations and handshake costs are outside the allocation-free
+protocol core. Accepted connections must close before their shared listener.
+
+# Pardes integration
+
+Pardes consumes the sibling package through build.zig.zon. Its `src/9p.zig` now
+adapts filesystem requests and retains editor/GPIO capacities and permissions.
+`src/9p_io.zig` retains mounting, discovery, the editor's event-loop scheduling,
+connection limits, and error presentation. Protocol bytes, session validation,
+and TCP/Unix/QUIC transport implementation come from cloud9. Pardes selects the
+existing `pardes-9p` ALPN for compatibility.
+
+The separate `05-zig-p4` firmware build adds cloud9 to the GPIO application's
+module map. UART hardware access remains in the board firmware. No hardware was
+flashed by this change.