Skip to content

CWIST v3.3

Choose a tag to compare

@gg582 gg582 released this 05 Sep 15:27
· 0 commits to d8f3b3d978ebd00f90fa35f1e72ee3b89626ac06 since this release

CWIST v3.3 — gRPC streaming, deferred async handlers, and stability hardening

Major changes compared to v3.2 (including subsequent patch updates in this tag):

  1. Full gRPC Streaming Support (d3222d6)

    • Connect incremental decoders/output sinks directly to HTTP/2 DATA frames via per-connection stream hooks.
    • Send grpc-status and grpc-message as actual trailer HEADERS frames.
    • Parse grpc-timeout, enforce DEADLINE_EXCEEDED, and propagate RST_STREAM cancellations.
    • Metadata normalization (case-insensitivity, *-bin base64 encoding), gzip request compression negotiation.
    • cwist proto extensions: repeated fields (packed/unpacked), recursive encode/decode/free for nested messages, proto3 open enum support.
    • New tests: test_grpc_stream (wire-level h2c) and test_proto_gen (roundtrip).
  2. Deferred Async Handlers & Packaging (2352d0f)

    • cwist_async_defer/respond/abort: delegate response completion to worker job threads with 504 timeout enforcement.
    • Per-reactor wake fd (eventfd/pipe) and lock-free MPSC completion routing.
    • make install support for cwist.pc (pkg-config), make dist tarball, and Homebrew/vcpkg drafts.
  3. RFC 9218 HTTP/3 Priority Compliance (52b023b, e7d8297)

    • Removed PRIORITY_UPDATE frame transmission on request streams (resolving H3_FRAME_UNEXPECTED on strict stacks).
    • Preserved set_stream_priority ABI with deprecation warnings.
  4. HTTP Connection Stability (e719cf6, 1ab0e9f)

    • Enhanced graceful close, added error-checking helpers, and enabled sanitizer CI.
    • Implemented grace-period serving after HTTP/2 idle GOAWAY.
  5. Benchmarks (22e9059, 3c76340)

    • Added the-benchmarker/web-frameworks contract app; fixed v3.3 tag build.
    • Fixed the-benchmarker/web-frameworks main.c build command missing vendored include paths (sqlite3, libttak, BoringSSL, ...), causing a clean-container build to fail with 'sqlite3.h: No such file or directory' (the-benchmarker/web-frameworks#9745).

--- Patch Updates ---

  1. Status Code & Header Consistency

    • Expanded cwist_http_status_t to cover the full standard 1xx–5xx range (RFC 9110 + WebDAV) while retaining legacy aliases.
    • Added cwist_http_status_reason() to automatically apply standard reason phrases to error responses and status line fallbacks.
    • Cleaned up duplicate app.h declarations and resolved header guard collisions: unified top-level <cwist/app.h> and <cwist/sys/app/app.h> under an umbrella header to eliminate differing cwist_app struct layouts across translation units.
    • Standardized build baseline to -std=c17 (aligned with documentation) and updated CLI scaffolding templates.
  2. Concurrency & Memory Safety

    • io_queue: Fixed node reclamation race (UAF/ABA) in Michael-Scott queue by guarding push/pop in ttak EBR critical sections and retiring unlinked nodes via 2-stage retirement (new -> old -> ttak_epoch_retire) past epoch boundaries (100x clean TSAN, clean ASan/UBSan).
    • execute_chain(): Fixed static files returning 500 on apps with 0 middleware due to lost handler_data.
    • rdbms_auto_mount: Fixed uninitialized host pointer free (ASAN BUS) by replacing it with zeroed allocation.
    • http2: Fixed sequenced DATA message leak on flow-control wait abort paths.
    • Added cwist_error_dispose() and eliminated cJSON error payload leaks in sstring/nuke-db (resolving prior ASan CI failures).
    • test_static_and_range: Fixed test hanging on keep-alive responses waiting for EOF by checking Content-Length instead.
    • http2: Fixed HPACK dynamic table desync on stream errors — a header block that failed pseudo-header validation (e.g. duplicated :method) was abandoned mid-decode, skipping later incremental-indexing inserts and corrupting the shared compression context for subsequent requests on the same connection.
  3. Hardening & Interop CI

    • Linux: Enabled -fstack-protector-strong, _FORTIFY_SOURCE=2, PIE, and full RELRO by default.
    • Added WERROR=1 build toggle (excluding vendored objects) and integrated it into ASan/UBSan workflows.
    • Introduced interop workflow: h2spec h2c compliance checks with baseline diff against known failures (fails build on unexpected regressions).
    • tests/lsan.supp: Documented known lsquic teardown leaks and h3 header-set teardown gaps (ROADMAP known issues).
  4. Tooling & Documentation

    • make install now installs the cwist CLI into $(PREFIX)/bin; uninstall cleans it up.
    • README: Added CLI project workflows (new/watcher/openapi/proto/describe) and stability/conformance sections.
    • NOTICE.md: Added summary of vendored dependency licenses.
  5. Async v2 Writer, P2C TLS Shepherd & Idle Reaper (428df58)

    • cwist_async_complete: removed synchronous SO_SNDTIMEO blocking; speculative non-blocking send pipeline with zero added latency on the hot path.
    • TLS shepherd: SSL_accept crypto offload out of the accept loop, Power-of-Two-Choices shard load balancing, SO_REUSEPORT ingress distribution.
  6. HTTP/2 DoS Mitigations — Rapid Reset & Control-Frame Floods (f89fb78)

    • CVE-2023-44487 (Rapid Reset): token-bucket RST_STREAM budget per connection (burst 100, refill 100/s; CWIST_HTTP2_MAX_RST_BURST / CWIST_HTTP2_MAX_RST_RATE); excess triggers GOAWAY(ENHANCE_YOUR_CALM) and connection teardown, enforced on both blocking and non-blocking send loops.
    • RFC 7540 §5.1: RST_STREAM on idle streams (stream_id > last_processed_stream_id) is now a PROTOCOL_ERROR connection error.
    • CVE-2024-27983 (CONTINUATION flood): 64KB header-block cap (CWIST_HTTP2_MAX_HEADER_BLOCK_SIZE), 32-frame CONTINUATION limit (CWIST_HTTP2_MAX_CONTINUATIONS), 256 headers/request cap, and SETTINGS_MAX_HEADER_LIST_SIZE=65536 advertised in the handshake.
    • CVE-2019-9512 (PING flood): token-bucket rate limit on non-ACK PING frames with ENHANCE_YOUR_CALM enforcement.
  7. Async HTTPS over TLS (f9d447c)

    • Deferred handlers on TLS connections now respond via SSL_write through the connection wrapper (cwist_https_send_response/_head) instead of writing plaintext to the socket; keep-alive connections re-arm through https_pool_submit_conn.
    • Thread-local arena: _Thread_local fast-path TLS lookup (no pthread_getspecific call on the hot path), owner_tid tagging so cross-thread destroys bypass foreign caches, and arena struct + buffer recycled together.
    • HTTP/2 responses are created inside the request arena — one arena block per request-response cycle.
  8. HTTP/2 Async Defer — MPSC Queue + eventfd (0183305)

    • Deferred handlers no longer block the HTTP/2 connection loop: completed (stream_id, req, res) nodes are pushed onto a per-connection MPSC queue and the connection thread is woken via eventfd; HPACK encoding and flow control stay single-threaded (no cross-thread frame injection, no output mutex).
    • RST_STREAM on a deferred stream removes it from the stream table; late completions for cancelled streams are dropped at drain time. Refcounted queue survives teardown races.
  9. HTTP/3 UDP GSO Fix (485ce64)

    • Capped GSO super-packet runs at 65535 bytes (max UDP payload); an exactly-64KiB batch previously failed sendmsg with EMSGSIZE and permanently disabled GSO.
  10. POLLOUT-Resumable Async Writer (6eef7a7)

    • Deferred async completions on the reactor path no longer poll-wait in the completion thread on slow clients: unsent bytes are deep-copied into an owned buffer, parked in a one-shot POLLOUT slot (new cwist_reactor_add_out; io_uring POLL_ADD / epoll EPOLLOUT|ONESHOT / kqueue EVFILT_WRITE|EV_ONESHOT), and resumed on write-readiness.
    • Parked writers are bounded by a deadline (keep-alive timeout, refreshed on progress); file-stream bodies and the classic pool path keep the existing bounded poll loop.
    • Removes the last case where a slow client could occupy a reactor thread for the SO_SNDTIMEO budget (ROADMAP "Async v2" item closed).
  11. HTTP/3 Header-Set Leak Fix (151f61c)

    • lsquic never calls hsi_discard_header_set for streams still open on abortive engine destroy, leaking cwist_h3_hset_t objects.
    • Header sets are now tracked in an intrusive list on cwist_http3_context and swept after lsquic_engine_destroy; hsi_discard untracks before freeing so the sweep only touches true orphans.
    • The leak:cwist_h3_hsi_create entry is removed from tests/lsan.supp — LSan now passes on the HTTP/3 suite without that suppression.
  12. gRPC WINDOW_UPDATE Backpressure (097c4cb)

    • Handler-thread gRPC sends no longer fail with UNAVAILABLE on zero flow-control credit: cwist_http2_stream_send_data now flushes pending DATA, parks the handler on a per-connection condvar (h2_fc_wait_credit) signalled by the dispatcher on WINDOW_UPDATE/SETTINGS credit, and resumes chunk-by-chunk without holding the output mutex.
    • RST_STREAM (Rapid Reset), stream removal, connection teardown, and stall timeout still fail fast.
    • With this, every HTTP-layer item under ROADMAP "Known limits" that is controllable in-tree is closed; remaining limits are upstream-bound (e.g. WebTransport pending lsquic PR #629).