Crafter.Network/implementations
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jorijn van der Graaf 9ea07c54f1
fix(quic): let the streams already stopped finish before ~ClientQUIC closes
~ClientQUIC shut the connection down first and drained its streams
after. msquic aborts every stream with the connection, and with them
whatever it had not sent yet, so a server that replied with
SendAsync(..., finish = true), let the stream go and deleted the
connection lost the reply whenever the shutdown, queued right behind
the send, reached the worker before the flush that would have sent it.
The interface promised the opposite: that the destructor waits for
every stream "to finish closing first".

Found with Crafter.Debug, whose session answers every request still
waiting when it ends and then deletes its connections: the follower
it told "shutting down" missed the reply in 4 runs of 30.

Streams now count as finishing from QUICStream::Stop to their
SHUTDOWN_COMPLETE, in the registry beside the open count, and the
destructor waits for that count to reach zero before the shutdown.
Only streams that can send are counted, since a stream that cannot has
nothing on its way. A stopped stream finishes once the peer has
acknowledged its FIN, about a round trip; the wait is bounded at 1 s
so a peer that stopped answering, or one that never reads, holds the
destructor no longer than that, and a peer closing meanwhile aborts the
streams, which ends the wait too. Streams their owner still holds are
not waited for: they are aborted as before.

Measured with ShouldFinishStoppedStreamsQUIC: before, 0 of 20 replies of
64 KiB arrived; after, 20 of 20, with the slowest delete at 1 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 03:03:20 +01:00
..
Crafter.Network-ClientHTTP-Browser.cpp SPDX license 2026-07-22 17:55:45 +02:00
Crafter.Network-ClientHTTP.cpp SPDX license 2026-07-22 17:55:45 +02:00
Crafter.Network-ClientHTTP1.cpp feat(http1): ClientHTTP1::Fetch follows redirects by the RFC, on a URL type 2026-10-31 20:39:43 +01:00
Crafter.Network-ClientQUIC-Browser.cpp feat: TCP-only builds; TCP options and timeouts; receives that report and keep what arrived 2026-10-20 20:04:57 +02:00
Crafter.Network-ClientQUIC.cpp fix(quic): let the streams already stopped finish before ~ClientQUIC closes 2026-11-01 03:03:20 +01:00
Crafter.Network-ClientTCP.cpp feat(tcp): socket errors as std::system_error, with the phase that failed 2026-10-31 20:33:37 +01:00
Crafter.Network-ListenerHTTP.cpp feat(http): give ListenerHTTP the same fallback and query-strip routing 2026-07-28 19:42:06 +00:00
Crafter.Network-ListenerHTTP1.cpp test(https): give the TLS tests ports of their own 2026-07-28 20:34:23 +00:00
Crafter.Network-ListenerQUIC.cpp 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.cpp 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.cpp 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.cpp fix(listener): make the selfSigned QUIC certificate per user, in-process, without a race 2026-11-01 01:56:44 +01:00
Crafter.Network-WebTransport.cpp SPDX license 2026-07-22 17:55:45 +02:00