blob: 21ac6c4fb5545c7c3b73b2291ca9272d182a37b2 [file] [log] [blame]
David Garcia Quintas6bd7b972016-01-27 19:21:12 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
David Garcia Quintas6bd7b972016-01-27 19:21:12 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
35#define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
36
David Garcia Quintas6848c4e2016-03-07 17:10:57 -080037#include <grpc++/impl/codegen/core_codegen_interface.h>
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080038#include <grpc++/impl/codegen/rpc_service_method.h>
39#include <grpc++/impl/codegen/sync_stream.h>
40
41namespace grpc {
42
43// A wrapper class of an application provided rpc method handler.
44template <class ServiceType, class RequestType, class ResponseType>
45class RpcMethodHandler : public MethodHandler {
46 public:
Jan Tattermuschb85e9d42016-05-11 10:21:45 -070047 RpcMethodHandler(std::function<Status(ServiceType*, ServerContext*,
48 const RequestType*, ResponseType*)>
49 func,
50 ServiceType* service)
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080051 : func_(func), service_(service) {}
52
53 void RunHandler(const HandlerParameter& param) GRPC_FINAL {
54 RequestType req;
55 Status status = SerializationTraits<RequestType>::Deserialize(
56 param.request, &req, param.max_message_size);
57 ResponseType rsp;
58 if (status.ok()) {
59 status = func_(service_, param.server_context, &req, &rsp);
60 }
61
David Garcia Quintas6848c4e2016-03-07 17:10:57 -080062 GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080063 CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
Craig Tillerf40df232016-03-25 13:38:14 -070064 CallOpServerSendStatus>
65 ops;
Craig Tiller399b3c42016-04-01 12:24:18 -070066 ops.SendInitialMetadata(param.server_context->initial_metadata_,
67 param.server_context->initial_metadata_flags());
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080068 if (status.ok()) {
69 status = ops.SendMessage(rsp);
70 }
71 ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
72 param.call->PerformOps(&ops);
73 param.call->cq()->Pluck(&ops);
74 }
75
76 private:
77 // Application provided rpc handler function.
78 std::function<Status(ServiceType*, ServerContext*, const RequestType*,
Craig Tillerf40df232016-03-25 13:38:14 -070079 ResponseType*)>
80 func_;
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080081 // The class the above handler function lives in.
82 ServiceType* service_;
83};
84
85// A wrapper class of an application provided client streaming handler.
86template <class ServiceType, class RequestType, class ResponseType>
87class ClientStreamingHandler : public MethodHandler {
88 public:
89 ClientStreamingHandler(
90 std::function<Status(ServiceType*, ServerContext*,
Jan Tattermuschb85e9d42016-05-11 10:21:45 -070091 ServerReader<RequestType>*, ResponseType*)>
92 func,
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080093 ServiceType* service)
94 : func_(func), service_(service) {}
95
96 void RunHandler(const HandlerParameter& param) GRPC_FINAL {
97 ServerReader<RequestType> reader(param.call, param.server_context);
98 ResponseType rsp;
99 Status status = func_(service_, param.server_context, &reader, &rsp);
100
David Garcia Quintas6848c4e2016-03-07 17:10:57 -0800101 GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800102 CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
Craig Tillerf40df232016-03-25 13:38:14 -0700103 CallOpServerSendStatus>
104 ops;
Craig Tiller399b3c42016-04-01 12:24:18 -0700105 ops.SendInitialMetadata(param.server_context->initial_metadata_,
106 param.server_context->initial_metadata_flags());
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800107 if (status.ok()) {
108 status = ops.SendMessage(rsp);
109 }
110 ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
111 param.call->PerformOps(&ops);
112 param.call->cq()->Pluck(&ops);
113 }
114
115 private:
116 std::function<Status(ServiceType*, ServerContext*, ServerReader<RequestType>*,
Craig Tillerf40df232016-03-25 13:38:14 -0700117 ResponseType*)>
118 func_;
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800119 ServiceType* service_;
120};
121
122// A wrapper class of an application provided server streaming handler.
123template <class ServiceType, class RequestType, class ResponseType>
124class ServerStreamingHandler : public MethodHandler {
125 public:
126 ServerStreamingHandler(
127 std::function<Status(ServiceType*, ServerContext*, const RequestType*,
Jan Tattermuschb85e9d42016-05-11 10:21:45 -0700128 ServerWriter<ResponseType>*)>
129 func,
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800130 ServiceType* service)
131 : func_(func), service_(service) {}
132
133 void RunHandler(const HandlerParameter& param) GRPC_FINAL {
134 RequestType req;
135 Status status = SerializationTraits<RequestType>::Deserialize(
136 param.request, &req, param.max_message_size);
137
138 if (status.ok()) {
139 ServerWriter<ResponseType> writer(param.call, param.server_context);
140 status = func_(service_, param.server_context, &req, &writer);
141 }
142
143 CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
144 if (!param.server_context->sent_initial_metadata_) {
Craig Tiller399b3c42016-04-01 12:24:18 -0700145 ops.SendInitialMetadata(param.server_context->initial_metadata_,
146 param.server_context->initial_metadata_flags());
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800147 }
148 ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
149 param.call->PerformOps(&ops);
150 param.call->cq()->Pluck(&ops);
151 }
152
153 private:
154 std::function<Status(ServiceType*, ServerContext*, const RequestType*,
Craig Tillerf40df232016-03-25 13:38:14 -0700155 ServerWriter<ResponseType>*)>
156 func_;
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800157 ServiceType* service_;
158};
159
160// A wrapper class of an application provided bidi-streaming handler.
161template <class ServiceType, class RequestType, class ResponseType>
162class BidiStreamingHandler : public MethodHandler {
163 public:
164 BidiStreamingHandler(
165 std::function<Status(ServiceType*, ServerContext*,
166 ServerReaderWriter<ResponseType, RequestType>*)>
167 func,
168 ServiceType* service)
169 : func_(func), service_(service) {}
170
171 void RunHandler(const HandlerParameter& param) GRPC_FINAL {
172 ServerReaderWriter<ResponseType, RequestType> stream(param.call,
173 param.server_context);
174 Status status = func_(service_, param.server_context, &stream);
175
176 CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
177 if (!param.server_context->sent_initial_metadata_) {
Craig Tiller399b3c42016-04-01 12:24:18 -0700178 ops.SendInitialMetadata(param.server_context->initial_metadata_,
179 param.server_context->initial_metadata_flags());
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800180 }
181 ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
182 param.call->PerformOps(&ops);
183 param.call->cq()->Pluck(&ops);
184 }
185
186 private:
187 std::function<Status(ServiceType*, ServerContext*,
Craig Tillerf40df232016-03-25 13:38:14 -0700188 ServerReaderWriter<ResponseType, RequestType>*)>
189 func_;
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800190 ServiceType* service_;
191};
192
193// Handle unknown method by returning UNIMPLEMENTED error.
194class UnknownMethodHandler : public MethodHandler {
195 public:
196 template <class T>
197 static void FillOps(ServerContext* context, T* ops) {
198 Status status(StatusCode::UNIMPLEMENTED, "");
199 if (!context->sent_initial_metadata_) {
Craig Tiller399b3c42016-04-01 12:24:18 -0700200 ops->SendInitialMetadata(context->initial_metadata_,
201 context->initial_metadata_flags());
David Garcia Quintas6bd7b972016-01-27 19:21:12 -0800202 context->sent_initial_metadata_ = true;
203 }
204 ops->ServerSendStatus(context->trailing_metadata_, status);
205 }
206
207 void RunHandler(const HandlerParameter& param) GRPC_FINAL {
208 CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
209 FillOps(param.server_context, &ops);
210 param.call->PerformOps(&ops);
211 param.call->cq()->Pluck(&ops);
212 }
213};
214
215} // namespace grpc
216
217#endif // GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H