Side-port apple/swift-nio#597. (#41)
Motivation: We never brought across the fix to apple/swift-nio#597 into swift-nio-transport-services. This has caused some users a few hard-to-track-down surprises. We fixed this in the mainline by way of #40, but users running the old codebase probably want this fix too. Modifications: - Side-ported the fix from apple/swift-nio#597. - Back-ported the test from #40. Result: Users can set multiple socket options.
This commit is contained in:
parent
1c2269d04b
commit
553f2f73ed
|
|
@ -177,8 +177,27 @@ public final class NIOTSConnectionBootstrap {
|
|||
internal struct ChannelOptionStorage {
|
||||
private var storage: [(Any, (Any, (Channel) -> (Any, Any) -> EventLoopFuture<Void>))] = []
|
||||
|
||||
mutating func put<K: ChannelOption & Equatable>(key: K, value: K.OptionType) {
|
||||
return self.put(key: key, value: value, equalsFunc: ==)
|
||||
}
|
||||
|
||||
// HACK: this function should go for NIO 2.0, all ChannelOptions should be equatable
|
||||
mutating func put<K: ChannelOption>(key: K, value: K.OptionType) {
|
||||
if K.self == SocketOption.self {
|
||||
return self.put(key: key as! SocketOption, value: value as! SocketOptionValue) { lhs, rhs in
|
||||
switch (lhs, rhs) {
|
||||
case (.const(let lLevel, let lName), .const(let rLevel, let rName)):
|
||||
return lLevel == rLevel && lName == rName
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return self.put(key: key, value: value) { _, _ in true }
|
||||
}
|
||||
}
|
||||
|
||||
mutating func put<K: ChannelOption>(key: K,
|
||||
value newValue: K.OptionType) {
|
||||
value newValue: K.OptionType,
|
||||
equalsFunc: (K, K) -> Bool) {
|
||||
func applier(_ t: Channel) -> (Any, Any) -> EventLoopFuture<Void> {
|
||||
return { (x, y) in
|
||||
return t.setOption(option: x as! K, value: y as! K.OptionType)
|
||||
|
|
@ -187,7 +206,7 @@ internal struct ChannelOptionStorage {
|
|||
var hasSet = false
|
||||
self.storage = self.storage.map { typeAndValue in
|
||||
let (type, value) = typeAndValue
|
||||
if type is K {
|
||||
if type is K && equalsFunc(type as! K, key) {
|
||||
hasSet = true
|
||||
return (key, (newValue, applier))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -120,5 +120,27 @@ class NIOTSSocketOptionsOnChannelTests: XCTestCase {
|
|||
func testSO_KEEPALIVE() throws {
|
||||
try self.assertChannelOptionAfterCreation(option: SocketOption(level: SOL_SOCKET, name: SO_KEEPALIVE), initialValue: 0, testAlternativeValue: 1)
|
||||
}
|
||||
|
||||
func testMultipleSocketOptions() throws {
|
||||
let listener = try NIOTSListenerBootstrap(group: group)
|
||||
.serverChannelOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR), value: 1)
|
||||
.serverChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
|
||||
.bind(host: "127.0.0.1", port: 0).wait()
|
||||
defer {
|
||||
XCTAssertNoThrow(try listener.close().wait())
|
||||
}
|
||||
let connector = try NIOTSConnectionBootstrap(group: group)
|
||||
.channelOption(ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR), value: 1)
|
||||
.channelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
|
||||
.connect(to: listener.localAddress!).wait()
|
||||
defer {
|
||||
XCTAssertNoThrow(try connector.close().wait())
|
||||
}
|
||||
|
||||
XCTAssertNoThrow(XCTAssertEqual(1, try listener.getOption(option: ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR)).wait()))
|
||||
XCTAssertNoThrow(XCTAssertEqual(1, try listener.getOption(option: ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY)).wait()))
|
||||
XCTAssertNoThrow(XCTAssertEqual(1, try connector.getOption(option: ChannelOptions.socket(SOL_SOCKET, SO_REUSEADDR)).wait()))
|
||||
XCTAssertNoThrow(XCTAssertEqual(1, try connector.getOption(option: ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY)).wait()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue