ServerStreamingCallHandler.swift 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. RequestDeserializer: MessageDeserializer,
  28. ResponseSerializer: MessageSerializer
  29. >: _BaseCallHandler<RequestDeserializer, ResponseSerializer> {
  30. @usableFromInline
  31. internal typealias _Context = StreamingResponseCallContext<ResponsePayload>
  32. @usableFromInline
  33. internal typealias _Observer = (RequestPayload) -> EventLoopFuture<GRPCStatus>
  34. @usableFromInline
  35. internal var _callHandlerState: _CallHandlerState
  36. // See 'UnaryCallHandler.State'.
  37. @usableFromInline
  38. internal enum _CallHandlerState {
  39. case requestIdleResponseIdle((_Context) -> _Observer)
  40. case requestOpenResponseOpen(_Context, ObserverState)
  41. case requestClosedResponseOpen(_Context)
  42. case requestClosedResponseClosed
  43. @usableFromInline
  44. enum ObserverState {
  45. case notObserved(_Observer)
  46. case observed
  47. }
  48. }
  49. @inlinable
  50. internal init(
  51. serializer: ResponseSerializer,
  52. deserializer: RequestDeserializer,
  53. callHandlerContext: CallHandlerContext,
  54. interceptors: [ServerInterceptor<RequestDeserializer.Output, ResponseSerializer.Input>],
  55. eventObserverFactory: @escaping (StreamingResponseCallContext<ResponsePayload>)
  56. -> (RequestPayload) -> EventLoopFuture<GRPCStatus>
  57. ) {
  58. self._callHandlerState = .requestIdleResponseIdle(eventObserverFactory)
  59. super.init(
  60. callHandlerContext: callHandlerContext,
  61. requestDeserializer: deserializer,
  62. responseSerializer: serializer,
  63. callType: .serverStreaming,
  64. interceptors: interceptors
  65. )
  66. }
  67. override public func channelInactive(context: ChannelHandlerContext) {
  68. super.channelInactive(context: context)
  69. // Fail any remaining promise.
  70. switch self._callHandlerState {
  71. case .requestIdleResponseIdle,
  72. .requestClosedResponseClosed:
  73. self._callHandlerState = .requestClosedResponseClosed
  74. case let .requestOpenResponseOpen(context, _),
  75. let .requestClosedResponseOpen(context):
  76. self._callHandlerState = .requestClosedResponseClosed
  77. context.statusPromise.fail(GRPCError.AlreadyComplete())
  78. }
  79. }
  80. /// Handle an error from the event observer.
  81. private func handleObserverError(_ error: Error) {
  82. switch self._callHandlerState {
  83. case .requestIdleResponseIdle:
  84. preconditionFailure("Invalid state: request observer hasn't been created")
  85. case .requestOpenResponseOpen(_, .notObserved):
  86. preconditionFailure("Invalid state: request observer hasn't been invoked")
  87. case let .requestOpenResponseOpen(context, .observed),
  88. let .requestClosedResponseOpen(context):
  89. let (status, trailers) = self.processObserverError(
  90. error,
  91. headers: context.headers,
  92. trailers: context.trailers
  93. )
  94. // This will handle the response promise as well.
  95. self.sendEnd(status: status, trailers: trailers)
  96. case .requestClosedResponseClosed:
  97. // We hit an error, but we're already closed (because we hit a library error first).
  98. ()
  99. }
  100. }
  101. /// Handle a 'library' error, i.e. an error emanating from the `Channel`.
  102. private func handleLibraryError(_ error: Error) {
  103. switch self._callHandlerState {
  104. case .requestIdleResponseIdle,
  105. .requestOpenResponseOpen(_, .notObserved):
  106. // We'll never see a request message: send end.
  107. let (status, trailers) = self.processLibraryError(error)
  108. self.sendEnd(status: status, trailers: trailers)
  109. case .requestOpenResponseOpen(_, .observed),
  110. .requestClosedResponseOpen:
  111. // We've invoked the observer, we expect a response. We'll let this play out.
  112. ()
  113. case .requestClosedResponseClosed:
  114. // We're already closed, no need to do anything here.
  115. ()
  116. }
  117. }
  118. // MARK: - Inbound
  119. override func observeLibraryError(_ error: Error) {
  120. self.handleLibraryError(error)
  121. }
  122. override internal func observeHeaders(_ headers: HPACKHeaders) {
  123. switch self._callHandlerState {
  124. case let .requestIdleResponseIdle(factory):
  125. let context = _StreamingResponseCallContext<RequestPayload, ResponsePayload>(
  126. eventLoop: self.eventLoop,
  127. headers: headers,
  128. logger: self.logger,
  129. userInfoRef: self._userInfoRef,
  130. compressionIsEnabled: self._callHandlerContext.encoding.isEnabled,
  131. sendResponse: self.sendResponse(_:metadata:promise:)
  132. )
  133. let observer = factory(context)
  134. // Fully open. We'll send the response headers back in a moment.
  135. self._callHandlerState = .requestOpenResponseOpen(context, .notObserved(observer))
  136. // Register callbacks for the status promise.
  137. context.statusPromise.futureResult.whenComplete { result in
  138. switch result {
  139. case let .success(status):
  140. self.sendEnd(status: status, trailers: context.trailers)
  141. case let .failure(error):
  142. self.handleObserverError(error)
  143. }
  144. }
  145. // Write back the response headers.
  146. self.sendResponsePartFromObserver(.metadata([:]), promise: nil)
  147. // The main state machine guards against this.
  148. case .requestOpenResponseOpen,
  149. .requestClosedResponseOpen,
  150. .requestClosedResponseClosed:
  151. preconditionFailure("Invalid state")
  152. }
  153. }
  154. override internal func observeRequest(_ message: RequestPayload) {
  155. switch self._callHandlerState {
  156. case .requestIdleResponseIdle:
  157. preconditionFailure("Invalid state: request received before headers")
  158. case let .requestOpenResponseOpen(context, request):
  159. switch request {
  160. case .observed:
  161. // We've already observed the request message. The main state machine doesn't guard against
  162. // too many messages for unary streams. Assuming downstream handlers protect against this
  163. // then this must be an errant interceptor.
  164. ()
  165. case let .notObserved(observer):
  166. self._callHandlerState = .requestOpenResponseOpen(context, .observed)
  167. // Complete the status promise with the observer block.
  168. context.statusPromise.completeWith(observer(message))
  169. }
  170. case .requestClosedResponseOpen,
  171. .requestClosedResponseClosed:
  172. preconditionFailure("Invalid state: the request stream has already been closed")
  173. }
  174. }
  175. override internal func observeEnd() {
  176. switch self._callHandlerState {
  177. case .requestIdleResponseIdle:
  178. preconditionFailure("Invalid state: no request headers received")
  179. case let .requestOpenResponseOpen(context, request):
  180. switch request {
  181. case .observed:
  182. // Close the request stream.
  183. self._callHandlerState = .requestClosedResponseOpen(context)
  184. case .notObserved:
  185. // We haven't received a request: this is an empty stream, the observer will never be
  186. // invoked. Fail the response promise (which will have no side effect).
  187. context.statusPromise.fail(GRPCError.StreamCardinalityViolation.request)
  188. }
  189. case .requestClosedResponseOpen,
  190. .requestClosedResponseClosed:
  191. preconditionFailure("Invalid state: request stream is already closed")
  192. }
  193. }
  194. // MARK: - Outbound
  195. private func sendResponse(
  196. _ message: ResponsePayload,
  197. metadata: MessageMetadata,
  198. promise: EventLoopPromise<Void>?
  199. ) {
  200. switch self._callHandlerState {
  201. case .requestIdleResponseIdle:
  202. preconditionFailure("Invalid state: can't send response before receiving headers and request")
  203. case .requestOpenResponseOpen(_, .notObserved):
  204. preconditionFailure("Invalid state: can't send response before receiving request")
  205. case .requestOpenResponseOpen(_, .observed),
  206. .requestClosedResponseOpen:
  207. self.sendResponsePartFromObserver(.message(message, metadata), promise: promise)
  208. case .requestClosedResponseClosed:
  209. // We're already closed. This isn't a precondition failure because we may have encountered
  210. // an error before the observer block completed.
  211. promise?.fail(GRPCError.AlreadyComplete())
  212. }
  213. }
  214. private func sendEnd(status: GRPCStatus, trailers: HPACKHeaders) {
  215. switch self._callHandlerState {
  216. case .requestIdleResponseIdle,
  217. .requestClosedResponseOpen:
  218. self._callHandlerState = .requestClosedResponseClosed
  219. self.sendResponsePartFromObserver(.end(status, trailers), promise: nil)
  220. case let .requestOpenResponseOpen(context, _):
  221. self._callHandlerState = .requestClosedResponseClosed
  222. self.sendResponsePartFromObserver(.end(status, trailers), promise: nil)
  223. // Fail the promise.
  224. context.statusPromise.fail(status)
  225. case .requestClosedResponseClosed:
  226. // Already closed, do nothing.
  227. ()
  228. }
  229. }
  230. }