Compare commits
7 Commits
5d809b1bc0
...
ad698fd52a
| Author | SHA1 | Date |
|---|---|---|
|
|
ad698fd52a | |
|
|
9eb2ebde13 | |
|
|
3958806697 | |
|
|
1d43eb3246 | |
|
|
73c30da46e | |
|
|
a5f1273fea | |
|
|
d1825d918b |
|
|
@ -27,7 +27,7 @@ let strictConcurrencySettings: [SwiftSetting] = {
|
|||
if strictConcurrencyDevelopment {
|
||||
// -warnings-as-errors here is a workaround so that IDE-based development can
|
||||
// get tripped up on -require-explicit-sendable.
|
||||
initialSettings.append(.unsafeFlags(["-require-explicit-sendable", "-warnings-as-errors"]))
|
||||
initialSettings.append(.unsafeFlags(["-Xfrontend", "-require-explicit-sendable", "-warnings-as-errors"]))
|
||||
}
|
||||
|
||||
return initialSettings
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public final class NIOTSDatagramBootstrap {
|
|||
private var qos: DispatchQoS?
|
||||
private var udpOptions: NWProtocolUDP.Options = .init()
|
||||
private var tlsOptions: NWProtocolTLS.Options?
|
||||
private var nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
private var nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
/// Create a `NIOTSDatagramConnectionBootstrap` on the `EventLoopGroup` `group`.
|
||||
///
|
||||
|
|
@ -136,7 +136,7 @@ public final class NIOTSDatagramBootstrap {
|
|||
|
||||
/// Customise the `NWParameters` to be used when creating the connection.
|
||||
public func configureNWParameters(
|
||||
_ configurator: @Sendable @escaping (inout NWParameters) -> Void
|
||||
_ configurator: @Sendable @escaping (NWParameters) -> Void
|
||||
) -> Self {
|
||||
self.nwParametersConfigurator = configurator
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -140,11 +140,11 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
|
|||
internal var allowLocalEndpointReuse = false
|
||||
internal var multipathServiceType: NWParameters.MultipathServiceType = .disabled
|
||||
|
||||
private let nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
private let nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
var parameters: NWParameters {
|
||||
var parameters = NWParameters(dtls: self.tlsOptions, udp: self.udpOptions)
|
||||
self.nwParametersConfigurator?(¶meters)
|
||||
let parameters = NWParameters(dtls: self.tlsOptions, udp: self.udpOptions)
|
||||
self.nwParametersConfigurator?(parameters)
|
||||
return parameters
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
|
|||
maximumReceiveLength: Int = 8192,
|
||||
udpOptions: NWProtocolUDP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.tsEventLoop = eventLoop
|
||||
self.closePromise = eventLoop.makePromise()
|
||||
|
|
@ -213,7 +213,7 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
|
|||
maximumReceiveLength: Int = 8192,
|
||||
udpOptions: NWProtocolUDP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
eventLoop: eventLoop,
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public final class NIOTSDatagramListenerBootstrap {
|
|||
private var udpOptions: NWProtocolUDP.Options = .init()
|
||||
private var tlsOptions: NWProtocolTLS.Options?
|
||||
private var bindTimeout: TimeAmount?
|
||||
private var nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
private var nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
/// Create a ``NIOTSListenerBootstrap`` for the `EventLoopGroup` `group`.
|
||||
///
|
||||
|
|
@ -239,7 +239,7 @@ public final class NIOTSDatagramListenerBootstrap {
|
|||
|
||||
/// Customise the `NWParameters` to be used when creating the connection.
|
||||
public func configureNWParameters(
|
||||
_ configurator: @Sendable @escaping (inout NWParameters) -> Void
|
||||
_ configurator: @Sendable @escaping (NWParameters) -> Void
|
||||
) -> Self {
|
||||
self.nwParametersConfigurator = configurator
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -81,12 +81,12 @@ internal final class NIOTSDatagramListenerChannel: StateManagedListenerChannel<N
|
|||
qos: DispatchQoS? = nil,
|
||||
udpOptions: NWProtocolUDP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?,
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?,
|
||||
childLoopGroup: EventLoopGroup,
|
||||
childChannelQoS: DispatchQoS?,
|
||||
childUDPOptions: NWProtocolUDP.Options,
|
||||
childTLSOptions: NWProtocolTLS.Options?,
|
||||
childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
eventLoop: eventLoop,
|
||||
|
|
@ -108,12 +108,12 @@ internal final class NIOTSDatagramListenerChannel: StateManagedListenerChannel<N
|
|||
qos: DispatchQoS? = nil,
|
||||
udpOptions: NWProtocolUDP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?,
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?,
|
||||
childLoopGroup: EventLoopGroup,
|
||||
childChannelQoS: DispatchQoS?,
|
||||
childUDPOptions: NWProtocolUDP.Options,
|
||||
childTLSOptions: NWProtocolTLS.Options?,
|
||||
childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
wrapping: listener,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public final class NIOTSConnectionBootstrap {
|
|||
private var tcpOptions: NWProtocolTCP.Options = .init()
|
||||
private var tlsOptions: NWProtocolTLS.Options?
|
||||
private var protocolHandlers: (@Sendable () -> [ChannelHandler])? = nil
|
||||
private var nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
private var nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
/// Create a `NIOTSConnectionBootstrap` on the `EventLoopGroup` `group`.
|
||||
///
|
||||
|
|
@ -168,7 +168,7 @@ public final class NIOTSConnectionBootstrap {
|
|||
|
||||
/// Customise the `NWParameters` to be used when creating the connection.
|
||||
public func configureNWParameters(
|
||||
_ configurator: @Sendable @escaping (inout NWParameters) -> Void
|
||||
_ configurator: @Sendable @escaping (NWParameters) -> Void
|
||||
) -> Self {
|
||||
self.nwParametersConfigurator = configurator
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -164,11 +164,11 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
|
|||
/// An `EventLoopPromise` that will be succeeded or failed when a connection attempt succeeds or fails.
|
||||
internal var connectPromise: EventLoopPromise<Void>?
|
||||
|
||||
private let nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
private let nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
internal var parameters: NWParameters {
|
||||
var parameters = NWParameters(tls: self.tlsOptions, tcp: self.tcpOptions)
|
||||
self.nwParametersConfigurator?(¶meters)
|
||||
let parameters = NWParameters(tls: self.tlsOptions, tcp: self.tcpOptions)
|
||||
self.nwParametersConfigurator?(parameters)
|
||||
return parameters
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +247,7 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
|
|||
maximumReceiveLength: Int = 8192,
|
||||
tcpOptions: NWProtocolTCP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.tsEventLoop = eventLoop
|
||||
self.closePromise = eventLoop.makePromise()
|
||||
|
|
@ -273,7 +273,7 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
|
|||
maximumReceiveLength: Int = 8192,
|
||||
tcpOptions: NWProtocolTCP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
eventLoop: eventLoop,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import NIOCore
|
|||
public protocol NIOTSError: Error, Equatable {}
|
||||
|
||||
@available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *)
|
||||
public enum NIOTSErrors {
|
||||
public enum NIOTSErrors: Sendable {
|
||||
/// ``InvalidChannelStateTransition`` is thrown when a channel has been asked to do something
|
||||
/// that is incompatible with its current channel state: e.g. attempting to register an
|
||||
/// already registered channel.
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public final class NIOTSListenerBootstrap {
|
|||
private var tcpOptions: NWProtocolTCP.Options = .init()
|
||||
private var tlsOptions: NWProtocolTLS.Options?
|
||||
private var bindTimeout: TimeAmount?
|
||||
private var nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
private var nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
/// Create a ``NIOTSListenerBootstrap`` for the `EventLoopGroup` `group`.
|
||||
///
|
||||
|
|
@ -240,6 +240,14 @@ public final class NIOTSListenerBootstrap {
|
|||
return self
|
||||
}
|
||||
|
||||
/// Customise the `NWParameters` to be used when creating the connection.
|
||||
public func configureNWParameters(
|
||||
_ configurator: @Sendable @escaping (NWParameters) -> Void
|
||||
) -> Self {
|
||||
self.nwParametersConfigurator = configurator
|
||||
return self
|
||||
}
|
||||
|
||||
/// Specifies a type of Multipath service to use for this listener, instead of the default
|
||||
/// service type for the event loop.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -81,12 +81,12 @@ internal final class NIOTSListenerChannel: StateManagedListenerChannel<NIOTSConn
|
|||
qos: DispatchQoS? = nil,
|
||||
tcpOptions: NWProtocolTCP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?,
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?,
|
||||
childLoopGroup: EventLoopGroup,
|
||||
childChannelQoS: DispatchQoS?,
|
||||
childTCPOptions: NWProtocolTCP.Options,
|
||||
childTLSOptions: NWProtocolTLS.Options?,
|
||||
childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
eventLoop: eventLoop,
|
||||
|
|
@ -108,12 +108,12 @@ internal final class NIOTSListenerChannel: StateManagedListenerChannel<NIOTSConn
|
|||
qos: DispatchQoS? = nil,
|
||||
tcpOptions: NWProtocolTCP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?,
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?,
|
||||
childLoopGroup: EventLoopGroup,
|
||||
childChannelQoS: DispatchQoS?,
|
||||
childTCPOptions: NWProtocolTCP.Options,
|
||||
childTLSOptions: NWProtocolTLS.Options?,
|
||||
childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
wrapping: listener,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ internal class StateManagedListenerChannel<ChildChannel: StateManagedChannel>: S
|
|||
/// The TLS options for this listener.
|
||||
internal let tlsOptions: NWProtocolTLS.Options?
|
||||
|
||||
internal var nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
internal var nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
/// The `DispatchQueue` that socket events for this connection will be dispatched onto.
|
||||
internal let connectionQueue: DispatchQueue
|
||||
|
|
@ -115,7 +115,7 @@ internal class StateManagedListenerChannel<ChildChannel: StateManagedChannel>: S
|
|||
/// The TLS options to use for child channels.
|
||||
internal let childTLSOptions: NWProtocolTLS.Options?
|
||||
|
||||
internal var childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
internal var childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
|
||||
/// The cache of the local and remote socket addresses. Must be accessed using _addressCacheLock.
|
||||
internal var addressCache = AddressCache(local: nil, remote: nil)
|
||||
|
|
@ -134,22 +134,24 @@ internal class StateManagedListenerChannel<ChildChannel: StateManagedChannel>: S
|
|||
qos: DispatchQoS? = nil,
|
||||
protocolOptions: ProtocolOptions,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?,
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?,
|
||||
childLoopGroup: EventLoopGroup,
|
||||
childChannelQoS: DispatchQoS?,
|
||||
childProtocolOptions: ProtocolOptions,
|
||||
childTLSOptions: NWProtocolTLS.Options?,
|
||||
childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.tsEventLoop = eventLoop
|
||||
self.closePromise = eventLoop.makePromise()
|
||||
self.connectionQueue = eventLoop.channelQueue(label: "nio.transportservices.listenerchannel", qos: qos)
|
||||
self.protocolOptions = protocolOptions
|
||||
self.tlsOptions = tlsOptions
|
||||
self.nwParametersConfigurator = nwParametersConfigurator
|
||||
self.childLoopGroup = childLoopGroup
|
||||
self.childChannelQoS = childChannelQoS
|
||||
self.childProtocolOptions = childProtocolOptions
|
||||
self.childTLSOptions = childTLSOptions
|
||||
self.childNWParametersConfigurator = childNWParametersConfigurator
|
||||
|
||||
// Must come last, as it requires self to be completely initialized.
|
||||
self._pipeline = ChannelPipeline(channel: self)
|
||||
|
|
@ -161,12 +163,12 @@ internal class StateManagedListenerChannel<ChildChannel: StateManagedChannel>: S
|
|||
qos: DispatchQoS? = nil,
|
||||
protocolOptions: ProtocolOptions,
|
||||
tlsOptions: NWProtocolTLS.Options?,
|
||||
nwParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?,
|
||||
nwParametersConfigurator: (@Sendable (NWParameters) -> Void)?,
|
||||
childLoopGroup: EventLoopGroup,
|
||||
childChannelQoS: DispatchQoS?,
|
||||
childProtocolOptions: ProtocolOptions,
|
||||
childTLSOptions: NWProtocolTLS.Options?,
|
||||
childNWParametersConfigurator: (@Sendable (inout NWParameters) -> Void)?
|
||||
childNWParametersConfigurator: (@Sendable (NWParameters) -> Void)?
|
||||
) {
|
||||
self.init(
|
||||
eventLoop: eventLoop,
|
||||
|
|
@ -408,6 +410,8 @@ extension StateManagedListenerChannel {
|
|||
|
||||
parameters.multipathServiceType = self.multipathServiceType
|
||||
|
||||
self.nwParametersConfigurator?(parameters)
|
||||
|
||||
let listener: NWListener
|
||||
do {
|
||||
listener = try NWListener(using: parameters)
|
||||
|
|
|
|||
|
|
@ -371,6 +371,36 @@ final class NIOTSBootstrapTests: XCTestCase {
|
|||
XCTAssertEqual(try listenerChannel.getOption(NIOTSChannelOptions.multipathServiceType).wait(), .handover)
|
||||
XCTAssertEqual(try connectionChannel.getOption(NIOTSChannelOptions.multipathServiceType).wait(), .handover)
|
||||
}
|
||||
|
||||
func testNWParametersConfigurator() throws {
|
||||
let group = NIOTSEventLoopGroup()
|
||||
defer {
|
||||
try! group.syncShutdownGracefully()
|
||||
}
|
||||
|
||||
let configuratorListenerCounter = NIOLockedValueBox(0)
|
||||
let configuratorConnectionCounter = NIOLockedValueBox(0)
|
||||
|
||||
let listenerChannel = try NIOTSListenerBootstrap(group: group)
|
||||
.configureNWParameters { _ in
|
||||
configuratorListenerCounter.withLockedValue { $0 += 1 }
|
||||
}
|
||||
.bind(host: "localhost", port: 0)
|
||||
.wait()
|
||||
|
||||
let connectionChannel: Channel = try NIOTSConnectionBootstrap(group: group)
|
||||
.configureNWParameters { _ in
|
||||
configuratorConnectionCounter.withLockedValue { $0 += 1 }
|
||||
}
|
||||
.connect(to: listenerChannel.localAddress!)
|
||||
.wait()
|
||||
|
||||
try listenerChannel.close().wait()
|
||||
try connectionChannel.close().wait()
|
||||
|
||||
XCTAssertEqual(1, configuratorListenerCounter.withLockedValue { $0 })
|
||||
XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 })
|
||||
}
|
||||
}
|
||||
|
||||
extension Channel {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import Network
|
|||
import NIOCore
|
||||
import NIOTransportServices
|
||||
import Foundation
|
||||
import NIOConcurrencyHelpers
|
||||
|
||||
extension Channel {
|
||||
func wait<T: Sendable>(for type: T.Type, count: Int) throws -> [T] {
|
||||
|
|
@ -232,6 +233,36 @@ final class NIOTSDatagramConnectionChannelTests: XCTestCase {
|
|||
XCTAssertNoThrow(try connection.close().wait())
|
||||
}
|
||||
|
||||
func testNWParametersConfigurator() throws {
|
||||
let group = NIOTSEventLoopGroup()
|
||||
defer {
|
||||
try! group.syncShutdownGracefully()
|
||||
}
|
||||
|
||||
let configuratorListenerCounter = NIOLockedValueBox(0)
|
||||
let configuratorConnectionCounter = NIOLockedValueBox(0)
|
||||
|
||||
let listenerChannel = try NIOTSDatagramListenerBootstrap(group: group)
|
||||
.configureNWParameters { _ in
|
||||
configuratorListenerCounter.withLockedValue { $0 += 1 }
|
||||
}
|
||||
.bind(host: "localhost", port: 0)
|
||||
.wait()
|
||||
|
||||
let connectionChannel: Channel = try NIOTSDatagramBootstrap(group: group)
|
||||
.configureNWParameters { _ in
|
||||
configuratorConnectionCounter.withLockedValue { $0 += 1 }
|
||||
}
|
||||
.connect(to: listenerChannel.localAddress!)
|
||||
.wait()
|
||||
|
||||
try listenerChannel.close().wait()
|
||||
try connectionChannel.close().wait()
|
||||
|
||||
XCTAssertEqual(1, configuratorListenerCounter.withLockedValue { $0 })
|
||||
XCTAssertEqual(1, configuratorConnectionCounter.withLockedValue { $0 })
|
||||
}
|
||||
|
||||
func testCanExtractTheConnection() throws {
|
||||
guard #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) else {
|
||||
throw XCTSkip("Option not available")
|
||||
|
|
|
|||
Loading…
Reference in New Issue