diff --git a/Sources/NIOCore/SocketOptionProvider.swift b/Sources/NIOCore/SocketOptionProvider.swift index 5c6e998fd9..d0592d0f53 100644 --- a/Sources/NIOCore/SocketOptionProvider.swift +++ b/Sources/NIOCore/SocketOptionProvider.swift @@ -182,6 +182,12 @@ public typealias NIOLinger = linger // around. As a result, if you change one, you should probably change them all. // // You are welcome to add more helper methods here, but each helper method you add must be tested. +// +// Please note that to work around a Swift compiler issue regarding lookup of the Sendability of +// libc types across modules, the actual calls to `unsafeSetSocketOption` and `unsafeGetSocketOption` +// _must_ be made inside non-`public` non-`@inlinable` methods. Otherwise we'll produce crashes +// in release mode. NIO's integration tests are a good canary for this: if you call your method +// from an alloc counter test in the integration tests, it'll crash if you messed it up. extension SocketOptionProvider { /// Sets the socket option SO_LINGER to `value`. /// @@ -190,6 +196,176 @@ extension SocketOptionProvider { /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. public func setSoLinger(_ value: linger) -> EventLoopFuture { + self._setSoLinger(value) + } + + /// Gets the value of the socket option SO_LINGER. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getSoLinger() -> EventLoopFuture { + self._getSoLinger() + } + + /// Sets the socket option IP_MULTICAST_IF to `value`. + /// + /// - Parameters: + /// - value: The value to set IP_MULTICAST_IF to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + public func setIPMulticastIF(_ value: in_addr) -> EventLoopFuture { + self._setIPMulticastIF(value) + } + + /// Gets the value of the socket option IP_MULTICAST_IF. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getIPMulticastIF() -> EventLoopFuture { + self._getIPMulticastIF() + } + + /// Sets the socket option IP_MULTICAST_TTL to `value`. + /// + /// - Parameters: + /// - value: The value to set IP_MULTICAST_TTL to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + public func setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture { + self._setIPMulticastTTL(value) + } + + /// Gets the value of the socket option IP_MULTICAST_TTL. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getIPMulticastTTL() -> EventLoopFuture { + self._getIPMulticastTTL() + } + + /// Sets the socket option IP_MULTICAST_LOOP to `value`. + /// + /// - Parameters: + /// - value: The value to set IP_MULTICAST_LOOP to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + public func setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture { + self._setIPMulticastLoop(value) + } + + /// Gets the value of the socket option IP_MULTICAST_LOOP. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getIPMulticastLoop() -> EventLoopFuture { + self._getIPMulticastLoop() + } + + /// Sets the socket option IPV6_MULTICAST_IF to `value`. + /// + /// - Parameters: + /// - value: The value to set IPV6_MULTICAST_IF to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + public func setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture { + self._setIPv6MulticastIF(value) + } + + /// Gets the value of the socket option IPV6_MULTICAST_IF. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getIPv6MulticastIF() -> EventLoopFuture { + self._getIPv6MulticastIF() + } + + /// Sets the socket option IPV6_MULTICAST_HOPS to `value`. + /// + /// - Parameters: + /// - value: The value to set IPV6_MULTICAST_HOPS to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + public func setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture { + self._setIPv6MulticastHops(value) + } + + /// Gets the value of the socket option IPV6_MULTICAST_HOPS. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getIPv6MulticastHops() -> EventLoopFuture { + self._getIPv6MulticastHops() + } + + /// Sets the socket option IPV6_MULTICAST_LOOP to `value`. + /// + /// - Parameters: + /// - value: The value to set IPV6_MULTICAST_LOOP to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + public func setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture { + self._setIPv6MulticastLoop(value) + } + + /// Gets the value of the socket option IPV6_MULTICAST_LOOP. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getIPv6MulticastLoop() -> EventLoopFuture { + self._getIPv6MulticastLoop() + } + + #if os(Linux) || os(FreeBSD) || os(Android) + /// Gets the value of the socket option TCP_INFO. + /// + /// This socket option cannot be set. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getTCPInfo() -> EventLoopFuture { + self._getTCPInfo() + } + #endif + + #if canImport(Darwin) + /// Gets the value of the socket option TCP_CONNECTION_INFO. + /// + /// This socket option cannot be set. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getTCPConnectionInfo() -> EventLoopFuture { + self._getTCPConnectionInfo() + } + #endif + + #if os(Linux) + /// Gets the value of the socket option MPTCP_INFO. + /// + /// This socket option cannot be set. + /// + /// - Returns: An `EventLoopFuture` containing the value of the socket option, or + /// any error that occurred while retrieving the socket option. + public func getMPTCPInfo() -> EventLoopFuture { + self._getMPTCPInfo() + } + #endif + + // MARK: Non-public non-inlinable actual implementations for the above. + // + // As discussed above, these are needed to work around a compiler issue + // that was present at least up to the 6.0 compiler series. This prevents + // the specialization being emitted in the caller code, which is unfortunate, + // but it also ensures that we avoid the crash. We should remove these when + // they're no longer needed. + + /// Sets the socket option SO_LINGER to `value`. + /// + /// - Parameters: + /// - value: The value to set SO_LINGER to. + /// - Returns: An `EventLoopFuture` that fires when the option has been set, + /// or if an error has occurred. + private func _setSoLinger(_ value: linger) -> EventLoopFuture { #if os(WASI) self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported) #else @@ -201,7 +377,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getSoLinger() -> EventLoopFuture { + private func _getSoLinger() -> EventLoopFuture { #if os(WASI) self.eventLoop.makeFailedFuture(SocketOptionProviderError.unsupported) #else @@ -215,7 +391,7 @@ extension SocketOptionProvider { /// - value: The value to set IP_MULTICAST_IF to. /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. - public func setIPMulticastIF(_ value: in_addr) -> EventLoopFuture { + private func _setIPMulticastIF(_ value: in_addr) -> EventLoopFuture { self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_if, value: value) } @@ -223,7 +399,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getIPMulticastIF() -> EventLoopFuture { + private func _getIPMulticastIF() -> EventLoopFuture { self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_if) } @@ -233,7 +409,7 @@ extension SocketOptionProvider { /// - value: The value to set IP_MULTICAST_TTL to. /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. - public func setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture { + private func _setIPMulticastTTL(_ value: CUnsignedChar) -> EventLoopFuture { self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_ttl, value: value) } @@ -241,7 +417,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getIPMulticastTTL() -> EventLoopFuture { + private func _getIPMulticastTTL() -> EventLoopFuture { self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_ttl) } @@ -251,7 +427,7 @@ extension SocketOptionProvider { /// - value: The value to set IP_MULTICAST_LOOP to. /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. - public func setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture { + private func _setIPMulticastLoop(_ value: CUnsignedChar) -> EventLoopFuture { self.unsafeSetSocketOption(level: .ip, name: .ip_multicast_loop, value: value) } @@ -259,7 +435,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getIPMulticastLoop() -> EventLoopFuture { + private func _getIPMulticastLoop() -> EventLoopFuture { self.unsafeGetSocketOption(level: .ip, name: .ip_multicast_loop) } @@ -269,7 +445,7 @@ extension SocketOptionProvider { /// - value: The value to set IPV6_MULTICAST_IF to. /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. - public func setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture { + private func _setIPv6MulticastIF(_ value: CUnsignedInt) -> EventLoopFuture { self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_if, value: value) } @@ -277,7 +453,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getIPv6MulticastIF() -> EventLoopFuture { + private func _getIPv6MulticastIF() -> EventLoopFuture { self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_if) } @@ -287,7 +463,7 @@ extension SocketOptionProvider { /// - value: The value to set IPV6_MULTICAST_HOPS to. /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. - public func setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture { + private func _setIPv6MulticastHops(_ value: CInt) -> EventLoopFuture { self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_hops, value: value) } @@ -295,7 +471,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getIPv6MulticastHops() -> EventLoopFuture { + private func _getIPv6MulticastHops() -> EventLoopFuture { self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_hops) } @@ -305,7 +481,7 @@ extension SocketOptionProvider { /// - value: The value to set IPV6_MULTICAST_LOOP to. /// - Returns: An `EventLoopFuture` that fires when the option has been set, /// or if an error has occurred. - public func setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture { + private func _setIPv6MulticastLoop(_ value: CUnsignedInt) -> EventLoopFuture { self.unsafeSetSocketOption(level: .ipv6, name: .ipv6_multicast_loop, value: value) } @@ -313,7 +489,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getIPv6MulticastLoop() -> EventLoopFuture { + private func _getIPv6MulticastLoop() -> EventLoopFuture { self.unsafeGetSocketOption(level: .ipv6, name: .ipv6_multicast_loop) } @@ -324,7 +500,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getTCPInfo() -> EventLoopFuture { + private func _getTCPInfo() -> EventLoopFuture { self.unsafeGetSocketOption(level: .tcp, name: .tcp_info) } #endif @@ -336,7 +512,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getTCPConnectionInfo() -> EventLoopFuture { + private func _getTCPConnectionInfo() -> EventLoopFuture { self.unsafeGetSocketOption(level: .tcp, name: .tcp_connection_info) } #endif @@ -348,7 +524,7 @@ extension SocketOptionProvider { /// /// - Returns: An `EventLoopFuture` containing the value of the socket option, or /// any error that occurred while retrieving the socket option. - public func getMPTCPInfo() -> EventLoopFuture { + private func _getMPTCPInfo() -> EventLoopFuture { self.unsafeGetSocketOption(level: .mptcp, name: .mptcp_info) } #endif