library: the envelope — one packet shape for every protocol
A protocol is now defined through envelope.Define rather than beside it.
Every packet begins with the same 16-byte prefix: a Header of {operation,
target} for a request or event, a Status for a reply. The header is folded
into each protocol's own layout, never stacked on top of it — Define walks
a spec's types and refuses one that carries a Header or Status field, so
the rule cannot be missed by reading. Operations number from 16, leaving
describe, enumerate, subscribe and unsubscribe reserved and answerable the
same way everywhere; describe the envelope answers itself, and an unknown
verb is -ENOSYS without a provider writing a line.
The size floor becomes something protocols can compile against: 256 bytes
for a call, 64 for a push, matching the kernel's own limits, checked at the
Define call with the prefix counted in. A protocol that outgrows either
fails the build with the reason and the remedy — shrink, or move the bulk
to shared memory, because packets never fragment. Events carry the header
too and number in their own space, so appending an operation can never
renumber a shipped event.
Beside it, the client half of the model: a Channel is what opening a
/protocol name yields, wrapping the endpoint capability so a program holds
a conversation rather than a handle. Nothing speaks through either yet —
the vfs protocol gains NodeKind.protocol and the convention that an open
reply may carry a capability, and that is the whole runtime change.
Suite 107/107, unchanged: P1 converts nothing.
This commit is contained in:
@@ -161,15 +161,26 @@ Aligned to the node-kind table in the file-system hierarchy
|
||||
| 4 | symbolic link |
|
||||
| 5 | fifo |
|
||||
| 6 | socket |
|
||||
| 7 | protocol |
|
||||
|
||||
Clients should map unknown values to *regular* rather than reject — the
|
||||
table can grow. Kind 6 (`socket`) keeps its wire value but is retired from
|
||||
the design — a named rendezvous point is exactly what a `protocol` node is,
|
||||
planned as value 7 with the protocol namespace
|
||||
landed as value 7 with the protocol namespace
|
||||
(docs/os-development/protocol-namespace.md). `character_device` (stream
|
||||
semantics — the tty/console shape) and `block_device` (raw sector-addressed
|
||||
volumes, reserved) remain part of the design.
|
||||
|
||||
## An open reply may carry a capability
|
||||
|
||||
`open` rides `ipc_call`, whose reply direction can hand back an endpoint
|
||||
capability alongside the `Reply` header. A file backend never uses it — FAT
|
||||
answers with a node id and nothing else — but a **synthetic** backend does:
|
||||
opening a `protocol` node returns the provider's endpoint, and possession of
|
||||
that endpoint *is* the channel. The convention is per-backend, not
|
||||
per-operation, so a client that opens an ordinary file simply receives no
|
||||
capability, exactly as before.
|
||||
|
||||
## Lifetimes and trust
|
||||
|
||||
Open-node ids live in the backend. A client that dies without closing leaks
|
||||
@@ -188,8 +199,8 @@ What a non-Zig implementation may rely on, and what it must not:
|
||||
- Operation values, flag bits, `NodeKind` values, and struct layouts are
|
||||
**append-only and frozen once shipped**. The unit test in
|
||||
`library/protocol/vfs/vfs-protocol.zig` pins a sample of them (the `DirectoryEntry`
|
||||
size, `NodeKind` 0–1, `Operation` values 0, 4 and 5); this page is the
|
||||
full record of the frozen values.
|
||||
size, `NodeKind` 0–1 and 6–7, `Operation` values 0, 4 and 5); this page is
|
||||
the full record of the frozen values.
|
||||
- The 256-byte message ceiling is a property of the current IPC transport,
|
||||
not a promise; clients should read `maximum_payload`-shaped limits from the
|
||||
reply lengths they actually get (loop-until-done), not hard-code 224.
|
||||
|
||||
@@ -35,7 +35,7 @@ the logging/USB-lifecycle track).
|
||||
- [x] **PM** — path-migration flag-day (`/etc`→`/system/configuration`, `/var/log`→`/system/logs`, `/mnt/usb`→`/volumes/usb`; vfs carve-out for the two writable `/system` subtrees, FAT's `/var` mount split in two; suite 106/106)
|
||||
- [x] **H1** — the `user-memory` module; nine stragglers converted; leaf U/S+W checks (plus physmap-coverage confirmation, so an `mmio_map`'d buffer cannot fault ring 0 — this also closes the same hazard on the IPC path; `fs_resolve`'s out-capacity bound made overflow-safe; suite 107/107)
|
||||
- [x] **merge** group 1 → main, push (f3bc23c, 2026-07-31)
|
||||
- [ ] **P1** — envelope module + `Define`; vfs `NodeKind.protocol` + open-reply-capability; client `Channel`
|
||||
- [x] **P1** — envelope module + `Define`; vfs `NodeKind.protocol` + open-reply-capability; client `Channel` (mechanics only, nothing converted; suite unchanged at 107)
|
||||
- [ ] **P2** — registry in init; `/protocol` reserved; ServiceId flag-day (11 binds, 17 lookups)
|
||||
- [ ] **P3** — open grants: `protocol.csv` enforcement, denial test
|
||||
- [ ] **merge** group 2 → main, push
|
||||
|
||||
Reference in New Issue
Block a user