From c7adf0f68e243d120a949935b23f9ab82acd0316 Mon Sep 17 00:00:00 2001 From: Gebri Mishtaku Date: Wed, 29 Jul 2026 11:07:56 -0700 Subject: [PATCH] Added support for attaching application-layer stream protocols to existing flows --- .../EndpointFlow/EndpointFlowProtocols.swift | 7 ++++++ .../Protocols/OneToOneProtocol.swift | 16 ++++++++++++ .../Protocols/ProtocolControlHandlers.swift | 25 +++++++++++++++++++ .../Protocols/ProtocolListenerHandlers.swift | 15 +++++++++++ .../Protocols/ProtocolOptions.swift | 8 ++++++ .../Protocols/ProtocolStreamHandlers.swift | 5 ++++ .../SwiftNetwork/Protocols/TopProtocol.swift | 13 ++++++++++ .../StreamPerfTestHandler.swift | 8 ++++++ 8 files changed, 97 insertions(+) diff --git a/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift b/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift index 75ac499..14f41d7 100644 --- a/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift +++ b/Sources/SwiftNetwork/EndpointFlow/EndpointFlowProtocols.swift @@ -446,6 +446,13 @@ final class StreamEndpointFlowProtocol: EndpointFlowProtocol ProtocolInstanceReference? { + nil + } + public var identifier: ProtocolIdentifier public var topID: Int? = nil @@ -232,6 +236,10 @@ public final class ProtocolOptions: AbstractProtocolOptions perProtocolOptions?.serialize() ?? nil } + public override func newProtocolInstance(context: NetworkContext) -> ProtocolInstanceReference? { + P().newProtocolInstance(context: context) + } + public init(protocolIdentifier: ProtocolIdentifier, perProtocolOptions: P.Options?) { self.perProtocolOptions = perProtocolOptions super.init(identifier: protocolIdentifier) diff --git a/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift b/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift index cb86f67..2fde116 100644 --- a/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift +++ b/Sources/SwiftNetwork/Protocols/ProtocolStreamHandlers.swift @@ -150,6 +150,11 @@ public protocol InboundStreamHandler: ~Copyable, InboundDataHandler where LowerP path: PathProperties? ) throws(NetworkError) + mutating func attachLowerStreamProtocolToExistingFlow( + listener: StreamListenerLinkage, + flowReference: ProtocolInstanceReference + ) throws(NetworkError) + mutating func handleInboundAbortedEvent(_ from: ProtocolInstanceReference, error: NetworkError?) mutating func handleOutboundAbortedEvent(_ from: ProtocolInstanceReference, error: NetworkError?) } diff --git a/Sources/SwiftNetwork/Protocols/TopProtocol.swift b/Sources/SwiftNetwork/Protocols/TopProtocol.swift index 5fd9dff..dbbca56 100644 --- a/Sources/SwiftNetwork/Protocols/TopProtocol.swift +++ b/Sources/SwiftNetwork/Protocols/TopProtocol.swift @@ -324,6 +324,19 @@ extension TopProtocolHandler where Self: ~Copyable, LowerProtocol == OutboundStr path: path ) } + + public mutating func attachLowerStreamProtocolToExistingFlow( + listener: StreamListenerLinkage, + flowReference: ProtocolInstanceReference + ) throws(NetworkError) { + guard lower.isDetached else { + throw NetworkError.posix(EALREADY) + } + self.lower = try listener.invokeAttachUpperStreamProtocolToExistingFlow( + reference, + flowReference: flowReference + ) + } } @available(Network 0.1.0, *) diff --git a/Sources/SwiftNetworkBenchmarks/StreamPerfTestHandler.swift b/Sources/SwiftNetworkBenchmarks/StreamPerfTestHandler.swift index 227f567..d0de768 100644 --- a/Sources/SwiftNetworkBenchmarks/StreamPerfTestHandler.swift +++ b/Sources/SwiftNetworkBenchmarks/StreamPerfTestHandler.swift @@ -284,6 +284,14 @@ extension StreamPerfTestHandler: UpperProtocolHandler { throw NetworkError.posix(ENOTSUP) } + // InboundStreamHandler conformance + public func attachLowerStreamProtocolToExistingFlow( + listener: StreamListenerLinkage, + flowReference: ProtocolInstanceReference + ) throws(NetworkError) { + throw NetworkError.posix(ENOTSUP) + } + // UpperProtocolHandler conformance public func attachLowerProtocol( _ lowerProtocol: ProtocolInstanceReference,