Skip to content

Commit c0d9a14

Browse files
authored
Allow retrieval of metadata from NWConnection (#163)
* Allow retrieval of metadata for a specific protocol from the underlying `NWConnection` * Address review comments * Address review comment * Add availability annotation to tests * Rename `NIOTSChannelIsNotATransportServicesChannel ` to `NIOTSChannelIsNotANIOTSConnectionChannel `
1 parent de5ea3d commit c0d9a14

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

Sources/NIOTransportServices/NIOTSConnectionChannel.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,4 +893,61 @@ extension NIOTSConnectionChannel {
893893
return SynchronousOptions(channel: self)
894894
}
895895
}
896+
897+
898+
public struct NIOTSConnectionNotInitialized: Error, Hashable {
899+
public init() {}
900+
}
901+
902+
public struct NIOTSChannelIsNotANIOTSConnectionChannel: Error, Hashable {
903+
public init() {}
904+
}
905+
906+
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
907+
extension NIOTSConnectionChannel {
908+
fileprivate func metadata(definition: NWProtocolDefinition) throws -> NWProtocolMetadata? {
909+
guard let nwConnection = self.nwConnection else {
910+
throw NIOTSConnectionNotInitialized()
911+
}
912+
return nwConnection.metadata(definition: definition)
913+
}
914+
}
915+
916+
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
917+
extension Channel {
918+
/// Retrieves the metadata for a specific protocol from the underlying ``NWConnection``
919+
/// - Throws: If `self` isn't a `NIOTS` channel with a `NWConnection` this method will throw
920+
/// ``NIOTSChannelIsNotATransportServicesChannel`` or ``NIOTSConnectionNotInitialized``.
921+
public func getMetadata(definition: NWProtocolDefinition) -> EventLoopFuture<NWProtocolMetadata?> {
922+
guard let channel = self as? NIOTSConnectionChannel else {
923+
return self.eventLoop.makeFailedFuture(NIOTSChannelIsNotANIOTSConnectionChannel())
924+
}
925+
if self.eventLoop.inEventLoop {
926+
return self.eventLoop.makeCompletedFuture {
927+
try channel.metadata(definition: definition)
928+
}
929+
} else {
930+
return self.eventLoop.submit {
931+
try channel.metadata(definition: definition)
932+
}
933+
}
934+
}
935+
936+
/// Retrieves the metadata for a specific protocol from the underlying ``NWConnection``
937+
/// - Precondition: Must be called on the `EventLoop` the `Channel` is running on.
938+
/// - Throws: If `self` isn't a `NIOTS` channel with a `NWConnection` this method will throw
939+
/// ``NIOTSChannelIsNotATransportServicesChannel`` or ``NIOTSConnectionNotInitialized``.
940+
public func getMetadataSync(
941+
definition: NWProtocolDefinition,
942+
file: StaticString = #fileID,
943+
line: UInt = #line
944+
) throws -> NWProtocolMetadata? {
945+
self.eventLoop.preconditionInEventLoop(file: file, line: line)
946+
guard let channel = self as? NIOTSConnectionChannel else {
947+
throw NIOTSChannelIsNotANIOTSConnectionChannel()
948+
}
949+
return try channel.metadata(definition: definition)
950+
}
951+
}
952+
896953
#endif

Tests/NIOTransportServicesTests/NIOTSBootstrapTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ final class NIOTSBootstrapTests: XCTestCase {
173173
XCTFail("can't connect to server1")
174174
return
175175
}
176+
XCTAssertNotNil(try client1.getMetadata(definition: NWProtocolTCP.definition).wait() as? NWProtocolTCP.Metadata)
176177
XCTAssertNoThrow(try client1.writeAndFlush(buffer).wait())
177178

178179
// The TLS connection won't actually succeed but it takes Network.framework a while to tell us, we don't
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftNIO open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the SwiftNIO project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#if canImport(Network)
16+
import Network
17+
import NIOCore
18+
import XCTest
19+
@testable import NIOTransportServices
20+
21+
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
22+
final class NIOTSChannelMetadataTests: XCTestCase {
23+
func testThrowsIfCalledOnWrongChannel() throws {
24+
let eventLoopGroup = NIOTSEventLoopGroup()
25+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
26+
let listenerBootsrap = NIOTSListenerBootstrap(group: eventLoopGroup)
27+
let listenerChannel = try listenerBootsrap.bind(host: "localhost", port: 0).wait()
28+
defer { XCTAssertNoThrow(try listenerChannel.close().wait()) }
29+
30+
XCTAssertThrowsError(try listenerChannel.getMetadata(definition: NWProtocolTLS.definition).wait()) { error in
31+
XCTAssertTrue(error is NIOTSChannelIsNotANIOTSConnectionChannel, "unexpected error \(error)")
32+
}
33+
try! listenerChannel.eventLoop.submit {
34+
XCTAssertThrowsError(try listenerChannel.getMetadataSync(definition: NWProtocolTLS.definition)) { error in
35+
XCTAssertTrue(error is NIOTSChannelIsNotANIOTSConnectionChannel, "unexpected error \(error)")
36+
}
37+
}.wait()
38+
39+
}
40+
func testThowsIfCalledOnANonInitializedChannel() {
41+
let eventLoopGroup = NIOTSEventLoopGroup()
42+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
43+
let channel = NIOTSConnectionChannel(eventLoop: eventLoopGroup.next() as! NIOTSEventLoop, tcpOptions: .init(), tlsOptions: .init())
44+
XCTAssertThrowsError(try channel.getMetadata(definition: NWProtocolTLS.definition).wait()) { error in
45+
XCTAssertTrue(error is NIOTSConnectionNotInitialized, "unexpected error \(error)")
46+
}
47+
try! channel.eventLoop.submit {
48+
XCTAssertThrowsError(try channel.getMetadataSync(definition: NWProtocolTLS.definition)) { error in
49+
XCTAssertTrue(error is NIOTSConnectionNotInitialized, "unexpected error \(error)")
50+
}
51+
}.wait()
52+
}
53+
}
54+
#endif

0 commit comments

Comments
 (0)