Seperate TransportLayer#41
Closed
st0o0 wants to merge 810 commits into
Closed
Conversation
…quest-to-frame conversion (RFC 9114 §4.1) Implements Http30Request2FrameStage that converts HttpRequestMessage to Http3Frame sequences using QPACK header compression. Produces HEADERS frames for all requests and DATA frames for request bodies. Unlike HTTP/2, no stream ID is needed (QUIC handles multiplexing).
Replace NotSupportedException stub with complete HTTP/3 Akka.Streams pipeline: Request2Frame → ConnectionStage → EncoderStage (outbound) and DecoderStage → ConnectionStage → StreamStage (inbound), with BatchWeighted consolidation for throughput. Add H3EngineFakeConnectionStage test helper and 5 end-to-end engine tests covering GET/POST round-trips, gzip decompression, SETTINGS emission, and body content preservation.
…e pipeline Wire the http30Factory parameter from Engine.CreateFlow through BuildExtendedPipeline to ProtocolCoreGraphBuilder.Build, completing HTTP/3 version routing. Add EROUTE-005 test verifying HTTP/3 requests are dispatched to Http30Engine.
…C 9114 §3.2) Add validation in QuicClientProvider to reject null/empty hostnames before establishing QUIC connections, ensuring SNI extension is always present in the TLS handshake. Add 11 unit tests covering hostname propagation, missing SNI rejection, ALPN protocol verification, and certificate callback forwarding.
…9114 §10.3 - Enhanced Http3FieldValidator with token character validation (reject spaces, control chars, separators, high-byte chars in field names) and field value validation (reject NUL, CR, LF to prevent response splitting) - Added Http3OriginValidator to reject prohibited origins (userinfo in authority, fragment identifiers in path) - Integrated origin validation into Http3RequestEncoder.Encode() - 20 new unit tests in 29_IntermediaryEncapsulationTests.cs, all passing - Build: 0 errors, 685 RFC9114 tests green
Add Http3PushLimiter to enforce configurable ceiling on server push promises per connection. Exceeding the limit triggers H3_EXCESSIVE_LOAD connection error. Includes RecommendedMaxPushId for aligning MAX_PUSH_ID with the DoS limit. 17 unit tests covering construction, enforcement, integration with Http3PushPromiseValidator, and flood scenarios.
…red (RFC 9114 §9) Fix DecodeAll to filter null frames from unknown types instead of adding nulls to the result list. Add 34 unit tests covering GREASE patterns (0x1f*N+0x21), HTTP/2 reserved frame types, unknown settings preservation, partial reassembly, and mixed known/unknown frame streams.
Wire RFC 9114 §4.2 field validation into the HTTP/3 response header pipeline. Http3FieldValidator.Validate() is now called after QPACK decode and before status/header extraction, rejecting uppercase field names, connection-specific headers, forbidden characters (NUL/CR/LF), and TE with non-trailers values. Added 6 stream tests covering all validation paths.
…Stage Wire Http3OriginValidator.Validate() into Http30Request2FrameStage.OnPush() before request encoding to prevent intermediary encapsulation attacks per RFC 9114 §10.3. CONNECT method detection passes isConnect=true for relaxed path validation. Invalid URIs (userinfo, empty scheme, empty path, fragments) throw Http3ConnectionException which propagates as stage failure.
…ider After QuicConnection.ConnectAsync(), validate server certificate hostname coverage via Http3CertificateValidator.CoversHostname() per RFC 9114 §3.3. Ensures connection coalescing safety with SAN/CN matching and wildcard support. Validation skipped when custom ServerCertificateValidationCallback is configured. On failure, connection is closed and Http3ConnectionException thrown with GeneralProtocolError.
…Stage Wire Http3IdleTimeoutHandler into Http30ConnectionStage to track idle connections per RFC 9114 §5.1. The stage now detects stale QUIC connections via periodic ScheduleOnce timer checks and sends GOAWAY when idle timeout expires with zero active streams.
ConnectionReuseStage now checks response.Version.Major >= 3 and routes HTTP/3 responses to Http3ConnectionReuseEvaluator.Evaluate() instead of the HTTP/1.x ConnectionReuseEvaluator. Parameters (scheme, host, port) are sourced from RequestMessage.RequestUri. serverCertificate and isGoingAway are not yet available in the response context — documented in XML remarks with guidance on how to thread them through the pipeline. HTTP/1.x and HTTP/2 behavior is unchanged (78 existing tests pass).
…PUSH_ID=0) Wire Http3MaxPushIdHandler, Http3PushLimiter, Http3CancelPushHandler, and Http3PushPromiseValidator into Http30ConnectionStage to defensively reject all server pushes per RFC 9114 §10.5. On PreStart, send MAX_PUSH_ID=0 on the control stream; any incoming PUSH_PROMISE triggers ExcessiveLoad error; CANCEL_PUSH frames are recorded via the cancel handler. GOAWAY-state prevents new MAX_PUSH_ID frames by design (only sent once at startup).
…ontrolStream and Http3SettingId Http3SettingsExchange was a thin wrapper around Http3ControlStream with no additional state. Migrated unique methods: ValidateFieldSectionSize and CalculateFieldSectionSize to Http3ControlStream, RejectForbiddenH2Settings to Http3SettingId. All 25 tests in 22_SettingsExchangeTests.cs updated to use the target classes directly.
Add 6 new test files in TurboHttp.StreamTests/RFC9114/ covering field validation, origin validation, certificate validation, idle timeout, connection reuse, and push rejection stages. - 07_Http30FieldValidationStageTests.cs (8 tests) — uppercase rejection, connection-specific headers, TE validation, forbidden chars - 08_Http30OriginValidationStageTests.cs (5 tests) — userinfo rejection, valid URI pass-through - 09_Http30CertificateValidationTests.cs (11 tests) — SAN match, wildcard, CN fallback, reuse evaluator integration - 10_Http30IdleTimeoutStageTests.cs (6 tests) — GOAWAY on idle expiry, timeout disabled, negative timeout, effective timeout - 11_Http30ConnectionReuseTests.cs (6 tests) — HTTP/3 version dispatch, endpoint key, mixed version boundary - 12_Http30PushRejectionStageTests.cs (6 tests) — MAX_PUSH_ID=0 at startup, PUSH_PROMISE ExcessiveLoad, CANCEL_PUSH absorption
All acceptance criteria verified: - Build: 0 errors, 0 warnings - Tests: 2,679/2,681 pass (2 pre-existing failures in HTTP/1.1 infrastructure) - Port naming: 33 stages, 91 ports, 0 violations - Zero Http3SettingsExchange references in production code - All 9 active HTTP/3 handlers integrated in production stages - No new [Obsolete] markers introduced
- Add `SupportsMultipleStreams` default interface property to `IClientProvider` (false for TCP/TLS, true for QUIC) - Refactor `QuicClientProvider.GetStreamAsync()` to use lazy connection establishment via `SemaphoreSlim`-guarded `EnsureConnectedAsync()` - First call connects + opens stream; subsequent calls reuse connection and open new streams - Catch `QuicException` on dead connection, clear connection ref, wrap as reconnectable `InvalidOperationException` - Use `Volatile.Read`/`Volatile.Write` and `Interlocked.CompareExchange` for thread-safe connection field access - Add 13 unit tests covering: SupportsMultipleStreams property (4), SNI validation (2), Close safety (2), RemoteEndPoint (1), multi-stream reuse (1), concurrent thread-safety (1), reconnect on dead connection (1), error wrapping (1)
…tProvider implementations - IClientProvider now extends IAsyncDisposable - QuicClientProvider.DisposeAsync() properly awaits QuicConnection.DisposeAsync() - TcpClientProvider.DisposeAsync() closes socket synchronously (wrapped in ValueTask) - TlsClientProvider.DisposeAsync() awaits SslStream.DisposeAsync() then delegates to TCP - Removed all fire-and-forget `_ = connection.DisposeAsync()` patterns from QuicClientProvider - ClientRunner.PostStop() now calls DisposeAsync() instead of Close() - ValidateCertificateHostname made async to properly await connection disposal on validation failure - Added unit test verifying DisposeAsync completes before actor terminates - Updated all fake IClientProvider implementations in test projects
…exing Add QUIC-aware connection pooling to HostPool and ConnectionActor so HTTP/3 requests multiplex over a single QUIC connection via OpenNewStream messages, while HTTP/1.x and HTTP/2 retain existing direct-handle behavior. Production changes: - ConnectionState: add SupportsMultipleStreams property (true for HTTP/3) - ConnectionActor: add OpenNewStream message, shared provider management, multi-runner lifecycle with BecomeStacked routing, pending stream queue - HostPool: version-aware HandleEnsureHost (QUIC sends OpenNewStream to connection actor), limiter bypass for QUIC, QUIC-aware HandleConnectionReady and ServeQueuedRequesters, suppress extra connection spawns while QUIC connection is still connecting - ClientRunner: skip disposal for shared QUIC providers (SupportsMultipleStreams) - IOActorTestBase: add Key30/QuicOptions, FakeConnectionActor message forwarding Test coverage (14 new tests): - 7 HostPool QUIC tests (QUIC-001 through QUIC-007): spawn, reuse, limiter bypass, HTTP/1.1+HTTP/2 regression, queued requesters, StreamCompleted - 3 ConnectionActor QUIC tests (CQ-001 through CQ-003): OpenNewStream ignored for TCP, message properties, ConnectionReady handle preservation - 4 ConnectionState tests (TASK-9-003-017 through 020): SupportsMultipleStreams for HTTP/1.x/2/3, HTTP/3 MaxConcurrentStreams, HTTP/3 HasAvailableSlot
Split ContinueWith into OnlyOnRanToCompletion (pull next element) and OnlyOnFaulted (FailStage with exception) branches so that write failures on a closed outbound channel propagate cleanly instead of being silently swallowed. Cancelled writes (stage shutdown) no longer trigger pull or fail. Added CS-011 test verifying the stage fails fast when the outbound channel is closed.
…or CloseSignalItem Two ConnectionStage stream tests (CS-004, CS-010) needed updating to account for the CloseSignalItem now emitted on inbound channel completion (introduced in TASK-007-004). All 3831 tests pass, zero warnings, zero errors.
Introduce abstract base class `ConnectionActorBase` that encapsulates shared connection lifecycle logic: channel management, exponential backoff reconnection, and HostPool message forwarding. This is the foundation for splitting the monolithic ConnectionActor into version-specific subclasses (Http1/Http2/Http3).
Simple single-connection actor inheriting from ConnectionActorBase, encapsulating TCP connect/disconnect logic for HTTP/1.0 and HTTP/1.1 without any multi-stream branching.
Add Http2ConnectionActor inheriting from ConnectionActorBase with simple TCP connect (no SharedProvider), stream lifecycle forwarding via base class (StreamAcquired/StreamCompleted), and no MarkBusy — stream accounting is handled exclusively by stage signals.
Extract QUIC-specific logic from the monolithic ConnectionActor into Http3ConnectionActor, inheriting from ConnectionActorBase. Isolates SharedProvider lifecycle, multi-runner tracking, pending stream queue, and BecomeStacked stream spawning — eliminating all _isMultiStream branches for QUIC handling.
HostPool.SpawnConnection() now creates the correct actor type based on HTTP version (Http1ConnectionActor, Http2ConnectionActor, or Http3ConnectionActor). All references to ConnectionActor.ConnectionReady migrated to ConnectionActorBase.ConnectionReady; OpenNewStream migrated to Http3ConnectionActor.OpenNewStream. The old monolithic ConnectionActor.cs is deleted. All 3832 tests pass with 0 warnings.
All test files already correctly reference the new ConnectionActor hierarchy (Http1ConnectionActor, Http2ConnectionActor, Http3ConnectionActor, ConnectionActorBase) from prior tasks. Fixed typo in ConnectionActorQuicTests doc comment (Http3Http3ConnectionActor → Http3ConnectionActor). All 3,832 tests pass, 0 warnings, 0 errors.
…ging Implement a FlowShape stage that assigns monotonically increasing client-initiated bidirectional QUIC stream IDs (0, 4, 8, 12, …) to each HTTP/3 request per RFC 9000 §2.1. Uses long for 62-bit QUIC stream IDs. Includes 10 stream tests verifying ID sequence, divisibility, monotonicity, and reference passthrough.
…matching Implements FanInShape stage that correlates HTTP/3 request/response pairs by QUIC stream ID (long), following the Http20CorrelationStage pattern. Sets HttpResponseMessage.RequestMessage for each correlated pair. Includes 7 stream tests covering single correlation, out-of-order responses, unmatched responses, reference equality, 10-request interleaving, upstream lifecycle, and immediate match on interleaved push.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
7dfb62e to
db064fc
Compare
Introduces `System.IO.Pipelines` for efficient byte movement, replacing direct `System.Threading.Channels` interactions in the core transport logic. This change streamlines buffer management, improves performance, and forms a key part of separating the transport layer. - Migrates `ClientByteMover` to a `Pipe`-centric architecture, utilizing `IoBuffer` for `MemoryPool` integration. - Updates `ClientState` to internally manage `Pipe` instances. - Adjusts `ConnectionHandle` and `NetworkBuffer` to interoperate with the new `IoBuffer` and `Pipe` paradigm. - Increases default HTTP/2 stream window size and max frame size, and HTTP/3 QPACK table capacity for improved performance. - Removes `Servus.Akka` project reference from `TurboHTTP.csproj`.
- Adjust HTTP/2 flow control window update threshold for more efficient `WINDOW_UPDATE` frames. - Optimize HPACK dynamic table lookups for header encoding by introducing an O(1) indexed cache. - Batch multiple HTTP/2 outbound frames into a single network buffer write to reduce overhead. - Improve HTTP/3 request body encoding to support streaming for unknown content lengths, preventing excessive memory allocation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.