Skip to content

Ioxide engine: ioxide 0.4.169, all endpoints served, native TLS termination - #887

Draft
MDA2AV wants to merge 7 commits into
mainfrom
ioxide-0.4.161
Draft

Ioxide engine: ioxide 0.4.169, all endpoints served, native TLS termination#887
MDA2AV wants to merge 7 commits into
mainfrom
ioxide-0.4.161

Conversation

@MDA2AV

@MDA2AV MDA2AV commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator
  • ioxide 0.1.10.4.169 (the separate ioxide.tls package is folded into core)
  • Migrates the renamed APIs: TcpConnection, TcpHandle, TcpConnectionDualPipe, ServerConfig.Tcp
  • Serves every configured endpoint (primary port + ExtraPorts) instead of the first only
  • Endpoints bound with a certificate are TLS-terminated ring-natively, one context per port; the certificate is exported as PEM in memory. Client certificate validation and SNI-only providers throw as unsupported
  • Replaces the hand-rolled TlsDuplexPipe with ioxide's TlsConnectionDualPipe (close_notify on teardown in both TLS backends)
  • Releases the connection when the TLS handshake or a custom connection factory faults

Verified with a two-endpoint host (plaintext + certificate-bound): both serve, and a strict client observes close_notify before FIN.

MDA2AV added 3 commits August 8, 2026 18:15
…nation

- ioxide 0.1.1 -> 0.4.161; the separate ioxide.tls package is folded into core
- migrate renamed APIs (TcpConnection, TcpHandle, TcpConnectionDualPipe, ServerConfig.Tcp)
- serve every configured endpoint (primary port + ExtraPorts) instead of the first only
- endpoints bound with a certificate are TLS-terminated ring-natively (per-port contexts,
  certificate exported as PEM); client cert validation and SNI report as unsupported
- replace the hand-rolled TlsDuplexPipe with ioxide's TlsConnectionDualPipe
- release the connection when the handshake or connection factory faults
… one

The eager Provide(null) in the constructor threw for SNI-only certificate
providers (SecurityTests' PickyCertificateProvider), failing host startup for
the secure-upgrade redirect cases that never actually handshake.

Certificates are now resolved per reactor in OnStart. A secure port whose
provider yields no default certificate stays advertised (so redirects derive
the https port) but its handshakes are refused with a FIN, so a client sees a
fast connection failure instead of a plaintext response on an https port.
@MDA2AV MDA2AV changed the title Ioxide engine: ioxide 0.4.161, all endpoints served, native TLS termination Ioxide engine: ioxide 0.4.165, all endpoints served, native TLS termination Aug 9, 2026
MDA2AV added 3 commits August 9, 2026 21:29
ioxide.file 0.4.167 became io_uring reads only - it hands out a descriptor
and a length, bakes no HTTP responses and caches no bytes. So Asset.Response,
Asset.ResponseLength and AssetCache.IsFresh are all gone, and this module
could not merely be re-pinned; the bump from 0.1.1 to 0.4.169 crosses that
redesign. The engine goes 0.4.165 -> 0.4.169 with it.

The baked-response branch is gone: the body is always read off the ring
through the per-reactor AssetReader pool, which this class already used for
assets too large to bake.

The freshness check moves here rather than disappearing. The package dropped
per-request statx deliberately - it trusts a snapshot's descriptors and
expects Reload() on deploy - but this module's documented behaviour is that
an edited file is served, and TestChangedFileServesUpdatedContent asserts it.
Adopting the package's model silently would have changed GenHTTP's contract
under its users, so AssetFreshness reproduces the size comparison the package
used to do. It matters beyond freshness: the handler's length becomes
Content-Length, so the body writer must agree with it or the response is
malformed - which is exactly how the built-in Files module misbehaves when a
file changes under it, serving new content at the old length.

Acceptance suite: 2044 (net11) + 1442 (net10) pass, including all 16 Ioxide
tests. Playground gains /ring and /disk over one directory to price the two
against each other; that file also carries unrelated in-progress work, so it
is left uncommitted deliberately.
/ring mounts IoxideFiles and /disk GenHTTP's built-in Files module over the
SAME directory, on the same engine, so the module is the only variable.
GENHTTP_STATIC picks the directory and neither route mounts without it.

Measured here with wrk -t8 -c64, best of two interleaved passes:

           /ring      /disk
   4 KiB   835409   1041891
  64 KiB   365531    509255

The built-in module is ahead, but part of that is work it does not do: edit a
file while it runs and it serves the new content at the old Content-Length,
truncating the response, where IoxideFiles serves it whole. That check is
what AssetFreshness restored.

One tuning note for later: IoxideAssetContent flushes every 12 KiB to stay
under the 16 KiB write slab, and at 64 KiB that costs about 19% - raising the
chunk to 64 KiB measured 433924 against 365531, content verified identical.
Left alone because a bigger chunk grows every connection's slab, which is a
memory tradeoff worth deciding rather than slipping in.
Added on a wrong assumption that 0.4.169 was unpublished. It is, so the
local feed was both unnecessary and a hazard - it pinned an absolute path
that only exists on one machine, and it shadowed the published package with
a locally built one of the same version.

Restore now resolves from nuget.org (verified via .nupkg.metadata source),
and the acceptance suite passes against the published package: 2044 on
net11, 1442 on net10.
@MDA2AV
MDA2AV marked this pull request as draft August 10, 2026 09:39
@MDA2AV MDA2AV changed the title Ioxide engine: ioxide 0.4.165, all endpoints served, native TLS termination Ioxide engine: ioxide 0.4.169, all endpoints served, native TLS termination Aug 10, 2026
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