summaryrefslogtreecommitdiff
path: root/README.md
blob: 226ec78345a9cc9455e98132e4f66bddeb15ed6e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# cloud9

A Zig 0.16 library for base **9P2000** clients, servers, and transports.

The protocol core uses caller-owned buffers and bounded request tables. It has
no heap allocation, OS calls, threads, or filesystem policy. TCP and Unix stream
adapters support `std.Io`; nonblocking POSIX adapters support existing event loops.
Optional QUIC transport takes caller-provided OpenSSL bindings and an ALPN name.

Mounting, namespace discovery, exported trees, permissions, and application
lifecycle stay with the application. There are no 9P2000.u or 9P2000.L messages.

```sh
zig build test
zig build transport-test
zig build quic-test -Dquic=true       # system OpenSSL 3.6+
zig build fuzz -Doptimize=ReleaseSafe -- 4200 1000000
zig build differential -Doptimize=ReleaseSafe -- --seed 4200 --rounds 1000
zig build differential -Doptimize=ReleaseSafe -- --seed 4201 --rounds 100 --chunk 1
```

The differential harness requires Go, downloads pinned test-only dependencies,
and saves a corpus, configuration, and JSON report under
`test/differential/results`. It compares valid messages with 9fans and go9p and
runs the cloud9 client against go9p's filesystem server over local pipes.
Malformed-input probes run only against cloud9. No remote targets are contacted.

To use a sibling checkout, add `.cloud9 = .{ .path = "../cloud9" }` to the package
dependencies, then import its module:

```zig
const cloud9 = b.dependency("cloud9", .{
    .target = target,
    .optimize = optimize,
}).module("cloud9");
app.root_module.addImport("cloud9", cloud9);
```

Start a client with `Client.init(.{ .in = input_buffer, .out = output_buffer })`.
Submit `.version` first. Drain `output()` through your transport and report the
number sent with `wrote()`. Feed received bytes using `push()` and collect tagged
results with `take()`. All base requests are available through `Client.Request`.

For a server, call `Server.receive()` after `push()`. A request borrows the input
until `release()`. After releasing backend fids and canceling outstanding work,
answer Tversion with `negotiate()`. Answer other requests with `reply()`. The
backend implements its filesystem and fid lifecycle; cloud9 checks reply types,
tags, counts, negotiated frame sizes, and flush completion.

See [design and ownership contracts](docs/design.md),
[specification references](docs/spec.md), and [validation](docs/validation.md).