Crafter.Network/interfaces
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jorijn van der Graaf 1b7417c2ba
feat(quic): QUICStream::SendAsync holds no thread and reports from SEND_COMPLETE
Native SendAsync was SendSync run as a pool task. That held a worker of
Crafter.Thread's pool, which the host shares and which runs each
worker's queue in order, for as long as msquic took to accept the
buffer, and a peer that reads slowly stretches that to its own pace: a
server streaming to a slow follower stalled the tasks queued behind it.
The task also reached back through `this`, so moving or destroying the
wrapper before it ran was a use-after-free, and two sends could reach
msquic out of order from two workers.

Now SendAsync copies the buffer into a SendRequest, hands it to msquic
and returns. SEND_COMPLETE, which msquic delivers exactly once for every
send it took and before the stream's SHUTDOWN_COMPLETE, frees the copy
and calls onSent on the msquic worker: true when msquic took the whole
buffer (in its send buffer or acknowledged, which is what SendSync's
return has always meant), false when it was canceled because the stream
or the connection ended first. Sends queue in msquic in call order and
none waits for another. A send msquic never took (a closed stream, a
moved-from wrapper, StreamSend refusing it) reports false from a pool
task, never from inside SendAsync, so a caller may hold a lock its own
callback takes. Only `impl` is read, not `handle`, so SendAsync is
callable from any thread, a callback included; on a stopped stream
msquic cancels the send.

BytesInFlight() and SendsInFlight() count what SendAsync and SendSync
handed msquic whose SEND_COMPLETE has not come, so a server can drop a
follower that falls too far behind.

Rewritten rather than added beside it: nothing in this repository calls
the native SendAsync (ListenerHTTP, WebTransport and ClientHTTP use
SendSync; the example's SendAsync is the browser build's), nor does any
consumer found here (3DForts uses SendSync natively); its contract is
unchanged, copy now and onSent once with whether it went; and the old
one's pool thread, `this` capture and reordering were defects, not
behaviour to keep. What changes is onSent's thread, msquic's worker
rather than a pool task, so a callback that blocks, a *Sync call above
all, now stalls its connection rather than a pool worker. The browser
build is untouched.

Breaking: native onSent runs on msquic's worker thread, not as a pool
task, and must not block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:24:15 +01:00
..
Crafter.Network-ClientHTTP.cppm SPDX license 2026-07-22 17:55:45 +02:00
Crafter.Network-ClientHTTP1.cppm feat(http1): ClientHTTP1::Fetch follows redirects by the RFC, on a URL type 2026-10-31 20:39:43 +01:00
Crafter.Network-ClientQUIC.cppm feat(quic): QUICStream::SendAsync holds no thread and reports from SEND_COMPLETE 2026-11-01 02:24:15 +01:00
Crafter.Network-ClientTCP.cppm feat(tcp): socket errors as std::system_error, with the phase that failed 2026-10-31 20:33:37 +01:00
Crafter.Network-HTTP.cppm feat(http1): dispatch unmatched paths to an optional fallback handler 2026-07-28 19:41:57 +00:00
Crafter.Network-HTTP1.cppm feat(tls): add a libssl TLS transport and an https:// HTTP/1.1 stack 2026-07-28 20:13:30 +00:00
Crafter.Network-HTTP3.cppm SPDX license 2026-07-22 17:55:45 +02:00
Crafter.Network-ListenerHTTP.cppm feat(http): give ListenerHTTP the same fallback and query-strip routing 2026-07-28 19:42:06 +00:00
Crafter.Network-ListenerHTTP1.cppm feat(tls): add a libssl TLS transport and an https:// HTTP/1.1 stack 2026-07-28 20:13:30 +00:00
Crafter.Network-ListenerQUIC.cppm fix(listener): make the selfSigned QUIC certificate per user, in-process, without a race 2026-11-01 01:56:44 +01:00
Crafter.Network-ListenerTCP.cppm feat(tcp): ListenerTCP binds the address it is given, at port 0 if asked 2026-10-31 20:28:32 +01:00
Crafter.Network-Stream.cppm feat(tls): add a libssl TLS transport and an https:// HTTP/1.1 stack 2026-07-28 20:13:30 +00:00
Crafter.Network-TLS.cppm fix(listener): make the selfSigned QUIC certificate per user, in-process, without a race 2026-11-01 01:56:44 +01:00
Crafter.Network-URL.cppm feat(http1): ClientHTTP1::Fetch follows redirects by the RFC, on a URL type 2026-10-31 20:39:43 +01:00
Crafter.Network-WebTransport.cppm SPDX license 2026-07-22 17:55:45 +02:00
Crafter.Network.cppm feat(http1): ClientHTTP1::Fetch follows redirects by the RFC, on a URL type 2026-10-31 20:39:43 +01:00