-
Notifications
You must be signed in to change notification settings - Fork 649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow two distinct ChannelOptions of one type #597
Conversation
dc8e9d8
to
aa10523
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally LGTM... a few things
Sources/NIO/Bootstrap.swift
Outdated
public func serverChannelOption<T: ChannelOption>(_ option: T, value: T.OptionType) -> Self { | ||
serverChannelOptions.put(key: option, value: value) | ||
print(serverChannelOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove
Sources/NIO/Bootstrap.swift
Outdated
/// - value: The value for the option. | ||
public func serverChannelOption<T: ChannelOption & Equatable>(_ option: T, value: T.OptionType) -> Self { | ||
serverChannelOptions.put(key: option, value: value) | ||
print(serverChannelOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove
Sources/NIO/Bootstrap.swift
Outdated
@@ -672,11 +720,34 @@ public final class DatagramBootstrap { | |||
} | |||
} | |||
|
|||
fileprivate struct ChannelOptionStorage { | |||
internal struct ChannelOptionStorage { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment that its internal for testing only
} | ||
XCTAssertNoThrow(XCTAssertGreaterThan(try channel.getOption(option: ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), | ||
SO_REUSEADDR)).wait(), | ||
0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting looks really odd... maybe merge with previous line ?
0)) | ||
XCTAssertNoThrow(XCTAssertGreaterThan(try channel.getOption(option: ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), | ||
SO_DEBUG)).wait(), | ||
0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting looks really odd... maybe merge with previous line ?
Tests/NIOTests/ChannelTests.swift
Outdated
0)) | ||
XCTAssertNoThrow(XCTAssertGreaterThan(try server3.getOption(option: ChannelOptions.socket(IPPROTO_TCP, | ||
TCP_NODELAY)).wait(), | ||
0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting looks really odd... maybe merge with previous line ? (same comment for others)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@normanmaurer then the line would be too long. And in github you couldn't see any of the important bits as they were hidden off screen. Still want me to merge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use this formatting then ?:
let value = XCTAssertNoThrow(try server3.getOption(option: ChannelOptions.socket(IPPROTO_TCP,TCP_NODELAY)).wait())
XCTAssertGreaterThan(value, 0))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just put the shared code in a function actually
aa10523
to
bc3f576
Compare
Tests/NIOTests/ChannelTests.swift
Outdated
} | ||
XCTAssertNoThrow(XCTAssertGreaterThan(try server.getOption(option: ChannelOptions.socket(SOL_SOCKET, | ||
SO_REUSEADDR)).wait(), | ||
0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also do the same refactoring here ?
e1d77cf
to
51532c1
Compare
51532c1
to
4765aae
Compare
} | ||
|
||
// HACK: this function should go for NIO 2.0, all ChannelOptions should be equatable | ||
mutating func put<K: ChannelOption>(key: K, value: K.OptionType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remember to open an issue once we merge this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done #598
0244764
to
2938130
Compare
@@ -332,7 +332,10 @@ class BaseSocket: Selectable { | |||
/// - value: The value for the option. | |||
/// - throws: An `IOError` if the operation failed. | |||
final func setOption<T>(level: Int32, name: Int32, value: T) throws { | |||
try withUnsafeFileDescriptor { fd in | |||
if level == SocketOptionValue(IPPROTO_TCP) && name == TCP_NODELAY && (try? self.localAddress().protocolFamily) == Optional<Int32>.some(Int32(Posix.AF_UNIX)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why we need to ignore these ? Maybe adding a comment would be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@normanmaurer done that, also #599
Motivation: Quite embarrasingly, we previously would only store one `ChannelOption` per `ChannelOption` type. Most channel option types are distinct and that's probably why it took so long to find this issue. Thanks @pushkarnk for reporting. Unfortunately though, the most important `ChannelOption` is `.socket` which crucially also holds a level and a name. That means if you set two `ChannelOptions.socket` options with distinct name/level, one would still override the other. Example: .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEPORT), value: 1) .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1) would only actually set the latter. Modifications: - made all common `ChannelOption` types equatable (for 2.0 this will be a protocol requirement) - deprecated non-Equatable `ChannelOption` types - zero out buffer before calling getsockopt as Linux doesn't do that Result: you can now set two distinct `ChannelOptions` for one type
2938130
to
19966aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Motivation: Quite embarrasingly, we previously would only store one `ChannelOption` per `ChannelOption` type. Most channel option types are distinct and that's probably why it took so long to find this issue. Thanks @pushkarnk for reporting. Unfortunately though, the most important `ChannelOption` is `.socket` which crucially also holds a level and a name. That means if you set two `ChannelOptions.socket` options with distinct name/level, one would still override the other. Example: .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEPORT), value: 1) .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1) would only actually set the latter. Modifications: - made all common `ChannelOption` types equatable (for 2.0 this will be a protocol requirement) - deprecated non-Equatable `ChannelOption` types - zero out buffer before calling getsockopt as Linux doesn't do that Result: you can now set two distinct `ChannelOptions` for one type Motivation: Explain here the context, and why you're making that change. What is the problem you're trying to solve. Modifications: Describe the modifications you've done. Result: After your change, what will change.
Motivation: While we fixed a bug in SwiftNIO about setting multiple options of the same type in apple/swift-nio#597, we never brought a fix for that issue forward. We did aim to resolve this in SwiftNIO 2.0 by providing ChannelOptions.Storage, but unfortunately we forgot to make the initializer for that type public (see apple/swift-nio#988). While SwiftNIO core has to get its ducks in a row, users of this library should still be able to set more than one socket option, in my humble opinion. Modifications: - Ported over ChannelOptions.Storage until apple/swift-nio#988 is fixed. - Transitioned our code to use it. - Tested it works. Result: Users can set multiple channel options.
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 apple#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 apple#40. Result: Users can set multiple socket options.
Motivation: While we fixed a bug in SwiftNIO about setting multiple options of the same type in apple/swift-nio#597, we never brought a fix for that issue forward. We did aim to resolve this in SwiftNIO 2.0 by providing ChannelOptions.Storage, but unfortunately we forgot to make the initializer for that type public (see apple/swift-nio#988). While SwiftNIO core has to get its ducks in a row, users of this library should still be able to set more than one socket option, in my humble opinion. Modifications: - Ported over ChannelOptions.Storage until apple/swift-nio#988 is fixed. - Transitioned our code to use it. - Tested it works. Result: Users can set multiple channel options.
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.
Motivation:
Quite embarrasingly, we previously would only store one
ChannelOption
per
ChannelOption
type. Most channel option types are distinct andthat's probably why it took so long to find this issue. Thanks
@pushkarnk for reporting. Unfortunately though, the most important
ChannelOption
is.socket
which crucially also holds a level and aname. That means if you set two
ChannelOptions.socket
options withdistinct name/level, one would still override the other.
Example:
would only actually set the latter.
Modifications:
ChannelOption
types equatable (for 2.0 this willbe a protocol requirement)
ChannelOption
typesResult:
you can now set two distinct
ChannelOptions
for one type