GRPCServer.swift 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import Foundation
  2. import NIO
  3. import NIOHTTP1
  4. import NIOHTTP2
  5. /// Wrapper object to manage the lifecycle of a gRPC server.
  6. public final class GRPCServer {
  7. /// Starts up a server that serves the given providers.
  8. ///
  9. /// - Returns: A future that is completed when the server has successfully started up.
  10. public static func start(
  11. hostname: String,
  12. port: Int,
  13. eventLoopGroup: EventLoopGroup,
  14. serviceProviders: [CallHandlerProvider]) -> EventLoopFuture<GRPCServer> {
  15. let servicesByName = Dictionary(uniqueKeysWithValues: serviceProviders.map { ($0.serviceName, $0) })
  16. let bootstrap = ServerBootstrap(group: eventLoopGroup)
  17. // Specify a backlog to avoid overloading the server.
  18. .serverChannelOption(ChannelOptions.backlog, value: 256)
  19. // Enable `SO_REUSEADDR` to avoid "address already in use" error.
  20. .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
  21. // Set the handlers that are applied to the accepted Channels
  22. .childChannelInitializer { channel in
  23. return channel.pipeline.add(handler: HTTPProtocolSwitcher {
  24. channel -> EventLoopFuture<Void> in
  25. return channel.pipeline.add(handler: HTTP1ToRawGRPCServerCodec())
  26. .then { channel.pipeline.add(handler: GRPCChannelHandler(servicesByName: servicesByName)) }
  27. })
  28. }
  29. // Enable TCP_NODELAY and SO_REUSEADDR for the accepted Channels
  30. .childChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
  31. .childChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
  32. return bootstrap.bind(host: hostname, port: port)
  33. .map { GRPCServer(channel: $0) }
  34. }
  35. private let channel: Channel
  36. private init(channel: Channel) {
  37. self.channel = channel
  38. }
  39. /// Fired when the server shuts down.
  40. public var onClose: EventLoopFuture<Void> {
  41. return channel.closeFuture
  42. }
  43. public func close() -> EventLoopFuture<Void> {
  44. return channel.close(mode: .all)
  45. }
  46. }