Provide configurability for receiving connection data (#212)
Motivation: Users are stuck with the hardcoded parameters for receiving data from a connection. Modifications: - Add new options to `NIOTSChannelOptions` for configuring how to receive data from a connection. Result: Users can configure how they receive data from a connection.
This commit is contained in:
parent
fc398db673
commit
bbd5e63cf9
|
|
@ -68,6 +68,12 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
|
|||
/// after the initial connection attempt has been made.
|
||||
internal var connection: NWConnection?
|
||||
|
||||
/// The minimum length of data to receive from this connection, until the content is complete.
|
||||
internal var minimumIncompleteReceiveLength: Int
|
||||
|
||||
/// The maximum length of data to receive from this connection in a single completion.
|
||||
internal var maximumReceiveLength: Int
|
||||
|
||||
/// The `DispatchQueue` that socket events for this connection will be dispatched onto.
|
||||
internal let connectionQueue: DispatchQueue
|
||||
|
||||
|
|
@ -169,11 +175,15 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
|
|||
internal init(eventLoop: NIOTSEventLoop,
|
||||
parent: Channel? = nil,
|
||||
qos: DispatchQoS? = nil,
|
||||
minimumIncompleteReceiveLength: Int = 1,
|
||||
maximumReceiveLength: Int = 8192,
|
||||
udpOptions: NWProtocolUDP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?) {
|
||||
self.tsEventLoop = eventLoop
|
||||
self.closePromise = eventLoop.makePromise()
|
||||
self.parent = parent
|
||||
self.minimumIncompleteReceiveLength = minimumIncompleteReceiveLength
|
||||
self.maximumReceiveLength = maximumReceiveLength
|
||||
self.connectionQueue = eventLoop.channelQueue(label: "nio.nioTransportServices.connectionchannel", qos: qos)
|
||||
self.udpOptions = udpOptions
|
||||
self.tlsOptions = tlsOptions
|
||||
|
|
@ -187,11 +197,15 @@ internal final class NIOTSDatagramChannel: StateManagedNWConnectionChannel {
|
|||
on eventLoop: NIOTSEventLoop,
|
||||
parent: Channel,
|
||||
qos: DispatchQoS? = nil,
|
||||
minimumIncompleteReceiveLength: Int = 1,
|
||||
maximumReceiveLength: Int = 8192,
|
||||
udpOptions: NWProtocolUDP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?) {
|
||||
self.init(eventLoop: eventLoop,
|
||||
parent: parent,
|
||||
qos: qos,
|
||||
minimumIncompleteReceiveLength: minimumIncompleteReceiveLength,
|
||||
maximumReceiveLength: maximumReceiveLength,
|
||||
udpOptions: udpOptions,
|
||||
tlsOptions: tlsOptions)
|
||||
self.connection = connection
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ public struct NIOTSChannelOptions {
|
|||
/// See: ``Types/NIOTSListenerOption``.
|
||||
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
|
||||
public static let listener = NIOTSChannelOptions.Types.NIOTSListenerOption()
|
||||
|
||||
/// See: ``Types/NIOTSMinimumIncompleteReceiveLengthOption``.
|
||||
public static let minimumIncompleteReceiveLength = NIOTSChannelOptions.Types.NIOTSMinimumIncompleteReceiveLengthOption()
|
||||
|
||||
/// See: ``Types/NIOTSMaximumReceiveLengthOption``.
|
||||
public static let maximumReceiveLength = NIOTSChannelOptions.Types.NIOTSMaximumReceiveLengthOption()
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -179,6 +185,26 @@ extension NIOTSChannelOptions {
|
|||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
/// ``NIOTSMinimumIncompleteReceiveLengthOption`` controls the minimum length to receive from a given
|
||||
/// `NWConnection`, until the content is complete.
|
||||
///
|
||||
/// This option is only valid with a `Channel` backed by an `NWConnection`.
|
||||
public struct NIOTSMinimumIncompleteReceiveLengthOption: ChannelOption, Equatable {
|
||||
public typealias Value = Int
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
/// ``NIOTSMaximumReceiveLengthOption`` controls the maximum length to receive from a given
|
||||
/// `NWConnection` in a single completion.
|
||||
///
|
||||
/// This option is only valid with a `Channel` backed by an `NWConnection`.
|
||||
public struct NIOTSMaximumReceiveLengthOption: ChannelOption, Equatable {
|
||||
public typealias Value = Int
|
||||
|
||||
public init() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,12 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
|
|||
/// after the initial connection attempt has been made.
|
||||
internal var connection: NWConnection?
|
||||
|
||||
/// The minimum length of data to receive from this connection, until the content is complete.
|
||||
internal var minimumIncompleteReceiveLength: Int
|
||||
|
||||
/// The maximum length of data to receive from this connection in a single completion.
|
||||
internal var maximumReceiveLength: Int
|
||||
|
||||
/// The `DispatchQueue` that socket events for this connection will be dispatched onto.
|
||||
internal let connectionQueue: DispatchQueue
|
||||
|
||||
|
|
@ -230,11 +236,15 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
|
|||
internal init(eventLoop: NIOTSEventLoop,
|
||||
parent: Channel? = nil,
|
||||
qos: DispatchQoS? = nil,
|
||||
minimumIncompleteReceiveLength: Int = 1,
|
||||
maximumReceiveLength: Int = 8192,
|
||||
tcpOptions: NWProtocolTCP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?) {
|
||||
self.tsEventLoop = eventLoop
|
||||
self.closePromise = eventLoop.makePromise()
|
||||
self.parent = parent
|
||||
self.minimumIncompleteReceiveLength = minimumIncompleteReceiveLength
|
||||
self.maximumReceiveLength = maximumReceiveLength
|
||||
self.connectionQueue = eventLoop.channelQueue(label: "nio.nioTransportServices.connectionchannel", qos: qos)
|
||||
self.tcpOptions = tcpOptions
|
||||
self.tlsOptions = tlsOptions
|
||||
|
|
@ -248,11 +258,15 @@ internal final class NIOTSConnectionChannel: StateManagedNWConnectionChannel {
|
|||
on eventLoop: NIOTSEventLoop,
|
||||
parent: Channel? = nil,
|
||||
qos: DispatchQoS? = nil,
|
||||
minimumIncompleteReceiveLength: Int = 1,
|
||||
maximumReceiveLength: Int = 8192,
|
||||
tcpOptions: NWProtocolTCP.Options,
|
||||
tlsOptions: NWProtocolTLS.Options?) {
|
||||
self.init(eventLoop: eventLoop,
|
||||
parent: parent,
|
||||
qos: qos,
|
||||
minimumIncompleteReceiveLength: minimumIncompleteReceiveLength,
|
||||
maximumReceiveLength: maximumReceiveLength,
|
||||
tcpOptions: tcpOptions,
|
||||
tlsOptions: tlsOptions)
|
||||
self.connection = connection
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ internal protocol StateManagedNWConnectionChannel: StateManagedChannel where Act
|
|||
|
||||
var connection: NWConnection? { get set }
|
||||
|
||||
var minimumIncompleteReceiveLength: Int { get set }
|
||||
|
||||
var maximumReceiveLength: Int { get set }
|
||||
|
||||
var connectionQueue: DispatchQueue { get }
|
||||
|
||||
var connectPromise: EventLoopPromise<Void>? { get set }
|
||||
|
|
@ -249,9 +253,13 @@ extension StateManagedNWConnectionChannel {
|
|||
preconditionFailure("Connection should not be nil")
|
||||
}
|
||||
|
||||
// TODO: Can we do something sensible with these numbers?
|
||||
self.outstandingRead = true
|
||||
conn.receive(minimumIncompleteLength: 1, maximumLength: 8192, completion: self.dataReceivedHandler(content:context:isComplete:error:))
|
||||
|
||||
conn.receive(
|
||||
minimumIncompleteLength: self.minimumIncompleteReceiveLength,
|
||||
maximumLength: self.maximumReceiveLength,
|
||||
completion: self.dataReceivedHandler(content:context:isComplete:error:)
|
||||
)
|
||||
}
|
||||
|
||||
public func doClose0(error: Error) {
|
||||
|
|
@ -554,6 +562,10 @@ extension StateManagedNWConnectionChannel {
|
|||
self.options.supportRemoteHalfClosure = value as! Bool
|
||||
case is NIOTSChannelOptions.Types.NIOTSAllowLocalEndpointReuse:
|
||||
self.allowLocalEndpointReuse = value as! NIOTSChannelOptions.Types.NIOTSAllowLocalEndpointReuse.Value
|
||||
case is NIOTSChannelOptions.Types.NIOTSMinimumIncompleteReceiveLengthOption:
|
||||
self.minimumIncompleteReceiveLength = value as! NIOTSChannelOptions.Types.NIOTSMinimumIncompleteReceiveLengthOption.Value
|
||||
case is NIOTSChannelOptions.Types.NIOTSMaximumReceiveLengthOption:
|
||||
self.maximumReceiveLength = value as! NIOTSChannelOptions.Types.NIOTSMaximumReceiveLengthOption.Value
|
||||
default:
|
||||
try self.setChannelSpecificOption0(option: option, value: value)
|
||||
}
|
||||
|
|
@ -610,6 +622,10 @@ extension StateManagedNWConnectionChannel {
|
|||
throw NIOTSErrors.NoCurrentConnection()
|
||||
}
|
||||
return connection.metadata(definition: optionValue.definition) as! Option.Value
|
||||
case is NIOTSChannelOptions.Types.NIOTSMinimumIncompleteReceiveLengthOption:
|
||||
return self.minimumIncompleteReceiveLength as! Option.Value
|
||||
case is NIOTSChannelOptions.Types.NIOTSMaximumReceiveLengthOption:
|
||||
return self.maximumReceiveLength as! Option.Value
|
||||
default:
|
||||
// watchOS 6.0 availability is covered by the @available on this extension.
|
||||
if #available(OSX 10.15, iOS 13.0, tvOS 13.0, *) {
|
||||
|
|
|
|||
|
|
@ -139,5 +139,45 @@ class NIOTSChannelOptionsTests: XCTestCase {
|
|||
XCTAssertEqual(listenerValue, .handover)
|
||||
XCTAssertEqual(connectionValue, .interactive)
|
||||
}
|
||||
|
||||
func testMinimumIncompleteReceiveLength() throws {
|
||||
let listener = try NIOTSListenerBootstrap(group: self.group)
|
||||
.bind(host: "localhost", port: 0).wait()
|
||||
defer {
|
||||
XCTAssertNoThrow(try listener.close().wait())
|
||||
}
|
||||
|
||||
let connection = try NIOTSConnectionBootstrap(group: self.group)
|
||||
.channelOption(NIOTSChannelOptions.minimumIncompleteReceiveLength, value: 1)
|
||||
.connect(to: listener.localAddress!)
|
||||
.wait()
|
||||
defer {
|
||||
XCTAssertNoThrow(try connection.close().wait())
|
||||
}
|
||||
|
||||
let connectionValue = try assertNoThrowWithValue(connection.getOption(NIOTSChannelOptions.minimumIncompleteReceiveLength).wait())
|
||||
|
||||
XCTAssertEqual(connectionValue, 1)
|
||||
}
|
||||
|
||||
func testMaximumReceiveLength() throws {
|
||||
let listener = try NIOTSListenerBootstrap(group: self.group)
|
||||
.bind(host: "localhost", port: 0).wait()
|
||||
defer {
|
||||
XCTAssertNoThrow(try listener.close().wait())
|
||||
}
|
||||
|
||||
let connection = try NIOTSConnectionBootstrap(group: self.group)
|
||||
.channelOption(NIOTSChannelOptions.maximumReceiveLength, value: 8192)
|
||||
.connect(to: listener.localAddress!)
|
||||
.wait()
|
||||
defer {
|
||||
XCTAssertNoThrow(try connection.close().wait())
|
||||
}
|
||||
|
||||
let connectionValue = try assertNoThrowWithValue(connection.getOption(NIOTSChannelOptions.maximumReceiveLength).wait())
|
||||
|
||||
XCTAssertEqual(connectionValue, 8192)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue