blob: f934619c20b997466025bb5b5df79e29c989a72e [file] [log] [blame]
David Garcia Quintas44f32492016-01-14 18:00:04 -08001/*
2 *
David Garcia Quintas61908542016-01-20 11:21:27 -08003 * Copyright 2015-2016, Google Inc.
David Garcia Quintas44f32492016-01-14 18:00:04 -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
David Garcia Quintas08a0a332016-01-21 01:04:36 -080034#ifndef GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H
35#define GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H
David Garcia Quintas44f32492016-01-14 18:00:04 -080036
David Garcia Quintasab5da5e2016-02-09 20:31:37 -080037#include <grpc/impl/codegen/grpc_types.h>
David Garcia Quintas08a0a332016-01-21 01:04:36 -080038#include <grpc++/impl/codegen/call_hook.h>
David Garcia Quintas6bd7b972016-01-27 19:21:12 -080039#include <grpc++/impl/codegen/completion_queue_tag.h>
40#include <grpc++/impl/codegen/rpc_service_method.h>
David Garcia Quintas44f32492016-01-14 18:00:04 -080041
42namespace grpc {
43
David Garcia Quintasa701ed72016-01-19 18:14:29 -080044class AsyncGenericService;
David Garcia Quintas44f32492016-01-14 18:00:04 -080045class GenericServerContext;
David Garcia Quintas44f32492016-01-14 18:00:04 -080046class RpcService;
David Garcia Quintas44f32492016-01-14 18:00:04 -080047class ServerAsyncStreamingInterface;
David Garcia Quintas2425bbb2016-01-25 17:32:48 -080048class ServerCompletionQueue;
David Garcia Quintas44f32492016-01-14 18:00:04 -080049class ServerContext;
David Garcia Quintasa701ed72016-01-19 18:14:29 -080050class ServerCredentials;
51class Service;
David Garcia Quintas44f32492016-01-14 18:00:04 -080052class ThreadPoolInterface;
53
54/// Models a gRPC server.
55///
56/// Servers are configured and started via \a grpc::ServerBuilder.
57class ServerInterface : public CallHook {
58 public:
David Garcia Quintas1f4e72c2016-01-19 14:45:32 -080059 virtual ~ServerInterface() {}
60
David Garcia Quintas44f32492016-01-14 18:00:04 -080061 /// Shutdown the server, blocking until all rpc processing finishes.
62 /// Forcefully terminate pending calls after \a deadline expires.
63 ///
64 /// \param deadline How long to wait until pending rpcs are forcefully
65 /// terminated.
66 template <class T>
67 void Shutdown(const T& deadline) {
68 ShutdownInternal(TimePoint<T>(deadline).raw_time());
69 }
70
71 /// Shutdown the server, waiting for all rpc processing to finish.
72 void Shutdown() { ShutdownInternal(gpr_inf_future(GPR_CLOCK_MONOTONIC)); }
73
74 /// Block waiting for all work to complete.
75 ///
76 /// \warning The server must be either shutting down or some other thread must
77 /// call \a Shutdown for this function to ever return.
78 virtual void Wait() = 0;
79
80 protected:
David Garcia Quintasa701ed72016-01-19 18:14:29 -080081 friend class Service;
David Garcia Quintas44f32492016-01-14 18:00:04 -080082
83 /// Register a service. This call does not take ownership of the service.
84 /// The service must exist for the lifetime of the Server instance.
David Garcia Quintasa701ed72016-01-19 18:14:29 -080085 virtual bool RegisterService(const grpc::string* host, Service* service) = 0;
David Garcia Quintas44f32492016-01-14 18:00:04 -080086
87 /// Register a generic service. This call does not take ownership of the
88 /// service. The service must exist for the lifetime of the Server instance.
89 virtual void RegisterAsyncGenericService(AsyncGenericService* service) = 0;
90
91 /// Tries to bind \a server to the given \a addr.
92 ///
93 /// It can be invoked multiple times.
94 ///
95 /// \param addr The address to try to bind to the server (eg, localhost:1234,
96 /// 192.168.1.1:31416, [::1]:27182, etc.).
97 /// \params creds The credentials associated with the server.
98 ///
99 /// \return bound port number on sucess, 0 on failure.
100 ///
101 /// \warning It's an error to call this method on an already started server.
David Garcia Quintasf3ddb7c2016-01-20 16:02:22 -0800102 virtual int AddListeningPort(const grpc::string& addr,
103 ServerCredentials* creds) = 0;
David Garcia Quintas44f32492016-01-14 18:00:04 -0800104
105 /// Start the server.
106 ///
107 /// \param cqs Completion queues for handling asynchronous services. The
108 /// caller is required to keep all completion queues live until the server is
109 /// destroyed.
110 /// \param num_cqs How many completion queues does \a cqs hold.
111 ///
112 /// \return true on a successful shutdown.
113 virtual bool Start(ServerCompletionQueue** cqs, size_t num_cqs) = 0;
114
115 /// Process one or more incoming calls.
116 virtual void RunRpc() = 0;
117
118 /// Schedule \a RunRpc to run in the threadpool.
119 virtual void ScheduleCallback() = 0;
120
121 virtual void ShutdownInternal(gpr_timespec deadline) = 0;
122
123 virtual int max_message_size() const = 0;
124
125 virtual grpc_server* server() = 0;
126
127 virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
128
129 class BaseAsyncRequest : public CompletionQueueTag {
130 public:
131 BaseAsyncRequest(ServerInterface* server, ServerContext* context,
132 ServerAsyncStreamingInterface* stream,
133 CompletionQueue* call_cq, void* tag,
134 bool delete_on_finalize);
135 virtual ~BaseAsyncRequest() {}
136
137 bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
138
139 protected:
140 ServerInterface* const server_;
141 ServerContext* const context_;
142 ServerAsyncStreamingInterface* const stream_;
143 CompletionQueue* const call_cq_;
144 void* const tag_;
145 const bool delete_on_finalize_;
146 grpc_call* call_;
147 grpc_metadata_array initial_metadata_array_;
148 };
149
150 class RegisteredAsyncRequest : public BaseAsyncRequest {
151 public:
152 RegisteredAsyncRequest(ServerInterface* server, ServerContext* context,
153 ServerAsyncStreamingInterface* stream,
154 CompletionQueue* call_cq, void* tag);
155
156 // uses BaseAsyncRequest::FinalizeResult
157
158 protected:
159 void IssueRequest(void* registered_method, grpc_byte_buffer** payload,
160 ServerCompletionQueue* notification_cq);
161 };
162
163 class NoPayloadAsyncRequest GRPC_FINAL : public RegisteredAsyncRequest {
164 public:
165 NoPayloadAsyncRequest(void* registered_method, ServerInterface* server,
166 ServerContext* context,
167 ServerAsyncStreamingInterface* stream,
168 CompletionQueue* call_cq,
169 ServerCompletionQueue* notification_cq, void* tag)
170 : RegisteredAsyncRequest(server, context, stream, call_cq, tag) {
171 IssueRequest(registered_method, nullptr, notification_cq);
172 }
173
174 // uses RegisteredAsyncRequest::FinalizeResult
175 };
176
177 template <class Message>
178 class PayloadAsyncRequest GRPC_FINAL : public RegisteredAsyncRequest {
179 public:
180 PayloadAsyncRequest(void* registered_method, ServerInterface* server,
181 ServerContext* context,
182 ServerAsyncStreamingInterface* stream,
183 CompletionQueue* call_cq,
184 ServerCompletionQueue* notification_cq, void* tag,
185 Message* request)
186 : RegisteredAsyncRequest(server, context, stream, call_cq, tag),
187 request_(request) {
188 IssueRequest(registered_method, &payload_, notification_cq);
189 }
190
191 bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
192 bool serialization_status =
193 *status && payload_ &&
194 SerializationTraits<Message>::Deserialize(
195 payload_, request_, server_->max_message_size()).ok();
196 bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
197 *status = serialization_status&&* status;
198 return ret;
199 }
200
201 private:
202 grpc_byte_buffer* payload_;
203 Message* const request_;
204 };
205
206 class GenericAsyncRequest : public BaseAsyncRequest {
207 public:
208 GenericAsyncRequest(ServerInterface* server, GenericServerContext* context,
209 ServerAsyncStreamingInterface* stream,
210 CompletionQueue* call_cq,
211 ServerCompletionQueue* notification_cq, void* tag,
212 bool delete_on_finalize);
213
214 bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
215
216 private:
217 grpc_call_details call_details_;
218 };
219
220 template <class Message>
David Garcia Quintasa701ed72016-01-19 18:14:29 -0800221 void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context,
David Garcia Quintas44f32492016-01-14 18:00:04 -0800222 ServerAsyncStreamingInterface* stream,
223 CompletionQueue* call_cq,
224 ServerCompletionQueue* notification_cq, void* tag,
225 Message* message) {
David Garcia Quintasa701ed72016-01-19 18:14:29 -0800226 GPR_ASSERT(method);
227 new PayloadAsyncRequest<Message>(method->server_tag(), this, context,
228 stream, call_cq, notification_cq, tag,
229 message);
David Garcia Quintas44f32492016-01-14 18:00:04 -0800230 }
231
David Garcia Quintasa701ed72016-01-19 18:14:29 -0800232 void RequestAsyncCall(RpcServiceMethod* method, ServerContext* context,
David Garcia Quintas44f32492016-01-14 18:00:04 -0800233 ServerAsyncStreamingInterface* stream,
234 CompletionQueue* call_cq,
235 ServerCompletionQueue* notification_cq, void* tag) {
David Garcia Quintasa701ed72016-01-19 18:14:29 -0800236 GPR_ASSERT(method);
237 new NoPayloadAsyncRequest(method->server_tag(), this, context, stream,
238 call_cq, notification_cq, tag);
David Garcia Quintas44f32492016-01-14 18:00:04 -0800239 }
240
241 void RequestAsyncGenericCall(GenericServerContext* context,
242 ServerAsyncStreamingInterface* stream,
243 CompletionQueue* call_cq,
244 ServerCompletionQueue* notification_cq,
245 void* tag) {
246 new GenericAsyncRequest(this, context, stream, call_cq, notification_cq,
247 tag, true);
248 }
249};
250
251} // namespace grpc
252
David Garcia Quintas08a0a332016-01-21 01:04:36 -0800253#endif // GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H