Experimental tunnel API for out-of-package network transports - #3152
Merged
Conversation
… (SER009, experimental) The [Experimental] transport seam decided with Marc: a duplex byte-transport abstraction that is deliberately NOT a Stream and NOT a pipe, plus a null-default virtual on Tunnel that supplies the ENTIRE transport for a connection -- the same hijack as BeforeAuthenticateAsync one level deeper (no socket is created at all), returning null for every existing tunnel. The shape is derived from measured transport work rather than taste, and each member's derivation is in its doc comment: any-thread copying writes with an explicit Flush (batching at the caller's natural boundaries was the largest single lever measured), PUSH inbound with transport-owned spans (pull adapters over a push transport measured 24-40%), and an OnBatchEnd notification (coalescing burst responses into one flush eliminated a measured 3x send amplification). Abstract classes by design so members can be added with safe defaults while experimental; receive-into-caller-buffer is deliberately deferred to exactly that mechanism. House ceremony: SER009 registered in Experiments, docs/exp/SER009.md, PublicAPI entries in both projects with the [SER009] experimental prefix. A working SocketSet implementation of this shape already exists and is gated across plaintext/TLS/@abstract surfaces (SocketSet repo, src/SocketSet.StackExchange.Redis + bench/tunnel-selftest); it retargets to these types next.
…members abstract on the transport With Flush on the transport, a separate .Output object never truly described output; the split was inherited from IDuplexPipe, whose 3-object shape exists for independent Input/Output completion that this contract does not have. GetMemory/GetSpan/Advance are now abstract members of DuplexTransport itself, and passing the transport AS IBufferWriter<byte> grants stage-only access: the holder composes, the owner flushes at its batch boundary. TransportReceiver deliberately stays separate: it is the CONSUMER's half, and it must remain abstract-class-evolvable on the net461/netstandard2.0 targets, where interfaces cannot grow. Experimental (SER009), so this is a free change; PublicAPI entries updated to match. Implementation side re-gated ALL PASS across plaintext/TLS/@abstract before this landed.
… abstract GetMemory is the one true abstract of the writer face; GetSpan defaults to GetMemory(sizeHint).Span, so an implementer owes exactly one buffer-acquisition member. Transports with a genuinely cheaper span path (the SocketSet implementation forwards to its connection's own GetSpan) override it -- nice if they do, correct if they don't.
The seam is public only because a seam must be public to be implemented; the doc now says so, spells out that no stability of any kind is implied (members, semantics, name, home, existence -- any version, no ceremony), and frames suppressing the diagnostic as accepting exactly that. If a generally useful transport seam emerges it gets stabilised deliberately, not by this surface quietly hardening.
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.
This is purely experimental work looking at SocketSet as a mechanism to potentially support io_uring, kTLS, and friends - without burying them in the core package for now.
Checklist