Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ let package = Package(
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.5.0"),
// TLS via SwiftNIO
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.4.0"),
// Support for Network.framework where possible. Note: from 1.0.2 the package
// is essentially an empty import on platforms where it isn't supported.
.package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.0.2"),
// Support for Network.framework where possible.
.package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.1.0"),

// Official SwiftProtobuf library, for [de]serializing data to send on the wire.
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.5.0"),
Expand Down
14 changes: 10 additions & 4 deletions Sources/GRPC/ClientConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public class ClientConnection {

self.channel = ClientConnection.makeChannel(
configuration: self.configuration,
eventLoop: self.configuration.eventLoopGroup.next(),
connectivity: self.connectivity,
backoffIterator: self.configuration.connectionBackoff?.makeIterator(),
logger: self.logger
Expand Down Expand Up @@ -230,6 +231,7 @@ extension ClientConnection {
self.logger.debug("client connection channel closed, creating a new one")
self.channel = ClientConnection.makeChannel(
configuration: self.configuration,
eventLoop: channel.eventLoop,
connectivity: self.connectivity,
backoffIterator: self.configuration.connectionBackoff?.makeIterator(),
logger: self.logger
Expand Down Expand Up @@ -258,11 +260,13 @@ extension ClientConnection {
/// `ConnectionBackoffIterator` is provided.
///
/// - Parameter configuration: The configuration to start the connection with.
/// - Parameter eventLoop: The event loop to use for this connection.
/// - Parameter connectivity: A connectivity state monitor.
/// - Parameter backoffIterator: An `Iterator` for `ConnectionBackoff` providing a sequence of
/// connection timeouts and backoff to use when attempting to create a connection.
private class func makeChannel(
configuration: Configuration,
eventLoop: EventLoop,
connectivity: ConnectivityStateMonitor,
backoffIterator: ConnectionBackoffIterator?,
logger: Logger
Expand All @@ -277,7 +281,7 @@ extension ClientConnection {

let bootstrap = self.makeBootstrap(
configuration: configuration,
group: configuration.eventLoopGroup,
eventLoop: eventLoop,
timeout: timeoutAndBackoff?.timeout,
connectivityMonitor: connectivity,
logger: logger
Expand Down Expand Up @@ -330,6 +334,7 @@ extension ClientConnection {
return eventLoop.scheduleTask(in: .seconds(timeInterval: timeout)) {
ClientConnection.makeChannel(
configuration: configuration,
eventLoop: eventLoop,
connectivity: connectivity,
backoffIterator: backoffIterator,
logger: logger
Expand All @@ -345,12 +350,12 @@ extension ClientConnection {
/// handlers detailed in the documentation for `ClientConnection`.
///
/// - Parameter configuration: The configuration to prepare the bootstrap with.
/// - Parameter group: The `EventLoopGroup` to use for the bootstrap.
/// - Parameter eventLoop: The `EventLoop` to use for the bootstrap.
/// - Parameter timeout: The connection timeout in seconds.
/// - Parameter connectivityMonitor: The connectivity state monitor for the created channel.
private class func makeBootstrap(
configuration: Configuration,
group: EventLoopGroup,
eventLoop: EventLoop,
timeout: TimeInterval?,
connectivityMonitor: ConnectivityStateMonitor,
logger: Logger
Expand All @@ -367,7 +372,7 @@ extension ClientConnection {
}
}

let bootstrap = PlatformSupport.makeClientBootstrap(group: group)
let bootstrap = PlatformSupport.makeClientBootstrap(group: eventLoop)
// Enable SO_REUSEADDR and TCP_NODELAY.
.channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.channelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
Expand All @@ -385,6 +390,7 @@ extension ClientConnection {
logger.info("setting connect timeout to \(timeout) seconds")
return bootstrap.connectTimeout(.seconds(timeInterval: timeout))
} else {
logger.info("no connect timeout provided")
return bootstrap
}
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/GRPC/PlatformSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ public enum PlatformSupport {
if let tsGroup = group as? NIOTSEventLoopGroup {
logger.debug("Network.framework is available and the group is correctly typed, creating a NIOTSConnectionBootstrap")
return NIOTSConnectionBootstrap(group: tsGroup)
} else if let qosEventLoop = group as? QoSEventLoop {
logger.debug("Network.framework is available and the group is correctly typed, creating a NIOTSConnectionBootstrap")
return NIOTSConnectionBootstrap(group: qosEventLoop)
}
logger.debug("Network.framework is available but the group is not typed for NIOTS, falling back to ClientBootstrap")
}
Expand All @@ -186,6 +189,9 @@ public enum PlatformSupport {
if let tsGroup = group as? NIOTSEventLoopGroup {
logger.debug("Network.framework is available and the group is correctly typed, creating a NIOTSListenerBootstrap")
return NIOTSListenerBootstrap(group: tsGroup)
} else if let qosEventLoop = group as? QoSEventLoop {
logger.debug("Network.framework is available and the group is correctly typed, creating a NIOTSListenerBootstrap")
return NIOTSListenerBootstrap(group: qosEventLoop)
}
logger.debug("Network.framework is available but the group is not typed for NIOTS, falling back to ServerBootstrap")
}
Expand Down
115 changes: 115 additions & 0 deletions Tests/GRPCTests/PlatformSupportTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import Foundation
import GRPC
import NIO
import NIOTransportServices
import XCTest

class PlatformSupportTests: GRPCTestCase {
var group: EventLoopGroup!

override func tearDown() {
XCTAssertNoThrow(try self.group?.syncShutdownGracefully())
}

func testMakeEventLoopGroupReturnsMultiThreadedGroupForPosix() {
self.group = PlatformSupport.makeEventLoopGroup(
loopCount: 1,
networkPreference: .userDefined(.posix)
)

XCTAssertTrue(self.group is MultiThreadedEventLoopGroup)
}

func testMakeEventLoopGroupReturnsNIOTSGroupForNetworkFramework() {
// If we don't have Network.framework then we can't test this.
#if canImport(Network)
guard #available(macOS 10.14, *) else { return }

self.group = PlatformSupport.makeEventLoopGroup(
loopCount: 1,
networkPreference: .userDefined(.networkFramework)
)

XCTAssertTrue(self.group is NIOTSEventLoopGroup)
#endif
}

func testMakeClientBootstrapReturnsClientBootstrapForMultiThreadedGroup() {
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let bootstrap = PlatformSupport.makeClientBootstrap(group: self.group)
XCTAssertTrue(bootstrap is ClientBootstrap)
}

func testMakeClientBootstrapReturnsClientBootstrapForEventLoop() {
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let eventLoop = self.group.next()
let bootstrap = PlatformSupport.makeClientBootstrap(group: eventLoop)
XCTAssertTrue(bootstrap is ClientBootstrap)
}

func testMakeClientBootstrapReturnsNIOTSConnectionBootstrapForNIOTSGroup() {
// If we don't have Network.framework then we can't test this.
#if canImport(Network)
guard #available(macOS 10.14, *) else { return }

self.group = NIOTSEventLoopGroup(loopCount: 1)
let bootstrap = PlatformSupport.makeClientBootstrap(group: self.group)
XCTAssertTrue(bootstrap is NIOTSConnectionBootstrap)
#endif
}

func testMakeClientBootstrapReturnsNIOTSConnectionBootstrapForQoSEventLoop() {
// If we don't have Network.framework then we can't test this.
#if canImport(Network)
guard #available(macOS 10.14, *) else { return }

self.group = NIOTSEventLoopGroup(loopCount: 1)

let eventLoop = self.group.next()
XCTAssertTrue(eventLoop is QoSEventLoop)

let bootstrap = PlatformSupport.makeClientBootstrap(group: eventLoop)
XCTAssertTrue(bootstrap is NIOTSConnectionBootstrap)
#endif
}

func testMakeServerBootstrapReturnsServerBootstrapForMultiThreadedGroup() {
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let bootstrap = PlatformSupport.makeServerBootstrap(group: self.group)
XCTAssertTrue(bootstrap is ServerBootstrap)
}

func testMakeServerBootstrapReturnsServerBootstrapForEventLoop() {
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)

let eventLoop = self.group.next()
let bootstrap = PlatformSupport.makeServerBootstrap(group: eventLoop)
XCTAssertTrue(bootstrap is ServerBootstrap)
}

func testMakeServerBootstrapReturnsNIOTSListenerBootstrapForNIOTSGroup() {
// If we don't have Network.framework then we can't test this.
#if canImport(Network)
guard #available(macOS 10.14, *) else { return }

self.group = NIOTSEventLoopGroup(loopCount: 1)
let bootstrap = PlatformSupport.makeServerBootstrap(group: self.group)
XCTAssertTrue(bootstrap is NIOTSListenerBootstrap)
#endif
}

func testMakeServerBootstrapReturnsNIOTSListenerBootstrapForQoSEventLoop() {
// If we don't have Network.framework then we can't test this.
#if canImport(Network)
guard #available(macOS 10.14, *) else { return }

self.group = NIOTSEventLoopGroup(loopCount: 1)

let eventLoop = self.group.next()
XCTAssertTrue(eventLoop is QoSEventLoop)

let bootstrap = PlatformSupport.makeServerBootstrap(group: eventLoop)
XCTAssertTrue(bootstrap is NIOTSListenerBootstrap)
#endif
}
}
19 changes: 19 additions & 0 deletions Tests/GRPCTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,24 @@ extension LengthPrefixedMessageReaderTests {
]
}

extension PlatformSupportTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__PlatformSupportTests = [
("testMakeClientBootstrapReturnsClientBootstrapForEventLoop", testMakeClientBootstrapReturnsClientBootstrapForEventLoop),
("testMakeClientBootstrapReturnsClientBootstrapForMultiThreadedGroup", testMakeClientBootstrapReturnsClientBootstrapForMultiThreadedGroup),
("testMakeClientBootstrapReturnsNIOTSConnectionBootstrapForNIOTSGroup", testMakeClientBootstrapReturnsNIOTSConnectionBootstrapForNIOTSGroup),
("testMakeClientBootstrapReturnsNIOTSConnectionBootstrapForQoSEventLoop", testMakeClientBootstrapReturnsNIOTSConnectionBootstrapForQoSEventLoop),
("testMakeEventLoopGroupReturnsMultiThreadedGroupForPosix", testMakeEventLoopGroupReturnsMultiThreadedGroupForPosix),
("testMakeEventLoopGroupReturnsNIOTSGroupForNetworkFramework", testMakeEventLoopGroupReturnsNIOTSGroupForNetworkFramework),
("testMakeServerBootstrapReturnsNIOTSListenerBootstrapForNIOTSGroup", testMakeServerBootstrapReturnsNIOTSListenerBootstrapForNIOTSGroup),
("testMakeServerBootstrapReturnsNIOTSListenerBootstrapForQoSEventLoop", testMakeServerBootstrapReturnsNIOTSListenerBootstrapForQoSEventLoop),
("testMakeServerBootstrapReturnsServerBootstrapForEventLoop", testMakeServerBootstrapReturnsServerBootstrapForEventLoop),
("testMakeServerBootstrapReturnsServerBootstrapForMultiThreadedGroup", testMakeServerBootstrapReturnsServerBootstrapForMultiThreadedGroup),
]
}

extension ServerDelayedThrowingTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
Expand Down Expand Up @@ -468,6 +486,7 @@ public func __allTests() -> [XCTestCaseEntry] {
testCase(HTTP1ToRawGRPCServerCodecTests.__allTests__HTTP1ToRawGRPCServerCodecTests),
testCase(ImmediatelyFailingProviderTests.__allTests__ImmediatelyFailingProviderTests),
testCase(LengthPrefixedMessageReaderTests.__allTests__LengthPrefixedMessageReaderTests),
testCase(PlatformSupportTests.__allTests__PlatformSupportTests),
testCase(ServerDelayedThrowingTests.__allTests__ServerDelayedThrowingTests),
testCase(ServerErrorTransformingTests.__allTests__ServerErrorTransformingTests),
testCase(ServerThrowingTests.__allTests__ServerThrowingTests),
Expand Down