Merge branch 'main' into main

This commit is contained in:
Cory Benfield 2024-09-18 17:47:44 +01:00 committed by GitHub
commit 5d335ce62a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 91 additions and 0 deletions

14
.github/release.yml vendored Normal file
View File

@ -0,0 +1,14 @@
changelog:
categories:
- title: SemVer Major
labels:
- ⚠️ semver/major
- title: SemVer Minor
labels:
- semver/minor
- title: SemVer Patch
labels:
- semver/patch
- title: Other Changes
labels:
- semver/none

View File

@ -409,6 +409,13 @@ extension NIOTSConnectionChannel {
self.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.BetterPathUnavailable())
}
}
/// Called by the underlying `NWConnection` when a path becomes viable or non-viable
///
/// Notifies the channel pipeline of the new viability.
private func viabilityUpdateHandler(_ isViable: Bool) {
self.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.ViabilityUpdate(isViable: isViable))
}
/// Called by the underlying `NWConnection` when this connection changes its network path.
///

View File

@ -43,6 +43,19 @@ public enum NIOTSNetworkEvents {
/// Create a new ``NIOTSNetworkEvents/BetterPathUnavailable`` event.
public init(){ }
}
/// ``ViabilityUpdate`` is triggered when the OS informs NIO that communication
/// with the remote endpoint is possible, indicating that the connection is viable.
public struct ViabilityUpdate: NIOTSNetworkEvent {
/// The current viability for the connection
public var isViable: Bool
/// Create a new ``NIOTSNetworkEvents/ViabilityUpdate`` event.
public init(isViable: Bool) {
self.isViable = isViable
}
}
/// ``PathChanged`` is fired whenever the OS has informed NIO that a new path is in use
/// for this `Channel`.
@ -106,6 +119,8 @@ extension NIOTSNetworkEvents.BetterPathAvailable: Sendable {}
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
extension NIOTSNetworkEvents.BetterPathUnavailable: Sendable {}
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
extension NIOTSNetworkEvents.ViabilityUpdate: Sendable {}
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
extension NIOTSNetworkEvents.PathChanged: Sendable {}
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
extension NIOTSNetworkEvents.ConnectToNWEndpoint: Sendable {}

View File

@ -140,6 +140,7 @@ extension StateManagedNWConnectionChannel {
let connection = NWConnection(to: target, using: parameters)
connection.stateUpdateHandler = self.stateUpdateHandler(newState:)
connection.betterPathUpdateHandler = self.betterPathHandler
connection.viabilityUpdateHandler = self.viabilityUpdateHandler
connection.pathUpdateHandler = self.pathChangedHandler(newPath:)
// Ok, state is ready. Let's go!
@ -230,6 +231,7 @@ extension StateManagedNWConnectionChannel {
self.connectPromise = promise
connection.stateUpdateHandler = self.stateUpdateHandler(newState:)
connection.betterPathUpdateHandler = self.betterPathHandler
connection.viabilityUpdateHandler = self.viabilityUpdateHandler
connection.pathUpdateHandler = self.pathChangedHandler(newPath:)
connection.start(queue: self.connectionQueue)
}
@ -433,6 +435,13 @@ extension StateManagedNWConnectionChannel {
self.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.BetterPathUnavailable())
}
}
/// Called by the underlying `NWConnection` when a path becomes viable or non-viable
///
/// Notifies the channel pipeline of the new viability.
private func viabilityUpdateHandler(_ isViable: Bool) {
self.pipeline.fireUserInboundEventTriggered(NIOTSNetworkEvents.ViabilityUpdate(isViable: isViable))
}
/// Called by the underlying `NWConnection` when this connection changes its network path.
///

View File

@ -557,5 +557,51 @@ class NIOTSEndToEndTests: XCTestCase {
print(error)
}
}
func testViabilityUpdate() throws {
final class ViabilityHandler: ChannelInboundHandler {
typealias InboundIn = ByteBuffer
private let testCompletePromise: EventLoopPromise<Bool>
init(testCompletePromise: EventLoopPromise<Bool>) {
self.testCompletePromise = testCompletePromise
}
func userInboundEventTriggered(context: ChannelHandlerContext, event: Any) {
if let update = event as? NIOTSNetworkEvents.ViabilityUpdate {
testCompletePromise.succeed(update.isViable)
}
}
}
let listener = try NIOTSListenerBootstrap(group: self.group)
.childChannelInitializer { channel in
return channel.eventLoop.makeSucceededVoidFuture()
}
.bind(host: "localhost", port: 0)
.wait()
let testCompletePromise = self.group.next().makePromise(of: Bool.self)
let connection = try NIOTSConnectionBootstrap(group: self.group)
.channelInitializer { channel in
channel.pipeline.addHandler(
ViabilityHandler(
testCompletePromise: testCompletePromise
)
)
}
.connect(to: listener.localAddress!)
.wait()
do {
let result = try testCompletePromise.futureResult.wait()
XCTAssertEqual(result, true)
} catch {
XCTFail("Threw unexpected error \(error)")
}
XCTAssertNoThrow(try connection.close().wait())
XCTAssertNoThrow(try listener.close().wait())
}
}
#endif