Server.swift 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import Foundation
  2. import NIO
  3. import NIOHTTP1
  4. import NIOHTTP2
  5. import NIOSSL
  6. /// Wrapper object to manage the lifecycle of a gRPC server.
  7. ///
  8. /// The pipeline is configured in three stages detailed below. Note: handlers marked with
  9. /// a '*' are responsible for handling errors.
  10. ///
  11. /// 1. Initial stage, prior to HTTP protocol detection.
  12. ///
  13. /// ┌───────────────────────────┐
  14. /// │ HTTPProtocolSwitcher* │
  15. /// └─▲───────────────────────┬─┘
  16. /// ByteBuffer│ │ByteBuffer
  17. /// ┌─┴───────────────────────▼─┐
  18. /// │ NIOSSLHandler │
  19. /// └─▲───────────────────────┬─┘
  20. /// ByteBuffer│ │ByteBuffer
  21. /// │ ▼
  22. ///
  23. /// The NIOSSLHandler is optional and depends on how the framework user has configured
  24. /// their server. The HTTPProtocolSwitched detects which HTTP version is being used and
  25. /// configures the pipeline accordingly.
  26. ///
  27. /// 2. HTTP version detected. "HTTP Handlers" depends on the HTTP version determined by
  28. /// HTTPProtocolSwitcher. All of these handlers are provided by NIO except for the
  29. /// WebCORSHandler which is used for HTTP/1.
  30. ///
  31. /// ┌───────────────────────────┐
  32. /// │ GRPCChannelHandler* │
  33. /// └─▲───────────────────────┬─┘
  34. /// RawGRPCServerRequestPart│ │RawGRPCServerResponsePart
  35. /// ┌─┴───────────────────────▼─┐
  36. /// │ HTTP1ToRawGRPCServerCodec │
  37. /// └─▲───────────────────────┬─┘
  38. /// HTTPServerRequestPart│ │HTTPServerResponsePart
  39. /// ┌─┴───────────────────────▼─┐
  40. /// │ HTTP Handlers │
  41. /// └─▲───────────────────────┬─┘
  42. /// ByteBuffer│ │ByteBuffer
  43. /// ┌─┴───────────────────────▼─┐
  44. /// │ NIOSSLHandler │
  45. /// └─▲───────────────────────┬─┘
  46. /// ByteBuffer│ │ByteBuffer
  47. /// │ ▼
  48. ///
  49. /// The GPRCChannelHandler resolves the request head and configures the rest of the pipeline
  50. /// based on the RPC call being made.
  51. ///
  52. /// 3. The call has been resolved and is a function that this server can handle. Responses are
  53. /// written into `BaseCallHandler` by a user-implemented `CallHandlerProvider`.
  54. ///
  55. /// ┌───────────────────────────┐
  56. /// │ BaseCallHandler* │
  57. /// └─▲───────────────────────┬─┘
  58. /// GRPCServerRequestPart<T1>│ │GRPCServerResponsePart<T2>
  59. /// ┌─┴───────────────────────▼─┐
  60. /// │ GRPCServerCodec │
  61. /// └─▲───────────────────────┬─┘
  62. /// RawGRPCServerRequestPart│ │RawGRPCServerResponsePart
  63. /// ┌─┴───────────────────────▼─┐
  64. /// │ HTTP1ToRawGRPCServerCodec │
  65. /// └─▲───────────────────────┬─┘
  66. /// HTTPServerRequestPart│ │HTTPServerResponsePart
  67. /// ┌─┴───────────────────────▼─┐
  68. /// │ HTTP Handlers │
  69. /// └─▲───────────────────────┬─┘
  70. /// ByteBuffer│ │ByteBuffer
  71. /// ┌─┴───────────────────────▼─┐
  72. /// │ NIOSSLHandler │
  73. /// └─▲───────────────────────┬─┘
  74. /// ByteBuffer│ │ByteBuffer
  75. /// │ ▼
  76. ///
  77. public final class Server {
  78. /// Starts up a server that serves the given providers.
  79. ///
  80. /// - Returns: A future that is completed when the server has successfully started up.
  81. public static func start(
  82. hostname: String,
  83. port: Int,
  84. eventLoopGroup: EventLoopGroup,
  85. serviceProviders: [CallHandlerProvider],
  86. errorDelegate: ServerErrorDelegate? = LoggingServerErrorDelegate(),
  87. tls tlsMode: TLSMode = .none
  88. ) throws -> EventLoopFuture<Server> {
  89. let servicesByName = Dictionary(uniqueKeysWithValues: serviceProviders.map { ($0.serviceName, $0) })
  90. let bootstrap = ServerBootstrap(group: eventLoopGroup)
  91. // Specify a backlog to avoid overloading the server.
  92. .serverChannelOption(ChannelOptions.backlog, value: 256)
  93. // Enable `SO_REUSEADDR` to avoid "address already in use" error.
  94. .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
  95. // Set the handlers that are applied to the accepted Channels
  96. .childChannelInitializer { channel in
  97. let protocolSwitcherHandler = HTTPProtocolSwitcher(errorDelegate: errorDelegate) { channel -> EventLoopFuture<Void> in
  98. channel.pipeline.addHandlers(HTTP1ToRawGRPCServerCodec(),
  99. GRPCChannelHandler(servicesByName: servicesByName, errorDelegate: errorDelegate))
  100. }
  101. return configureTLS(mode: tlsMode, channel: channel).flatMap {
  102. channel.pipeline.addHandler(protocolSwitcherHandler)
  103. }
  104. }
  105. // Enable TCP_NODELAY and SO_REUSEADDR for the accepted Channels
  106. .childChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
  107. .childChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
  108. return bootstrap.bind(host: hostname, port: port)
  109. .map { Server(channel: $0, errorDelegate: errorDelegate) }
  110. }
  111. /// Configure an SSL handler on the channel, if one is provided.
  112. ///
  113. /// - Parameters:
  114. /// - mode: TLS mode to run the server in.
  115. /// - channel: The channel on which to add the SSL handler.
  116. /// - Returns: A future which will be succeeded when the pipeline has been configured.
  117. private static func configureTLS(mode: TLSMode, channel: Channel) -> EventLoopFuture<Void> {
  118. guard let sslContext = mode.sslContext else {
  119. return channel.eventLoop.makeSucceededFuture(())
  120. }
  121. let handlerAddedPromise: EventLoopPromise<Void> = channel.eventLoop.makePromise()
  122. do {
  123. channel.pipeline.addHandler(try NIOSSLServerHandler(context: sslContext)).cascade(to: handlerAddedPromise)
  124. } catch {
  125. handlerAddedPromise.fail(error)
  126. }
  127. return handlerAddedPromise.futureResult
  128. }
  129. public let channel: Channel
  130. private var errorDelegate: ServerErrorDelegate?
  131. private init(channel: Channel, errorDelegate: ServerErrorDelegate?) {
  132. self.channel = channel
  133. // Maintain a strong reference to ensure it lives as long as the server.
  134. self.errorDelegate = errorDelegate
  135. // nil out errorDelegate to avoid retain cycles.
  136. onClose.whenComplete { _ in
  137. self.errorDelegate = nil
  138. }
  139. }
  140. /// Fired when the server shuts down.
  141. public var onClose: EventLoopFuture<Void> {
  142. return channel.closeFuture
  143. }
  144. /// Shut down the server; this should be called to avoid leaking resources.
  145. public func close() -> EventLoopFuture<Void> {
  146. return channel.close(mode: .all)
  147. }
  148. }
  149. extension Server {
  150. public enum TLSMode {
  151. case none
  152. case custom(NIOSSLContext)
  153. var sslContext: NIOSSLContext? {
  154. switch self {
  155. case .none:
  156. return nil
  157. case .custom(let context):
  158. return context
  159. }
  160. }
  161. }
  162. }