Skip to content

feat(net): portable C network core, POSIX driver, TLS providers (stack B) - #306

Draft
HalfSweet wants to merge 2 commits into
feat/network-v2-a-contractsfrom
feat/network-v2-b-core
Draft

feat(net): portable C network core, POSIX driver, TLS providers (stack B)#306
HalfSweet wants to merge 2 commits into
feat/network-v2-a-contractsfrom
feat/network-v2-b-core

Conversation

@HalfSweet

Copy link
Copy Markdown
Collaborator

Summary

Stack B of 3 (on top of #305, stack A). engine/net: the portable C network core — HTTP/1.1 client and server, RFC 6455 client, strict framing profile, bounded receive/send queues with backpressure, the immutable policy (the plan's ResolvedNetworkPolicy), tick queues with a per-tick budget and readable-before-terminal ordering, the TLS handshake state machine; pnet_driver_ops (BSD/lwIP driver under drivers/posix) and pnet_tls_ops (OpenSSL reference provider; the ESP-TLS provider is in stack C) are the only host interfaces. The conformance harness (pnet_unit_test, pnet_host_test over real loopback sockets, pnet_tls_test against an in-process OpenSSL PKI) runs under ASan/UBSan.

Review-round changes in this PR (reviewer items 2, 4, 9, 1/3)

  • poll is transactional (2). The batch is sized and reserved before a single visible event is dequeued; an allocation failure leaves the visible set intact and the next poll retries — a handle's terminal end/error can no longer vanish under the heap cap (the ESP host caps the core at 1 MiB). pnet_*_poll_render / _consume expose the two phases for hosts that marshal into a guest value. Unit tests pin the deferred batch, idempotent render, consume-exactly-the-rendered set with a freeze in between. The original repro (cap at current usage → poll returned NULL, visible_count 0, terminal lost) now recovers.
  • DNS off the network task (4). getaddrinfo runs on the driver's resolver worker (pthread / pnet-dns task on ESP-IDF); select, sockets and the core's deadlines keep running during a lookup, so connectMs covers DNS as the spec says. Host test: hostname through the worker, NXDOMAIN → dns, a literal-address exchange completes while a lookup is in flight.
  • Spec-pinned semantics (9). Methods / owned headers / bodyless framing / redirect plan / null-body statuses come from spec.h (pnet_http_redirect_plan, pnet_status_is_bodyless, pnet_status_is_null_body); the server refuses content on 205; pnet_unit_test runs contracts/spec/vectors/http-semantics.json.
  • Policy parser parity (1/3). pnet_policy_parse accepts exactly the canonical document (version 1, A-label hostnames, no bare wildcard, no wildcard over an IP literal, no leading-zero IPv4 octets) and runs contracts/spec/vectors/network-policy.json — the same decisions as the TypeScript reference and the Rust core. The header comment now states the true provenance (plan → host → core).

Validation

ctest --test-dir engine/net/build 3/3 under ASan/UBSan: unit 519 checks, host 171 checks, tls 16 checks.

…t client, POSIX driver, TLS providers (stack B)

engine/net (stacked PR B of three, on top of A's contracts): HTTP/1.1
client and server, the RFC 6455 client, the strict framing profile,
bounded receive/send queues with backpressure, the immutable policy
(contracts/spec/network-policy.ts), tick queues with a per-tick budget and
readable-before-terminal ordering, and the TLS handshake state machine.
The only host interfaces are pnet_driver_ops (a BSD/lwIP driver under
drivers/posix) and an optional pnet_tls_ops TlsProvider: the OpenSSL
reference provider (drivers/openssl) and the conformance harness —
pnet_unit_test (framing, URL, policy, JSON, codecs, tick queue),
pnet_host_test (both cores over real loopback sockets against scripted
peers) and pnet_tls_test (an in-process OpenSSL PKI: valid chain, unknown
CA, expired, hostname mismatch, untrusted clock, development-insecure
refusal, WSS echo) under ASan/UBSan.
…nned semantics, policy parser parity (stack B)

The review fixes for the C core (stack B):

- poll is transactional (reviewer item 2): the batch is sized and reserved
  before a single visible event is dequeued; an allocation failure leaves
  the whole visible set in place and the next poll retries, so a handle's
  terminal end/error is never lost to the heap cap (the ESP host caps the
  core at 1 MiB). pnet_*_poll_render / _consume expose the two phases for
  hosts that marshal the batch into a guest value. Unit tests pin the
  deferred batch, idempotent render and consume-exactly-the-rendered set.
- getaddrinfo runs on the driver's resolver worker (item 4): a pthread on
  desktop, the pnet-dns task on ESP-IDF; the network task's select loop,
  the sockets and the core's deadlines keep running during a lookup
  (connectMs covers DNS). The host test drives a hostname through the
  worker, checks NXDOMAIN → dns, and shows a literal-address exchange
  completing while a lookup is in flight.
- Spec-pinned semantics (item 9): the client uses PNET_METHODS_FORBIDDEN
  (TRACK included) and PNET_HTTP_CORE_OWNED_REQUEST_HEADERS, framing uses
  pnet_status_is_bodyless, the redirect plan (pnet_http_redirect_plan) uses
  the spec's tables, the server refuses content on every null-body status
  (205 included); pnet_unit_test runs contracts/spec/vectors/
  http-semantics.json.
- Policy parser parity (item 1/3): pnet_policy_parse accepts exactly the
  canonical ResolvedNetworkPolicy (version 1, A-label hostnames, no bare
  wildcard, no wildcard over an IP literal, no leading-zero IPv4 octets)
  and runs contracts/spec/vectors/network-policy.json; pnet_json records
  container source spans so a sub-document can be handed to another parser.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant