Handler.swift 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright 2016, 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. #if SWIFT_PACKAGE
  17. import CgRPC
  18. #endif
  19. import Foundation // for String.Encoding
  20. /// A gRPC request handler
  21. public class Handler {
  22. /// Pointer to underlying C representation
  23. fileprivate let underlyingHandler: UnsafeMutableRawPointer
  24. /// Completion queue for handler response operations
  25. let completionQueue: CompletionQueue
  26. /// Metadata received with the request
  27. public let requestMetadata: Metadata
  28. /// A Call object that can be used to respond to the request
  29. lazy var call: Call = {
  30. Call(underlyingCall: cgrpc_handler_get_call(self.underlyingHandler),
  31. owned: false,
  32. completionQueue: self.completionQueue)
  33. }()
  34. /// The host name sent with the request
  35. public lazy var host: String? = {
  36. // We actually know that this method will never return nil,
  37. // so we can forcibly unwrap the result. (Also below.)
  38. let string = cgrpc_handler_copy_host(self.underlyingHandler)!
  39. defer { cgrpc_free_copied_string(string) }
  40. return String(cString: string, encoding: .utf8)
  41. }()
  42. /// The method name sent with the request
  43. public lazy var method: String? = {
  44. let string = cgrpc_handler_copy_method(self.underlyingHandler)!
  45. defer { cgrpc_free_copied_string(string) }
  46. return String(cString: string, encoding: .utf8)
  47. }()
  48. /// The caller address associated with the request
  49. public lazy var caller: String? = {
  50. let string = cgrpc_handler_call_peer(self.underlyingHandler)!
  51. defer { cgrpc_free_copied_string(string) }
  52. return String(cString: string, encoding: .utf8)
  53. }()
  54. /// Initializes a Handler
  55. ///
  56. /// - Parameter underlyingServer: the underlying C representation of the associated server
  57. init(underlyingServer: UnsafeMutableRawPointer) {
  58. underlyingHandler = cgrpc_handler_create_with_server(underlyingServer)
  59. requestMetadata = Metadata()
  60. completionQueue = CompletionQueue(underlyingCompletionQueue: cgrpc_handler_get_completion_queue(underlyingHandler))
  61. completionQueue.name = "Handler"
  62. }
  63. deinit {
  64. cgrpc_handler_destroy(self.underlyingHandler)
  65. }
  66. /// Requests a call for the handler
  67. ///
  68. /// Fills the handler properties with information about the received request
  69. ///
  70. func requestCall(tag: Int) throws {
  71. let error = cgrpc_handler_request_call(underlyingHandler, requestMetadata.underlyingArray, tag)
  72. if error != GRPC_CALL_OK {
  73. throw CallError.callError(grpcCallError: error)
  74. }
  75. }
  76. /// Receive the message sent with a call
  77. ///
  78. public func receiveMessage(initialMetadata: Metadata,
  79. completion: @escaping (Data?) throws -> Void) throws {
  80. let operations = OperationGroup(call: call,
  81. operations: [
  82. .sendInitialMetadata(initialMetadata),
  83. .receiveMessage
  84. ]) { operationGroup in
  85. if operationGroup.success {
  86. try completion(operationGroup.receivedMessage()?.data())
  87. } else {
  88. try completion(nil)
  89. }
  90. }
  91. try call.perform(operations)
  92. }
  93. /// Sends the response to a request
  94. ///
  95. /// - Parameter message: the message to send
  96. /// - Parameter statusCode: status code to send
  97. /// - Parameter statusMessage: status message to send
  98. /// - Parameter trailingMetadata: trailing metadata to send
  99. public func sendResponse(message: Data,
  100. statusCode: StatusCode,
  101. statusMessage: String,
  102. trailingMetadata: Metadata) throws {
  103. let messageBuffer = ByteBuffer(data: message)
  104. let operations = OperationGroup(call: call,
  105. operations: [
  106. .receiveCloseOnServer,
  107. .sendStatusFromServer(statusCode, statusMessage, trailingMetadata),
  108. .sendMessage(messageBuffer)
  109. ]) { operationGroup in
  110. // TODO(timburks): Should we also shut down do in case of error?
  111. if operationGroup.success {
  112. self.shutdown()
  113. }
  114. }
  115. try call.perform(operations)
  116. }
  117. /// Sends the response to a request
  118. ///
  119. /// - Parameter statusCode: status code to send
  120. /// - Parameter statusMessage: status message to send
  121. /// - Parameter trailingMetadata: trailing metadata to send
  122. public func sendResponse(statusCode: StatusCode,
  123. statusMessage: String,
  124. trailingMetadata: Metadata) throws {
  125. let operations = OperationGroup(call: call,
  126. operations: [
  127. .receiveCloseOnServer,
  128. .sendStatusFromServer(statusCode, statusMessage, trailingMetadata)
  129. ]) { operationGroup in
  130. // TODO(timburks): Should we also shut down do in case of error?
  131. if operationGroup.success {
  132. self.shutdown()
  133. }
  134. }
  135. try call.perform(operations)
  136. }
  137. /// Shuts down the handler's completion queue
  138. public func shutdown() {
  139. completionQueue.shutdown()
  140. }
  141. /// Send initial metadata in response to a connection
  142. ///
  143. /// - Parameter initialMetadata: initial metadata to send
  144. /// - Parameter completion: a completion handler to call after the metadata has been sent
  145. public func sendMetadata(initialMetadata: Metadata,
  146. completion: ((Bool) throws -> Void)? = nil) throws {
  147. let operations = OperationGroup(call: call,
  148. operations: [.sendInitialMetadata(initialMetadata)],
  149. completion: completion != nil
  150. ? { operationGroup in try completion?(operationGroup.success) }
  151. : nil)
  152. try call.perform(operations)
  153. }
  154. /// Receive the message sent with a call
  155. ///
  156. /// - Parameter completion: a completion handler to call after the message has been received
  157. /// - Returns: a tuple containing status codes and a message (if available)
  158. public func receiveMessage(completion: @escaping (Data?) throws -> Void) throws {
  159. let operations = OperationGroup(call: call, operations: [.receiveMessage]) { operationGroup in
  160. if operationGroup.success {
  161. try completion(operationGroup.receivedMessage()?.data())
  162. } else {
  163. try completion(nil)
  164. }
  165. }
  166. try call.perform(operations)
  167. }
  168. /// Sends the response to a request
  169. ///
  170. /// - Parameter message: the message to send
  171. /// - Parameter completion: a completion handler to call after the response has been sent
  172. public func sendResponse(message: Data,
  173. completion: ((Bool) throws -> Void)? = nil) throws {
  174. let operations = OperationGroup(call: call,
  175. operations: [.sendMessage(ByteBuffer(data: message))],
  176. completion: completion != nil
  177. ? { operationGroup in try completion?(operationGroup.success) }
  178. : nil)
  179. try call.perform(operations)
  180. }
  181. /// Recognize when the client has closed a request
  182. ///
  183. /// - Parameter completion: a completion handler to call after request has been closed
  184. public func receiveClose(completion: @escaping (Bool) throws -> Void) throws {
  185. let operations = OperationGroup(call: call,
  186. operations: [.receiveCloseOnServer]) { operationGroup in
  187. try completion(operationGroup.success)
  188. }
  189. try call.perform(operations)
  190. }
  191. /// Send final status to the client
  192. ///
  193. /// - Parameter statusCode: status code to send
  194. /// - Parameter statusMessage: status message to send
  195. /// - Parameter trailingMetadata: trailing metadata to send
  196. /// - Parameter completion: a completion handler to call after the status has been sent
  197. public func sendStatus(statusCode: StatusCode,
  198. statusMessage: String,
  199. trailingMetadata: Metadata,
  200. completion: ((Bool) -> Void)? = nil) throws {
  201. let operations = OperationGroup(call: call,
  202. operations: [
  203. .sendStatusFromServer(statusCode,
  204. statusMessage,
  205. trailingMetadata)
  206. ], completion: completion != nil
  207. ? { operationGroup in completion?(operationGroup.success) }
  208. : nil)
  209. try call.perform(operations)
  210. }
  211. }
  212. extension Handler: Hashable {
  213. public var hashValue: Int { return underlyingHandler.hashValue }
  214. public static func ==(A: Handler, B: Handler) -> Bool {
  215. return A === B
  216. }
  217. }