ServerStreamingCallHandler.swift 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright 2019, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Foundation
  17. import Logging
  18. import NIO
  19. import NIOHPACK
  20. import NIOHTTP1
  21. import SwiftProtobuf
  22. /// Handles server-streaming calls. Calls the observer block with the request message.
  23. ///
  24. /// - The observer block is implemented by the framework user and calls `context.sendResponse` as needed.
  25. /// - To close the call and send the status, complete the status future returned by the observer block.
  26. public final class ServerStreamingCallHandler<
  27. RequestPayload,
  28. ResponsePayload
  29. >: _BaseCallHandler<RequestPayload, ResponsePayload> {
  30. private typealias Context = StreamingResponseCallContext<ResponsePayload>
  31. private typealias Observer = (RequestPayload) -> EventLoopFuture<GRPCStatus>
  32. private var state: State
  33. // See 'UnaryCallHandler.State'.
  34. private enum State {
  35. case requestIdleResponseIdle((Context) -> Observer)
  36. case requestOpenResponseOpen(Context, ObserverState)
  37. case requestClosedResponseOpen(Context)
  38. case requestClosedResponseClosed
  39. enum ObserverState {
  40. case notObserved(Observer)
  41. case observed
  42. }
  43. }
  44. internal init<Serializer: MessageSerializer, Deserializer: MessageDeserializer>(
  45. serializer: Serializer,
  46. deserializer: Deserializer,
  47. callHandlerContext: CallHandlerContext,
  48. interceptors: [ServerInterceptor<Deserializer.Output, Serializer.Input>],
  49. eventObserverFactory: @escaping (StreamingResponseCallContext<ResponsePayload>)
  50. -> (RequestPayload) -> EventLoopFuture<GRPCStatus>
  51. ) where Serializer.Input == ResponsePayload, Deserializer.Output == RequestPayload {
  52. self.state = .requestIdleResponseIdle(eventObserverFactory)
  53. super.init(
  54. callHandlerContext: callHandlerContext,
  55. codec: GRPCServerCodecHandler(serializer: serializer, deserializer: deserializer),
  56. callType: .serverStreaming,
  57. interceptors: interceptors
  58. )
  59. }
  60. override public func channelInactive(context: ChannelHandlerContext) {
  61. super.channelInactive(context: context)
  62. // Fail any remaining promise.
  63. switch self.state {
  64. case .requestIdleResponseIdle,
  65. .requestClosedResponseClosed:
  66. self.state = .requestClosedResponseClosed
  67. case let .requestOpenResponseOpen(context, _),
  68. let .requestClosedResponseOpen(context):
  69. self.state = .requestClosedResponseClosed
  70. context.statusPromise.fail(GRPCError.AlreadyComplete())
  71. }
  72. }
  73. /// Handle an error from the event observer.
  74. private func handleObserverError(_ error: Error) {
  75. switch self.state {
  76. case .requestIdleResponseIdle:
  77. preconditionFailure("Invalid state: request observer hasn't been created")
  78. case .requestOpenResponseOpen(_, .notObserved):
  79. preconditionFailure("Invalid state: request observer hasn't been invoked")
  80. case let .requestOpenResponseOpen(context, .observed),
  81. let .requestClosedResponseOpen(context):
  82. let (status, trailers) = self.processObserverError(
  83. error,
  84. headers: context.headers,
  85. trailers: context.trailers
  86. )
  87. // This will handle the response promise as well.
  88. self.sendEnd(status: status, trailers: trailers)
  89. case .requestClosedResponseClosed:
  90. // We hit an error, but we're already closed (because we hit a library error first).
  91. ()
  92. }
  93. }
  94. /// Handle a 'library' error, i.e. an error emanating from the `Channel`.
  95. private func handleLibraryError(_ error: Error) {
  96. switch self.state {
  97. case .requestIdleResponseIdle,
  98. .requestOpenResponseOpen(_, .notObserved):
  99. // We'll never see a request message: send end.
  100. let (status, trailers) = self.processLibraryError(error)
  101. self.sendEnd(status: status, trailers: trailers)
  102. case .requestOpenResponseOpen(_, .observed),
  103. .requestClosedResponseOpen:
  104. // We've invoked the observer, we expect a response. We'll let this play out.
  105. ()
  106. case .requestClosedResponseClosed:
  107. // We're already closed, no need to do anything here.
  108. ()
  109. }
  110. }
  111. // MARK: - Inbound
  112. override func observeLibraryError(_ error: Error) {
  113. self.handleLibraryError(error)
  114. }
  115. override internal func observeHeaders(_ headers: HPACKHeaders) {
  116. switch self.state {
  117. case let .requestIdleResponseIdle(factory):
  118. let context = _StreamingResponseCallContext<RequestPayload, ResponsePayload>(
  119. eventLoop: self.eventLoop,
  120. headers: headers,
  121. logger: self.logger,
  122. userInfoRef: self.userInfoRef,
  123. sendResponse: self.sendResponse(_:metadata:promise:)
  124. )
  125. let observer = factory(context)
  126. // Fully open. We'll send the response headers back in a moment.
  127. self.state = .requestOpenResponseOpen(context, .notObserved(observer))
  128. // Register callbacks for the status promise.
  129. context.statusPromise.futureResult.whenComplete { result in
  130. switch result {
  131. case let .success(status):
  132. self.sendEnd(status: status, trailers: context.trailers)
  133. case let .failure(error):
  134. self.handleObserverError(error)
  135. }
  136. }
  137. // Write back the response headers.
  138. self.sendResponsePartFromObserver(.metadata([:]), promise: nil)
  139. // The main state machine guards against this.
  140. case .requestOpenResponseOpen,
  141. .requestClosedResponseOpen,
  142. .requestClosedResponseClosed:
  143. preconditionFailure("Invalid state")
  144. }
  145. }
  146. override internal func observeRequest(_ message: RequestPayload) {
  147. switch self.state {
  148. case .requestIdleResponseIdle:
  149. preconditionFailure("Invalid state: request received before headers")
  150. case let .requestOpenResponseOpen(context, request):
  151. switch request {
  152. case .observed:
  153. // We've already observed the request message. The main state machine doesn't guard against
  154. // too many messages for unary streams. Assuming downstream handlers protect against this
  155. // then this must be an errant interceptor.
  156. ()
  157. case let .notObserved(observer):
  158. self.state = .requestOpenResponseOpen(context, .observed)
  159. // Complete the status promise with the observer block.
  160. context.statusPromise.completeWith(observer(message))
  161. }
  162. case .requestClosedResponseOpen,
  163. .requestClosedResponseClosed:
  164. preconditionFailure("Invalid state: the request stream has already been closed")
  165. }
  166. }
  167. override internal func observeEnd() {
  168. switch self.state {
  169. case .requestIdleResponseIdle:
  170. preconditionFailure("Invalid state: no request headers received")
  171. case let .requestOpenResponseOpen(context, request):
  172. switch request {
  173. case .observed:
  174. // Close the request stream.
  175. self.state = .requestClosedResponseOpen(context)
  176. case .notObserved:
  177. // We haven't received a request: this is an empty stream, the observer will never be
  178. // invoked. Fail the response promise (which will have no side effect).
  179. context.statusPromise.fail(GRPCError.StreamCardinalityViolation.request)
  180. }
  181. case .requestClosedResponseOpen,
  182. .requestClosedResponseClosed:
  183. preconditionFailure("Invalid state: request stream is already closed")
  184. }
  185. }
  186. // MARK: - Outbound
  187. private func sendResponse(
  188. _ message: ResponsePayload,
  189. metadata: MessageMetadata,
  190. promise: EventLoopPromise<Void>?
  191. ) {
  192. switch self.state {
  193. case .requestIdleResponseIdle:
  194. preconditionFailure("Invalid state: can't send response before receiving headers and request")
  195. case .requestOpenResponseOpen(_, .notObserved):
  196. preconditionFailure("Invalid state: can't send response before receiving request")
  197. case .requestOpenResponseOpen(_, .observed),
  198. .requestClosedResponseOpen:
  199. self.sendResponsePartFromObserver(.message(message, metadata), promise: promise)
  200. case .requestClosedResponseClosed:
  201. // We're already closed. This isn't a precondition failure because we may have encountered
  202. // an error before the observer block completed.
  203. promise?.fail(GRPCError.AlreadyComplete())
  204. }
  205. }
  206. private func sendEnd(status: GRPCStatus, trailers: HPACKHeaders) {
  207. switch self.state {
  208. case .requestIdleResponseIdle,
  209. .requestClosedResponseOpen:
  210. self.state = .requestClosedResponseClosed
  211. self.sendResponsePartFromObserver(.end(status, trailers), promise: nil)
  212. case let .requestOpenResponseOpen(context, _):
  213. self.state = .requestClosedResponseClosed
  214. self.sendResponsePartFromObserver(.end(status, trailers), promise: nil)
  215. // Fail the promise.
  216. context.statusPromise.fail(status)
  217. case .requestClosedResponseClosed:
  218. // Already closed, do nothing.
  219. ()
  220. }
  221. }
  222. }