Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
 
root / fuzz / seeds / h1-request / upgrade-h2c.http
Author[]Andy Green <andy@warmcat.com> 2026-10-05 16:38 UTC
Committer[]Andy Green <andy@warmcat.com> 2026-10-05 19:18 UTC
Tree8689947cd7364a526bc204c850b78dc3b38038ab   Raw Patch
 
docs: port plan: phase 1e is done
docs: port plan: phase 1e is done

What the client half is, what replays, the one difference kept from C,
and what is not done yet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019kg5Eemy68ZaqDBcUJQG6J
diff --git a/docs/port-plan.md b/docs/port-plan.md index c3ce9f3..9b01da2 100644 --- a/docs/port-plan.md +++ b/docs/port-plan.md @@ -747,13 +747,43 @@ byte for byte, four bytes at a time, with C's echo app: all of `-huge-frame`. The fuzz target `ws-server` is seeded from C's `fuzz/fuzz-ws/seeds`. -Not yet: the client half (its handshake, masking with a mask drawn per -frame, the client's side of the parser, and the `ws-client-*` -transcripts) comes next; nothing here has time, so there are no close -deadlines and no keepalive pings; the frame maximum is C's fixed 256 MiB, +**The client half (done, 2026-10-05)**: `handshake::ClientKey` is C's +`lws_generate_client_ws_handshake()` and `lws_client_ws_upgrade()`: a +key of 16 bytes drawn in one draw, the request's upgrade lines in C's +order, which the h1 client's request carries in place of `connection: +close` (`npro_h1::client::Connection::Upgrade`, after which the final +response is handed over unframed), and C's checks of the response in C's +order: a 101, an accept, `Upgrade: websocket`, `upgrade` among the +`Connection` tokens, a subprotocol, if named, that was offered, no +extension, and the key's accept. `conn::Ws` is now one parser for both +ends, a client's `Ws::client` masking each frame with a mask drawn when +the frame is begun, and checking each end's rules in its C parser's order +("srv mask", "bad fin", the client taking 1012 to 1015 from a server). +After a refusal, as C, the rest of the read is dropped, and once our close +has gone, whatever comes ends the connection. +`crates/npro-test/tests/ws_client_replay.rs` replays, byte for byte, with +C's seeded random and C's `callback_client`, `ws-client`, +`ws-client-interim`, `ws-client-ping-close`, `ws-client-huge-frame`, +`ws-client-rsv1-no-ext` and `ws-client-rsv2`: the request, every masked +frame, the app's messages and where C closed. The fuzz target `ws-client` +is seeded from those transcripts, C having no client corpus. + +Porting it found one difference kept from C: C's client takes any +`Connection` token that starts `upgrade` (it compares only the token's +length of it), so `Connection: up` passes; npro takes only `upgrade`. + +**Exit check, met**: `ws-client` (seeded) and `h1-ws-server` replay byte +for byte, as do the new ws transcripts but the pmd ones (phase 1f) and +`ws-client-digest-retry` (digest auth); the fuzz targets are seeded from +`fuzz/fuzz-ws/seeds` and the client transcripts. + +Not yet: nothing here has time, so there are no close deadlines and no +keepalive pings; the application cannot yet begin a close of its own with +a code, only close once flushed; the frame maximum is C's fixed 256 MiB, not configured, and there is no message maximum; the h1 server does not yet answer an unknown `Upgrade` with C's 403, or an upgrade with a body -with its 400; and a message's pieces are the application's to gather. +with its 400; a message's pieces are the application's to gather; and an +application's message goes as one final frame. ### Phase 1f: permessage-deflate (feature `pmd`)
Page fetched 0s ago, creation time: 3ms (vhost etag hits: 0%, cache hits: 0%)