Move headers from grpc++ to grpcpp
diff --git a/include/grpcpp/alarm.h b/include/grpcpp/alarm.h
new file mode 100644
index 0000000..f484610
--- /dev/null
+++ b/include/grpcpp/alarm.h
@@ -0,0 +1,87 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/// An Alarm posts the user provided tag to its associated completion queue upon
+/// expiry or cancellation.
+#ifndef GRPCPP_ALARM_H
+#define GRPCPP_ALARM_H
+
+#include <grpc/grpc.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/impl/codegen/time.h>
+#include <grpcpp/impl/grpc_library.h>
+
+namespace grpc {
+
+/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h).
+class Alarm : private GrpcLibraryCodegen {
+ public:
+ /// Create an unset completion queue alarm
+ Alarm();
+
+ /// Destroy the given completion queue alarm, cancelling it in the process.
+ ~Alarm();
+
+ /// DEPRECATED: Create and set a completion queue alarm instance associated to
+ /// \a cq.
+ /// This form is deprecated because it is inherently racy.
+ /// \internal We rely on the presence of \a cq for grpc initialization. If \a
+ /// cq were ever to be removed, a reference to a static
+ /// internal::GrpcLibraryInitializer instance would need to be introduced
+ /// here. \endinternal.
+ template <typename T>
+ Alarm(CompletionQueue* cq, const T& deadline, void* tag) : Alarm() {
+ SetInternal(cq, TimePoint<T>(deadline).raw_time(), tag);
+ }
+
+ /// Trigger an alarm instance on completion queue \a cq at the specified time.
+ /// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel),
+ /// an event with tag \a tag will be added to \a cq. If the alarm expired, the
+ /// event's success bit will be true, false otherwise (ie, upon cancellation).
+ template <typename T>
+ void Set(CompletionQueue* cq, const T& deadline, void* tag) {
+ SetInternal(cq, TimePoint<T>(deadline).raw_time(), tag);
+ }
+
+ /// Alarms aren't copyable.
+ Alarm(const Alarm&) = delete;
+ Alarm& operator=(const Alarm&) = delete;
+
+ /// Alarms are movable.
+ Alarm(Alarm&& rhs) : alarm_(rhs.alarm_) { rhs.alarm_ = nullptr; }
+ Alarm& operator=(Alarm&& rhs) {
+ alarm_ = rhs.alarm_;
+ rhs.alarm_ = nullptr;
+ return *this;
+ }
+
+ /// Cancel a completion queue alarm. Calling this function over an alarm that
+ /// has already fired has no effect.
+ void Cancel();
+
+ private:
+ void SetInternal(CompletionQueue* cq, gpr_timespec deadline, void* tag);
+
+ internal::CompletionQueueTag* alarm_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_ALARM_H
diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h
new file mode 100644
index 0000000..4b45d53
--- /dev/null
+++ b/include/grpcpp/channel.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_CHANNEL_H
+#define GRPCPP_CHANNEL_H
+
+#include <memory>
+
+#include <grpc/grpc.h>
+#include <grpcpp/impl/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+
+struct grpc_channel;
+
+namespace grpc {
+/// Channels represent a connection to an endpoint. Created by \a CreateChannel.
+class Channel final : public ChannelInterface,
+ public internal::CallHook,
+ public std::enable_shared_from_this<Channel>,
+ private GrpcLibraryCodegen {
+ public:
+ ~Channel();
+
+ /// Get the current channel state. If the channel is in IDLE and
+ /// \a try_to_connect is set to true, try to connect.
+ grpc_connectivity_state GetState(bool try_to_connect) override;
+
+ /// Returns the LB policy name, or the empty string if not yet available.
+ grpc::string GetLoadBalancingPolicyName() const;
+
+ /// Returns the service config in JSON form, or the empty string if
+ /// not available.
+ grpc::string GetServiceConfigJSON() const;
+
+ private:
+ template <class InputMessage, class OutputMessage>
+ friend class internal::BlockingUnaryCallImpl;
+ friend std::shared_ptr<Channel> CreateChannelInternal(
+ const grpc::string& host, grpc_channel* c_channel);
+ Channel(const grpc::string& host, grpc_channel* c_channel);
+
+ internal::Call CreateCall(const internal::RpcMethod& method,
+ ClientContext* context,
+ CompletionQueue* cq) override;
+ void PerformOpsOnCall(internal::CallOpSetInterface* ops,
+ internal::Call* call) override;
+ void* RegisterMethod(const char* method) override;
+
+ void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
+ gpr_timespec deadline, CompletionQueue* cq,
+ void* tag) override;
+ bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
+ gpr_timespec deadline) override;
+
+ const grpc::string host_;
+ grpc_channel* const c_channel_; // owned
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_CHANNEL_H
diff --git a/include/grpcpp/client_context.h b/include/grpcpp/client_context.h
new file mode 100644
index 0000000..8c12577
--- /dev/null
+++ b/include/grpcpp/client_context.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistant at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+
+#ifndef GRPCPP_CLIENT_CONTEXT_H
+#define GRPCPP_CLIENT_CONTEXT_H
+
+#include <grpcpp/impl/codegen/client_context.h>
+
+#endif // GRPCPP_CLIENT_CONTEXT_H
diff --git a/include/grpcpp/completion_queue.h b/include/grpcpp/completion_queue.h
new file mode 100644
index 0000000..123b277
--- /dev/null
+++ b/include/grpcpp/completion_queue.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_COMPLETION_QUEUE_H
+#define GRPCPP_COMPLETION_QUEUE_H
+
+#include <grpcpp/impl/codegen/completion_queue.h>
+
+#endif // GRPCPP_COMPLETION_QUEUE_H
diff --git a/include/grpcpp/create_channel.h b/include/grpcpp/create_channel.h
new file mode 100644
index 0000000..7a505a7
--- /dev/null
+++ b/include/grpcpp/create_channel.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_CREATE_CHANNEL_H
+#define GRPCPP_CREATE_CHANNEL_H
+
+#include <memory>
+
+#include <grpcpp/channel.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/support/channel_arguments.h>
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+
+/// Create a new \a Channel pointing to \a target.
+///
+/// \param target The URI of the endpoint to connect to.
+/// \param creds Credentials to use for the created channel. If it does not
+/// hold an object or is invalid, a lame channel (one on which all operations
+/// fail) is returned.
+std::shared_ptr<Channel> CreateChannel(
+ const grpc::string& target,
+ const std::shared_ptr<ChannelCredentials>& creds);
+
+/// Create a new \em custom \a Channel pointing to \a target.
+///
+/// \warning For advanced use and testing ONLY. Override default channel
+/// arguments only if necessary.
+///
+/// \param target The URI of the endpoint to connect to.
+/// \param creds Credentials to use for the created channel. If it does not
+/// hold an object or is invalid, a lame channel (one on which all operations
+/// fail) is returned.
+/// \param args Options for channel creation.
+std::shared_ptr<Channel> CreateCustomChannel(
+ const grpc::string& target,
+ const std::shared_ptr<ChannelCredentials>& creds,
+ const ChannelArguments& args);
+
+} // namespace grpc
+
+#endif // GRPCPP_CREATE_CHANNEL_H
diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h
new file mode 100644
index 0000000..9bf5acc
--- /dev/null
+++ b/include/grpcpp/create_channel_posix.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_CREATE_CHANNEL_POSIX_H
+#define GRPCPP_CREATE_CHANNEL_POSIX_H
+
+#include <memory>
+
+#include <grpc/support/port_platform.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/support/channel_arguments.h>
+
+namespace grpc {
+
+#ifdef GPR_SUPPORT_CHANNELS_FROM_FD
+
+/// Create a new \a Channel communicating over the given file descriptor.
+///
+/// \param target The name of the target.
+/// \param fd The file descriptor representing a socket.
+std::shared_ptr<Channel> CreateInsecureChannelFromFd(const grpc::string& target,
+ int fd);
+
+/// Create a new \a Channel communicating over given file descriptor with custom
+/// channel arguments.
+///
+/// \param target The name of the target.
+/// \param fd The file descriptor representing a socket.
+/// \param args Options for channel creation.
+std::shared_ptr<Channel> CreateCustomInsecureChannelFromFd(
+ const grpc::string& target, int fd, const ChannelArguments& args);
+
+#endif // GPR_SUPPORT_CHANNELS_FROM_FD
+
+} // namespace grpc
+
+#endif // GRPCPP_CREATE_CHANNEL_POSIX_H
diff --git a/include/grpcpp/ext/health_check_service_server_builder_option.h b/include/grpcpp/ext/health_check_service_server_builder_option.h
new file mode 100644
index 0000000..dd43b05
--- /dev/null
+++ b/include/grpcpp/ext/health_check_service_server_builder_option.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H
+#define GRPCPP_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H
+
+#include <memory>
+
+#include <grpcpp/health_check_service_interface.h>
+#include <grpcpp/impl/server_builder_option.h>
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+
+class HealthCheckServiceServerBuilderOption : public ServerBuilderOption {
+ public:
+ /// The ownership of \a hc will be taken and transferred to the grpc server.
+ /// To explicitly disable default service, pass in a nullptr.
+ explicit HealthCheckServiceServerBuilderOption(
+ std::unique_ptr<HealthCheckServiceInterface> hc);
+ ~HealthCheckServiceServerBuilderOption() override {}
+ void UpdateArguments(ChannelArguments* args) override;
+ void UpdatePlugins(
+ std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override;
+
+ private:
+ std::unique_ptr<HealthCheckServiceInterface> hc_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_EXT_HEALTH_CHECK_SERVICE_SERVER_BUILDER_OPTION_H
diff --git a/include/grpcpp/ext/proto_server_reflection_plugin.h b/include/grpcpp/ext/proto_server_reflection_plugin.h
new file mode 100644
index 0000000..1cfdc1b
--- /dev/null
+++ b/include/grpcpp/ext/proto_server_reflection_plugin.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H
+#define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H
+
+#include <grpcpp/impl/server_builder_plugin.h>
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+class ServerInitializer;
+class ProtoServerReflection;
+} // namespace grpc
+
+namespace grpc {
+namespace reflection {
+
+class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin {
+ public:
+ ProtoServerReflectionPlugin();
+ ::grpc::string name() override;
+ void InitServer(::grpc::ServerInitializer* si) override;
+ void Finish(::grpc::ServerInitializer* si) override;
+ void ChangeArguments(const ::grpc::string& name, void* value) override;
+ bool has_async_methods() const override;
+ bool has_sync_methods() const override;
+
+ private:
+ std::shared_ptr<grpc::ProtoServerReflection> reflection_service_;
+};
+
+/// Add proto reflection plugin to \a ServerBuilder.
+/// This function should be called at the static initialization time.
+void InitProtoReflectionServerBuilderPlugin();
+
+} // namespace reflection
+} // namespace grpc
+
+#endif // GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H
diff --git a/include/grpcpp/generic/async_generic_service.h b/include/grpcpp/generic/async_generic_service.h
new file mode 100644
index 0000000..7eaa541
--- /dev/null
+++ b/include/grpcpp/generic/async_generic_service.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_GENERIC_ASYNC_GENERIC_SERVICE_H
+#define GRPCPP_GENERIC_ASYNC_GENERIC_SERVICE_H
+
+#include <grpcpp/support/async_stream.h>
+#include <grpcpp/support/byte_buffer.h>
+
+struct grpc_server;
+
+namespace grpc {
+
+typedef ServerAsyncReaderWriter<ByteBuffer, ByteBuffer>
+ GenericServerAsyncReaderWriter;
+
+class GenericServerContext final : public ServerContext {
+ public:
+ const grpc::string& method() const { return method_; }
+ const grpc::string& host() const { return host_; }
+
+ private:
+ friend class Server;
+ friend class ServerInterface;
+
+ grpc::string method_;
+ grpc::string host_;
+};
+
+// A generic service at the server side accepts all RPC methods and hosts. It is
+// typically used in proxies. The generic service can be registered to a server
+// which also has other services.
+// Sample usage:
+// ServerBuilder builder;
+// auto cq = builder.AddCompletionQueue();
+// AsyncGenericService generic_service;
+// builder.RegisterAsyncGeneicService(&generic_service);
+// auto server = builder.BuildAndStart();
+//
+// // request a new call
+// GenericServerContext context;
+// GenericAsyncReaderWriter stream;
+// generic_service.RequestCall(&context, &stream, cq.get(), cq.get(), tag);
+//
+// When tag is retrieved from cq->Next(), context.method() can be used to look
+// at the method and the RPC can be handled accordingly.
+class AsyncGenericService final {
+ public:
+ AsyncGenericService() : server_(nullptr) {}
+
+ void RequestCall(GenericServerContext* ctx,
+ GenericServerAsyncReaderWriter* reader_writer,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag);
+
+ private:
+ friend class Server;
+ Server* server_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_GENERIC_ASYNC_GENERIC_SERVICE_H
diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h
new file mode 100644
index 0000000..92405a4
--- /dev/null
+++ b/include/grpcpp/generic/generic_stub.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_GENERIC_GENERIC_STUB_H
+#define GRPCPP_GENERIC_GENERIC_STUB_H
+
+#include <grpcpp/support/async_stream.h>
+#include <grpcpp/support/async_unary_call.h>
+#include <grpcpp/support/byte_buffer.h>
+
+namespace grpc {
+
+class CompletionQueue;
+typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
+ GenericClientAsyncReaderWriter;
+typedef ClientAsyncResponseReader<ByteBuffer> GenericClientAsyncResponseReader;
+
+/// Generic stubs provide a type-unsafe interface to call gRPC methods
+/// by name.
+class GenericStub final {
+ public:
+ explicit GenericStub(std::shared_ptr<ChannelInterface> channel)
+ : channel_(channel) {}
+
+ /// Setup a call to a named method \a method using \a context, but don't
+ /// start it. Let it be started explicitly with StartCall and a tag.
+ /// The return value only indicates whether or not registration of the call
+ /// succeeded (i.e. the call won't proceed if the return value is nullptr).
+ std::unique_ptr<GenericClientAsyncReaderWriter> PrepareCall(
+ ClientContext* context, const grpc::string& method, CompletionQueue* cq);
+
+ /// Setup a unary call to a named method \a method using \a context, and don't
+ /// start it. Let it be started explicitly with StartCall.
+ /// The return value only indicates whether or not registration of the call
+ /// succeeded (i.e. the call won't proceed if the return value is nullptr).
+ std::unique_ptr<GenericClientAsyncResponseReader> PrepareUnaryCall(
+ ClientContext* context, const grpc::string& method,
+ const ByteBuffer& request, CompletionQueue* cq);
+
+ /// DEPRECATED for multi-threaded use
+ /// Begin a call to a named method \a method using \a context.
+ /// A tag \a tag will be delivered to \a cq when the call has been started
+ /// (i.e, initial metadata has been sent).
+ /// The return value only indicates whether or not registration of the call
+ /// succeeded (i.e. the call won't proceed if the return value is nullptr).
+ std::unique_ptr<GenericClientAsyncReaderWriter> Call(
+ ClientContext* context, const grpc::string& method, CompletionQueue* cq,
+ void* tag);
+
+ private:
+ std::shared_ptr<ChannelInterface> channel_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_GENERIC_GENERIC_STUB_H
diff --git a/include/grpcpp/grpcpp.h b/include/grpcpp/grpcpp.h
new file mode 100644
index 0000000..aa8a242
--- /dev/null
+++ b/include/grpcpp/grpcpp.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/// \mainpage gRPC C++ API
+///
+/// The gRPC C++ API mainly consists of the following classes:
+/// <br>
+/// - grpc::Channel, which represents the connection to an endpoint. See [the
+/// gRPC Concepts page](https://grpc.io/docs/guides/concepts.html) for more
+/// details. Channels are created by the factory function grpc::CreateChannel.
+///
+/// - grpc::CompletionQueue, the producer-consumer queue used for all
+/// asynchronous communication with the gRPC runtime.
+///
+/// - grpc::ClientContext and grpc::ServerContext, where optional configuration
+/// for an RPC can be set, such as setting custom metadata to be conveyed to the
+/// peer, compression settings, authentication, etc.
+///
+/// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder.
+///
+/// Streaming calls are handled with the streaming classes in
+/// \ref sync_stream.h and
+/// \ref async_stream.h.
+///
+/// Refer to the
+/// [examples](https://github.com/grpc/grpc/blob/master/examples/cpp)
+/// for code putting these pieces into play.
+
+#ifndef GRPCPP_GRPCPP_H
+#define GRPCPP_GRPCPP_H
+
+// Pragma for http://include-what-you-use.org/ tool, tells that following
+// headers are not private for grpcpp.h and are part of its interface.
+// IWYU pragma: begin_exports
+#include <grpc/grpc.h>
+
+#include <grpcpp/channel.h>
+#include <grpcpp/client_context.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/create_channel_posix.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/server_context.h>
+#include <grpcpp/server_posix.h>
+// IWYU pragma: end_exports
+
+namespace grpc {
+/// Return gRPC library version.
+grpc::string Version();
+} // namespace grpc
+
+#endif // GRPCPP_GRPCPP_H
diff --git a/include/grpcpp/health_check_service_interface.h b/include/grpcpp/health_check_service_interface.h
new file mode 100644
index 0000000..b45a699
--- /dev/null
+++ b/include/grpcpp/health_check_service_interface.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H
+#define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H
+
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+
+const char kHealthCheckServiceInterfaceArg[] =
+ "grpc.health_check_service_interface";
+
+/// The gRPC server uses this interface to expose the health checking service
+/// without depending on protobuf.
+class HealthCheckServiceInterface {
+ public:
+ virtual ~HealthCheckServiceInterface() {}
+
+ /// Set or change the serving status of the given \a service_name.
+ virtual void SetServingStatus(const grpc::string& service_name,
+ bool serving) = 0;
+ /// Apply to all registered service names.
+ virtual void SetServingStatus(bool serving) = 0;
+};
+
+/// Enable/disable the default health checking service. This applies to all C++
+/// servers created afterwards. For each server, user can override the default
+/// with a HealthCheckServiceServerBuilderOption.
+/// NOT thread safe.
+void EnableDefaultHealthCheckService(bool enable);
+
+/// Returns whether the default health checking service is enabled.
+/// NOT thread safe.
+bool DefaultHealthCheckServiceEnabled();
+
+} // namespace grpc
+
+#endif // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H
diff --git a/include/grpcpp/impl/README.md b/include/grpcpp/impl/README.md
new file mode 100644
index 0000000..612150c
--- /dev/null
+++ b/include/grpcpp/impl/README.md
@@ -0,0 +1,4 @@
+**The APIs in this directory are not stable!**
+
+This directory contains header files that need to be installed but are not part
+of the public API. Users should not use these headers directly.
diff --git a/include/grpcpp/impl/call.h b/include/grpcpp/impl/call.h
new file mode 100644
index 0000000..a6b1312
--- /dev/null
+++ b/include/grpcpp/impl/call.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CALL_H
+#define GRPCPP_IMPL_CALL_H
+
+#include <grpcpp/impl/codegen/call.h>
+
+#endif // GRPCPP_IMPL_CALL_H
diff --git a/include/grpcpp/impl/channel_argument_option.h b/include/grpcpp/impl/channel_argument_option.h
new file mode 100644
index 0000000..0c48824
--- /dev/null
+++ b/include/grpcpp/impl/channel_argument_option.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CHANNEL_ARGUMENT_OPTION_H
+#define GRPCPP_IMPL_CHANNEL_ARGUMENT_OPTION_H
+
+#include <map>
+#include <memory>
+
+#include <grpcpp/impl/server_builder_option.h>
+#include <grpcpp/support/channel_arguments.h>
+
+namespace grpc {
+
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+ const grpc::string& name, const grpc::string& value);
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+ const grpc::string& name, int value);
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CHANNEL_ARGUMENT_OPTION_H
diff --git a/include/grpcpp/impl/client_unary_call.h b/include/grpcpp/impl/client_unary_call.h
new file mode 100644
index 0000000..378482c
--- /dev/null
+++ b/include/grpcpp/impl/client_unary_call.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CLIENT_UNARY_CALL_H
+#define GRPCPP_IMPL_CLIENT_UNARY_CALL_H
+
+#include <grpcpp/impl/codegen/client_unary_call.h>
+
+#endif // GRPCPP_IMPL_CLIENT_UNARY_CALL_H
diff --git a/include/grpcpp/impl/codegen/async_stream.h b/include/grpcpp/impl/codegen/async_stream.h
new file mode 100644
index 0000000..b213459
--- /dev/null
+++ b/include/grpcpp/impl/codegen/async_stream.h
@@ -0,0 +1,1068 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_ASYNC_STREAM_H
+#define GRPCPP_IMPL_CODEGEN_ASYNC_STREAM_H
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class CompletionQueue;
+
+namespace internal {
+/// Common interface for all client side asynchronous streaming.
+class ClientAsyncStreamingInterface {
+ public:
+ virtual ~ClientAsyncStreamingInterface() {}
+
+ /// Start the call that was set up by the constructor, but only if the
+ /// constructor was invoked through the "Prepare" API which doesn't actually
+ /// start the call
+ virtual void StartCall(void* tag) = 0;
+
+ /// Request notification of the reading of the initial metadata. Completion
+ /// will be notified by \a tag on the associated completion queue.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a AsyncReaderInterface::Read method.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ virtual void ReadInitialMetadata(void* tag) = 0;
+
+ /// Indicate that the stream is to be finished and request notification for
+ /// when the call has been ended.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when both:
+ /// * the client side has no more message to send
+ /// (this can be declared implicitly by calling this method, or
+ /// explicitly through an earlier call to the <i>WritesDone</i> method
+ /// of the class in use, e.g. \a ClientAsyncWriterInterface::WritesDone or
+ /// \a ClientAsyncReaderWriterInterface::WritesDone).
+ /// * there are no more messages to be received from the server (this can
+ /// be known implicitly by the calling code, or explicitly from an
+ /// earlier call to \a AsyncReaderInterface::Read that yielded a failed
+ /// result, e.g. cq->Next(&read_tag, &ok) filled in 'ok' with 'false').
+ ///
+ /// This function will return when either:
+ /// - all incoming messages have been read and the server has returned
+ /// a status.
+ /// - the server has returned a non-OK status.
+ /// - the call failed for some reason and the library generated a
+ /// status.
+ ///
+ /// Note that implementations of this method attempt to receive initial
+ /// metadata from the server if initial metadata hasn't yet been received.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[out] status To be updated with the operation status.
+ virtual void Finish(Status* status, void* tag) = 0;
+};
+
+/// An interface that yields a sequence of messages of type \a R.
+template <class R>
+class AsyncReaderInterface {
+ public:
+ virtual ~AsyncReaderInterface() {}
+
+ /// Read a message of type \a R into \a msg. Completion will be notified by \a
+ /// tag on the associated completion queue.
+ /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+ /// should not be called concurrently with other streaming APIs
+ /// on the same stream. It is not meaningful to call it concurrently
+ /// with another \a AsyncReaderInterface::Read on the same stream since reads
+ /// on the same stream are delivered in order.
+ ///
+ /// \param[out] msg Where to eventually store the read message.
+ /// \param[in] tag The tag identifying the operation.
+ ///
+ /// Side effect: note that this method attempt to receive initial metadata for
+ /// a stream if it hasn't yet been received.
+ virtual void Read(R* msg, void* tag) = 0;
+};
+
+/// An interface that can be fed a sequence of messages of type \a W.
+template <class W>
+class AsyncWriterInterface {
+ public:
+ virtual ~AsyncWriterInterface() {}
+
+ /// Request the writing of \a msg with identifying tag \a tag.
+ ///
+ /// Only one write may be outstanding at any given time. This means that
+ /// after calling Write, one must wait to receive \a tag from the completion
+ /// queue BEFORE calling Write again.
+ /// This is thread-safe with respect to \a AsyncReaderInterface::Read
+ ///
+ /// \param[in] msg The message to be written.
+ /// \param[in] tag The tag identifying the operation.
+ virtual void Write(const W& msg, void* tag) = 0;
+
+ /// Request the writing of \a msg using WriteOptions \a options with
+ /// identifying tag \a tag.
+ ///
+ /// Only one write may be outstanding at any given time. This means that
+ /// after calling Write, one must wait to receive \a tag from the completion
+ /// queue BEFORE calling Write again.
+ /// WriteOptions \a options is used to set the write options of this message.
+ /// This is thread-safe with respect to \a AsyncReaderInterface::Read
+ ///
+ /// \param[in] msg The message to be written.
+ /// \param[in] options The WriteOptions to be used to write this message.
+ /// \param[in] tag The tag identifying the operation.
+ virtual void Write(const W& msg, WriteOptions options, void* tag) = 0;
+
+ /// Request the writing of \a msg and coalesce it with the writing
+ /// of trailing metadata, using WriteOptions \a options with
+ /// identifying tag \a tag.
+ ///
+ /// For client, WriteLast is equivalent of performing Write and
+ /// WritesDone in a single step.
+ /// For server, WriteLast buffers the \a msg. The writing of \a msg is held
+ /// until Finish is called, where \a msg and trailing metadata are coalesced
+ /// and write is initiated. Note that WriteLast can only buffer \a msg up to
+ /// the flow control window size. If \a msg size is larger than the window
+ /// size, it will be sent on wire without buffering.
+ ///
+ /// \param[in] msg The message to be written.
+ /// \param[in] options The WriteOptions to be used to write this message.
+ /// \param[in] tag The tag identifying the operation.
+ void WriteLast(const W& msg, WriteOptions options, void* tag) {
+ Write(msg, options.set_last_message(), tag);
+ }
+};
+
+} // namespace internal
+
+template <class R>
+class ClientAsyncReaderInterface
+ : public internal::ClientAsyncStreamingInterface,
+ public internal::AsyncReaderInterface<R> {};
+
+namespace internal {
+template <class R>
+class ClientAsyncReaderFactory {
+ public:
+ /// Create a stream object.
+ /// Write the first request out if \a start is set.
+ /// \a tag will be notified on \a cq when the call has been started and
+ /// \a request has been written out. If \a start is not set, \a tag must be
+ /// nullptr and the actual call must be initiated by StartCall
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
+ template <class W>
+ static ClientAsyncReader<R>* Create(ChannelInterface* channel,
+ CompletionQueue* cq,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context, const W& request,
+ bool start, void* tag) {
+ ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+ return new (g_core_codegen_interface->grpc_call_arena_alloc(
+ call.call(), sizeof(ClientAsyncReader<R>)))
+ ClientAsyncReader<R>(call, context, request, start, tag);
+ }
+};
+} // namespace internal
+
+/// Async client-side API for doing server-streaming RPCs,
+/// where the incoming message stream coming from the server has
+/// messages of type \a R.
+template <class R>
+class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
+ public:
+ // always allocated against a call arena, no memory free required
+ static void operator delete(void* ptr, std::size_t size) {
+ assert(size == sizeof(ClientAsyncReader));
+ }
+
+ void StartCall(void* tag) override {
+ assert(!started_);
+ started_ = true;
+ StartCallInternal(tag);
+ }
+
+ /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata
+ /// method for semantics.
+ ///
+ /// Side effect:
+ /// - upon receiving initial metadata from the server,
+ /// the \a ClientContext associated with this call is updated, and the
+ /// calling code can access the received metadata through the
+ /// \a ClientContext.
+ void ReadInitialMetadata(void* tag) override {
+ assert(started_);
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ meta_ops_.set_output_tag(tag);
+ meta_ops_.RecvInitialMetadata(context_);
+ call_.PerformOps(&meta_ops_);
+ }
+
+ void Read(R* msg, void* tag) override {
+ assert(started_);
+ read_ops_.set_output_tag(tag);
+ if (!context_->initial_metadata_received_) {
+ read_ops_.RecvInitialMetadata(context_);
+ }
+ read_ops_.RecvMessage(msg);
+ call_.PerformOps(&read_ops_);
+ }
+
+ /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata received from the server.
+ void Finish(Status* status, void* tag) override {
+ assert(started_);
+ finish_ops_.set_output_tag(tag);
+ if (!context_->initial_metadata_received_) {
+ finish_ops_.RecvInitialMetadata(context_);
+ }
+ finish_ops_.ClientRecvStatus(context_, status);
+ call_.PerformOps(&finish_ops_);
+ }
+
+ private:
+ friend class internal::ClientAsyncReaderFactory<R>;
+ template <class W>
+ ClientAsyncReader(::grpc::internal::Call call, ClientContext* context,
+ const W& request, bool start, void* tag)
+ : context_(context), call_(call), started_(start) {
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
+ init_ops_.ClientSendClose();
+ if (start) {
+ StartCallInternal(tag);
+ } else {
+ assert(tag == nullptr);
+ }
+ }
+
+ void StartCallInternal(void* tag) {
+ init_ops_.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ init_ops_.set_output_tag(tag);
+ call_.PerformOps(&init_ops_);
+ }
+
+ ClientContext* context_;
+ ::grpc::internal::Call call_;
+ bool started_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ init_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ meta_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpRecvMessage<R>>
+ read_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpClientRecvStatus>
+ finish_ops_;
+};
+
+/// Common interface for client side asynchronous writing.
+template <class W>
+class ClientAsyncWriterInterface
+ : public internal::ClientAsyncStreamingInterface,
+ public internal::AsyncWriterInterface<W> {
+ public:
+ /// Signal the client is done with the writes (half-close the client stream).
+ /// Thread-safe with respect to \a AsyncReaderInterface::Read
+ ///
+ /// \param[in] tag The tag identifying the operation.
+ virtual void WritesDone(void* tag) = 0;
+};
+
+namespace internal {
+template <class W>
+class ClientAsyncWriterFactory {
+ public:
+ /// Create a stream object.
+ /// Start the RPC if \a start is set
+ /// \a tag will be notified on \a cq when the call has been started (i.e.
+ /// intitial metadata sent) and \a request has been written out.
+ /// If \a start is not set, \a tag must be nullptr and the actual call
+ /// must be initiated by StartCall
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
+ /// \a response will be filled in with the single expected response
+ /// message from the server upon a successful call to the \a Finish
+ /// method of this instance.
+ template <class R>
+ static ClientAsyncWriter<W>* Create(ChannelInterface* channel,
+ CompletionQueue* cq,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context, R* response,
+ bool start, void* tag) {
+ ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+ return new (g_core_codegen_interface->grpc_call_arena_alloc(
+ call.call(), sizeof(ClientAsyncWriter<W>)))
+ ClientAsyncWriter<W>(call, context, response, start, tag);
+ }
+};
+} // namespace internal
+
+/// Async API on the client side for doing client-streaming RPCs,
+/// where the outgoing message stream going to the server contains
+/// messages of type \a W.
+template <class W>
+class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
+ public:
+ // always allocated against a call arena, no memory free required
+ static void operator delete(void* ptr, std::size_t size) {
+ assert(size == sizeof(ClientAsyncWriter));
+ }
+
+ void StartCall(void* tag) override {
+ assert(!started_);
+ started_ = true;
+ StartCallInternal(tag);
+ }
+
+ /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for
+ /// semantics.
+ ///
+ /// Side effect:
+ /// - upon receiving initial metadata from the server, the \a ClientContext
+ /// associated with this call is updated, and the calling code can access
+ /// the received metadata through the \a ClientContext.
+ void ReadInitialMetadata(void* tag) override {
+ assert(started_);
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ meta_ops_.set_output_tag(tag);
+ meta_ops_.RecvInitialMetadata(context_);
+ call_.PerformOps(&meta_ops_);
+ }
+
+ void Write(const W& msg, void* tag) override {
+ assert(started_);
+ write_ops_.set_output_tag(tag);
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ void Write(const W& msg, WriteOptions options, void* tag) override {
+ assert(started_);
+ write_ops_.set_output_tag(tag);
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ write_ops_.ClientSendClose();
+ }
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ void WritesDone(void* tag) override {
+ assert(started_);
+ write_ops_.set_output_tag(tag);
+ write_ops_.ClientSendClose();
+ call_.PerformOps(&write_ops_);
+ }
+
+ /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata received from the server.
+ /// - attempts to fill in the \a response parameter passed to this class's
+ /// constructor with the server's response message.
+ void Finish(Status* status, void* tag) override {
+ assert(started_);
+ finish_ops_.set_output_tag(tag);
+ if (!context_->initial_metadata_received_) {
+ finish_ops_.RecvInitialMetadata(context_);
+ }
+ finish_ops_.ClientRecvStatus(context_, status);
+ call_.PerformOps(&finish_ops_);
+ }
+
+ private:
+ friend class internal::ClientAsyncWriterFactory<W>;
+ template <class R>
+ ClientAsyncWriter(::grpc::internal::Call call, ClientContext* context,
+ R* response, bool start, void* tag)
+ : context_(context), call_(call), started_(start) {
+ finish_ops_.RecvMessage(response);
+ finish_ops_.AllowNoMessage();
+ if (start) {
+ StartCallInternal(tag);
+ } else {
+ assert(tag == nullptr);
+ }
+ }
+
+ void StartCallInternal(void* tag) {
+ write_ops_.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ // if corked bit is set in context, we just keep the initial metadata
+ // buffered up to coalesce with later message send. No op is performed.
+ if (!context_->initial_metadata_corked_) {
+ write_ops_.set_output_tag(tag);
+ call_.PerformOps(&write_ops_);
+ }
+ }
+
+ ClientContext* context_;
+ ::grpc::internal::Call call_;
+ bool started_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ meta_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ write_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpGenericRecvMessage,
+ ::grpc::internal::CallOpClientRecvStatus>
+ finish_ops_;
+};
+
+/// Async client-side interface for bi-directional streaming,
+/// where the client-to-server message stream has messages of type \a W,
+/// and the server-to-client message stream has messages of type \a R.
+template <class W, class R>
+class ClientAsyncReaderWriterInterface
+ : public internal::ClientAsyncStreamingInterface,
+ public internal::AsyncWriterInterface<W>,
+ public internal::AsyncReaderInterface<R> {
+ public:
+ /// Signal the client is done with the writes (half-close the client stream).
+ /// Thread-safe with respect to \a AsyncReaderInterface::Read
+ ///
+ /// \param[in] tag The tag identifying the operation.
+ virtual void WritesDone(void* tag) = 0;
+};
+
+namespace internal {
+template <class W, class R>
+class ClientAsyncReaderWriterFactory {
+ public:
+ /// Create a stream object.
+ /// Start the RPC request if \a start is set.
+ /// \a tag will be notified on \a cq when the call has been started (i.e.
+ /// intitial metadata sent). If \a start is not set, \a tag must be
+ /// nullptr and the actual call must be initiated by StartCall
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
+ static ClientAsyncReaderWriter<W, R>* Create(
+ ChannelInterface* channel, CompletionQueue* cq,
+ const ::grpc::internal::RpcMethod& method, ClientContext* context,
+ bool start, void* tag) {
+ ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+
+ return new (g_core_codegen_interface->grpc_call_arena_alloc(
+ call.call(), sizeof(ClientAsyncReaderWriter<W, R>)))
+ ClientAsyncReaderWriter<W, R>(call, context, start, tag);
+ }
+};
+} // namespace internal
+
+/// Async client-side interface for bi-directional streaming,
+/// where the outgoing message stream going to the server
+/// has messages of type \a W, and the incoming message stream coming
+/// from the server has messages of type \a R.
+template <class W, class R>
+class ClientAsyncReaderWriter final
+ : public ClientAsyncReaderWriterInterface<W, R> {
+ public:
+ // always allocated against a call arena, no memory free required
+ static void operator delete(void* ptr, std::size_t size) {
+ assert(size == sizeof(ClientAsyncReaderWriter));
+ }
+
+ void StartCall(void* tag) override {
+ assert(!started_);
+ started_ = true;
+ StartCallInternal(tag);
+ }
+
+ /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method
+ /// for semantics of this method.
+ ///
+ /// Side effect:
+ /// - upon receiving initial metadata from the server, the \a ClientContext
+ /// is updated with it, and then the receiving initial metadata can
+ /// be accessed through this \a ClientContext.
+ void ReadInitialMetadata(void* tag) override {
+ assert(started_);
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ meta_ops_.set_output_tag(tag);
+ meta_ops_.RecvInitialMetadata(context_);
+ call_.PerformOps(&meta_ops_);
+ }
+
+ void Read(R* msg, void* tag) override {
+ assert(started_);
+ read_ops_.set_output_tag(tag);
+ if (!context_->initial_metadata_received_) {
+ read_ops_.RecvInitialMetadata(context_);
+ }
+ read_ops_.RecvMessage(msg);
+ call_.PerformOps(&read_ops_);
+ }
+
+ void Write(const W& msg, void* tag) override {
+ assert(started_);
+ write_ops_.set_output_tag(tag);
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ void Write(const W& msg, WriteOptions options, void* tag) override {
+ assert(started_);
+ write_ops_.set_output_tag(tag);
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ write_ops_.ClientSendClose();
+ }
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ void WritesDone(void* tag) override {
+ assert(started_);
+ write_ops_.set_output_tag(tag);
+ write_ops_.ClientSendClose();
+ call_.PerformOps(&write_ops_);
+ }
+
+ /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+ /// Side effect
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata sent from the server.
+ void Finish(Status* status, void* tag) override {
+ assert(started_);
+ finish_ops_.set_output_tag(tag);
+ if (!context_->initial_metadata_received_) {
+ finish_ops_.RecvInitialMetadata(context_);
+ }
+ finish_ops_.ClientRecvStatus(context_, status);
+ call_.PerformOps(&finish_ops_);
+ }
+
+ private:
+ friend class internal::ClientAsyncReaderWriterFactory<W, R>;
+ ClientAsyncReaderWriter(::grpc::internal::Call call, ClientContext* context,
+ bool start, void* tag)
+ : context_(context), call_(call), started_(start) {
+ if (start) {
+ StartCallInternal(tag);
+ } else {
+ assert(tag == nullptr);
+ }
+ }
+
+ void StartCallInternal(void* tag) {
+ write_ops_.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ // if corked bit is set in context, we just keep the initial metadata
+ // buffered up to coalesce with later message send. No op is performed.
+ if (!context_->initial_metadata_corked_) {
+ write_ops_.set_output_tag(tag);
+ call_.PerformOps(&write_ops_);
+ }
+ }
+
+ ClientContext* context_;
+ ::grpc::internal::Call call_;
+ bool started_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ meta_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpRecvMessage<R>>
+ read_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ write_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpClientRecvStatus>
+ finish_ops_;
+};
+
+template <class W, class R>
+class ServerAsyncReaderInterface
+ : public internal::ServerAsyncStreamingInterface,
+ public internal::AsyncReaderInterface<R> {
+ public:
+ /// Indicate that the stream is to be finished with a certain status code
+ /// and also send out \a msg response to the client.
+ /// Request notification for when the server has sent the response and the
+ /// appropriate signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when:
+ /// * all messages from the client have been received (either known
+ /// implictly, or explicitly because a previous
+ /// \a AsyncReaderInterface::Read operation with a non-ok result,
+ /// e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false').
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), response message, and status, or if
+ /// some failure occurred when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
+ /// \param[in] msg To be sent to the client as the response for this call.
+ virtual void Finish(const W& msg, const Status& status, void* tag) = 0;
+
+ /// Indicate that the stream is to be finished with a certain
+ /// non-OK status code.
+ /// Request notification for when the server has sent the appropriate
+ /// signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// This call is meant to end the call with some error, and can be called at
+ /// any point that the server would like to "fail" the call (though note
+ /// this shouldn't be called concurrently with any other "sending" call, like
+ /// \a AsyncWriterInterface::Write).
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), and status, or if some failure occurred
+ /// when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
+ /// - Note: \a status must have a non-OK code.
+ virtual void FinishWithError(const Status& status, void* tag) = 0;
+};
+
+/// Async server-side API for doing client-streaming RPCs,
+/// where the incoming message stream from the client has messages of type \a R,
+/// and the single response message sent from the server is type \a W.
+template <class W, class R>
+class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
+ public:
+ explicit ServerAsyncReader(ServerContext* ctx)
+ : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ void SendInitialMetadata(void* tag) override {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ meta_ops_.set_output_tag(tag);
+ meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ meta_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_.PerformOps(&meta_ops_);
+ }
+
+ void Read(R* msg, void* tag) override {
+ read_ops_.set_output_tag(tag);
+ read_ops_.RecvMessage(msg);
+ call_.PerformOps(&read_ops_);
+ }
+
+ /// See the \a ServerAsyncReaderInterface.Read method for semantics
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not alreay sent.
+ /// - uses the \a ServerContext associated with this call to send possible
+ /// initial and trailing metadata.
+ ///
+ /// Note: \a msg is not sent if \a status has a non-OK code.
+ void Finish(const W& msg, const Status& status, void* tag) override {
+ finish_ops_.set_output_tag(tag);
+ if (!ctx_->sent_initial_metadata_) {
+ finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ finish_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ // The response is dropped if the status is not OK.
+ if (status.ok()) {
+ finish_ops_.ServerSendStatus(ctx_->trailing_metadata_,
+ finish_ops_.SendMessage(msg));
+ } else {
+ finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ }
+ call_.PerformOps(&finish_ops_);
+ }
+
+ /// See the \a ServerAsyncReaderInterface.Read method for semantics
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not alreay sent.
+ /// - uses the \a ServerContext associated with this call to send possible
+ /// initial and trailing metadata.
+ void FinishWithError(const Status& status, void* tag) override {
+ GPR_CODEGEN_ASSERT(!status.ok());
+ finish_ops_.set_output_tag(tag);
+ if (!ctx_->sent_initial_metadata_) {
+ finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ finish_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ call_.PerformOps(&finish_ops_);
+ }
+
+ private:
+ void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+ ::grpc::internal::Call call_;
+ ServerContext* ctx_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+ meta_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpServerSendStatus>
+ finish_ops_;
+};
+
+template <class W>
+class ServerAsyncWriterInterface
+ : public internal::ServerAsyncStreamingInterface,
+ public internal::AsyncWriterInterface<W> {
+ public:
+ /// Indicate that the stream is to be finished with a certain status code.
+ /// Request notification for when the server has sent the appropriate
+ /// signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when either:
+ /// * all messages from the client have been received (either known
+ /// implictly, or explicitly because a previous \a
+ /// AsyncReaderInterface::Read operation with a non-ok
+ /// result (e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false'.
+ /// * it is desired to end the call early with some non-OK status code.
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), response message, and status, or if
+ /// some failure occurred when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
+ virtual void Finish(const Status& status, void* tag) = 0;
+
+ /// Request the writing of \a msg and coalesce it with trailing metadata which
+ /// contains \a status, using WriteOptions options with
+ /// identifying tag \a tag.
+ ///
+ /// WriteAndFinish is equivalent of performing WriteLast and Finish
+ /// in a single step.
+ ///
+ /// \param[in] msg The message to be written.
+ /// \param[in] options The WriteOptions to be used to write this message.
+ /// \param[in] status The Status that server returns to client.
+ /// \param[in] tag The tag identifying the operation.
+ virtual void WriteAndFinish(const W& msg, WriteOptions options,
+ const Status& status, void* tag) = 0;
+};
+
+/// Async server-side API for doing server streaming RPCs,
+/// where the outgoing message stream from the server has messages of type \a W.
+template <class W>
+class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
+ public:
+ explicit ServerAsyncWriter(ServerContext* ctx)
+ : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ void SendInitialMetadata(void* tag) override {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ meta_ops_.set_output_tag(tag);
+ meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ meta_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_.PerformOps(&meta_ops_);
+ }
+
+ void Write(const W& msg, void* tag) override {
+ write_ops_.set_output_tag(tag);
+ EnsureInitialMetadataSent(&write_ops_);
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ void Write(const W& msg, WriteOptions options, void* tag) override {
+ write_ops_.set_output_tag(tag);
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ }
+
+ EnsureInitialMetadataSent(&write_ops_);
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ /// See the \a ServerAsyncWriterInterface.WriteAndFinish method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used
+ /// for sending trailing (and initial) metadata to the client.
+ ///
+ /// Note: \a status must have an OK code.
+ void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
+ void* tag) override {
+ write_ops_.set_output_tag(tag);
+ EnsureInitialMetadataSent(&write_ops_);
+ options.set_buffer_hint();
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+ write_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ call_.PerformOps(&write_ops_);
+ }
+
+ /// See the \a ServerAsyncWriterInterface.Finish method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used for sending
+ /// trailing (and initial if not already sent) metadata to the client.
+ ///
+ /// Note: there are no restrictions are the code of
+ /// \a status,it may be non-OK
+ void Finish(const Status& status, void* tag) override {
+ finish_ops_.set_output_tag(tag);
+ EnsureInitialMetadataSent(&finish_ops_);
+ finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ call_.PerformOps(&finish_ops_);
+ }
+
+ private:
+ void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+ template <class T>
+ void EnsureInitialMetadataSent(T* ops) {
+ if (!ctx_->sent_initial_metadata_) {
+ ops->SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ops->set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ }
+
+ ::grpc::internal::Call call_;
+ ServerContext* ctx_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+ meta_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpServerSendStatus>
+ write_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpServerSendStatus>
+ finish_ops_;
+};
+
+/// Server-side interface for asynchronous bi-directional streaming.
+template <class W, class R>
+class ServerAsyncReaderWriterInterface
+ : public internal::ServerAsyncStreamingInterface,
+ public internal::AsyncWriterInterface<W>,
+ public internal::AsyncReaderInterface<R> {
+ public:
+ /// Indicate that the stream is to be finished with a certain status code.
+ /// Request notification for when the server has sent the appropriate
+ /// signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when either:
+ /// * all messages from the client have been received (either known
+ /// implictly, or explicitly because a previous \a
+ /// AsyncReaderInterface::Read operation
+ /// with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+ /// with 'false'.
+ /// * it is desired to end the call early with some non-OK status code.
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), response message, and status, or if some
+ /// failure occurred when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
+ virtual void Finish(const Status& status, void* tag) = 0;
+
+ /// Request the writing of \a msg and coalesce it with trailing metadata which
+ /// contains \a status, using WriteOptions options with
+ /// identifying tag \a tag.
+ ///
+ /// WriteAndFinish is equivalent of performing WriteLast and Finish in a
+ /// single step.
+ ///
+ /// \param[in] msg The message to be written.
+ /// \param[in] options The WriteOptions to be used to write this message.
+ /// \param[in] status The Status that server returns to client.
+ /// \param[in] tag The tag identifying the operation.
+ virtual void WriteAndFinish(const W& msg, WriteOptions options,
+ const Status& status, void* tag) = 0;
+};
+
+/// Async server-side API for doing bidirectional streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R, and the outgoing message stream coming from the server has
+/// messages of type \a W.
+template <class W, class R>
+class ServerAsyncReaderWriter final
+ : public ServerAsyncReaderWriterInterface<W, R> {
+ public:
+ explicit ServerAsyncReaderWriter(ServerContext* ctx)
+ : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ void SendInitialMetadata(void* tag) override {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ meta_ops_.set_output_tag(tag);
+ meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ meta_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_.PerformOps(&meta_ops_);
+ }
+
+ void Read(R* msg, void* tag) override {
+ read_ops_.set_output_tag(tag);
+ read_ops_.RecvMessage(msg);
+ call_.PerformOps(&read_ops_);
+ }
+
+ void Write(const W& msg, void* tag) override {
+ write_ops_.set_output_tag(tag);
+ EnsureInitialMetadataSent(&write_ops_);
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ void Write(const W& msg, WriteOptions options, void* tag) override {
+ write_ops_.set_output_tag(tag);
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ }
+ EnsureInitialMetadataSent(&write_ops_);
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+ call_.PerformOps(&write_ops_);
+ }
+
+ /// See the \a ServerAsyncReaderWriterInterface.WriteAndFinish
+ /// method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used
+ /// for sending trailing (and initial) metadata to the client.
+ ///
+ /// Note: \a status must have an OK code.
+ void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
+ void* tag) override {
+ write_ops_.set_output_tag(tag);
+ EnsureInitialMetadataSent(&write_ops_);
+ options.set_buffer_hint();
+ GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+ write_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ call_.PerformOps(&write_ops_);
+ }
+
+ /// See the \a ServerAsyncReaderWriterInterface.Finish method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used for sending
+ /// trailing (and initial if not already sent) metadata to the client.
+ ///
+ /// Note: there are no restrictions are the code of \a status,
+ /// it may be non-OK
+ void Finish(const Status& status, void* tag) override {
+ finish_ops_.set_output_tag(tag);
+ EnsureInitialMetadataSent(&finish_ops_);
+
+ finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ call_.PerformOps(&finish_ops_);
+ }
+
+ private:
+ friend class ::grpc::Server;
+
+ void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+ template <class T>
+ void EnsureInitialMetadataSent(T* ops) {
+ if (!ctx_->sent_initial_metadata_) {
+ ops->SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ops->set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ }
+
+ ::grpc::internal::Call call_;
+ ServerContext* ctx_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+ meta_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpServerSendStatus>
+ write_ops_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpServerSendStatus>
+ finish_ops_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_ASYNC_STREAM_H
diff --git a/include/grpcpp/impl/codegen/async_unary_call.h b/include/grpcpp/impl/codegen/async_unary_call.h
new file mode 100644
index 0000000..255f874
--- /dev/null
+++ b/include/grpcpp/impl/codegen/async_unary_call.h
@@ -0,0 +1,309 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
+#define GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
+
+#include <assert.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class CompletionQueue;
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// An interface relevant for async client side unary RPCs (which send
+/// one request message to a server and receive one response message).
+template <class R>
+class ClientAsyncResponseReaderInterface {
+ public:
+ virtual ~ClientAsyncResponseReaderInterface() {}
+
+ /// Start the call that was set up by the constructor, but only if the
+ /// constructor was invoked through the "Prepare" API which doesn't actually
+ /// start the call
+ virtual void StartCall() = 0;
+
+ /// Request notification of the reading of initial metadata. Completion
+ /// will be notified by \a tag on the associated completion queue.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a Finish method.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ virtual void ReadInitialMetadata(void* tag) = 0;
+
+ /// Request to receive the server's response \a msg and final \a status for
+ /// the call, and to notify \a tag on this call's completion queue when
+ /// finished.
+ ///
+ /// This function will return when either:
+ /// - when the server's response message and status have been received.
+ /// - when the server has returned a non-OK status (no message expected in
+ /// this case).
+ /// - when the call failed for some reason and the library generated a
+ /// non-OK status.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[out] status To be updated with the operation status.
+ /// \param[out] msg To be filled in with the server's response message.
+ virtual void Finish(R* msg, Status* status, void* tag) = 0;
+};
+
+namespace internal {
+template <class R>
+class ClientAsyncResponseReaderFactory {
+ public:
+ /// Start a call and write the request out if \a start is set.
+ /// \a tag will be notified on \a cq when the call has been started (i.e.
+ /// intitial metadata sent) and \a request has been written out.
+ /// If \a start is not set, the actual call must be initiated by StartCall
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
+ template <class W>
+ static ClientAsyncResponseReader<R>* Create(
+ ChannelInterface* channel, CompletionQueue* cq,
+ const ::grpc::internal::RpcMethod& method, ClientContext* context,
+ const W& request, bool start) {
+ ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+ return new (g_core_codegen_interface->grpc_call_arena_alloc(
+ call.call(), sizeof(ClientAsyncResponseReader<R>)))
+ ClientAsyncResponseReader<R>(call, context, request, start);
+ }
+};
+} // namespace internal
+
+/// Async API for client-side unary RPCs, where the message response
+/// received from the server is of type \a R.
+template <class R>
+class ClientAsyncResponseReader final
+ : public ClientAsyncResponseReaderInterface<R> {
+ public:
+ // always allocated against a call arena, no memory free required
+ static void operator delete(void* ptr, std::size_t size) {
+ assert(size == sizeof(ClientAsyncResponseReader));
+ }
+
+ // This operator should never be called as the memory should be freed as part
+ // of the arena destruction. It only exists to provide a matching operator
+ // delete to the operator new so that some compilers will not complain (see
+ // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+ // there are no tests catching the compiler warning.
+ static void operator delete(void*, void*) { assert(0); }
+
+ void StartCall() override {
+ assert(!started_);
+ started_ = true;
+ StartCallInternal();
+ }
+
+ /// See \a ClientAsyncResponseReaderInterface::ReadInitialMetadata for
+ /// semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata sent from the server.
+ void ReadInitialMetadata(void* tag) override {
+ assert(started_);
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ meta_buf.set_output_tag(tag);
+ meta_buf.RecvInitialMetadata(context_);
+ call_.PerformOps(&meta_buf);
+ }
+
+ /// See \a ClientAysncResponseReaderInterface::Finish for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata sent from the server.
+ void Finish(R* msg, Status* status, void* tag) override {
+ assert(started_);
+ finish_buf.set_output_tag(tag);
+ if (!context_->initial_metadata_received_) {
+ finish_buf.RecvInitialMetadata(context_);
+ }
+ finish_buf.RecvMessage(msg);
+ finish_buf.AllowNoMessage();
+ finish_buf.ClientRecvStatus(context_, status);
+ call_.PerformOps(&finish_buf);
+ }
+
+ private:
+ friend class internal::ClientAsyncResponseReaderFactory<R>;
+ ClientContext* const context_;
+ ::grpc::internal::Call call_;
+ bool started_;
+
+ template <class W>
+ ClientAsyncResponseReader(::grpc::internal::Call call, ClientContext* context,
+ const W& request, bool start)
+ : context_(context), call_(call), started_(start) {
+ // Bind the metadata at time of StartCallInternal but set up the rest here
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(init_buf.SendMessage(request).ok());
+ init_buf.ClientSendClose();
+ if (start) StartCallInternal();
+ }
+
+ void StartCallInternal() {
+ init_buf.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ call_.PerformOps(&init_buf);
+ }
+
+ // disable operator new
+ static void* operator new(std::size_t size);
+ static void* operator new(std::size_t size, void* p) { return p; }
+
+ ::grpc::internal::SneakyCallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ init_buf;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ meta_buf;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpRecvMessage<R>,
+ ::grpc::internal::CallOpClientRecvStatus>
+ finish_buf;
+};
+
+/// Async server-side API for handling unary calls, where the single
+/// response message sent to the client is of type \a W.
+template <class W>
+class ServerAsyncResponseWriter final
+ : public internal::ServerAsyncStreamingInterface {
+ public:
+ explicit ServerAsyncResponseWriter(ServerContext* ctx)
+ : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Side effect:
+ /// The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ void SendInitialMetadata(void* tag) override {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ meta_buf_.set_output_tag(tag);
+ meta_buf_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ meta_buf_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_.PerformOps(&meta_buf_);
+ }
+
+ /// Indicate that the stream is to be finished and request notification
+ /// when the server has sent the appropriate signals to the client to
+ /// end the call. Should not be used concurrently with other operations.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of the call.
+ /// \param[in] msg Message to be sent to the client.
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not already sent (using the
+ /// \a ServerContext associated with this call).
+ ///
+ /// Note: if \a status has a non-OK code, then \a msg will not be sent,
+ /// and the client will receive only the status with possible trailing
+ /// metadata.
+ void Finish(const W& msg, const Status& status, void* tag) {
+ finish_buf_.set_output_tag(tag);
+ if (!ctx_->sent_initial_metadata_) {
+ finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ finish_buf_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ // The response is dropped if the status is not OK.
+ if (status.ok()) {
+ finish_buf_.ServerSendStatus(ctx_->trailing_metadata_,
+ finish_buf_.SendMessage(msg));
+ } else {
+ finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ }
+ call_.PerformOps(&finish_buf_);
+ }
+
+ /// Indicate that the stream is to be finished with a non-OK status,
+ /// and request notification for when the server has finished sending the
+ /// appropriate signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of the call.
+ /// - Note: \a status must have a non-OK code.
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not already sent (using the
+ /// \a ServerContext associated with this call).
+ void FinishWithError(const Status& status, void* tag) {
+ GPR_CODEGEN_ASSERT(!status.ok());
+ finish_buf_.set_output_tag(tag);
+ if (!ctx_->sent_initial_metadata_) {
+ finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ finish_buf_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);
+ call_.PerformOps(&finish_buf_);
+ }
+
+ private:
+ void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+ ::grpc::internal::Call call_;
+ ServerContext* ctx_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+ meta_buf_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpServerSendStatus>
+ finish_buf_;
+};
+
+} // namespace grpc
+
+namespace std {
+template <class R>
+class default_delete<grpc::ClientAsyncResponseReader<R>> {
+ public:
+ void operator()(void* p) {}
+};
+template <class R>
+class default_delete<grpc::ClientAsyncResponseReaderInterface<R>> {
+ public:
+ void operator()(void* p) {}
+};
+} // namespace std
+
+#endif // GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
diff --git a/include/grpcpp/impl/codegen/byte_buffer.h b/include/grpcpp/impl/codegen/byte_buffer.h
new file mode 100644
index 0000000..8d6a169
--- /dev/null
+++ b/include/grpcpp/impl/codegen/byte_buffer.h
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
+#define GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
+
+#include <grpc/impl/codegen/byte_buffer.h>
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+
+#include <vector>
+
+namespace grpc {
+
+namespace internal {
+class CallOpSendMessage;
+template <class R>
+class CallOpRecvMessage;
+class CallOpGenericRecvMessage;
+class MethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class R>
+class DeserializeFuncType;
+} // namespace internal
+/// A sequence of bytes.
+class ByteBuffer final {
+ public:
+ /// Constuct an empty buffer.
+ ByteBuffer() : buffer_(nullptr) {}
+
+ /// Construct buffer from \a slices, of which there are \a nslices.
+ ByteBuffer(const Slice* slices, size_t nslices);
+
+ /// Constuct a byte buffer by referencing elements of existing buffer
+ /// \a buf. Wrapper of core function grpc_byte_buffer_copy
+ ByteBuffer(const ByteBuffer& buf);
+
+ ~ByteBuffer() {
+ if (buffer_) {
+ g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
+ }
+ }
+
+ ByteBuffer& operator=(const ByteBuffer&);
+
+ /// Dump (read) the buffer contents into \a slices.
+ Status Dump(std::vector<Slice>* slices) const;
+
+ /// Remove all data.
+ void Clear() {
+ if (buffer_) {
+ g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
+ buffer_ = nullptr;
+ }
+ }
+
+ /// Make a duplicate copy of the internals of this byte
+ /// buffer so that we have our own owned version of it.
+ /// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable
+ void Duplicate() {
+ buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(buffer_);
+ }
+
+ /// Forget underlying byte buffer without destroying
+ /// Use this only for un-owned byte buffers
+ void Release() { buffer_ = nullptr; }
+
+ /// Buffer size in bytes.
+ size_t Length() const;
+
+ /// Swap the state of *this and *other.
+ void Swap(ByteBuffer* other);
+
+ /// Is this ByteBuffer valid?
+ bool Valid() const { return (buffer_ != nullptr); }
+
+ private:
+ friend class SerializationTraits<ByteBuffer, void>;
+ friend class internal::CallOpSendMessage;
+ template <class R>
+ friend class internal::CallOpRecvMessage;
+ friend class internal::CallOpGenericRecvMessage;
+ friend class internal::MethodHandler;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class internal::RpcMethodHandler;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class internal::ServerStreamingHandler;
+ template <class R>
+ friend class internal::DeserializeFuncType;
+
+ grpc_byte_buffer* buffer_;
+
+ // takes ownership
+ void set_buffer(grpc_byte_buffer* buf) {
+ if (buffer_) {
+ Clear();
+ }
+ buffer_ = buf;
+ }
+
+ grpc_byte_buffer* c_buffer() { return buffer_; }
+ grpc_byte_buffer** c_buffer_ptr() { return &buffer_; }
+
+ class ByteBufferPointer {
+ public:
+ ByteBufferPointer(const ByteBuffer* b)
+ : bbuf_(const_cast<ByteBuffer*>(b)) {}
+ operator ByteBuffer*() { return bbuf_; }
+ operator grpc_byte_buffer*() { return bbuf_->buffer_; }
+ operator grpc_byte_buffer**() { return &bbuf_->buffer_; }
+
+ private:
+ ByteBuffer* bbuf_;
+ };
+ ByteBufferPointer bbuf_ptr() const { return ByteBufferPointer(this); }
+};
+
+template <>
+class SerializationTraits<ByteBuffer, void> {
+ public:
+ static Status Deserialize(ByteBuffer* byte_buffer, ByteBuffer* dest) {
+ dest->set_buffer(byte_buffer->buffer_);
+ return Status::OK;
+ }
+ static Status Serialize(const ByteBuffer& source, ByteBuffer* buffer,
+ bool* own_buffer) {
+ *buffer = source;
+ *own_buffer = true;
+ return Status::OK;
+ }
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h
new file mode 100644
index 0000000..3b0fd60
--- /dev/null
+++ b/include/grpcpp/impl/codegen/call.h
@@ -0,0 +1,709 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CALL_H
+#define GRPCPP_IMPL_CODEGEN_CALL_H
+
+#include <assert.h>
+#include <cstring>
+#include <functional>
+#include <map>
+#include <memory>
+
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/call_hook.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+#include <grpc/impl/codegen/atm.h>
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/grpc_types.h>
+
+namespace grpc {
+
+class ByteBuffer;
+class CompletionQueue;
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+namespace internal {
+class Call;
+class CallHook;
+
+const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin";
+
+// TODO(yangg) if the map is changed before we send, the pointers will be a
+// mess. Make sure it does not happen.
+inline grpc_metadata* FillMetadataArray(
+ const std::multimap<grpc::string, grpc::string>& metadata,
+ size_t* metadata_count, const grpc::string& optional_error_details) {
+ *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1);
+ if (*metadata_count == 0) {
+ return nullptr;
+ }
+ grpc_metadata* metadata_array =
+ (grpc_metadata*)(g_core_codegen_interface->gpr_malloc(
+ (*metadata_count) * sizeof(grpc_metadata)));
+ size_t i = 0;
+ for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
+ metadata_array[i].key = SliceReferencingString(iter->first);
+ metadata_array[i].value = SliceReferencingString(iter->second);
+ }
+ if (!optional_error_details.empty()) {
+ metadata_array[i].key =
+ g_core_codegen_interface->grpc_slice_from_static_buffer(
+ kBinaryErrorDetailsKey, sizeof(kBinaryErrorDetailsKey) - 1);
+ metadata_array[i].value = SliceReferencingString(optional_error_details);
+ }
+ return metadata_array;
+}
+} // namespace internal
+
+/// Per-message write options.
+class WriteOptions {
+ public:
+ WriteOptions() : flags_(0), last_message_(false) {}
+ WriteOptions(const WriteOptions& other)
+ : flags_(other.flags_), last_message_(other.last_message_) {}
+
+ /// Clear all flags.
+ inline void Clear() { flags_ = 0; }
+
+ /// Returns raw flags bitset.
+ inline uint32_t flags() const { return flags_; }
+
+ /// Sets flag for the disabling of compression for the next message write.
+ ///
+ /// \sa GRPC_WRITE_NO_COMPRESS
+ inline WriteOptions& set_no_compression() {
+ SetBit(GRPC_WRITE_NO_COMPRESS);
+ return *this;
+ }
+
+ /// Clears flag for the disabling of compression for the next message write.
+ ///
+ /// \sa GRPC_WRITE_NO_COMPRESS
+ inline WriteOptions& clear_no_compression() {
+ ClearBit(GRPC_WRITE_NO_COMPRESS);
+ return *this;
+ }
+
+ /// Get value for the flag indicating whether compression for the next
+ /// message write is forcefully disabled.
+ ///
+ /// \sa GRPC_WRITE_NO_COMPRESS
+ inline bool get_no_compression() const {
+ return GetBit(GRPC_WRITE_NO_COMPRESS);
+ }
+
+ /// Sets flag indicating that the write may be buffered and need not go out on
+ /// the wire immediately.
+ ///
+ /// \sa GRPC_WRITE_BUFFER_HINT
+ inline WriteOptions& set_buffer_hint() {
+ SetBit(GRPC_WRITE_BUFFER_HINT);
+ return *this;
+ }
+
+ /// Clears flag indicating that the write may be buffered and need not go out
+ /// on the wire immediately.
+ ///
+ /// \sa GRPC_WRITE_BUFFER_HINT
+ inline WriteOptions& clear_buffer_hint() {
+ ClearBit(GRPC_WRITE_BUFFER_HINT);
+ return *this;
+ }
+
+ /// Get value for the flag indicating that the write may be buffered and need
+ /// not go out on the wire immediately.
+ ///
+ /// \sa GRPC_WRITE_BUFFER_HINT
+ inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
+
+ /// corked bit: aliases set_buffer_hint currently, with the intent that
+ /// set_buffer_hint will be removed in the future
+ inline WriteOptions& set_corked() {
+ SetBit(GRPC_WRITE_BUFFER_HINT);
+ return *this;
+ }
+
+ inline WriteOptions& clear_corked() {
+ ClearBit(GRPC_WRITE_BUFFER_HINT);
+ return *this;
+ }
+
+ inline bool is_corked() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
+
+ /// last-message bit: indicates this is the last message in a stream
+ /// client-side: makes Write the equivalent of performing Write, WritesDone
+ /// in a single step
+ /// server-side: hold the Write until the service handler returns (sync api)
+ /// or until Finish is called (async api)
+ inline WriteOptions& set_last_message() {
+ last_message_ = true;
+ return *this;
+ }
+
+ /// Clears flag indicating that this is the last message in a stream,
+ /// disabling coalescing.
+ inline WriteOptions& clear_last_message() {
+ last_message_ = false;
+ return *this;
+ }
+
+ /// Guarantee that all bytes have been written to the wire before completing
+ /// this write (usually writes are completed when they pass flow control)
+ inline WriteOptions& set_write_through() {
+ SetBit(GRPC_WRITE_THROUGH);
+ return *this;
+ }
+
+ inline bool is_write_through() const { return GetBit(GRPC_WRITE_THROUGH); }
+
+ /// Get value for the flag indicating that this is the last message, and
+ /// should be coalesced with trailing metadata.
+ ///
+ /// \sa GRPC_WRITE_LAST_MESSAGE
+ bool is_last_message() const { return last_message_; }
+
+ WriteOptions& operator=(const WriteOptions& rhs) {
+ flags_ = rhs.flags_;
+ return *this;
+ }
+
+ private:
+ void SetBit(const uint32_t mask) { flags_ |= mask; }
+
+ void ClearBit(const uint32_t mask) { flags_ &= ~mask; }
+
+ bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; }
+
+ uint32_t flags_;
+ bool last_message_;
+};
+
+namespace internal {
+/// Default argument for CallOpSet. I is unused by the class, but can be
+/// used for generating multiple names for the same thing.
+template <int I>
+class CallNoOp {
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {}
+ void FinishOp(bool* status) {}
+};
+
+class CallOpSendInitialMetadata {
+ public:
+ CallOpSendInitialMetadata() : send_(false) {
+ maybe_compression_level_.is_set = false;
+ }
+
+ void SendInitialMetadata(
+ const std::multimap<grpc::string, grpc::string>& metadata,
+ uint32_t flags) {
+ maybe_compression_level_.is_set = false;
+ send_ = true;
+ flags_ = flags;
+ initial_metadata_ =
+ FillMetadataArray(metadata, &initial_metadata_count_, "");
+ }
+
+ void set_compression_level(grpc_compression_level level) {
+ maybe_compression_level_.is_set = true;
+ maybe_compression_level_.level = level;
+ }
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (!send_) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->flags = flags_;
+ op->reserved = NULL;
+ op->data.send_initial_metadata.count = initial_metadata_count_;
+ op->data.send_initial_metadata.metadata = initial_metadata_;
+ op->data.send_initial_metadata.maybe_compression_level.is_set =
+ maybe_compression_level_.is_set;
+ if (maybe_compression_level_.is_set) {
+ op->data.send_initial_metadata.maybe_compression_level.level =
+ maybe_compression_level_.level;
+ }
+ }
+ void FinishOp(bool* status) {
+ if (!send_) return;
+ g_core_codegen_interface->gpr_free(initial_metadata_);
+ send_ = false;
+ }
+
+ bool send_;
+ uint32_t flags_;
+ size_t initial_metadata_count_;
+ grpc_metadata* initial_metadata_;
+ struct {
+ bool is_set;
+ grpc_compression_level level;
+ } maybe_compression_level_;
+};
+
+class CallOpSendMessage {
+ public:
+ CallOpSendMessage() : send_buf_() {}
+
+ /// Send \a message using \a options for the write. The \a options are cleared
+ /// after use.
+ template <class M>
+ Status SendMessage(const M& message,
+ WriteOptions options) GRPC_MUST_USE_RESULT;
+
+ template <class M>
+ Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (!send_buf_.Valid()) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_SEND_MESSAGE;
+ op->flags = write_options_.flags();
+ op->reserved = NULL;
+ op->data.send_message.send_message = send_buf_.c_buffer();
+ // Flags are per-message: clear them after use.
+ write_options_.Clear();
+ }
+ void FinishOp(bool* status) { send_buf_.Clear(); }
+
+ private:
+ ByteBuffer send_buf_;
+ WriteOptions write_options_;
+};
+
+template <class M>
+Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
+ write_options_ = options;
+ bool own_buf;
+ // TODO(vjpai): Remove the void below when possible
+ // The void in the template parameter below should not be needed
+ // (since it should be implicit) but is needed due to an observed
+ // difference in behavior between clang and gcc for certain internal users
+ Status result = SerializationTraits<M, void>::Serialize(
+ message, send_buf_.bbuf_ptr(), &own_buf);
+ if (!own_buf) {
+ send_buf_.Duplicate();
+ }
+ return result;
+}
+
+template <class M>
+Status CallOpSendMessage::SendMessage(const M& message) {
+ return SendMessage(message, WriteOptions());
+}
+
+template <class R>
+class CallOpRecvMessage {
+ public:
+ CallOpRecvMessage()
+ : got_message(false),
+ message_(nullptr),
+ allow_not_getting_message_(false) {}
+
+ void RecvMessage(R* message) { message_ = message; }
+
+ // Do not change status if no message is received.
+ void AllowNoMessage() { allow_not_getting_message_ = true; }
+
+ bool got_message;
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (message_ == nullptr) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->flags = 0;
+ op->reserved = NULL;
+ op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
+ }
+
+ void FinishOp(bool* status) {
+ if (message_ == nullptr) return;
+ if (recv_buf_.Valid()) {
+ if (*status) {
+ got_message = *status =
+ SerializationTraits<R>::Deserialize(recv_buf_.bbuf_ptr(), message_)
+ .ok();
+ recv_buf_.Release();
+ } else {
+ got_message = false;
+ recv_buf_.Clear();
+ }
+ } else {
+ got_message = false;
+ if (!allow_not_getting_message_) {
+ *status = false;
+ }
+ }
+ message_ = nullptr;
+ }
+
+ private:
+ R* message_;
+ ByteBuffer recv_buf_;
+ bool allow_not_getting_message_;
+};
+
+class DeserializeFunc {
+ public:
+ virtual Status Deserialize(ByteBuffer* buf) = 0;
+ virtual ~DeserializeFunc() {}
+};
+
+template <class R>
+class DeserializeFuncType final : public DeserializeFunc {
+ public:
+ DeserializeFuncType(R* message) : message_(message) {}
+ Status Deserialize(ByteBuffer* buf) override {
+ return SerializationTraits<R>::Deserialize(buf->bbuf_ptr(), message_);
+ }
+
+ ~DeserializeFuncType() override {}
+
+ private:
+ R* message_; // Not a managed pointer because management is external to this
+};
+
+class CallOpGenericRecvMessage {
+ public:
+ CallOpGenericRecvMessage()
+ : got_message(false), allow_not_getting_message_(false) {}
+
+ template <class R>
+ void RecvMessage(R* message) {
+ // Use an explicit base class pointer to avoid resolution error in the
+ // following unique_ptr::reset for some old implementations.
+ DeserializeFunc* func = new DeserializeFuncType<R>(message);
+ deserialize_.reset(func);
+ }
+
+ // Do not change status if no message is received.
+ void AllowNoMessage() { allow_not_getting_message_ = true; }
+
+ bool got_message;
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (!deserialize_) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->flags = 0;
+ op->reserved = NULL;
+ op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
+ }
+
+ void FinishOp(bool* status) {
+ if (!deserialize_) return;
+ if (recv_buf_.Valid()) {
+ if (*status) {
+ got_message = true;
+ *status = deserialize_->Deserialize(&recv_buf_).ok();
+ recv_buf_.Release();
+ } else {
+ got_message = false;
+ recv_buf_.Clear();
+ }
+ } else {
+ got_message = false;
+ if (!allow_not_getting_message_) {
+ *status = false;
+ }
+ }
+ deserialize_.reset();
+ }
+
+ private:
+ std::unique_ptr<DeserializeFunc> deserialize_;
+ ByteBuffer recv_buf_;
+ bool allow_not_getting_message_;
+};
+
+class CallOpClientSendClose {
+ public:
+ CallOpClientSendClose() : send_(false) {}
+
+ void ClientSendClose() { send_ = true; }
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (!send_) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op->flags = 0;
+ op->reserved = NULL;
+ }
+ void FinishOp(bool* status) { send_ = false; }
+
+ private:
+ bool send_;
+};
+
+class CallOpServerSendStatus {
+ public:
+ CallOpServerSendStatus() : send_status_available_(false) {}
+
+ void ServerSendStatus(
+ const std::multimap<grpc::string, grpc::string>& trailing_metadata,
+ const Status& status) {
+ send_error_details_ = status.error_details();
+ trailing_metadata_ = FillMetadataArray(
+ trailing_metadata, &trailing_metadata_count_, send_error_details_);
+ send_status_available_ = true;
+ send_status_code_ = static_cast<grpc_status_code>(status.error_code());
+ send_error_message_ = status.error_message();
+ }
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (!send_status_available_) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+ op->data.send_status_from_server.trailing_metadata_count =
+ trailing_metadata_count_;
+ op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
+ op->data.send_status_from_server.status = send_status_code_;
+ error_message_slice_ = SliceReferencingString(send_error_message_);
+ op->data.send_status_from_server.status_details =
+ send_error_message_.empty() ? nullptr : &error_message_slice_;
+ op->flags = 0;
+ op->reserved = NULL;
+ }
+
+ void FinishOp(bool* status) {
+ if (!send_status_available_) return;
+ g_core_codegen_interface->gpr_free(trailing_metadata_);
+ send_status_available_ = false;
+ }
+
+ private:
+ bool send_status_available_;
+ grpc_status_code send_status_code_;
+ grpc::string send_error_details_;
+ grpc::string send_error_message_;
+ size_t trailing_metadata_count_;
+ grpc_metadata* trailing_metadata_;
+ grpc_slice error_message_slice_;
+};
+
+class CallOpRecvInitialMetadata {
+ public:
+ CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
+
+ void RecvInitialMetadata(ClientContext* context) {
+ context->initial_metadata_received_ = true;
+ metadata_map_ = &context->recv_initial_metadata_;
+ }
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (metadata_map_ == nullptr) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
+ op->flags = 0;
+ op->reserved = NULL;
+ }
+
+ void FinishOp(bool* status) {
+ if (metadata_map_ == nullptr) return;
+ metadata_map_->FillMap();
+ metadata_map_ = nullptr;
+ }
+
+ private:
+ MetadataMap* metadata_map_;
+};
+
+class CallOpClientRecvStatus {
+ public:
+ CallOpClientRecvStatus()
+ : recv_status_(nullptr), debug_error_string_(nullptr) {}
+
+ void ClientRecvStatus(ClientContext* context, Status* status) {
+ client_context_ = context;
+ metadata_map_ = &client_context_->trailing_metadata_;
+ recv_status_ = status;
+ error_message_ = g_core_codegen_interface->grpc_empty_slice();
+ }
+
+ protected:
+ void AddOp(grpc_op* ops, size_t* nops) {
+ if (recv_status_ == nullptr) return;
+ grpc_op* op = &ops[(*nops)++];
+ op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
+ op->data.recv_status_on_client.status = &status_code_;
+ op->data.recv_status_on_client.status_details = &error_message_;
+ op->data.recv_status_on_client.error_string = &debug_error_string_;
+ op->flags = 0;
+ op->reserved = NULL;
+ }
+
+ void FinishOp(bool* status) {
+ if (recv_status_ == nullptr) return;
+ metadata_map_->FillMap();
+ grpc::string binary_error_details;
+ auto iter = metadata_map_->map()->find(kBinaryErrorDetailsKey);
+ if (iter != metadata_map_->map()->end()) {
+ binary_error_details =
+ grpc::string(iter->second.begin(), iter->second.length());
+ }
+ *recv_status_ = Status(static_cast<StatusCode>(status_code_),
+ grpc::string(GRPC_SLICE_START_PTR(error_message_),
+ GRPC_SLICE_END_PTR(error_message_)),
+ binary_error_details);
+ client_context_->set_debug_error_string(
+ debug_error_string_ != nullptr ? debug_error_string_ : "");
+ g_core_codegen_interface->grpc_slice_unref(error_message_);
+ if (debug_error_string_ != nullptr) {
+ g_core_codegen_interface->gpr_free((void*)debug_error_string_);
+ }
+ recv_status_ = nullptr;
+ }
+
+ private:
+ ClientContext* client_context_;
+ MetadataMap* metadata_map_;
+ Status* recv_status_;
+ const char* debug_error_string_;
+ grpc_status_code status_code_;
+ grpc_slice error_message_;
+};
+
+/// An abstract collection of call ops, used to generate the
+/// grpc_call_op structure to pass down to the lower layers,
+/// and as it is-a CompletionQueueTag, also massages the final
+/// completion into the correct form for consumption in the C++
+/// API.
+class CallOpSetInterface : public CompletionQueueTag {
+ public:
+ /// Fills in grpc_op, starting from ops[*nops] and moving
+ /// upwards.
+ virtual void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) = 0;
+};
+
+/// Primary implementation of CallOpSetInterface.
+/// Since we cannot use variadic templates, we declare slots up to
+/// the maximum count of ops we'll need in a set. We leverage the
+/// empty base class optimization to slim this class (especially
+/// when there are many unused slots used). To avoid duplicate base classes,
+/// the template parmeter for CallNoOp is varied by argument position.
+template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
+ class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
+ class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
+class CallOpSet : public CallOpSetInterface,
+ public Op1,
+ public Op2,
+ public Op3,
+ public Op4,
+ public Op5,
+ public Op6 {
+ public:
+ CallOpSet() : return_tag_(this), call_(nullptr) {}
+ void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) override {
+ this->Op1::AddOp(ops, nops);
+ this->Op2::AddOp(ops, nops);
+ this->Op3::AddOp(ops, nops);
+ this->Op4::AddOp(ops, nops);
+ this->Op5::AddOp(ops, nops);
+ this->Op6::AddOp(ops, nops);
+ g_core_codegen_interface->grpc_call_ref(call);
+ call_ = call;
+ }
+
+ bool FinalizeResult(void** tag, bool* status) override {
+ this->Op1::FinishOp(status);
+ this->Op2::FinishOp(status);
+ this->Op3::FinishOp(status);
+ this->Op4::FinishOp(status);
+ this->Op5::FinishOp(status);
+ this->Op6::FinishOp(status);
+ *tag = return_tag_;
+
+ g_core_codegen_interface->grpc_call_unref(call_);
+ return true;
+ }
+
+ void set_output_tag(void* return_tag) { return_tag_ = return_tag; }
+
+ private:
+ void* return_tag_;
+ grpc_call* call_;
+};
+
+/// A CallOpSet that does not post completions to the completion queue.
+///
+/// Allows hiding some completions that the C core must generate from
+/// C++ users.
+template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
+ class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
+ class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
+class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> {
+ public:
+ bool FinalizeResult(void** tag, bool* status) override {
+ typedef CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> Base;
+ return Base::FinalizeResult(tag, status) && false;
+ }
+};
+
+/// Straightforward wrapping of the C call object
+class Call final {
+ public:
+ /** call is owned by the caller */
+ Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
+ : call_hook_(call_hook),
+ cq_(cq),
+ call_(call),
+ max_receive_message_size_(-1) {}
+
+ Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
+ int max_receive_message_size)
+ : call_hook_(call_hook),
+ cq_(cq),
+ call_(call),
+ max_receive_message_size_(max_receive_message_size) {}
+
+ void PerformOps(CallOpSetInterface* ops) {
+ call_hook_->PerformOpsOnCall(ops, this);
+ }
+
+ grpc_call* call() const { return call_; }
+ CompletionQueue* cq() const { return cq_; }
+
+ int max_receive_message_size() const { return max_receive_message_size_; }
+
+ private:
+ CallHook* call_hook_;
+ CompletionQueue* cq_;
+ grpc_call* call_;
+ int max_receive_message_size_;
+};
+} // namespace internal
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CALL_H
diff --git a/include/grpcpp/impl/codegen/call_hook.h b/include/grpcpp/impl/codegen/call_hook.h
new file mode 100644
index 0000000..4f7d370
--- /dev/null
+++ b/include/grpcpp/impl/codegen/call_hook.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CALL_HOOK_H
+#define GRPCPP_IMPL_CODEGEN_CALL_HOOK_H
+
+namespace grpc {
+
+namespace internal {
+class CallOpSetInterface;
+class Call;
+
+/// This is an interface that Channel and Server implement to allow them to hook
+/// performing ops.
+class CallHook {
+ public:
+ virtual ~CallHook() {}
+ virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
+};
+} // namespace internal
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CALL_HOOK_H
diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h
new file mode 100644
index 0000000..ec1c6c2
--- /dev/null
+++ b/include/grpcpp/impl/codegen/channel_interface.h
@@ -0,0 +1,121 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
+
+#include <grpc/impl/codegen/connectivity_state.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/time.h>
+
+namespace grpc {
+class ChannelInterface;
+class ClientContext;
+class CompletionQueue;
+
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+
+namespace internal {
+class Call;
+class CallOpSetInterface;
+class RpcMethod;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+template <class R>
+class ClientAsyncReaderFactory;
+template <class W>
+class ClientAsyncWriterFactory;
+template <class W, class R>
+class ClientAsyncReaderWriterFactory;
+template <class R>
+class ClientAsyncResponseReaderFactory;
+} // namespace internal
+
+/// Codegen interface for \a grpc::Channel.
+class ChannelInterface {
+ public:
+ virtual ~ChannelInterface() {}
+ /// Get the current channel state. If the channel is in IDLE and
+ /// \a try_to_connect is set to true, try to connect.
+ virtual grpc_connectivity_state GetState(bool try_to_connect) = 0;
+
+ /// Return the \a tag on \a cq when the channel state is changed or \a
+ /// deadline expires. \a GetState needs to called to get the current state.
+ template <typename T>
+ void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline,
+ CompletionQueue* cq, void* tag) {
+ TimePoint<T> deadline_tp(deadline);
+ NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag);
+ }
+
+ /// Blocking wait for channel state change or \a deadline expiration.
+ /// \a GetState needs to called to get the current state.
+ template <typename T>
+ bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) {
+ TimePoint<T> deadline_tp(deadline);
+ return WaitForStateChangeImpl(last_observed, deadline_tp.raw_time());
+ }
+
+ /// Wait for this channel to be connected
+ template <typename T>
+ bool WaitForConnected(T deadline) {
+ grpc_connectivity_state state;
+ while ((state = GetState(true)) != GRPC_CHANNEL_READY) {
+ if (!WaitForStateChange(state, deadline)) return false;
+ }
+ return true;
+ }
+
+ private:
+ template <class R>
+ friend class ::grpc::ClientReader;
+ template <class W>
+ friend class ::grpc::ClientWriter;
+ template <class W, class R>
+ friend class ::grpc::ClientReaderWriter;
+ template <class R>
+ friend class ::grpc::internal::ClientAsyncReaderFactory;
+ template <class W>
+ friend class ::grpc::internal::ClientAsyncWriterFactory;
+ template <class W, class R>
+ friend class ::grpc::internal::ClientAsyncReaderWriterFactory;
+ template <class R>
+ friend class ::grpc::internal::ClientAsyncResponseReaderFactory;
+ template <class InputMessage, class OutputMessage>
+ friend class ::grpc::internal::BlockingUnaryCallImpl;
+ friend class ::grpc::internal::RpcMethod;
+ virtual internal::Call CreateCall(const internal::RpcMethod& method,
+ ClientContext* context,
+ CompletionQueue* cq) = 0;
+ virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
+ internal::Call* call) = 0;
+ virtual void* RegisterMethod(const char* method) = 0;
+ virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
+ gpr_timespec deadline,
+ CompletionQueue* cq, void* tag) = 0;
+ virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
+ gpr_timespec deadline) = 0;
+};
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h
new file mode 100644
index 0000000..9dda4c7
--- /dev/null
+++ b/include/grpcpp/impl/codegen/client_context.h
@@ -0,0 +1,442 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistent at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+
+#ifndef GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/propagation_bits.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/create_auth_context.h>
+#include <grpcpp/impl/codegen/metadata_map.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct census_context;
+struct grpc_call;
+
+namespace grpc {
+
+class Channel;
+class ChannelInterface;
+class CompletionQueue;
+class CallCredentials;
+class ClientContext;
+
+namespace internal {
+class RpcMethod;
+class CallOpClientRecvStatus;
+class CallOpRecvInitialMetadata;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+} // namespace internal
+
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+template <class R>
+class ClientAsyncReader;
+template <class W>
+class ClientAsyncWriter;
+template <class W, class R>
+class ClientAsyncReaderWriter;
+template <class R>
+class ClientAsyncResponseReader;
+class ServerContext;
+
+/// Options for \a ClientContext::FromServerContext specifying which traits from
+/// the \a ServerContext to propagate (copy) from it into a new \a
+/// ClientContext.
+///
+/// \see ClientContext::FromServerContext
+class PropagationOptions {
+ public:
+ PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {}
+
+ PropagationOptions& enable_deadline_propagation() {
+ propagate_ |= GRPC_PROPAGATE_DEADLINE;
+ return *this;
+ }
+
+ PropagationOptions& disable_deadline_propagation() {
+ propagate_ &= ~GRPC_PROPAGATE_DEADLINE;
+ return *this;
+ }
+
+ PropagationOptions& enable_census_stats_propagation() {
+ propagate_ |= GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
+ return *this;
+ }
+
+ PropagationOptions& disable_census_stats_propagation() {
+ propagate_ &= ~GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
+ return *this;
+ }
+
+ PropagationOptions& enable_census_tracing_propagation() {
+ propagate_ |= GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
+ return *this;
+ }
+
+ PropagationOptions& disable_census_tracing_propagation() {
+ propagate_ &= ~GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
+ return *this;
+ }
+
+ PropagationOptions& enable_cancellation_propagation() {
+ propagate_ |= GRPC_PROPAGATE_CANCELLATION;
+ return *this;
+ }
+
+ PropagationOptions& disable_cancellation_propagation() {
+ propagate_ &= ~GRPC_PROPAGATE_CANCELLATION;
+ return *this;
+ }
+
+ uint32_t c_bitmask() const { return propagate_; }
+
+ private:
+ uint32_t propagate_;
+};
+
+namespace testing {
+class InteropClientContextInspector;
+} // namespace testing
+
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistent at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+class ClientContext {
+ public:
+ ClientContext();
+ ~ClientContext();
+
+ /// Create a new \a ClientContext as a child of an incoming server call,
+ /// according to \a options (\see PropagationOptions).
+ ///
+ /// \param server_context The source server context to use as the basis for
+ /// constructing the client context.
+ /// \param options The options controlling what to copy from the \a
+ /// server_context.
+ ///
+ /// \return A newly constructed \a ClientContext instance based on \a
+ /// server_context, with traits propagated (copied) according to \a options.
+ static std::unique_ptr<ClientContext> FromServerContext(
+ const ServerContext& server_context,
+ PropagationOptions options = PropagationOptions());
+
+ /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with
+ /// a client call. These are made available at the server side by the \a
+ /// grpc::ServerContext::client_metadata() method.
+ ///
+ /// \warning This method should only be called before invoking the rpc.
+ ///
+ /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+ /// end in "-bin".
+ /// \param meta_value The metadata value. If its value is binary, the key name
+ /// must end in "-bin".
+ void AddMetadata(const grpc::string& meta_key,
+ const grpc::string& meta_value);
+
+ /// Return a collection of initial metadata key-value pairs. Note that keys
+ /// may happen more than once (ie, a \a std::multimap is returned).
+ ///
+ /// \warning This method should only be called after initial metadata has been
+ /// received. For streaming calls, see \a
+ /// ClientReaderInterface::WaitForInitialMetadata().
+ ///
+ /// \return A multimap of initial metadata key-value pairs from the server.
+ const std::multimap<grpc::string_ref, grpc::string_ref>&
+ GetServerInitialMetadata() const {
+ GPR_CODEGEN_ASSERT(initial_metadata_received_);
+ return *recv_initial_metadata_.map();
+ }
+
+ /// Return a collection of trailing metadata key-value pairs. Note that keys
+ /// may happen more than once (ie, a \a std::multimap is returned).
+ ///
+ /// \warning This method is only callable once the stream has finished.
+ ///
+ /// \return A multimap of metadata trailing key-value pairs from the server.
+ const std::multimap<grpc::string_ref, grpc::string_ref>&
+ GetServerTrailingMetadata() const {
+ // TODO(yangg) check finished
+ return *trailing_metadata_.map();
+ }
+
+ /// Set the deadline for the client call.
+ ///
+ /// \warning This method should only be called before invoking the rpc.
+ ///
+ /// \param deadline the deadline for the client call. Units are determined by
+ /// the type used.
+ template <typename T>
+ void set_deadline(const T& deadline) {
+ TimePoint<T> deadline_tp(deadline);
+ deadline_ = deadline_tp.raw_time();
+ }
+
+ /// EXPERIMENTAL: Indicate that this request is idempotent.
+ /// By default, RPCs are assumed to <i>not</i> be idempotent.
+ ///
+ /// If true, the gRPC library assumes that it's safe to initiate
+ /// this RPC multiple times.
+ void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
+
+ /// EXPERIMENTAL: Set this request to be cacheable.
+ /// If set, grpc is free to use the HTTP GET verb for sending the request,
+ /// with the possibility of receiving a cached response.
+ void set_cacheable(bool cacheable) { cacheable_ = cacheable; }
+
+ /// EXPERIMENTAL: Trigger wait-for-ready or not on this request.
+ /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
+ /// If set, if an RPC is made when a channel's connectivity state is
+ /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast",
+ /// and the channel will wait until the channel is READY before making the
+ /// call.
+ void set_wait_for_ready(bool wait_for_ready) {
+ wait_for_ready_ = wait_for_ready;
+ wait_for_ready_explicitly_set_ = true;
+ }
+
+ /// DEPRECATED: Use set_wait_for_ready() instead.
+ void set_fail_fast(bool fail_fast) { set_wait_for_ready(!fail_fast); }
+
+ /// Return the deadline for the client call.
+ std::chrono::system_clock::time_point deadline() const {
+ return Timespec2Timepoint(deadline_);
+ }
+
+ /// Return a \a gpr_timespec representation of the client call's deadline.
+ gpr_timespec raw_deadline() const { return deadline_; }
+
+ /// Set the per call authority header (see
+ /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3).
+ void set_authority(const grpc::string& authority) { authority_ = authority; }
+
+ /// Return the authentication context for this client call.
+ ///
+ /// \see grpc::AuthContext.
+ std::shared_ptr<const AuthContext> auth_context() const {
+ if (auth_context_.get() == nullptr) {
+ auth_context_ = CreateAuthContext(call_);
+ }
+ return auth_context_;
+ }
+
+ /// Set credentials for the client call.
+ ///
+ /// A credentials object encapsulates all the state needed by a client to
+ /// authenticate with a server and make various assertions, e.g., about the
+ /// client’s identity, role, or whether it is authorized to make a particular
+ /// call.
+ ///
+ /// \see https://grpc.io/docs/guides/auth.html
+ void set_credentials(const std::shared_ptr<CallCredentials>& creds) {
+ creds_ = creds;
+ }
+
+ /// Return the compression algorithm the client call will request be used.
+ /// Note that the gRPC runtime may decide to ignore this request, for example,
+ /// due to resource constraints.
+ grpc_compression_algorithm compression_algorithm() const {
+ return compression_algorithm_;
+ }
+
+ /// Set \a algorithm to be the compression algorithm used for the client call.
+ ///
+ /// \param algorithm The compression algorithm used for the client call.
+ void set_compression_algorithm(grpc_compression_algorithm algorithm);
+
+ /// Flag whether the initial metadata should be \a corked
+ ///
+ /// If \a corked is true, then the initial metadata will be coalesced with the
+ /// write of first message in the stream. As a result, any tag set for the
+ /// initial metadata operation (starting a client-streaming or bidi-streaming
+ /// RPC) will not actually be sent to the completion queue or delivered
+ /// via Next.
+ ///
+ /// \param corked The flag indicating whether the initial metadata is to be
+ /// corked or not.
+ void set_initial_metadata_corked(bool corked) {
+ initial_metadata_corked_ = corked;
+ }
+
+ /// Return the peer uri in a string.
+ ///
+ /// \warning This value is never authenticated or subject to any security
+ /// related code. It must not be used for any authentication related
+ /// functionality. Instead, use auth_context.
+ ///
+ /// \return The call's peer URI.
+ grpc::string peer() const;
+
+ /// Get and set census context.
+ void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
+ struct census_context* census_context() const {
+ return census_context_;
+ }
+
+ /// Send a best-effort out-of-band cancel on the call associated with
+ /// this client context. The call could be in any stage; e.g., if it is
+ /// already finished, it may still return success.
+ ///
+ /// There is no guarantee the call will be cancelled.
+ ///
+ /// Note that TryCancel() does not change any of the tags that are pending
+ /// on the completion queue. All pending tags will still be delivered
+ /// (though their ok result may reflect the effect of cancellation).
+ void TryCancel();
+
+ /// Global Callbacks
+ ///
+ /// Can be set exactly once per application to install hooks whenever
+ /// a client context is constructed and destructed.
+ class GlobalCallbacks {
+ public:
+ virtual ~GlobalCallbacks() {}
+ virtual void DefaultConstructor(ClientContext* context) = 0;
+ virtual void Destructor(ClientContext* context) = 0;
+ };
+ static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
+ /// Should be used for framework-level extensions only.
+ /// Applications never need to call this method.
+ grpc_call* c_call() { return call_; }
+
+ /// EXPERIMENTAL debugging API
+ ///
+ /// if status is not ok() for an RPC, this will return a detailed string
+ /// of the gRPC Core error that led to the failure. It should not be relied
+ /// upon for anything other than gaining more debug data in failure cases.
+ grpc::string debug_error_string() const { return debug_error_string_; }
+
+ private:
+ // Disallow copy and assign.
+ ClientContext(const ClientContext&);
+ ClientContext& operator=(const ClientContext&);
+
+ friend class ::grpc::testing::InteropClientContextInspector;
+ friend class ::grpc::internal::CallOpClientRecvStatus;
+ friend class ::grpc::internal::CallOpRecvInitialMetadata;
+ friend class Channel;
+ template <class R>
+ friend class ::grpc::ClientReader;
+ template <class W>
+ friend class ::grpc::ClientWriter;
+ template <class W, class R>
+ friend class ::grpc::ClientReaderWriter;
+ template <class R>
+ friend class ::grpc::ClientAsyncReader;
+ template <class W>
+ friend class ::grpc::ClientAsyncWriter;
+ template <class W, class R>
+ friend class ::grpc::ClientAsyncReaderWriter;
+ template <class R>
+ friend class ::grpc::ClientAsyncResponseReader;
+ template <class InputMessage, class OutputMessage>
+ friend class ::grpc::internal::BlockingUnaryCallImpl;
+
+ // Used by friend class CallOpClientRecvStatus
+ void set_debug_error_string(const grpc::string& debug_error_string) {
+ debug_error_string_ = debug_error_string;
+ }
+
+ grpc_call* call() const { return call_; }
+ void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel);
+
+ uint32_t initial_metadata_flags() const {
+ return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) |
+ (wait_for_ready_ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0) |
+ (cacheable_ ? GRPC_INITIAL_METADATA_CACHEABLE_REQUEST : 0) |
+ (wait_for_ready_explicitly_set_
+ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET
+ : 0) |
+ (initial_metadata_corked_ ? GRPC_INITIAL_METADATA_CORKED : 0);
+ }
+
+ grpc::string authority() { return authority_; }
+
+ bool initial_metadata_received_;
+ bool wait_for_ready_;
+ bool wait_for_ready_explicitly_set_;
+ bool idempotent_;
+ bool cacheable_;
+ std::shared_ptr<Channel> channel_;
+ std::mutex mu_;
+ grpc_call* call_;
+ bool call_canceled_;
+ gpr_timespec deadline_;
+ grpc::string authority_;
+ std::shared_ptr<CallCredentials> creds_;
+ mutable std::shared_ptr<const AuthContext> auth_context_;
+ struct census_context* census_context_;
+ std::multimap<grpc::string, grpc::string> send_initial_metadata_;
+ internal::MetadataMap recv_initial_metadata_;
+ internal::MetadataMap trailing_metadata_;
+
+ grpc_call* propagate_from_call_;
+ PropagationOptions propagation_options_;
+
+ grpc_compression_algorithm compression_algorithm_;
+ bool initial_metadata_corked_;
+
+ grpc::string debug_error_string_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
diff --git a/include/grpcpp/impl/codegen/client_unary_call.h b/include/grpcpp/impl/codegen/client_unary_call.h
new file mode 100644
index 0000000..a37a81b
--- /dev/null
+++ b/include/grpcpp/impl/codegen/client_unary_call.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CLIENT_UNARY_CALL_H
+#define GRPCPP_IMPL_CODEGEN_CLIENT_UNARY_CALL_H
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class Channel;
+class ClientContext;
+class CompletionQueue;
+
+namespace internal {
+class RpcMethod;
+/// Wrapper that performs a blocking unary call
+template <class InputMessage, class OutputMessage>
+Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
+ ClientContext* context, const InputMessage& request,
+ OutputMessage* result) {
+ return BlockingUnaryCallImpl<InputMessage, OutputMessage>(
+ channel, method, context, request, result)
+ .status();
+}
+
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl {
+ public:
+ BlockingUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
+ ClientContext* context, const InputMessage& request,
+ OutputMessage* result) {
+ CompletionQueue cq(grpc_completion_queue_attributes{
+ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+ GRPC_CQ_DEFAULT_POLLING}); // Pluckable completion queue
+ Call call(channel->CreateCall(method, context, &cq));
+ CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+ CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
+ CallOpClientSendClose, CallOpClientRecvStatus>
+ ops;
+ status_ = ops.SendMessage(request);
+ if (!status_.ok()) {
+ return;
+ }
+ ops.SendInitialMetadata(context->send_initial_metadata_,
+ context->initial_metadata_flags());
+ ops.RecvInitialMetadata(context);
+ ops.RecvMessage(result);
+ ops.AllowNoMessage();
+ ops.ClientSendClose();
+ ops.ClientRecvStatus(context, &status_);
+ call.PerformOps(&ops);
+ if (cq.Pluck(&ops)) {
+ if (!ops.got_message && status_.ok()) {
+ status_ = Status(StatusCode::UNIMPLEMENTED,
+ "No message returned for unary request");
+ }
+ } else {
+ GPR_CODEGEN_ASSERT(!status_.ok());
+ }
+ }
+ Status status() { return status_; }
+
+ private:
+ Status status_;
+};
+
+} // namespace internal
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CLIENT_UNARY_CALL_H
diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h
new file mode 100644
index 0000000..80c7c41
--- /dev/null
+++ b/include/grpcpp/impl/codegen/completion_queue.h
@@ -0,0 +1,383 @@
+/*
+ *
+ * Copyright 2015-2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/// A completion queue implements a concurrent producer-consumer queue, with
+/// two main API-exposed methods: \a Next and \a AsyncNext. These
+/// methods are the essential component of the gRPC C++ asynchronous API.
+/// There is also a \a Shutdown method to indicate that a given completion queue
+/// will no longer have regular events. This must be called before the
+/// completion queue is destroyed.
+/// All completion queue APIs are thread-safe and may be used concurrently with
+/// any other completion queue API invocation; it is acceptable to have
+/// multiple threads calling \a Next or \a AsyncNext on the same or different
+/// completion queues, or to call these methods concurrently with a \a Shutdown
+/// elsewhere.
+/// \remark{All other API calls on completion queue should be completed before
+/// a completion queue destructor is called.}
+#ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
+#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
+
+#include <grpc/impl/codegen/atm.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct grpc_completion_queue;
+
+namespace grpc {
+
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+template <class R>
+class ServerReader;
+template <class W>
+class ServerWriter;
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody;
+} // namespace internal
+
+class Channel;
+class ChannelInterface;
+class ClientContext;
+class CompletionQueue;
+class Server;
+class ServerBuilder;
+class ServerContext;
+class ServerInterface;
+
+namespace internal {
+class CompletionQueueTag;
+class RpcMethod;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class BidiStreamingHandler;
+class UnknownMethodHandler;
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+} // namespace internal
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// A thin wrapper around \ref grpc_completion_queue (see \ref
+/// src/core/lib/surface/completion_queue.h).
+/// See \ref doc/cpp/perf_notes.md for notes on best practices for high
+/// performance servers.
+class CompletionQueue : private GrpcLibraryCodegen {
+ public:
+ /// Default constructor. Implicitly creates a \a grpc_completion_queue
+ /// instance.
+ CompletionQueue()
+ : CompletionQueue(grpc_completion_queue_attributes{
+ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING}) {}
+
+ /// Wrap \a take, taking ownership of the instance.
+ ///
+ /// \param take The completion queue instance to wrap. Ownership is taken.
+ explicit CompletionQueue(grpc_completion_queue* take);
+
+ /// Destructor. Destroys the owned wrapped completion queue / instance.
+ ~CompletionQueue() {
+ g_core_codegen_interface->grpc_completion_queue_destroy(cq_);
+ }
+
+ /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
+ enum NextStatus {
+ SHUTDOWN, ///< The completion queue has been shutdown and fully-drained
+ GOT_EVENT, ///< Got a new event; \a tag will be filled in with its
+ ///< associated value; \a ok indicating its success.
+ TIMEOUT ///< deadline was reached.
+ };
+
+ /// Read from the queue, blocking until an event is available or the queue is
+ /// shutting down.
+ ///
+ /// \param tag[out] Updated to point to the read event's tag.
+ /// \param ok[out] true if read a successful event, false otherwise.
+ ///
+ /// Note that each tag sent to the completion queue (through RPC operations
+ /// or alarms) will be delivered out of the completion queue by a call to
+ /// Next (or a related method), regardless of whether the operation succeeded
+ /// or not. Success here means that this operation completed in the normal
+ /// valid manner.
+ ///
+ /// Server-side RPC request: \a ok indicates that the RPC has indeed
+ /// been started. If it is false, the server has been Shutdown
+ /// before this particular call got matched to an incoming RPC.
+ ///
+ /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is
+ /// going to go to the wire. If it is false, it not going to the wire. This
+ /// would happen if the channel is either permanently broken or
+ /// transiently broken but with the fail-fast option. (Note that async unary
+ /// RPCs don't post a CQ tag at this point, nor do client-streaming
+ /// or bidi-streaming RPCs that have the initial metadata corked option set.)
+ ///
+ /// Client-side Write, Client-side WritesDone, Server-side Write,
+ /// Server-side Finish, Server-side SendInitialMetadata (which is
+ /// typically included in Write or Finish when not done explicitly):
+ /// \a ok means that the data/metadata/status/etc is going to go to the
+ /// wire. If it is false, it not going to the wire because the call
+ /// is already dead (i.e., canceled, deadline expired, other side
+ /// dropped the channel, etc).
+ ///
+ /// Client-side Read, Server-side Read, Client-side
+ /// RecvInitialMetadata (which is typically included in Read if not
+ /// done explicitly): \a ok indicates whether there is a valid message
+ /// that got read. If not, you know that there are certainly no more
+ /// messages that can ever be read from this stream. For the client-side
+ /// operations, this only happens because the call is dead. For the
+ /// server-sider operation, though, this could happen because the client
+ /// has done a WritesDone already.
+ ///
+ /// Client-side Finish: \a ok should always be true
+ ///
+ /// Server-side AsyncNotifyWhenDone: \a ok should always be true
+ ///
+ /// Alarm: \a ok is true if it expired, false if it was canceled
+ ///
+ /// \return true if got an event, false if the queue is fully drained and
+ /// shut down.
+ bool Next(void** tag, bool* ok) {
+ return (AsyncNextInternal(tag, ok,
+ g_core_codegen_interface->gpr_inf_future(
+ GPR_CLOCK_REALTIME)) != SHUTDOWN);
+ }
+
+ /// Read from the queue, blocking up to \a deadline (or the queue's shutdown).
+ /// Both \a tag and \a ok are updated upon success (if an event is available
+ /// within the \a deadline). A \a tag points to an arbitrary location usually
+ /// employed to uniquely identify an event.
+ ///
+ /// \param tag[out] Upon sucess, updated to point to the event's tag.
+ /// \param ok[out] Upon sucess, true if a successful event, false otherwise
+ /// See documentation for CompletionQueue::Next for explanation of ok
+ /// \param deadline[in] How long to block in wait for an event.
+ ///
+ /// \return The type of event read.
+ template <typename T>
+ NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) {
+ TimePoint<T> deadline_tp(deadline);
+ return AsyncNextInternal(tag, ok, deadline_tp.raw_time());
+ }
+
+ /// EXPERIMENTAL
+ /// First executes \a F, then reads from the queue, blocking up to
+ /// \a deadline (or the queue's shutdown).
+ /// Both \a tag and \a ok are updated upon success (if an event is available
+ /// within the \a deadline). A \a tag points to an arbitrary location usually
+ /// employed to uniquely identify an event.
+ ///
+ /// \param F[in] Function to execute before calling AsyncNext on this queue.
+ /// \param tag[out] Upon sucess, updated to point to the event's tag.
+ /// \param ok[out] Upon sucess, true if read a regular event, false otherwise.
+ /// \param deadline[in] How long to block in wait for an event.
+ ///
+ /// \return The type of event read.
+ template <typename T, typename F>
+ NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) {
+ CompletionQueueTLSCache cache = CompletionQueueTLSCache(this);
+ f();
+ if (cache.Flush(tag, ok)) {
+ return GOT_EVENT;
+ } else {
+ return AsyncNext(tag, ok, deadline);
+ }
+ }
+
+ /// Request the shutdown of the queue.
+ ///
+ /// \warning This method must be called at some point if this completion queue
+ /// is accessed with Next or AsyncNext. \a Next will not return false
+ /// until this method has been called and all pending tags have been drained.
+ /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .)
+ /// Only once either one of these methods does that (that is, once the queue
+ /// has been \em drained) can an instance of this class be destroyed.
+ /// Also note that applications must ensure that no work is enqueued on this
+ /// completion queue after this method is called.
+ void Shutdown();
+
+ /// Returns a \em raw pointer to the underlying \a grpc_completion_queue
+ /// instance.
+ ///
+ /// \warning Remember that the returned instance is owned. No transfer of
+ /// owership is performed.
+ grpc_completion_queue* cq() { return cq_; }
+
+ protected:
+ /// Private constructor of CompletionQueue only visible to friend classes
+ CompletionQueue(const grpc_completion_queue_attributes& attributes) {
+ cq_ = g_core_codegen_interface->grpc_completion_queue_create(
+ g_core_codegen_interface->grpc_completion_queue_factory_lookup(
+ &attributes),
+ &attributes, NULL);
+ InitialAvalanching(); // reserve this for the future shutdown
+ }
+
+ private:
+ // Friend synchronous wrappers so that they can access Pluck(), which is
+ // a semi-private API geared towards the synchronous implementation.
+ template <class R>
+ friend class ::grpc::ClientReader;
+ template <class W>
+ friend class ::grpc::ClientWriter;
+ template <class W, class R>
+ friend class ::grpc::ClientReaderWriter;
+ template <class R>
+ friend class ::grpc::ServerReader;
+ template <class W>
+ friend class ::grpc::ServerWriter;
+ template <class W, class R>
+ friend class ::grpc::internal::ServerReaderWriterBody;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class ::grpc::internal::RpcMethodHandler;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class ::grpc::internal::ClientStreamingHandler;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class ::grpc::internal::ServerStreamingHandler;
+ template <class Streamer, bool WriteNeeded>
+ friend class ::grpc::internal::TemplatedBidiStreamingHandler;
+ friend class ::grpc::internal::UnknownMethodHandler;
+ friend class ::grpc::Server;
+ friend class ::grpc::ServerContext;
+ friend class ::grpc::ServerInterface;
+ template <class InputMessage, class OutputMessage>
+ friend class ::grpc::internal::BlockingUnaryCallImpl;
+
+ /// EXPERIMENTAL
+ /// Creates a Thread Local cache to store the first event
+ /// On this completion queue queued from this thread. Once
+ /// initialized, it must be flushed on the same thread.
+ class CompletionQueueTLSCache {
+ public:
+ CompletionQueueTLSCache(CompletionQueue* cq);
+ ~CompletionQueueTLSCache();
+ bool Flush(void** tag, bool* ok);
+
+ private:
+ CompletionQueue* cq_;
+ bool flushed_;
+ };
+
+ NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline);
+
+ /// Wraps \a grpc_completion_queue_pluck.
+ /// \warning Must not be mixed with calls to \a Next.
+ bool Pluck(internal::CompletionQueueTag* tag) {
+ auto deadline =
+ g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
+ auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
+ cq_, tag, deadline, nullptr);
+ bool ok = ev.success != 0;
+ void* ignored = tag;
+ GPR_CODEGEN_ASSERT(tag->FinalizeResult(&ignored, &ok));
+ GPR_CODEGEN_ASSERT(ignored == tag);
+ // Ignore mutations by FinalizeResult: Pluck returns the C API status
+ return ev.success != 0;
+ }
+
+ /// Performs a single polling pluck on \a tag.
+ /// \warning Must not be mixed with calls to \a Next.
+ ///
+ /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already
+ /// shutdown. This is most likely a bug and if it is a bug, then change this
+ /// implementation to simple call the other TryPluck function with a zero
+ /// timeout. i.e:
+ /// TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME))
+ void TryPluck(internal::CompletionQueueTag* tag) {
+ auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME);
+ auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
+ cq_, tag, deadline, nullptr);
+ if (ev.type == GRPC_QUEUE_TIMEOUT) return;
+ bool ok = ev.success != 0;
+ void* ignored = tag;
+ // the tag must be swallowed if using TryPluck
+ GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
+ }
+
+ /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if
+ /// the pluck() was successful and returned the tag.
+ ///
+ /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects
+ /// that the tag is internal not something that is returned to the user.
+ void TryPluck(internal::CompletionQueueTag* tag, gpr_timespec deadline) {
+ auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
+ cq_, tag, deadline, nullptr);
+ if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) {
+ return;
+ }
+
+ bool ok = ev.success != 0;
+ void* ignored = tag;
+ GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
+ }
+
+ /// Manage state of avalanching operations : completion queue tags that
+ /// trigger other completion queue operations. The underlying core completion
+ /// queue should not really shutdown until all avalanching operations have
+ /// been finalized. Note that we maintain the requirement that an avalanche
+ /// registration must take place before CQ shutdown (which must be maintained
+ /// elsehwere)
+ void InitialAvalanching() {
+ gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1));
+ }
+ void RegisterAvalanching() {
+ gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
+ static_cast<gpr_atm>(1));
+ }
+ void CompleteAvalanching();
+
+ grpc_completion_queue* cq_; // owned
+
+ gpr_atm avalanches_in_flight_;
+};
+
+/// A specific type of completion queue used by the processing of notifications
+/// by servers. Instantiated by \a ServerBuilder.
+class ServerCompletionQueue : public CompletionQueue {
+ public:
+ bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; }
+
+ private:
+ grpc_cq_polling_type polling_type_;
+ friend class ServerBuilder;
+ /// \param is_frequently_polled Informs the GRPC library about whether the
+ /// server completion queue would be actively polled (by calling Next() or
+ /// AsyncNext()). By default all server completion queues are assumed to be
+ /// frequently polled.
+ ServerCompletionQueue(grpc_cq_polling_type polling_type)
+ : CompletionQueue(grpc_completion_queue_attributes{
+ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, polling_type}),
+ polling_type_(polling_type) {}
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
diff --git a/include/grpcpp/impl/codegen/completion_queue_tag.h b/include/grpcpp/impl/codegen/completion_queue_tag.h
new file mode 100644
index 0000000..ffb642c
--- /dev/null
+++ b/include/grpcpp/impl/codegen/completion_queue_tag.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H
+#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H
+
+namespace grpc {
+
+namespace internal {
+/// An interface allowing implementors to process and filter event tags.
+class CompletionQueueTag {
+ public:
+ virtual ~CompletionQueueTag() {}
+ /// Called prior to returning from Next(), return value is the status of the
+ /// operation (return status is the default thing to do). If this function
+ /// returns false, the tag is dropped and not returned from the completion
+ /// queue
+ virtual bool FinalizeResult(void** tag, bool* status) = 0;
+};
+} // namespace internal
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H
diff --git a/include/grpcpp/impl/codegen/config.h b/include/grpcpp/impl/codegen/config.h
new file mode 100644
index 0000000..37f0fd1
--- /dev/null
+++ b/include/grpcpp/impl/codegen/config.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CONFIG_H
+#define GRPCPP_IMPL_CODEGEN_CONFIG_H
+
+#ifndef GRPC_CUSTOM_STRING
+#include <string>
+#define GRPC_CUSTOM_STRING std::string
+#endif
+
+/// The following macros are deprecated and appear only for users
+/// with PB files generated using gRPC 1.0.x plugins. They should
+/// not be used in new code
+#define GRPC_OVERRIDE override // deprecated
+#define GRPC_FINAL final // deprecated
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+using std::to_string;
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CONFIG_H
diff --git a/include/grpcpp/impl/codegen/config_protobuf.h b/include/grpcpp/impl/codegen/config_protobuf.h
new file mode 100644
index 0000000..94e593d
--- /dev/null
+++ b/include/grpcpp/impl/codegen/config_protobuf.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CONFIG_PROTOBUF_H
+#define GRPCPP_IMPL_CODEGEN_CONFIG_PROTOBUF_H
+
+#define GRPC_OPEN_SOURCE_PROTO
+
+#ifndef GRPC_CUSTOM_PROTOBUF_INT64
+#include <google/protobuf/stubs/common.h>
+#define GRPC_CUSTOM_PROTOBUF_INT64 ::google::protobuf::int64
+#endif
+
+#ifndef GRPC_CUSTOM_MESSAGE
+#ifdef GRPC_USE_PROTO_LITE
+#include <google/protobuf/message_lite.h>
+#define GRPC_CUSTOM_MESSAGE ::google::protobuf::MessageLite
+#else
+#include <google/protobuf/message.h>
+#define GRPC_CUSTOM_MESSAGE ::google::protobuf::Message
+#endif
+#endif
+
+#ifndef GRPC_CUSTOM_DESCRIPTOR
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor
+#define GRPC_CUSTOM_DESCRIPTORPOOL ::google::protobuf::DescriptorPool
+#define GRPC_CUSTOM_FIELDDESCRIPTOR ::google::protobuf::FieldDescriptor
+#define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor
+#define GRPC_CUSTOM_FILEDESCRIPTORPROTO ::google::protobuf::FileDescriptorProto
+#define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor
+#define GRPC_CUSTOM_SERVICEDESCRIPTOR ::google::protobuf::ServiceDescriptor
+#define GRPC_CUSTOM_SOURCELOCATION ::google::protobuf::SourceLocation
+#endif
+
+#ifndef GRPC_CUSTOM_DESCRIPTORDATABASE
+#include <google/protobuf/descriptor_database.h>
+#define GRPC_CUSTOM_DESCRIPTORDATABASE ::google::protobuf::DescriptorDatabase
+#define GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE \
+ ::google::protobuf::SimpleDescriptorDatabase
+#endif
+
+#ifndef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#define GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM \
+ ::google::protobuf::io::ZeroCopyOutputStream
+#define GRPC_CUSTOM_ZEROCOPYINPUTSTREAM \
+ ::google::protobuf::io::ZeroCopyInputStream
+#define GRPC_CUSTOM_CODEDINPUTSTREAM ::google::protobuf::io::CodedInputStream
+#endif
+
+namespace grpc {
+namespace protobuf {
+
+typedef GRPC_CUSTOM_MESSAGE Message;
+typedef GRPC_CUSTOM_PROTOBUF_INT64 int64;
+
+typedef GRPC_CUSTOM_DESCRIPTOR Descriptor;
+typedef GRPC_CUSTOM_DESCRIPTORPOOL DescriptorPool;
+typedef GRPC_CUSTOM_DESCRIPTORDATABASE DescriptorDatabase;
+typedef GRPC_CUSTOM_FIELDDESCRIPTOR FieldDescriptor;
+typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor;
+typedef GRPC_CUSTOM_FILEDESCRIPTORPROTO FileDescriptorProto;
+typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor;
+typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor;
+typedef GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE SimpleDescriptorDatabase;
+typedef GRPC_CUSTOM_SOURCELOCATION SourceLocation;
+
+namespace io {
+typedef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM ZeroCopyOutputStream;
+typedef GRPC_CUSTOM_ZEROCOPYINPUTSTREAM ZeroCopyInputStream;
+typedef GRPC_CUSTOM_CODEDINPUTSTREAM CodedInputStream;
+} // namespace io
+
+} // namespace protobuf
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CONFIG_PROTOBUF_H
diff --git a/include/grpcpp/impl/codegen/core_codegen.h b/include/grpcpp/impl/codegen/core_codegen.h
new file mode 100644
index 0000000..0ca4ad5
--- /dev/null
+++ b/include/grpcpp/impl/codegen/core_codegen.h
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_H
+#define GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_H
+
+// This file should be compiled as part of grpcpp.
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+
+namespace grpc {
+
+/// Implementation of the core codegen interface.
+class CoreCodegen final : public CoreCodegenInterface {
+ private:
+ virtual const grpc_completion_queue_factory*
+ grpc_completion_queue_factory_lookup(
+ const grpc_completion_queue_attributes* attributes) override;
+ virtual grpc_completion_queue* grpc_completion_queue_create(
+ const grpc_completion_queue_factory* factory,
+ const grpc_completion_queue_attributes* attributes,
+ void* reserved) override;
+ grpc_completion_queue* grpc_completion_queue_create_for_next(
+ void* reserved) override;
+ grpc_completion_queue* grpc_completion_queue_create_for_pluck(
+ void* reserved) override;
+ void grpc_completion_queue_destroy(grpc_completion_queue* cq) override;
+ grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag,
+ gpr_timespec deadline,
+ void* reserved) override;
+
+ void* gpr_malloc(size_t size) override;
+ void gpr_free(void* p) override;
+
+ void grpc_init() override;
+ void grpc_shutdown() override;
+
+ void gpr_mu_init(gpr_mu* mu) override;
+ void gpr_mu_destroy(gpr_mu* mu) override;
+ void gpr_mu_lock(gpr_mu* mu) override;
+ void gpr_mu_unlock(gpr_mu* mu) override;
+ void gpr_cv_init(gpr_cv* cv) override;
+ void gpr_cv_destroy(gpr_cv* cv) override;
+ int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) override;
+ void gpr_cv_signal(gpr_cv* cv) override;
+ void gpr_cv_broadcast(gpr_cv* cv) override;
+
+ grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
+ grpc_status_code status,
+ const char* description,
+ void* reserved) override;
+ void grpc_call_ref(grpc_call* call) override;
+ void grpc_call_unref(grpc_call* call) override;
+ virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) override;
+
+ grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) override;
+ void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;
+
+ int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
+ grpc_byte_buffer* buffer) override;
+ void grpc_byte_buffer_reader_destroy(
+ grpc_byte_buffer_reader* reader) override;
+ int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader,
+ grpc_slice* slice) override;
+
+ grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice,
+ size_t nslices) override;
+ grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
+ void (*destroy)(void*),
+ void* user_data) override;
+ grpc_slice grpc_empty_slice() override;
+ grpc_slice grpc_slice_malloc(size_t length) override;
+ void grpc_slice_unref(grpc_slice slice) override;
+ grpc_slice grpc_slice_ref(grpc_slice slice) override;
+ grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override;
+ grpc_slice grpc_slice_split_head(grpc_slice* s, size_t split) override;
+ grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end) override;
+ void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override;
+ void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override;
+ grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+ size_t length) override;
+ grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+ size_t length) override;
+ void grpc_metadata_array_init(grpc_metadata_array* array) override;
+ void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
+
+ gpr_timespec gpr_inf_future(gpr_clock_type type) override;
+ gpr_timespec gpr_time_0(gpr_clock_type type) override;
+
+ virtual const Status& ok() override;
+ virtual const Status& cancelled() override;
+
+ void assert_fail(const char* failed_assertion, const char* file,
+ int line) override;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_H
diff --git a/include/grpcpp/impl/codegen/core_codegen_interface.h b/include/grpcpp/impl/codegen/core_codegen_interface.h
new file mode 100644
index 0000000..64bc9ef
--- /dev/null
+++ b/include/grpcpp/impl/codegen/core_codegen_interface.h
@@ -0,0 +1,140 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
+
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/sync.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+/// Interface between the codegen library and the minimal subset of core
+/// features required by the generated code.
+///
+/// All undocumented methods are simply forwarding the call to their namesakes.
+/// Please refer to their corresponding documentation for details.
+///
+/// \warning This interface should be considered internal and private.
+class CoreCodegenInterface {
+ public:
+ /// Upon a failed assertion, log the error.
+ virtual void assert_fail(const char* failed_assertion, const char* file,
+ int line) = 0;
+
+ virtual const grpc_completion_queue_factory*
+ grpc_completion_queue_factory_lookup(
+ const grpc_completion_queue_attributes* attributes) = 0;
+ virtual grpc_completion_queue* grpc_completion_queue_create(
+ const grpc_completion_queue_factory* factory,
+ const grpc_completion_queue_attributes* attributes, void* reserved) = 0;
+ virtual grpc_completion_queue* grpc_completion_queue_create_for_next(
+ void* reserved) = 0;
+ virtual grpc_completion_queue* grpc_completion_queue_create_for_pluck(
+ void* reserved) = 0;
+ virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0;
+ virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq,
+ void* tag,
+ gpr_timespec deadline,
+ void* reserved) = 0;
+
+ virtual void* gpr_malloc(size_t size) = 0;
+ virtual void gpr_free(void* p) = 0;
+
+ // These are only to be used to fix edge cases involving grpc_init and
+ // grpc_shutdown. Calling grpc_init from the codegen interface before
+ // the real grpc_init is called will cause a crash, so if you use this
+ // function, ensure that it is not the first call to grpc_init.
+ virtual void grpc_init() = 0;
+ virtual void grpc_shutdown() = 0;
+
+ virtual void gpr_mu_init(gpr_mu* mu) = 0;
+ virtual void gpr_mu_destroy(gpr_mu* mu) = 0;
+ virtual void gpr_mu_lock(gpr_mu* mu) = 0;
+ virtual void gpr_mu_unlock(gpr_mu* mu) = 0;
+ virtual void gpr_cv_init(gpr_cv* cv) = 0;
+ virtual void gpr_cv_destroy(gpr_cv* cv) = 0;
+ virtual int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu,
+ gpr_timespec abs_deadline) = 0;
+ virtual void gpr_cv_signal(gpr_cv* cv) = 0;
+ virtual void gpr_cv_broadcast(gpr_cv* cv) = 0;
+
+ virtual grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) = 0;
+ virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0;
+
+ virtual int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
+ grpc_byte_buffer* buffer)
+ GRPC_MUST_USE_RESULT = 0;
+ virtual void grpc_byte_buffer_reader_destroy(
+ grpc_byte_buffer_reader* reader) = 0;
+ virtual int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader,
+ grpc_slice* slice) = 0;
+
+ virtual grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice,
+ size_t nslices) = 0;
+ virtual grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
+ void (*destroy)(void*),
+ void* user_data) = 0;
+ virtual grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
+ grpc_status_code status,
+ const char* description,
+ void* reserved) = 0;
+ virtual void grpc_call_ref(grpc_call* call) = 0;
+ virtual void grpc_call_unref(grpc_call* call) = 0;
+ virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) = 0;
+ virtual grpc_slice grpc_empty_slice() = 0;
+ virtual grpc_slice grpc_slice_malloc(size_t length) = 0;
+ virtual void grpc_slice_unref(grpc_slice slice) = 0;
+ virtual grpc_slice grpc_slice_ref(grpc_slice slice) = 0;
+ virtual grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) = 0;
+ virtual grpc_slice grpc_slice_split_head(grpc_slice* s, size_t split) = 0;
+ virtual grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end) = 0;
+ virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb,
+ grpc_slice slice) = 0;
+ virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0;
+ virtual grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+ size_t length) = 0;
+ virtual grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+ size_t length) = 0;
+
+ virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
+ virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
+
+ virtual const Status& ok() = 0;
+ virtual const Status& cancelled() = 0;
+
+ virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0;
+ virtual gpr_timespec gpr_time_0(gpr_clock_type type) = 0;
+};
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// Codegen specific version of \a GPR_ASSERT.
+#define GPR_CODEGEN_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ grpc::g_core_codegen_interface->assert_fail(#x, __FILE__, __LINE__); \
+ } \
+ } while (0)
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
diff --git a/include/grpcpp/impl/codegen/create_auth_context.h b/include/grpcpp/impl/codegen/create_auth_context.h
new file mode 100644
index 0000000..cb6095c
--- /dev/null
+++ b/include/grpcpp/impl/codegen/create_auth_context.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
+
+#include <memory>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+
+namespace grpc {
+
+std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
diff --git a/include/grpcpp/impl/codegen/grpc_library.h b/include/grpcpp/impl/codegen/grpc_library.h
new file mode 100644
index 0000000..684031f
--- /dev/null
+++ b/include/grpcpp/impl/codegen/grpc_library.h
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_GRPC_LIBRARY_H
+#define GRPCPP_IMPL_CODEGEN_GRPC_LIBRARY_H
+
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+
+namespace grpc {
+
+class GrpcLibraryInterface {
+ public:
+ virtual void init() = 0;
+ virtual void shutdown() = 0;
+};
+
+/// Initialized by \a grpc::GrpcLibraryInitializer from
+/// <grpcpp/impl/grpc_library.h>
+extern GrpcLibraryInterface* g_glip;
+
+/// Classes that require gRPC to be initialized should inherit from this class.
+class GrpcLibraryCodegen {
+ public:
+ GrpcLibraryCodegen(bool call_grpc_init = true) : grpc_init_called_(false) {
+ if (call_grpc_init) {
+ GPR_CODEGEN_ASSERT(g_glip &&
+ "gRPC library not initialized. See "
+ "grpc::internal::GrpcLibraryInitializer.");
+ g_glip->init();
+ grpc_init_called_ = true;
+ }
+ }
+ virtual ~GrpcLibraryCodegen() {
+ if (grpc_init_called_) {
+ GPR_CODEGEN_ASSERT(g_glip &&
+ "gRPC library not initialized. See "
+ "grpc::internal::GrpcLibraryInitializer.");
+ g_glip->shutdown();
+ }
+ }
+
+ private:
+ bool grpc_init_called_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_GRPC_LIBRARY_H
diff --git a/include/grpcpp/impl/codegen/metadata_map.h b/include/grpcpp/impl/codegen/metadata_map.h
new file mode 100644
index 0000000..0866539
--- /dev/null
+++ b/include/grpcpp/impl/codegen/metadata_map.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
+#define GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
+
+#include <grpcpp/impl/codegen/slice.h>
+
+namespace grpc {
+
+namespace internal {
+class MetadataMap {
+ public:
+ MetadataMap() { memset(&arr_, 0, sizeof(arr_)); }
+
+ ~MetadataMap() {
+ g_core_codegen_interface->grpc_metadata_array_destroy(&arr_);
+ }
+
+ void FillMap() {
+ for (size_t i = 0; i < arr_.count; i++) {
+ // TODO(yangg) handle duplicates?
+ map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
+ StringRefFromSlice(&arr_.metadata[i].key),
+ StringRefFromSlice(&arr_.metadata[i].value)));
+ }
+ }
+
+ std::multimap<grpc::string_ref, grpc::string_ref>* map() { return &map_; }
+ const std::multimap<grpc::string_ref, grpc::string_ref>* map() const {
+ return &map_;
+ }
+ grpc_metadata_array* arr() { return &arr_; }
+
+ private:
+ grpc_metadata_array arr_;
+ std::multimap<grpc::string_ref, grpc::string_ref> map_;
+};
+} // namespace internal
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
diff --git a/include/grpcpp/impl/codegen/method_handler_impl.h b/include/grpcpp/impl/codegen/method_handler_impl.h
new file mode 100644
index 0000000..27552d7
--- /dev/null
+++ b/include/grpcpp/impl/codegen/method_handler_impl.h
@@ -0,0 +1,302 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
+#define GRPCPP_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
+
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+#include <grpcpp/impl/codegen/sync_stream.h>
+
+namespace grpc {
+
+namespace internal {
+
+// Invoke the method handler, fill in the status, and
+// return whether or not we finished safely (without an exception).
+// Note that exception handling is 0-cost in most compiler/library
+// implementations (except when an exception is actually thrown),
+// so this process doesn't require additional overhead in the common case.
+// Additionally, we don't need to return if we caught an exception or not;
+// the handling is the same in either case.
+template <class Callable>
+Status CatchingFunctionHandler(Callable&& handler) {
+#if GRPC_ALLOW_EXCEPTIONS
+ try {
+ return handler();
+ } catch (...) {
+ return Status(StatusCode::UNKNOWN, "Unexpected error in RPC handling");
+ }
+#else // GRPC_ALLOW_EXCEPTIONS
+ return handler();
+#endif // GRPC_ALLOW_EXCEPTIONS
+}
+
+/// A wrapper class of an application provided rpc method handler.
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler : public MethodHandler {
+ public:
+ RpcMethodHandler(std::function<Status(ServiceType*, ServerContext*,
+ const RequestType*, ResponseType*)>
+ func,
+ ServiceType* service)
+ : func_(func), service_(service) {}
+
+ void RunHandler(const HandlerParameter& param) final {
+ RequestType req;
+ Status status = SerializationTraits<RequestType>::Deserialize(
+ param.request.bbuf_ptr(), &req);
+ ResponseType rsp;
+ if (status.ok()) {
+ status = CatchingFunctionHandler([this, ¶m, &req, &rsp] {
+ return func_(service_, param.server_context, &req, &rsp);
+ });
+ }
+
+ GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
+ CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+ CallOpServerSendStatus>
+ ops;
+ ops.SendInitialMetadata(param.server_context->initial_metadata_,
+ param.server_context->initial_metadata_flags());
+ if (param.server_context->compression_level_set()) {
+ ops.set_compression_level(param.server_context->compression_level());
+ }
+ if (status.ok()) {
+ status = ops.SendMessage(rsp);
+ }
+ ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
+ param.call->PerformOps(&ops);
+ param.call->cq()->Pluck(&ops);
+ }
+
+ private:
+ /// Application provided rpc handler function.
+ std::function<Status(ServiceType*, ServerContext*, const RequestType*,
+ ResponseType*)>
+ func_;
+ // The class the above handler function lives in.
+ ServiceType* service_;
+};
+
+/// A wrapper class of an application provided client streaming handler.
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler : public MethodHandler {
+ public:
+ ClientStreamingHandler(
+ std::function<Status(ServiceType*, ServerContext*,
+ ServerReader<RequestType>*, ResponseType*)>
+ func,
+ ServiceType* service)
+ : func_(func), service_(service) {}
+
+ void RunHandler(const HandlerParameter& param) final {
+ ServerReader<RequestType> reader(param.call, param.server_context);
+ ResponseType rsp;
+ Status status = CatchingFunctionHandler([this, ¶m, &reader, &rsp] {
+ return func_(service_, param.server_context, &reader, &rsp);
+ });
+
+ GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
+ CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+ CallOpServerSendStatus>
+ ops;
+ ops.SendInitialMetadata(param.server_context->initial_metadata_,
+ param.server_context->initial_metadata_flags());
+ if (param.server_context->compression_level_set()) {
+ ops.set_compression_level(param.server_context->compression_level());
+ }
+ if (status.ok()) {
+ status = ops.SendMessage(rsp);
+ }
+ ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
+ param.call->PerformOps(&ops);
+ param.call->cq()->Pluck(&ops);
+ }
+
+ private:
+ std::function<Status(ServiceType*, ServerContext*, ServerReader<RequestType>*,
+ ResponseType*)>
+ func_;
+ ServiceType* service_;
+};
+
+/// A wrapper class of an application provided server streaming handler.
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler : public MethodHandler {
+ public:
+ ServerStreamingHandler(
+ std::function<Status(ServiceType*, ServerContext*, const RequestType*,
+ ServerWriter<ResponseType>*)>
+ func,
+ ServiceType* service)
+ : func_(func), service_(service) {}
+
+ void RunHandler(const HandlerParameter& param) final {
+ RequestType req;
+ Status status = SerializationTraits<RequestType>::Deserialize(
+ param.request.bbuf_ptr(), &req);
+
+ if (status.ok()) {
+ ServerWriter<ResponseType> writer(param.call, param.server_context);
+ status = CatchingFunctionHandler([this, ¶m, &req, &writer] {
+ return func_(service_, param.server_context, &req, &writer);
+ });
+ }
+
+ CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
+ if (!param.server_context->sent_initial_metadata_) {
+ ops.SendInitialMetadata(param.server_context->initial_metadata_,
+ param.server_context->initial_metadata_flags());
+ if (param.server_context->compression_level_set()) {
+ ops.set_compression_level(param.server_context->compression_level());
+ }
+ }
+ ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
+ param.call->PerformOps(&ops);
+ if (param.server_context->has_pending_ops_) {
+ param.call->cq()->Pluck(¶m.server_context->pending_ops_);
+ }
+ param.call->cq()->Pluck(&ops);
+ }
+
+ private:
+ std::function<Status(ServiceType*, ServerContext*, const RequestType*,
+ ServerWriter<ResponseType>*)>
+ func_;
+ ServiceType* service_;
+};
+
+/// A wrapper class of an application provided bidi-streaming handler.
+/// This also applies to server-streamed implementation of a unary method
+/// with the additional requirement that such methods must have done a
+/// write for status to be ok
+/// Since this is used by more than 1 class, the service is not passed in.
+/// Instead, it is expected to be an implicitly-captured argument of func
+/// (through bind or something along those lines)
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler : public MethodHandler {
+ public:
+ TemplatedBidiStreamingHandler(
+ std::function<Status(ServerContext*, Streamer*)> func)
+ : func_(func), write_needed_(WriteNeeded) {}
+
+ void RunHandler(const HandlerParameter& param) final {
+ Streamer stream(param.call, param.server_context);
+ Status status = CatchingFunctionHandler([this, ¶m, &stream] {
+ return func_(param.server_context, &stream);
+ });
+
+ CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
+ if (!param.server_context->sent_initial_metadata_) {
+ ops.SendInitialMetadata(param.server_context->initial_metadata_,
+ param.server_context->initial_metadata_flags());
+ if (param.server_context->compression_level_set()) {
+ ops.set_compression_level(param.server_context->compression_level());
+ }
+ if (write_needed_ && status.ok()) {
+ // If we needed a write but never did one, we need to mark the
+ // status as a fail
+ status = Status(StatusCode::INTERNAL,
+ "Service did not provide response message");
+ }
+ }
+ ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
+ param.call->PerformOps(&ops);
+ if (param.server_context->has_pending_ops_) {
+ param.call->cq()->Pluck(¶m.server_context->pending_ops_);
+ }
+ param.call->cq()->Pluck(&ops);
+ }
+
+ private:
+ std::function<Status(ServerContext*, Streamer*)> func_;
+ const bool write_needed_;
+};
+
+template <class ServiceType, class RequestType, class ResponseType>
+class BidiStreamingHandler
+ : public TemplatedBidiStreamingHandler<
+ ServerReaderWriter<ResponseType, RequestType>, false> {
+ public:
+ BidiStreamingHandler(
+ std::function<Status(ServiceType*, ServerContext*,
+ ServerReaderWriter<ResponseType, RequestType>*)>
+ func,
+ ServiceType* service)
+ : TemplatedBidiStreamingHandler<
+ ServerReaderWriter<ResponseType, RequestType>, false>(std::bind(
+ func, service, std::placeholders::_1, std::placeholders::_2)) {}
+};
+
+template <class RequestType, class ResponseType>
+class StreamedUnaryHandler
+ : public TemplatedBidiStreamingHandler<
+ ServerUnaryStreamer<RequestType, ResponseType>, true> {
+ public:
+ explicit StreamedUnaryHandler(
+ std::function<Status(ServerContext*,
+ ServerUnaryStreamer<RequestType, ResponseType>*)>
+ func)
+ : TemplatedBidiStreamingHandler<
+ ServerUnaryStreamer<RequestType, ResponseType>, true>(func) {}
+};
+
+template <class RequestType, class ResponseType>
+class SplitServerStreamingHandler
+ : public TemplatedBidiStreamingHandler<
+ ServerSplitStreamer<RequestType, ResponseType>, false> {
+ public:
+ explicit SplitServerStreamingHandler(
+ std::function<Status(ServerContext*,
+ ServerSplitStreamer<RequestType, ResponseType>*)>
+ func)
+ : TemplatedBidiStreamingHandler<
+ ServerSplitStreamer<RequestType, ResponseType>, false>(func) {}
+};
+
+/// Handle unknown method by returning UNIMPLEMENTED error.
+class UnknownMethodHandler : public MethodHandler {
+ public:
+ template <class T>
+ static void FillOps(ServerContext* context, T* ops) {
+ Status status(StatusCode::UNIMPLEMENTED, "");
+ if (!context->sent_initial_metadata_) {
+ ops->SendInitialMetadata(context->initial_metadata_,
+ context->initial_metadata_flags());
+ if (context->compression_level_set()) {
+ ops->set_compression_level(context->compression_level());
+ }
+ context->sent_initial_metadata_ = true;
+ }
+ ops->ServerSendStatus(context->trailing_metadata_, status);
+ }
+
+ void RunHandler(const HandlerParameter& param) final {
+ CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
+ FillOps(param.server_context, &ops);
+ param.call->PerformOps(&ops);
+ param.call->cq()->Pluck(&ops);
+ }
+};
+
+} // namespace internal
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
diff --git a/include/grpcpp/impl/codegen/proto_utils.h b/include/grpcpp/impl/codegen/proto_utils.h
new file mode 100644
index 0000000..81438ee
--- /dev/null
+++ b/include/grpcpp/impl/codegen/proto_utils.h
@@ -0,0 +1,268 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
+#define GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
+
+#include <type_traits>
+
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/config_protobuf.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+namespace internal {
+
+class GrpcBufferWriterPeer;
+
+const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024;
+
+class GrpcBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
+ public:
+ GrpcBufferWriter(grpc_byte_buffer** bp, int block_size, int total_size)
+ : block_size_(block_size),
+ total_size_(total_size),
+ byte_count_(0),
+ have_backup_(false) {
+ *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0);
+ slice_buffer_ = &(*bp)->data.raw.slice_buffer;
+ }
+
+ ~GrpcBufferWriter() override {
+ if (have_backup_) {
+ g_core_codegen_interface->grpc_slice_unref(backup_slice_);
+ }
+ }
+
+ bool Next(void** data, int* size) override {
+ // Protobuf should not ask for more memory than total_size_.
+ GPR_CODEGEN_ASSERT(byte_count_ < total_size_);
+ size_t remain = total_size_ - byte_count_;
+ if (have_backup_) {
+ slice_ = backup_slice_;
+ have_backup_ = false;
+ if (GRPC_SLICE_LENGTH(slice_) > remain) {
+ GRPC_SLICE_SET_LENGTH(slice_, remain);
+ }
+ } else {
+ // When less than a whole block is needed, only allocate that much.
+ // But make sure the allocated slice is not inlined.
+ size_t allocate_length =
+ remain > static_cast<size_t>(block_size_) ? block_size_ : remain;
+ slice_ = g_core_codegen_interface->grpc_slice_malloc(
+ allocate_length > GRPC_SLICE_INLINED_SIZE
+ ? allocate_length
+ : GRPC_SLICE_INLINED_SIZE + 1);
+ }
+ *data = GRPC_SLICE_START_PTR(slice_);
+ // On win x64, int is only 32bit
+ GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
+ byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
+ g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
+ return true;
+ }
+
+ void BackUp(int count) override {
+ g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_);
+ if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) {
+ backup_slice_ = slice_;
+ } else {
+ backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail(
+ &slice_, GRPC_SLICE_LENGTH(slice_) - count);
+ g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
+ }
+ // It's dangerous to keep an inlined grpc_slice as the backup slice, since
+ // on a following Next() call, a reference will be returned to this slice
+ // via GRPC_SLICE_START_PTR, which will not be an adddress held by
+ // slice_buffer_.
+ have_backup_ = backup_slice_.refcount != NULL;
+ byte_count_ -= count;
+ }
+
+ grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
+
+ protected:
+ friend class GrpcBufferWriterPeer;
+ const int block_size_;
+ const int total_size_;
+ int64_t byte_count_;
+ grpc_slice_buffer* slice_buffer_;
+ bool have_backup_;
+ grpc_slice backup_slice_;
+ grpc_slice slice_;
+};
+
+class GrpcBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream {
+ public:
+ explicit GrpcBufferReader(grpc_byte_buffer* buffer)
+ : byte_count_(0), backup_count_(0), status_() {
+ if (!g_core_codegen_interface->grpc_byte_buffer_reader_init(&reader_,
+ buffer)) {
+ status_ = Status(StatusCode::INTERNAL,
+ "Couldn't initialize byte buffer reader");
+ }
+ }
+ ~GrpcBufferReader() override {
+ g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_);
+ }
+
+ bool Next(const void** data, int* size) override {
+ if (!status_.ok()) {
+ return false;
+ }
+ if (backup_count_ > 0) {
+ *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) -
+ backup_count_;
+ GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
+ *size = (int)backup_count_;
+ backup_count_ = 0;
+ return true;
+ }
+ if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_,
+ &slice_)) {
+ return false;
+ }
+ g_core_codegen_interface->grpc_slice_unref(slice_);
+ *data = GRPC_SLICE_START_PTR(slice_);
+ // On win x64, int is only 32bit
+ GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
+ byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
+ return true;
+ }
+
+ Status status() const { return status_; }
+
+ void BackUp(int count) override { backup_count_ = count; }
+
+ bool Skip(int count) override {
+ const void* data;
+ int size;
+ while (Next(&data, &size)) {
+ if (size >= count) {
+ BackUp(size - count);
+ return true;
+ }
+ // size < count;
+ count -= size;
+ }
+ // error or we have too large count;
+ return false;
+ }
+
+ grpc::protobuf::int64 ByteCount() const override {
+ return byte_count_ - backup_count_;
+ }
+
+ protected:
+ int64_t byte_count_;
+ int64_t backup_count_;
+ grpc_byte_buffer_reader reader_;
+ grpc_slice slice_;
+ Status status_;
+};
+
+// BufferWriter must be a subclass of io::ZeroCopyOutputStream.
+template <class BufferWriter, class T>
+Status GenericSerialize(const grpc::protobuf::Message& msg,
+ grpc_byte_buffer** bp, bool* own_buffer) {
+ static_assert(
+ std::is_base_of<protobuf::io::ZeroCopyOutputStream, BufferWriter>::value,
+ "BufferWriter must be a subclass of io::ZeroCopyOutputStream");
+ *own_buffer = true;
+ int byte_size = msg.ByteSize();
+ if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) {
+ grpc_slice slice = g_core_codegen_interface->grpc_slice_malloc(byte_size);
+ GPR_CODEGEN_ASSERT(
+ GRPC_SLICE_END_PTR(slice) ==
+ msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice)));
+ *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1);
+ g_core_codegen_interface->grpc_slice_unref(slice);
+
+ return g_core_codegen_interface->ok();
+ }
+ BufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength, byte_size);
+ return msg.SerializeToZeroCopyStream(&writer)
+ ? g_core_codegen_interface->ok()
+ : Status(StatusCode::INTERNAL, "Failed to serialize message");
+}
+
+// BufferReader must be a subclass of io::ZeroCopyInputStream.
+template <class BufferReader, class T>
+Status GenericDeserialize(grpc_byte_buffer* buffer,
+ grpc::protobuf::Message* msg) {
+ static_assert(
+ std::is_base_of<protobuf::io::ZeroCopyInputStream, BufferReader>::value,
+ "BufferReader must be a subclass of io::ZeroCopyInputStream");
+ if (buffer == nullptr) {
+ return Status(StatusCode::INTERNAL, "No payload");
+ }
+ Status result = g_core_codegen_interface->ok();
+ {
+ BufferReader reader(buffer);
+ if (!reader.status().ok()) {
+ return reader.status();
+ }
+ ::grpc::protobuf::io::CodedInputStream decoder(&reader);
+ decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
+ if (!msg->ParseFromCodedStream(&decoder)) {
+ result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
+ }
+ if (!decoder.ConsumedEntireMessage()) {
+ result = Status(StatusCode::INTERNAL, "Did not read entire message");
+ }
+ }
+ g_core_codegen_interface->grpc_byte_buffer_destroy(buffer);
+ return result;
+}
+
+} // namespace internal
+
+// this is needed so the following class does not conflict with protobuf
+// serializers that utilize internal-only tools.
+#ifdef GRPC_OPEN_SOURCE_PROTO
+// This class provides a protobuf serializer. It translates between protobuf
+// objects and grpc_byte_buffers. More information about SerializationTraits can
+// be found in include/grpcpp/impl/codegen/serialization_traits.h.
+template <class T>
+class SerializationTraits<T, typename std::enable_if<std::is_base_of<
+ grpc::protobuf::Message, T>::value>::type> {
+ public:
+ static Status Serialize(const grpc::protobuf::Message& msg,
+ grpc_byte_buffer** bp, bool* own_buffer) {
+ return internal::GenericSerialize<internal::GrpcBufferWriter, T>(
+ msg, bp, own_buffer);
+ }
+
+ static Status Deserialize(grpc_byte_buffer* buffer,
+ grpc::protobuf::Message* msg) {
+ return internal::GenericDeserialize<internal::GrpcBufferReader, T>(buffer,
+ msg);
+ }
+};
+#endif
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
diff --git a/include/grpcpp/impl/codegen/rpc_method.h b/include/grpcpp/impl/codegen/rpc_method.h
new file mode 100644
index 0000000..9dcde95
--- /dev/null
+++ b/include/grpcpp/impl/codegen/rpc_method.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_RPC_METHOD_H
+#define GRPCPP_IMPL_CODEGEN_RPC_METHOD_H
+
+#include <memory>
+
+#include <grpcpp/impl/codegen/channel_interface.h>
+
+namespace grpc {
+namespace internal {
+/// Descriptor of an RPC method
+class RpcMethod {
+ public:
+ enum RpcType {
+ NORMAL_RPC = 0,
+ CLIENT_STREAMING, // request streaming
+ SERVER_STREAMING, // response streaming
+ BIDI_STREAMING
+ };
+
+ RpcMethod(const char* name, RpcType type)
+ : name_(name), method_type_(type), channel_tag_(NULL) {}
+
+ RpcMethod(const char* name, RpcType type,
+ const std::shared_ptr<ChannelInterface>& channel)
+ : name_(name),
+ method_type_(type),
+ channel_tag_(channel->RegisterMethod(name)) {}
+
+ const char* name() const { return name_; }
+ RpcType method_type() const { return method_type_; }
+ void SetMethodType(RpcType type) { method_type_ = type; }
+ void* channel_tag() const { return channel_tag_; }
+
+ private:
+ const char* const name_;
+ RpcType method_type_;
+ void* const channel_tag_;
+};
+
+} // namespace internal
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_RPC_METHOD_H
diff --git a/include/grpcpp/impl/codegen/rpc_service_method.h b/include/grpcpp/impl/codegen/rpc_service_method.h
new file mode 100644
index 0000000..dd85405
--- /dev/null
+++ b/include/grpcpp/impl/codegen/rpc_service_method.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H
+#define GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H
+
+#include <climits>
+#include <functional>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+class ServerContext;
+
+namespace internal {
+/// Base class for running an RPC handler.
+class MethodHandler {
+ public:
+ virtual ~MethodHandler() {}
+ struct HandlerParameter {
+ HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req)
+ : call(c), server_context(context) {
+ request.set_buffer(req);
+ }
+ ~HandlerParameter() { request.Release(); }
+ Call* call;
+ ServerContext* server_context;
+ // Handler required to destroy these contents
+ ByteBuffer request;
+ };
+ virtual void RunHandler(const HandlerParameter& param) = 0;
+};
+
+/// Server side rpc method class
+class RpcServiceMethod : public RpcMethod {
+ public:
+ /// Takes ownership of the handler
+ RpcServiceMethod(const char* name, RpcMethod::RpcType type,
+ MethodHandler* handler)
+ : RpcMethod(name, type), server_tag_(nullptr), handler_(handler) {}
+
+ void set_server_tag(void* tag) { server_tag_ = tag; }
+ void* server_tag() const { return server_tag_; }
+ /// if MethodHandler is nullptr, then this is an async method
+ MethodHandler* handler() const { return handler_.get(); }
+ void ResetHandler() { handler_.reset(); }
+ void SetHandler(MethodHandler* handler) { handler_.reset(handler); }
+
+ private:
+ void* server_tag_;
+ std::unique_ptr<MethodHandler> handler_;
+};
+} // namespace internal
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H
diff --git a/include/grpcpp/impl/codegen/security/auth_context.h b/include/grpcpp/impl/codegen/security/auth_context.h
new file mode 100644
index 0000000..0e30f7c
--- /dev/null
+++ b/include/grpcpp/impl/codegen/security/auth_context.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H
+
+#include <iterator>
+#include <vector>
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+struct grpc_auth_context;
+struct grpc_auth_property;
+struct grpc_auth_property_iterator;
+
+namespace grpc {
+class SecureAuthContext;
+
+typedef std::pair<grpc::string_ref, grpc::string_ref> AuthProperty;
+
+class AuthPropertyIterator
+ : public std::iterator<std::input_iterator_tag, const AuthProperty> {
+ public:
+ ~AuthPropertyIterator();
+ AuthPropertyIterator& operator++();
+ AuthPropertyIterator operator++(int);
+ bool operator==(const AuthPropertyIterator& rhs) const;
+ bool operator!=(const AuthPropertyIterator& rhs) const;
+ const AuthProperty operator*();
+
+ protected:
+ AuthPropertyIterator();
+ AuthPropertyIterator(const grpc_auth_property* property,
+ const grpc_auth_property_iterator* iter);
+
+ private:
+ friend class SecureAuthContext;
+ const grpc_auth_property* property_;
+ // The following items form a grpc_auth_property_iterator.
+ const grpc_auth_context* ctx_;
+ size_t index_;
+ const char* name_;
+};
+
+/// Class encapsulating the Authentication Information.
+///
+/// It includes the secure identity of the peer, the type of secure transport
+/// used as well as any other properties required by the authorization layer.
+class AuthContext {
+ public:
+ virtual ~AuthContext() {}
+
+ /// Returns true if the peer is authenticated.
+ virtual bool IsPeerAuthenticated() const = 0;
+
+ /// A peer identity.
+ ///
+ /// It is, in general, comprised of one or more properties (in which case they
+ /// have the same name).
+ virtual std::vector<grpc::string_ref> GetPeerIdentity() const = 0;
+ virtual grpc::string GetPeerIdentityPropertyName() const = 0;
+
+ /// Returns all the property values with the given name.
+ virtual std::vector<grpc::string_ref> FindPropertyValues(
+ const grpc::string& name) const = 0;
+
+ /// Iteration over all the properties.
+ virtual AuthPropertyIterator begin() const = 0;
+ virtual AuthPropertyIterator end() const = 0;
+
+ /// Mutation functions: should only be used by an AuthMetadataProcessor.
+ virtual void AddProperty(const grpc::string& key,
+ const grpc::string_ref& value) = 0;
+ virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H
diff --git a/include/grpcpp/impl/codegen/serialization_traits.h b/include/grpcpp/impl/codegen/serialization_traits.h
new file mode 100644
index 0000000..8f79223
--- /dev/null
+++ b/include/grpcpp/impl/codegen/serialization_traits.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SERIALIZATION_TRAITS_H
+#define GRPCPP_IMPL_CODEGEN_SERIALIZATION_TRAITS_H
+
+namespace grpc {
+
+/// Defines how to serialize and deserialize some type.
+///
+/// Used for hooking different message serialization API's into GRPC.
+/// Each SerializationTraits<Message> implementation must provide the
+/// following functions:
+/// 1. static Status Serialize(const Message& msg,
+/// ByteBuffer* buffer,
+/// bool* own_buffer);
+/// OR
+/// static Status Serialize(const Message& msg,
+/// grpc_byte_buffer** buffer,
+/// bool* own_buffer);
+/// The former is preferred; the latter is deprecated
+///
+/// 2. static Status Deserialize(ByteBuffer* buffer,
+/// Message* msg);
+/// OR
+/// static Status Deserialize(grpc_byte_buffer* buffer,
+/// Message* msg);
+/// The former is preferred; the latter is deprecated
+///
+/// Serialize is required to convert message to a ByteBuffer, and
+/// return that byte buffer through *buffer. *own_buffer should
+/// be set to true if the caller owns said byte buffer, or false if
+/// ownership is retained elsewhere.
+///
+/// Deserialize is required to convert buffer into the message stored at
+/// msg. max_receive_message_size is passed in as a bound on the maximum
+/// number of message bytes Deserialize should accept.
+///
+/// Both functions return a Status, allowing them to explain what went
+/// wrong if required.
+template <class Message,
+ class UnusedButHereForPartialTemplateSpecialization = void>
+class SerializationTraits;
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SERIALIZATION_TRAITS_H
diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h
new file mode 100644
index 0000000..bb357d6
--- /dev/null
+++ b/include/grpcpp/impl/codegen/server_context.h
@@ -0,0 +1,309 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <grpc/impl/codegen/compression_types.h>
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/create_auth_context.h>
+#include <grpcpp/impl/codegen/metadata_map.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct grpc_metadata;
+struct grpc_call;
+struct census_context;
+
+namespace grpc {
+class ClientContext;
+template <class W, class R>
+class ServerAsyncReader;
+template <class W>
+class ServerAsyncWriter;
+template <class W>
+class ServerAsyncResponseWriter;
+template <class W, class R>
+class ServerAsyncReaderWriter;
+template <class R>
+class ServerReader;
+template <class W>
+class ServerWriter;
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class BidiStreamingHandler;
+class UnknownMethodHandler;
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler;
+class Call;
+} // namespace internal
+
+class CompletionQueue;
+class Server;
+class ServerInterface;
+
+namespace testing {
+class InteropServerContextInspector;
+class ServerContextTestSpouse;
+} // namespace testing
+
+/// A ServerContext allows the person implementing a service handler to:
+///
+/// - Add custom initial and trailing metadata key-value pairs that will
+/// propagated to the client side.
+/// - Control call settings such as compression and authentication.
+/// - Access metadata coming from the client.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call handler they are supplied to,
+/// that is to say, they aren't sticky across multiple calls. Some of these
+/// settings, such as the compression options, can be made persistant at server
+/// construction time by specifying the approriate \a ChannelArguments
+/// to a \a grpc::ServerBuilder, via \a ServerBuilder::AddChannelArgument.
+///
+/// \warning ServerContext instances should \em not be reused across rpcs.
+class ServerContext {
+ public:
+ ServerContext(); // for async calls
+ ~ServerContext();
+
+ /// Return the deadline for the server call.
+ std::chrono::system_clock::time_point deadline() const {
+ return Timespec2Timepoint(deadline_);
+ }
+
+ /// Return a \a gpr_timespec representation of the server call's deadline.
+ gpr_timespec raw_deadline() const { return deadline_; }
+
+ /// Add the (\a meta_key, \a meta_value) pair to the initial metadata
+ /// associated with a server call. These are made available at the client side
+ /// by the \a grpc::ClientContext::GetServerInitialMetadata() method.
+ ///
+ /// \warning This method should only be called before sending initial metadata
+ /// to the client (which can happen explicitly, or implicitly when sending a
+ /// a response message or status to the client).
+ ///
+ /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+ /// end in "-bin".
+ /// \param meta_value The metadata value. If its value is binary, the key name
+ /// must end in "-bin".
+ void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
+
+ /// Add the (\a meta_key, \a meta_value) pair to the initial metadata
+ /// associated with a server call. These are made available at the client
+ /// side by the \a grpc::ClientContext::GetServerTrailingMetadata() method.
+ ///
+ /// \warning This method should only be called before sending trailing
+ /// metadata to the client (which happens when the call is finished and a
+ /// status is sent to the client).
+ ///
+ /// \param meta_key The metadata key. If \a meta_value is binary data,
+ /// it must end in "-bin".
+ /// \param meta_value The metadata value. If its value is binary, the key name
+ /// must end in "-bin".
+ void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
+
+ /// IsCancelled is always safe to call when using sync API.
+ /// When using async API, it is only safe to call IsCancelled after
+ /// the AsyncNotifyWhenDone tag has been delivered.
+ bool IsCancelled() const;
+
+ /// Cancel the Call from the server. This is a best-effort API and
+ /// depending on when it is called, the RPC may still appear successful to
+ /// the client.
+ /// For example, if TryCancel() is called on a separate thread, it might race
+ /// with the server handler which might return success to the client before
+ /// TryCancel() was even started by the thread.
+ ///
+ /// It is the caller's responsibility to prevent such races and ensure that if
+ /// TryCancel() is called, the serverhandler must return Status::CANCELLED.
+ /// The only exception is that if the serverhandler is already returning an
+ /// error status code, it is ok to not return Status::CANCELLED even if
+ /// TryCancel() was called.
+ ///
+ /// Note that TryCancel() does not change any of the tags that are pending
+ /// on the completion queue. All pending tags will still be delivered
+ /// (though their ok result may reflect the effect of cancellation).
+ void TryCancel() const;
+
+ /// Return a collection of initial metadata key-value pairs sent from the
+ /// client. Note that keys may happen more than
+ /// once (ie, a \a std::multimap is returned).
+ ///
+ /// It is safe to use this method after initial metadata has been received,
+ /// Calls always begin with the client sending initial metadata, so this is
+ /// safe to access as soon as the call has begun on the server side.
+ ///
+ /// \return A multimap of initial metadata key-value pairs from the server.
+ const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
+ const {
+ return *client_metadata_.map();
+ }
+
+ /// Return the compression algorithm to be used by the server call.
+ grpc_compression_level compression_level() const {
+ return compression_level_;
+ }
+
+ /// Set \a algorithm to be the compression algorithm used for the server call.
+ ///
+ /// \param algorithm The compression algorithm used for the server call.
+ void set_compression_level(grpc_compression_level level) {
+ compression_level_set_ = true;
+ compression_level_ = level;
+ }
+
+ /// Return a bool indicating whether the compression level for this call
+ /// has been set (either implicitly or through a previous call to
+ /// \a set_compression_level.
+ bool compression_level_set() const { return compression_level_set_; }
+
+ /// Return the compression algorithm the server call will request be used.
+ /// Note that the gRPC runtime may decide to ignore this request, for example,
+ /// due to resource constraints, or if the server is aware the client doesn't
+ /// support the requested algorithm.
+ grpc_compression_algorithm compression_algorithm() const {
+ return compression_algorithm_;
+ }
+ /// Set \a algorithm to be the compression algorithm used for the server call.
+ ///
+ /// \param algorithm The compression algorithm used for the server call.
+ void set_compression_algorithm(grpc_compression_algorithm algorithm);
+
+ /// Set the load reporting costs in \a cost_data for the call.
+ void SetLoadReportingCosts(const std::vector<grpc::string>& cost_data);
+
+ /// Return the authentication context for this server call.
+ ///
+ /// \see grpc::AuthContext.
+ std::shared_ptr<const AuthContext> auth_context() const {
+ if (auth_context_.get() == nullptr) {
+ auth_context_ = CreateAuthContext(call_);
+ }
+ return auth_context_;
+ }
+
+ /// Return the peer uri in a string.
+ /// WARNING: this value is never authenticated or subject to any security
+ /// related code. It must not be used for any authentication related
+ /// functionality. Instead, use auth_context.
+ grpc::string peer() const;
+
+ /// Get the census context associated with this server call.
+ const struct census_context* census_context() const;
+
+ /// Async only. Has to be called before the rpc starts.
+ /// Returns the tag in completion queue when the rpc finishes.
+ /// IsCancelled() can then be called to check whether the rpc was cancelled.
+ void AsyncNotifyWhenDone(void* tag) {
+ has_notify_when_done_tag_ = true;
+ async_notify_when_done_tag_ = tag;
+ }
+
+ /// Should be used for framework-level extensions only.
+ /// Applications never need to call this method.
+ grpc_call* c_call() { return call_; }
+
+ private:
+ friend class ::grpc::testing::InteropServerContextInspector;
+ friend class ::grpc::testing::ServerContextTestSpouse;
+ friend class ::grpc::ServerInterface;
+ friend class ::grpc::Server;
+ template <class W, class R>
+ friend class ::grpc::ServerAsyncReader;
+ template <class W>
+ friend class ::grpc::ServerAsyncWriter;
+ template <class W>
+ friend class ::grpc::ServerAsyncResponseWriter;
+ template <class W, class R>
+ friend class ::grpc::ServerAsyncReaderWriter;
+ template <class R>
+ friend class ::grpc::ServerReader;
+ template <class W>
+ friend class ::grpc::ServerWriter;
+ template <class W, class R>
+ friend class ::grpc::internal::ServerReaderWriterBody;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class ::grpc::internal::RpcMethodHandler;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class ::grpc::internal::ClientStreamingHandler;
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class ::grpc::internal::ServerStreamingHandler;
+ template <class Streamer, bool WriteNeeded>
+ friend class ::grpc::internal::TemplatedBidiStreamingHandler;
+ friend class ::grpc::internal::UnknownMethodHandler;
+ friend class ::grpc::ClientContext;
+
+ /// Prevent copying.
+ ServerContext(const ServerContext&);
+ ServerContext& operator=(const ServerContext&);
+
+ class CompletionOp;
+
+ void BeginCompletionOp(internal::Call* call);
+ /// Return the tag queued by BeginCompletionOp()
+ internal::CompletionQueueTag* GetCompletionOpTag();
+
+ ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
+
+ void set_call(grpc_call* call) { call_ = call; }
+
+ uint32_t initial_metadata_flags() const { return 0; }
+
+ CompletionOp* completion_op_;
+ bool has_notify_when_done_tag_;
+ void* async_notify_when_done_tag_;
+
+ gpr_timespec deadline_;
+ grpc_call* call_;
+ CompletionQueue* cq_;
+ bool sent_initial_metadata_;
+ mutable std::shared_ptr<const AuthContext> auth_context_;
+ internal::MetadataMap client_metadata_;
+ std::multimap<grpc::string, grpc::string> initial_metadata_;
+ std::multimap<grpc::string, grpc::string> trailing_metadata_;
+
+ bool compression_level_set_;
+ grpc_compression_level compression_level_;
+ grpc_compression_algorithm compression_algorithm_;
+
+ internal::CallOpSet<internal::CallOpSendInitialMetadata,
+ internal::CallOpSendMessage>
+ pending_ops_;
+ bool has_pending_ops_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H
diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h
new file mode 100644
index 0000000..4700763
--- /dev/null
+++ b/include/grpcpp/impl/codegen/server_interface.h
@@ -0,0 +1,274 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/call_hook.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+
+namespace grpc {
+
+class AsyncGenericService;
+class Channel;
+class GenericServerContext;
+class ServerCompletionQueue;
+class ServerContext;
+class ServerCredentials;
+class Service;
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// Models a gRPC server.
+///
+/// Servers are configured and started via \a grpc::ServerBuilder.
+namespace internal {
+class ServerAsyncStreamingInterface;
+} // namespace internal
+
+class ServerInterface : public internal::CallHook {
+ public:
+ virtual ~ServerInterface() {}
+
+ /// Shutdown the server, blocking until all rpc processing finishes.
+ /// Forcefully terminate pending calls after \a deadline expires.
+ ///
+ /// All completion queue associated with the server (for example, for async
+ /// serving) must be shutdown *after* this method has returned:
+ /// See \a ServerBuilder::AddCompletionQueue for details.
+ ///
+ /// \param deadline How long to wait until pending rpcs are forcefully
+ /// terminated.
+ template <class T>
+ void Shutdown(const T& deadline) {
+ ShutdownInternal(TimePoint<T>(deadline).raw_time());
+ }
+
+ /// Shutdown the server, waiting for all rpc processing to finish.
+ ///
+ /// All completion queue associated with the server (for example, for async
+ /// serving) must be shutdown *after* this method has returned:
+ /// See \a ServerBuilder::AddCompletionQueue for details.
+ void Shutdown() {
+ ShutdownInternal(
+ g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_MONOTONIC));
+ }
+
+ /// Block waiting for all work to complete.
+ ///
+ /// \warning The server must be either shutting down or some other thread must
+ /// call \a Shutdown for this function to ever return.
+ virtual void Wait() = 0;
+
+ protected:
+ friend class ::grpc::Service;
+
+ /// Register a service. This call does not take ownership of the service.
+ /// The service must exist for the lifetime of the Server instance.
+ virtual bool RegisterService(const grpc::string* host, Service* service) = 0;
+
+ /// Register a generic service. This call does not take ownership of the
+ /// service. The service must exist for the lifetime of the Server instance.
+ virtual void RegisterAsyncGenericService(AsyncGenericService* service) = 0;
+
+ /// Tries to bind \a server to the given \a addr.
+ ///
+ /// It can be invoked multiple times.
+ ///
+ /// \param addr The address to try to bind to the server (eg, localhost:1234,
+ /// 192.168.1.1:31416, [::1]:27182, etc.).
+ /// \params creds The credentials associated with the server.
+ ///
+ /// \return bound port number on sucess, 0 on failure.
+ ///
+ /// \warning It's an error to call this method on an already started server.
+ virtual int AddListeningPort(const grpc::string& addr,
+ ServerCredentials* creds) = 0;
+
+ /// Start the server.
+ ///
+ /// \param cqs Completion queues for handling asynchronous services. The
+ /// caller is required to keep all completion queues live until the server is
+ /// destroyed.
+ /// \param num_cqs How many completion queues does \a cqs hold.
+ virtual void Start(ServerCompletionQueue** cqs, size_t num_cqs) = 0;
+
+ virtual void ShutdownInternal(gpr_timespec deadline) = 0;
+
+ virtual int max_receive_message_size() const = 0;
+
+ virtual grpc_server* server() = 0;
+
+ virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
+ internal::Call* call) = 0;
+
+ class BaseAsyncRequest : public internal::CompletionQueueTag {
+ public:
+ BaseAsyncRequest(ServerInterface* server, ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq, void* tag,
+ bool delete_on_finalize);
+ virtual ~BaseAsyncRequest();
+
+ bool FinalizeResult(void** tag, bool* status) override;
+
+ protected:
+ ServerInterface* const server_;
+ ServerContext* const context_;
+ internal::ServerAsyncStreamingInterface* const stream_;
+ CompletionQueue* const call_cq_;
+ void* const tag_;
+ const bool delete_on_finalize_;
+ grpc_call* call_;
+ };
+
+ class RegisteredAsyncRequest : public BaseAsyncRequest {
+ public:
+ RegisteredAsyncRequest(ServerInterface* server, ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq, void* tag);
+
+ // uses BaseAsyncRequest::FinalizeResult
+
+ protected:
+ void IssueRequest(void* registered_method, grpc_byte_buffer** payload,
+ ServerCompletionQueue* notification_cq);
+ };
+
+ class NoPayloadAsyncRequest final : public RegisteredAsyncRequest {
+ public:
+ NoPayloadAsyncRequest(void* registered_method, ServerInterface* server,
+ ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag)
+ : RegisteredAsyncRequest(server, context, stream, call_cq, tag) {
+ IssueRequest(registered_method, nullptr, notification_cq);
+ }
+
+ // uses RegisteredAsyncRequest::FinalizeResult
+ };
+
+ template <class Message>
+ class PayloadAsyncRequest final : public RegisteredAsyncRequest {
+ public:
+ PayloadAsyncRequest(void* registered_method, ServerInterface* server,
+ ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag,
+ Message* request)
+ : RegisteredAsyncRequest(server, context, stream, call_cq, tag),
+ registered_method_(registered_method),
+ server_(server),
+ context_(context),
+ stream_(stream),
+ call_cq_(call_cq),
+ notification_cq_(notification_cq),
+ tag_(tag),
+ request_(request) {
+ IssueRequest(registered_method, &payload_, notification_cq);
+ }
+
+ bool FinalizeResult(void** tag, bool* status) override {
+ if (*status) {
+ if (payload_ == nullptr ||
+ !SerializationTraits<Message>::Deserialize(payload_, request_)
+ .ok()) {
+ // If deserialization fails, we cancel the call and instantiate
+ // a new instance of ourselves to request another call. We then
+ // return false, which prevents the call from being returned to
+ // the application.
+ g_core_codegen_interface->grpc_call_cancel_with_status(
+ call_, GRPC_STATUS_INTERNAL, "Unable to parse request", nullptr);
+ g_core_codegen_interface->grpc_call_unref(call_);
+ new PayloadAsyncRequest(registered_method_, server_, context_,
+ stream_, call_cq_, notification_cq_, tag_,
+ request_);
+ delete this;
+ return false;
+ }
+ }
+ return RegisteredAsyncRequest::FinalizeResult(tag, status);
+ }
+
+ private:
+ void* const registered_method_;
+ ServerInterface* const server_;
+ ServerContext* const context_;
+ internal::ServerAsyncStreamingInterface* const stream_;
+ CompletionQueue* const call_cq_;
+ ServerCompletionQueue* const notification_cq_;
+ void* const tag_;
+ Message* const request_;
+ grpc_byte_buffer* payload_;
+ };
+
+ class GenericAsyncRequest : public BaseAsyncRequest {
+ public:
+ GenericAsyncRequest(ServerInterface* server, GenericServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag,
+ bool delete_on_finalize);
+
+ bool FinalizeResult(void** tag, bool* status) override;
+
+ private:
+ grpc_call_details call_details_;
+ };
+
+ template <class Message>
+ void RequestAsyncCall(internal::RpcServiceMethod* method,
+ ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag,
+ Message* message) {
+ GPR_CODEGEN_ASSERT(method);
+ new PayloadAsyncRequest<Message>(method->server_tag(), this, context,
+ stream, call_cq, notification_cq, tag,
+ message);
+ }
+
+ void RequestAsyncCall(internal::RpcServiceMethod* method,
+ ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag) {
+ GPR_CODEGEN_ASSERT(method);
+ new NoPayloadAsyncRequest(method->server_tag(), this, context, stream,
+ call_cq, notification_cq, tag);
+ }
+
+ void RequestAsyncGenericCall(GenericServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq,
+ void* tag) {
+ new GenericAsyncRequest(this, context, stream, call_cq, notification_cq,
+ tag, true);
+ }
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
diff --git a/include/grpcpp/impl/codegen/service_type.h b/include/grpcpp/impl/codegen/service_type.h
new file mode 100644
index 0000000..a576f66
--- /dev/null
+++ b/include/grpcpp/impl/codegen/service_type.h
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
+#define GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/server_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class CompletionQueue;
+class Server;
+class ServerInterface;
+class ServerCompletionQueue;
+class ServerContext;
+
+namespace internal {
+class Call;
+class ServerAsyncStreamingInterface {
+ public:
+ virtual ~ServerAsyncStreamingInterface() {}
+
+ /// Request notification of the sending of initial metadata to the client.
+ /// Completion will be notified by \a tag on the associated completion
+ /// queue. This call is optional, but if it is used, it cannot be used
+ /// concurrently with or after the \a Finish method.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ virtual void SendInitialMetadata(void* tag) = 0;
+
+ private:
+ friend class ::grpc::ServerInterface;
+ virtual void BindCall(Call* call) = 0;
+};
+} // namespace internal
+
+/// Desriptor of an RPC service and its various RPC methods
+class Service {
+ public:
+ Service() : server_(nullptr) {}
+ virtual ~Service() {}
+
+ bool has_async_methods() const {
+ for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+ if (*it && (*it)->handler() == nullptr) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool has_synchronous_methods() const {
+ for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+ if (*it && (*it)->handler() != nullptr) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool has_generic_methods() const {
+ for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+ if (it->get() == nullptr) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected:
+ template <class Message>
+ void RequestAsyncUnary(int index, ServerContext* context, Message* request,
+ internal::ServerAsyncStreamingInterface* stream,
+ CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag) {
+ server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
+ notification_cq, tag, request);
+ }
+ void RequestAsyncClientStreaming(
+ int index, ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag) {
+ server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
+ notification_cq, tag);
+ }
+ template <class Message>
+ void RequestAsyncServerStreaming(
+ int index, ServerContext* context, Message* request,
+ internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag) {
+ server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
+ notification_cq, tag, request);
+ }
+ void RequestAsyncBidiStreaming(
+ int index, ServerContext* context,
+ internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+ ServerCompletionQueue* notification_cq, void* tag) {
+ server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
+ notification_cq, tag);
+ }
+
+ void AddMethod(internal::RpcServiceMethod* method) {
+ methods_.emplace_back(method);
+ }
+
+ void MarkMethodAsync(int index) {
+ GPR_CODEGEN_ASSERT(
+ methods_[index].get() != nullptr &&
+ "Cannot mark the method as 'async' because it has already been "
+ "marked as 'generic'.");
+ methods_[index]->ResetHandler();
+ }
+
+ void MarkMethodGeneric(int index) {
+ GPR_CODEGEN_ASSERT(
+ methods_[index]->handler() != nullptr &&
+ "Cannot mark the method as 'generic' because it has already been "
+ "marked as 'async'.");
+ methods_[index].reset();
+ }
+
+ void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
+ GPR_CODEGEN_ASSERT(methods_[index] && methods_[index]->handler() &&
+ "Cannot mark an async or generic method Streamed");
+ methods_[index]->SetHandler(streamed_method);
+
+ // From the server's point of view, streamed unary is a special
+ // case of BIDI_STREAMING that has 1 read and 1 write, in that order,
+ // and split server-side streaming is BIDI_STREAMING with 1 read and
+ // any number of writes, in that order.
+ methods_[index]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
+ }
+
+ private:
+ friend class Server;
+ friend class ServerInterface;
+ ServerInterface* server_;
+ std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
diff --git a/include/grpcpp/impl/codegen/slice.h b/include/grpcpp/impl/codegen/slice.h
new file mode 100644
index 0000000..fcccd4b
--- /dev/null
+++ b/include/grpcpp/impl/codegen/slice.h
@@ -0,0 +1,128 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SLICE_H
+#define GRPCPP_IMPL_CODEGEN_SLICE_H
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+#include <grpc/impl/codegen/slice.h>
+
+namespace grpc {
+
+/// A wrapper around \a grpc_slice.
+///
+/// A slice represents a contiguous reference counted array of bytes.
+/// It is cheap to take references to a slice, and it is cheap to create a
+/// slice pointing to a subset of another slice.
+class Slice final {
+ public:
+ /// Construct an empty slice.
+ Slice();
+ /// Destructor - drops one reference.
+ ~Slice();
+
+ enum AddRef { ADD_REF };
+ /// Construct a slice from \a slice, adding a reference.
+ Slice(grpc_slice slice, AddRef);
+
+ enum StealRef { STEAL_REF };
+ /// Construct a slice from \a slice, stealing a reference.
+ Slice(grpc_slice slice, StealRef);
+
+ /// Allocate a slice of specified size
+ Slice(size_t len);
+
+ /// Construct a slice from a copied buffer
+ Slice(const void* buf, size_t len);
+
+ /// Construct a slice from a copied string
+ Slice(const grpc::string& str);
+
+ enum StaticSlice { STATIC_SLICE };
+
+ /// Construct a slice from a static buffer
+ Slice(const void* buf, size_t len, StaticSlice);
+
+ /// Copy constructor, adds a reference.
+ Slice(const Slice& other);
+
+ /// Assignment, reference count is unchanged.
+ Slice& operator=(Slice other) {
+ std::swap(slice_, other.slice_);
+ return *this;
+ }
+
+ /// Create a slice pointing at some data. Calls malloc to allocate a refcount
+ /// for the object, and arranges that destroy will be called with the
+ /// user data pointer passed in at destruction. Can be the same as buf or
+ /// different (e.g., if data is part of a larger structure that must be
+ /// destroyed when the data is no longer needed)
+ Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data);
+
+ /// Specialization of above for common case where buf == user_data
+ Slice(void* buf, size_t len, void (*destroy)(void*))
+ : Slice(buf, len, destroy, buf) {}
+
+ /// Similar to the above but has a destroy that also takes slice length
+ Slice(void* buf, size_t len, void (*destroy)(void*, size_t));
+
+ /// Byte size.
+ size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
+
+ /// Raw pointer to the beginning (first element) of the slice.
+ const uint8_t* begin() const { return GRPC_SLICE_START_PTR(slice_); }
+
+ /// Raw pointer to the end (one byte \em past the last element) of the slice.
+ const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); }
+
+ /// Raw C slice. Caller needs to call grpc_slice_unref when done.
+ grpc_slice c_slice() const;
+
+ private:
+ friend class ByteBuffer;
+
+ grpc_slice slice_;
+};
+
+inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) {
+ return grpc::string_ref(
+ reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)),
+ GRPC_SLICE_LENGTH(*slice));
+}
+
+inline grpc::string StringFromCopiedSlice(grpc_slice slice) {
+ return grpc::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
+ GRPC_SLICE_LENGTH(slice));
+}
+
+inline grpc_slice SliceReferencingString(const grpc::string& str) {
+ return g_core_codegen_interface->grpc_slice_from_static_buffer(str.data(),
+ str.length());
+}
+
+inline grpc_slice SliceFromCopiedString(const grpc::string& str) {
+ return g_core_codegen_interface->grpc_slice_from_copied_buffer(str.data(),
+ str.length());
+}
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SLICE_H
diff --git a/include/grpcpp/impl/codegen/status.h b/include/grpcpp/impl/codegen/status.h
new file mode 100644
index 0000000..9f409eb
--- /dev/null
+++ b/include/grpcpp/impl/codegen/status.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_STATUS_H
+#define GRPCPP_IMPL_CODEGEN_STATUS_H
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/status_code_enum.h>
+
+namespace grpc {
+
+/// Did it work? If it didn't, why?
+///
+/// See \a grpc::StatusCode for details on the available code and their meaning.
+class Status {
+ public:
+ /// Construct an OK instance.
+ Status() : code_(StatusCode::OK) {}
+
+ /// Construct an instance with associated \a code and \a error_message.
+ /// It is an error to construct an OK status with non-empty \a error_message.
+ Status(StatusCode code, const grpc::string& error_message)
+ : code_(code), error_message_(error_message) {}
+
+ /// Construct an instance with \a code, \a error_message and
+ /// \a error_details. It is an error to construct an OK status with non-empty
+ /// \a error_message and/or \a error_details.
+ Status(StatusCode code, const grpc::string& error_message,
+ const grpc::string& error_details)
+ : code_(code),
+ error_message_(error_message),
+ binary_error_details_(error_details) {}
+
+ // Pre-defined special status objects.
+ /// An OK pre-defined instance.
+ static const Status& OK;
+ /// A CANCELLED pre-defined instance.
+ static const Status& CANCELLED;
+
+ /// Return the instance's error code.
+ StatusCode error_code() const { return code_; }
+ /// Return the instance's error message.
+ grpc::string error_message() const { return error_message_; }
+ /// Return the (binary) error details.
+ // Usually it contains a serialized google.rpc.Status proto.
+ grpc::string error_details() const { return binary_error_details_; }
+
+ /// Is the status OK?
+ bool ok() const { return code_ == StatusCode::OK; }
+
+ // Ignores any errors. This method does nothing except potentially suppress
+ // complaints from any tools that are checking that errors are not dropped on
+ // the floor.
+ void IgnoreError() const {}
+
+ private:
+ StatusCode code_;
+ grpc::string error_message_;
+ grpc::string binary_error_details_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_STATUS_H
diff --git a/include/grpcpp/impl/codegen/status_code_enum.h b/include/grpcpp/impl/codegen/status_code_enum.h
new file mode 100644
index 0000000..09943f1
--- /dev/null
+++ b/include/grpcpp/impl/codegen/status_code_enum.h
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_STATUS_CODE_ENUM_H
+#define GRPCPP_IMPL_CODEGEN_STATUS_CODE_ENUM_H
+
+namespace grpc {
+
+enum StatusCode {
+ /// Not an error; returned on success.
+ OK = 0,
+
+ /// The operation was cancelled (typically by the caller).
+ CANCELLED = 1,
+
+ /// Unknown error. An example of where this error may be returned is if a
+ /// Status value received from another address space belongs to an error-space
+ /// that is not known in this address space. Also errors raised by APIs that
+ /// do not return enough error information may be converted to this error.
+ UNKNOWN = 2,
+
+ /// Client specified an invalid argument. Note that this differs from
+ /// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
+ /// problematic regardless of the state of the system (e.g., a malformed file
+ /// name).
+ INVALID_ARGUMENT = 3,
+
+ /// Deadline expired before operation could complete. For operations that
+ /// change the state of the system, this error may be returned even if the
+ /// operation has completed successfully. For example, a successful response
+ /// from a server could have been delayed long enough for the deadline to
+ /// expire.
+ DEADLINE_EXCEEDED = 4,
+
+ /// Some requested entity (e.g., file or directory) was not found.
+ NOT_FOUND = 5,
+
+ /// Some entity that we attempted to create (e.g., file or directory) already
+ /// exists.
+ ALREADY_EXISTS = 6,
+
+ /// The caller does not have permission to execute the specified operation.
+ /// PERMISSION_DENIED must not be used for rejections caused by exhausting
+ /// some resource (use RESOURCE_EXHAUSTED instead for those errors).
+ /// PERMISSION_DENIED must not be used if the caller can not be identified
+ /// (use UNAUTHENTICATED instead for those errors).
+ PERMISSION_DENIED = 7,
+
+ /// The request does not have valid authentication credentials for the
+ /// operation.
+ UNAUTHENTICATED = 16,
+
+ /// Some resource has been exhausted, perhaps a per-user quota, or perhaps the
+ /// entire file system is out of space.
+ RESOURCE_EXHAUSTED = 8,
+
+ /// Operation was rejected because the system is not in a state required for
+ /// the operation's execution. For example, directory to be deleted may be
+ /// non-empty, an rmdir operation is applied to a non-directory, etc.
+ ///
+ /// A litmus test that may help a service implementor in deciding
+ /// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
+ /// (a) Use UNAVAILABLE if the client can retry just the failing call.
+ /// (b) Use ABORTED if the client should retry at a higher-level
+ /// (e.g., restarting a read-modify-write sequence).
+ /// (c) Use FAILED_PRECONDITION if the client should not retry until
+ /// the system state has been explicitly fixed. E.g., if an "rmdir"
+ /// fails because the directory is non-empty, FAILED_PRECONDITION
+ /// should be returned since the client should not retry unless
+ /// they have first fixed up the directory by deleting files from it.
+ /// (d) Use FAILED_PRECONDITION if the client performs conditional
+ /// REST Get/Update/Delete on a resource and the resource on the
+ /// server does not match the condition. E.g., conflicting
+ /// read-modify-write on the same resource.
+ FAILED_PRECONDITION = 9,
+
+ /// The operation was aborted, typically due to a concurrency issue like
+ /// sequencer check failures, transaction aborts, etc.
+ ///
+ /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
+ /// and UNAVAILABLE.
+ ABORTED = 10,
+
+ /// Operation was attempted past the valid range. E.g., seeking or reading
+ /// past end of file.
+ ///
+ /// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
+ /// if the system state changes. For example, a 32-bit file system will
+ /// generate INVALID_ARGUMENT if asked to read at an offset that is not in the
+ /// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
+ /// an offset past the current file size.
+ ///
+ /// There is a fair bit of overlap between FAILED_PRECONDITION and
+ /// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
+ /// when it applies so that callers who are iterating through a space can
+ /// easily look for an OUT_OF_RANGE error to detect when they are done.
+ OUT_OF_RANGE = 11,
+
+ /// Operation is not implemented or not supported/enabled in this service.
+ UNIMPLEMENTED = 12,
+
+ /// Internal errors. Means some invariants expected by underlying System has
+ /// been broken. If you see one of these errors, Something is very broken.
+ INTERNAL = 13,
+
+ /// The service is currently unavailable. This is a most likely a transient
+ /// condition and may be corrected by retrying with a backoff.
+ ///
+ /// \warning Although data MIGHT not have been transmitted when this
+ /// status occurs, there is NOT A GUARANTEE that the server has not seen
+ /// anything. So in general it is unsafe to retry on this status code
+ /// if the call is non-idempotent.
+ ///
+ /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
+ /// and UNAVAILABLE.
+ UNAVAILABLE = 14,
+
+ /// Unrecoverable data loss or corruption.
+ DATA_LOSS = 15,
+
+ /// Force users to include a default branch:
+ DO_NOT_USE = -1
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_STATUS_CODE_ENUM_H
diff --git a/include/grpcpp/impl/codegen/string_ref.h b/include/grpcpp/impl/codegen/string_ref.h
new file mode 100644
index 0000000..5d55fc4
--- /dev/null
+++ b/include/grpcpp/impl/codegen/string_ref.h
@@ -0,0 +1,146 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_STRING_REF_H
+#define GRPCPP_IMPL_CODEGEN_STRING_REF_H
+
+#include <string.h>
+
+#include <algorithm>
+#include <iosfwd>
+#include <iostream>
+#include <iterator>
+
+#include <grpcpp/impl/codegen/config.h>
+
+namespace grpc {
+
+/// This class is a non owning reference to a string.
+///
+/// It should be a strict subset of the upcoming std::string_ref.
+///
+/// \see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
+///
+/// The constexpr is dropped or replaced with const for legacy compiler
+/// compatibility.
+class string_ref {
+ public:
+ /// types
+ typedef const char* const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ /// constants
+ const static size_t npos;
+
+ /// construct/copy.
+ string_ref() : data_(nullptr), length_(0) {}
+ string_ref(const string_ref& other)
+ : data_(other.data_), length_(other.length_) {}
+ string_ref& operator=(const string_ref& rhs) {
+ data_ = rhs.data_;
+ length_ = rhs.length_;
+ return *this;
+ }
+
+ string_ref(const char* s) : data_(s), length_(strlen(s)) {}
+ string_ref(const char* s, size_t l) : data_(s), length_(l) {}
+ string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {}
+
+ /// iterators
+ const_iterator begin() const { return data_; }
+ const_iterator end() const { return data_ + length_; }
+ const_iterator cbegin() const { return data_; }
+ const_iterator cend() const { return data_ + length_; }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator crend() const {
+ return const_reverse_iterator(begin());
+ }
+
+ /// capacity
+ size_t size() const { return length_; }
+ size_t length() const { return length_; }
+ size_t max_size() const { return length_; }
+ bool empty() const { return length_ == 0; }
+
+ /// element access
+ const char* data() const { return data_; }
+
+ /// string operations
+ int compare(string_ref x) const {
+ size_t min_size = length_ < x.length_ ? length_ : x.length_;
+ int r = memcmp(data_, x.data_, min_size);
+ if (r < 0) return -1;
+ if (r > 0) return 1;
+ if (length_ < x.length_) return -1;
+ if (length_ > x.length_) return 1;
+ return 0;
+ }
+
+ bool starts_with(string_ref x) const {
+ return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0);
+ }
+
+ bool ends_with(string_ref x) const {
+ return length_ >= x.length_ &&
+ (memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0);
+ }
+
+ size_t find(string_ref s) const {
+ auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend());
+ return it == cend() ? npos : std::distance(cbegin(), it);
+ }
+
+ size_t find(char c) const {
+ auto it = std::find(cbegin(), cend(), c);
+ return it == cend() ? npos : std::distance(cbegin(), it);
+ }
+
+ string_ref substr(size_t pos, size_t n = npos) const {
+ if (pos > length_) pos = length_;
+ if (n > (length_ - pos)) n = length_ - pos;
+ return string_ref(data_ + pos, n);
+ }
+
+ private:
+ const char* data_;
+ size_t length_;
+};
+
+/// Comparison operators
+inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
+inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
+inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
+inline bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; }
+inline bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; }
+inline bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; }
+
+inline std::ostream& operator<<(std::ostream& out, const string_ref& string) {
+ return out << grpc::string(string.begin(), string.end());
+}
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_STRING_REF_H
diff --git a/include/grpcpp/impl/codegen/stub_options.h b/include/grpcpp/impl/codegen/stub_options.h
new file mode 100644
index 0000000..a56695a
--- /dev/null
+++ b/include/grpcpp/impl/codegen/stub_options.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_STUB_OPTIONS_H
+#define GRPCPP_IMPL_CODEGEN_STUB_OPTIONS_H
+
+namespace grpc {
+
+/// Useful interface for generated stubs
+class StubOptions {};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_STUB_OPTIONS_H
diff --git a/include/grpcpp/impl/codegen/sync_stream.h b/include/grpcpp/impl/codegen/sync_stream.h
new file mode 100644
index 0000000..7152eaf
--- /dev/null
+++ b/include/grpcpp/impl/codegen/sync_stream.h
@@ -0,0 +1,934 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_SYNC_STREAM_H
+#define GRPCPP_IMPL_CODEGEN_SYNC_STREAM_H
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+namespace internal {
+/// Common interface for all synchronous client side streaming.
+class ClientStreamingInterface {
+ public:
+ virtual ~ClientStreamingInterface() {}
+
+ /// Block waiting until the stream finishes and a final status of the call is
+ /// available.
+ ///
+ /// It is appropriate to call this method when both:
+ /// * the calling code (client-side) has no more message to send
+ /// (this can be declared implicitly by calling this method, or
+ /// explicitly through an earlier call to <i>WritesDone</i> method of the
+ /// class in use, e.g. \a ClientWriterInterface::WritesDone or
+ /// \a ClientReaderWriterInterface::WritesDone).
+ /// * there are no more messages to be received from the server (which can
+ /// be known implicitly, or explicitly from an earlier call to \a
+ /// ReaderInterface::Read that returned "false").
+ ///
+ /// This function will return either:
+ /// - when all incoming messages have been read and the server has
+ /// returned status.
+ /// - when the server has returned a non-OK status.
+ /// - OR when the call failed for some reason and the library generated a
+ /// status.
+ ///
+ /// Return values:
+ /// - \a Status contains the status code, message and details for the call
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible trailing metadata sent from the server.
+ virtual Status Finish() = 0;
+};
+
+/// Common interface for all synchronous server side streaming.
+class ServerStreamingInterface {
+ public:
+ virtual ~ServerStreamingInterface() {}
+
+ /// Block to send initial metadata to client.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a Finish method.
+ ///
+ /// The initial metadata that will be sent to the client will be
+ /// taken from the \a ServerContext associated with the call.
+ virtual void SendInitialMetadata() = 0;
+};
+
+/// An interface that yields a sequence of messages of type \a R.
+template <class R>
+class ReaderInterface {
+ public:
+ virtual ~ReaderInterface() {}
+
+ /// Get an upper bound on the next message size available for reading on this
+ /// stream.
+ virtual bool NextMessageSize(uint32_t* sz) = 0;
+
+ /// Block to read a message and parse to \a msg. Returns \a true on success.
+ /// This is thread-safe with respect to \a Write or \WritesDone methods on
+ /// the same stream. It should not be called concurrently with another \a
+ /// Read on the same stream as the order of delivery will not be defined.
+ ///
+ /// \param[out] msg The read message.
+ ///
+ /// \return \a false when there will be no more incoming messages, either
+ /// because the other side has called \a WritesDone() or the stream has failed
+ /// (or been cancelled).
+ virtual bool Read(R* msg) = 0;
+};
+
+/// An interface that can be fed a sequence of messages of type \a W.
+template <class W>
+class WriterInterface {
+ public:
+ virtual ~WriterInterface() {}
+
+ /// Block to write \a msg to the stream with WriteOptions \a options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \param msg The message to be written to the stream.
+ /// \param options The WriteOptions affecting the write operation.
+ ///
+ /// \return \a true on success, \a false when the stream has been closed.
+ virtual bool Write(const W& msg, WriteOptions options) = 0;
+
+ /// Block to write \a msg to the stream with default write options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \param msg The message to be written to the stream.
+ ///
+ /// \return \a true on success, \a false when the stream has been closed.
+ inline bool Write(const W& msg) { return Write(msg, WriteOptions()); }
+
+ /// Write \a msg and coalesce it with the writing of trailing metadata, using
+ /// WriteOptions \a options.
+ ///
+ /// For client, WriteLast is equivalent of performing Write and WritesDone in
+ /// a single step. \a msg and trailing metadata are coalesced and sent on wire
+ /// by calling this function. For server, WriteLast buffers the \a msg.
+ /// The writing of \a msg is held until the service handler returns,
+ /// where \a msg and trailing metadata are coalesced and sent on wire.
+ /// Note that WriteLast can only buffer \a msg up to the flow control window
+ /// size. If \a msg size is larger than the window size, it will be sent on
+ /// wire without buffering.
+ ///
+ /// \param[in] msg The message to be written to the stream.
+ /// \param[in] options The WriteOptions to be used to write this message.
+ void WriteLast(const W& msg, WriteOptions options) {
+ Write(msg, options.set_last_message());
+ }
+};
+
+} // namespace internal
+
+/// Client-side interface for streaming reads of message of type \a R.
+template <class R>
+class ClientReaderInterface : public internal::ClientStreamingInterface,
+ public internal::ReaderInterface<R> {
+ public:
+ /// Block to wait for initial metadata from server. The received metadata
+ /// can only be accessed after this call returns. Should only be called before
+ /// the first read. Calling this method is optional, and if it is not called
+ /// the metadata will be available in ClientContext after the first read.
+ virtual void WaitForInitialMetadata() = 0;
+};
+
+namespace internal {
+template <class R>
+class ClientReaderFactory {
+ public:
+ template <class W>
+ static ClientReader<R>* Create(ChannelInterface* channel,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context, const W& request) {
+ return new ClientReader<R>(channel, method, context, request);
+ }
+};
+} // namespace internal
+
+/// Synchronous (blocking) client-side API for doing server-streaming RPCs,
+/// where the stream of messages coming from the server has messages
+/// of type \a R.
+template <class R>
+class ClientReader final : public ClientReaderInterface<R> {
+ public:
+ /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+ /// semantics.
+ ///
+ // Side effect:
+ /// Once complete, the initial metadata read from
+ /// the server will be accessable through the \a ClientContext used to
+ /// construct this object.
+ void WaitForInitialMetadata() override {
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ ops;
+ ops.RecvInitialMetadata(context_);
+ call_.PerformOps(&ops);
+ cq_.Pluck(&ops); /// status ignored
+ }
+
+ bool NextMessageSize(uint32_t* sz) override {
+ *sz = call_.max_receive_message_size();
+ return true;
+ }
+
+ /// See the \a ReaderInterface.Read method for semantics.
+ /// Side effect:
+ /// This also receives initial metadata from the server, if not
+ /// already received (if initial metadata is received, it can be then
+ /// accessed through the \a ClientContext associated with this call).
+ bool Read(R* msg) override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpRecvMessage<R>>
+ ops;
+ if (!context_->initial_metadata_received_) {
+ ops.RecvInitialMetadata(context_);
+ }
+ ops.RecvMessage(msg);
+ call_.PerformOps(&ops);
+ return cq_.Pluck(&ops) && ops.got_message;
+ }
+
+ /// See the \a ClientStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// The \a ClientContext associated with this call is updated with
+ /// possible metadata received from the server.
+ Status Finish() override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientRecvStatus> ops;
+ Status status;
+ ops.ClientRecvStatus(context_, &status);
+ call_.PerformOps(&ops);
+ GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
+ return status;
+ }
+
+ private:
+ friend class internal::ClientReaderFactory<R>;
+ ClientContext* context_;
+ CompletionQueue cq_;
+ ::grpc::internal::Call call_;
+
+ /// Block to create a stream and write the initial metadata and \a request
+ /// out. Note that \a context will be used to fill in custom initial
+ /// metadata used to send to the server when starting the call.
+ template <class W>
+ ClientReader(::grpc::ChannelInterface* channel,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context, const W& request)
+ : context_(context),
+ cq_(grpc_completion_queue_attributes{
+ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+ GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq
+ call_(channel->CreateCall(method, context, &cq_)) {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ ops;
+ ops.SendInitialMetadata(context->send_initial_metadata_,
+ context->initial_metadata_flags());
+ // TODO(ctiller): don't assert
+ GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
+ ops.ClientSendClose();
+ call_.PerformOps(&ops);
+ cq_.Pluck(&ops);
+ }
+};
+
+/// Client-side interface for streaming writes of message type \a W.
+template <class W>
+class ClientWriterInterface : public internal::ClientStreamingInterface,
+ public internal::WriterInterface<W> {
+ public:
+ /// Half close writing from the client. (signal that the stream of messages
+ /// coming from the client is complete).
+ /// Blocks until currently-pending writes are completed.
+ /// Thread safe with respect to \a ReaderInterface::Read operations only
+ ///
+ /// \return Whether the writes were successful.
+ virtual bool WritesDone() = 0;
+};
+
+namespace internal {
+template <class W>
+class ClientWriterFactory {
+ public:
+ template <class R>
+ static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context, R* response) {
+ return new ClientWriter<W>(channel, method, context, response);
+ }
+};
+} // namespace internal
+
+/// Synchronous (blocking) client-side API for doing client-streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of
+/// type \a W.
+template <class W>
+class ClientWriter : public ClientWriterInterface<W> {
+ public:
+ /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+ /// semantics.
+ ///
+ // Side effect:
+ /// Once complete, the initial metadata read from the server will be
+ /// accessable through the \a ClientContext used to construct this object.
+ void WaitForInitialMetadata() {
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ ops;
+ ops.RecvInitialMetadata(context_);
+ call_.PerformOps(&ops);
+ cq_.Pluck(&ops); // status ignored
+ }
+
+ /// See the WriterInterface.Write(const W& msg, WriteOptions options) method
+ /// for semantics.
+ ///
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the
+ /// \a ClientContext associated with this call).
+ using ::grpc::internal::WriterInterface<W>::Write;
+ bool Write(const W& msg, WriteOptions options) override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ ops;
+
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ ops.ClientSendClose();
+ }
+ if (context_->initial_metadata_corked_) {
+ ops.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ context_->set_initial_metadata_corked(false);
+ }
+ if (!ops.SendMessage(msg, options).ok()) {
+ return false;
+ }
+
+ call_.PerformOps(&ops);
+ return cq_.Pluck(&ops);
+ }
+
+ bool WritesDone() override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
+ ops.ClientSendClose();
+ call_.PerformOps(&ops);
+ return cq_.Pluck(&ops);
+ }
+
+ /// See the ClientStreamingInterface.Finish method for semantics.
+ /// Side effects:
+ /// - Also receives initial metadata if not already received.
+ /// - Attempts to fill in the \a response parameter passed
+ /// to the constructor of this instance with the response
+ /// message from the server.
+ Status Finish() override {
+ Status status;
+ if (!context_->initial_metadata_received_) {
+ finish_ops_.RecvInitialMetadata(context_);
+ }
+ finish_ops_.ClientRecvStatus(context_, &status);
+ call_.PerformOps(&finish_ops_);
+ GPR_CODEGEN_ASSERT(cq_.Pluck(&finish_ops_));
+ return status;
+ }
+
+ private:
+ friend class internal::ClientWriterFactory<W>;
+
+ /// Block to create a stream (i.e. send request headers and other initial
+ /// metadata to the server). Note that \a context will be used to fill
+ /// in custom initial metadata. \a response will be filled in with the
+ /// single expected response message from the server upon a successful
+ /// call to the \a Finish method of this instance.
+ template <class R>
+ ClientWriter(ChannelInterface* channel,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context, R* response)
+ : context_(context),
+ cq_(grpc_completion_queue_attributes{
+ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+ GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq
+ call_(channel->CreateCall(method, context, &cq_)) {
+ finish_ops_.RecvMessage(response);
+ finish_ops_.AllowNoMessage();
+
+ if (!context_->initial_metadata_corked_) {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+ ops;
+ ops.SendInitialMetadata(context->send_initial_metadata_,
+ context->initial_metadata_flags());
+ call_.PerformOps(&ops);
+ cq_.Pluck(&ops);
+ }
+ }
+
+ ClientContext* context_;
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpGenericRecvMessage,
+ ::grpc::internal::CallOpClientRecvStatus>
+ finish_ops_;
+ CompletionQueue cq_;
+ ::grpc::internal::Call call_;
+};
+
+/// Client-side interface for bi-directional streaming with
+/// client-to-server stream messages of type \a W and
+/// server-to-client stream messages of type \a R.
+template <class W, class R>
+class ClientReaderWriterInterface : public internal::ClientStreamingInterface,
+ public internal::WriterInterface<W>,
+ public internal::ReaderInterface<R> {
+ public:
+ /// Block to wait for initial metadata from server. The received metadata
+ /// can only be accessed after this call returns. Should only be called before
+ /// the first read. Calling this method is optional, and if it is not called
+ /// the metadata will be available in ClientContext after the first read.
+ virtual void WaitForInitialMetadata() = 0;
+
+ /// Half close writing from the client. (signal that the stream of messages
+ /// coming from the clinet is complete).
+ /// Blocks until currently-pending writes are completed.
+ /// Thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \return Whether the writes were successful.
+ virtual bool WritesDone() = 0;
+};
+
+namespace internal {
+template <class W, class R>
+class ClientReaderWriterFactory {
+ public:
+ static ClientReaderWriter<W, R>* Create(
+ ::grpc::ChannelInterface* channel,
+ const ::grpc::internal::RpcMethod& method, ClientContext* context) {
+ return new ClientReaderWriter<W, R>(channel, method, context);
+ }
+};
+} // namespace internal
+
+/// Synchronous (blocking) client-side API for bi-directional streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of
+/// type \a W, and the incoming messages stream coming from the server has
+/// messages of type \a R.
+template <class W, class R>
+class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
+ public:
+ /// Block waiting to read initial metadata from the server.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a Finish method.
+ ///
+ /// Once complete, the initial metadata read from the server will be
+ /// accessable through the \a ClientContext used to construct this object.
+ void WaitForInitialMetadata() override {
+ GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+ ops;
+ ops.RecvInitialMetadata(context_);
+ call_.PerformOps(&ops);
+ cq_.Pluck(&ops); // status ignored
+ }
+
+ bool NextMessageSize(uint32_t* sz) override {
+ *sz = call_.max_receive_message_size();
+ return true;
+ }
+
+ /// See the \a ReaderInterface.Read method for semantics.
+ /// Side effect:
+ /// Also receives initial metadata if not already received (updates the \a
+ /// ClientContext associated with this call in that case).
+ bool Read(R* msg) override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpRecvMessage<R>>
+ ops;
+ if (!context_->initial_metadata_received_) {
+ ops.RecvInitialMetadata(context_);
+ }
+ ops.RecvMessage(msg);
+ call_.PerformOps(&ops);
+ return cq_.Pluck(&ops) && ops.got_message;
+ }
+
+ /// See the \a WriterInterface.Write method for semantics.
+ ///
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the
+ /// \a ClientContext associated with this call to fill in values).
+ using ::grpc::internal::WriterInterface<W>::Write;
+ bool Write(const W& msg, WriteOptions options) override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+ ::grpc::internal::CallOpSendMessage,
+ ::grpc::internal::CallOpClientSendClose>
+ ops;
+
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ ops.ClientSendClose();
+ }
+ if (context_->initial_metadata_corked_) {
+ ops.SendInitialMetadata(context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ context_->set_initial_metadata_corked(false);
+ }
+ if (!ops.SendMessage(msg, options).ok()) {
+ return false;
+ }
+
+ call_.PerformOps(&ops);
+ return cq_.Pluck(&ops);
+ }
+
+ bool WritesDone() override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
+ ops.ClientSendClose();
+ call_.PerformOps(&ops);
+ return cq_.Pluck(&ops);
+ }
+
+ /// See the ClientStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible trailing metadata sent from the server.
+ Status Finish() override {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+ ::grpc::internal::CallOpClientRecvStatus>
+ ops;
+ if (!context_->initial_metadata_received_) {
+ ops.RecvInitialMetadata(context_);
+ }
+ Status status;
+ ops.ClientRecvStatus(context_, &status);
+ call_.PerformOps(&ops);
+ GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
+ return status;
+ }
+
+ private:
+ friend class internal::ClientReaderWriterFactory<W, R>;
+
+ ClientContext* context_;
+ CompletionQueue cq_;
+ ::grpc::internal::Call call_;
+
+ /// Block to create a stream and write the initial metadata and \a request
+ /// out. Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
+ ClientReaderWriter(::grpc::ChannelInterface* channel,
+ const ::grpc::internal::RpcMethod& method,
+ ClientContext* context)
+ : context_(context),
+ cq_(grpc_completion_queue_attributes{
+ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK,
+ GRPC_CQ_DEFAULT_POLLING}), // Pluckable cq
+ call_(channel->CreateCall(method, context, &cq_)) {
+ if (!context_->initial_metadata_corked_) {
+ ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+ ops;
+ ops.SendInitialMetadata(context->send_initial_metadata_,
+ context->initial_metadata_flags());
+ call_.PerformOps(&ops);
+ cq_.Pluck(&ops);
+ }
+ }
+};
+
+/// Server-side interface for streaming reads of message of type \a R.
+template <class R>
+class ServerReaderInterface : public internal::ServerStreamingInterface,
+ public internal::ReaderInterface<R> {};
+
+/// Synchronous (blocking) server-side API for doing client-streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R.
+template <class R>
+class ServerReader final : public ServerReaderInterface<R> {
+ public:
+ /// See the \a ServerStreamingInterface.SendInitialMetadata method
+ /// for semantics. Note that initial metadata will be affected by the
+ /// \a ServerContext associated with this call.
+ void SendInitialMetadata() override {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
+ ops.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ops.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_->PerformOps(&ops);
+ call_->cq()->Pluck(&ops);
+ }
+
+ bool NextMessageSize(uint32_t* sz) override {
+ *sz = call_->max_receive_message_size();
+ return true;
+ }
+
+ bool Read(R* msg) override {
+ internal::CallOpSet<internal::CallOpRecvMessage<R>> ops;
+ ops.RecvMessage(msg);
+ call_->PerformOps(&ops);
+ return call_->cq()->Pluck(&ops) && ops.got_message;
+ }
+
+ private:
+ internal::Call* const call_;
+ ServerContext* const ctx_;
+
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class internal::ClientStreamingHandler;
+
+ ServerReader(internal::Call* call, ServerContext* ctx)
+ : call_(call), ctx_(ctx) {}
+};
+
+/// Server-side interface for streaming writes of message of type \a W.
+template <class W>
+class ServerWriterInterface : public internal::ServerStreamingInterface,
+ public internal::WriterInterface<W> {};
+
+/// Synchronous (blocking) server-side API for doing for doing a
+/// server-streaming RPCs, where the outgoing message stream coming from the
+/// server has messages of type \a W.
+template <class W>
+class ServerWriter final : public ServerWriterInterface<W> {
+ public:
+ /// See the \a ServerStreamingInterface.SendInitialMetadata method
+ /// for semantics.
+ /// Note that initial metadata will be affected by the
+ /// \a ServerContext associated with this call.
+ void SendInitialMetadata() override {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
+ ops.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ops.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_->PerformOps(&ops);
+ call_->cq()->Pluck(&ops);
+ }
+
+ /// See the \a WriterInterface.Write method for semantics.
+ ///
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the
+ /// \a ClientContext associated with this call to fill in values).
+ using internal::WriterInterface<W>::Write;
+ bool Write(const W& msg, WriteOptions options) override {
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ }
+
+ if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
+ return false;
+ }
+ if (!ctx_->sent_initial_metadata_) {
+ ctx_->pending_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ctx_->pending_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ call_->PerformOps(&ctx_->pending_ops_);
+ // if this is the last message we defer the pluck until AFTER we start
+ // the trailing md op. This prevents hangs. See
+ // https://github.com/grpc/grpc/issues/11546
+ if (options.is_last_message()) {
+ ctx_->has_pending_ops_ = true;
+ return true;
+ }
+ ctx_->has_pending_ops_ = false;
+ return call_->cq()->Pluck(&ctx_->pending_ops_);
+ }
+
+ private:
+ internal::Call* const call_;
+ ServerContext* const ctx_;
+
+ template <class ServiceType, class RequestType, class ResponseType>
+ friend class internal::ServerStreamingHandler;
+
+ ServerWriter(internal::Call* call, ServerContext* ctx)
+ : call_(call), ctx_(ctx) {}
+};
+
+/// Server-side interface for bi-directional streaming.
+template <class W, class R>
+class ServerReaderWriterInterface : public internal::ServerStreamingInterface,
+ public internal::WriterInterface<W>,
+ public internal::ReaderInterface<R> {};
+
+/// Actual implementation of bi-directional streaming
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody final {
+ public:
+ ServerReaderWriterBody(Call* call, ServerContext* ctx)
+ : call_(call), ctx_(ctx) {}
+
+ void SendInitialMetadata() {
+ GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+ CallOpSet<CallOpSendInitialMetadata> ops;
+ ops.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ops.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ call_->PerformOps(&ops);
+ call_->cq()->Pluck(&ops);
+ }
+
+ bool NextMessageSize(uint32_t* sz) {
+ *sz = call_->max_receive_message_size();
+ return true;
+ }
+
+ bool Read(R* msg) {
+ CallOpSet<CallOpRecvMessage<R>> ops;
+ ops.RecvMessage(msg);
+ call_->PerformOps(&ops);
+ return call_->cq()->Pluck(&ops) && ops.got_message;
+ }
+
+ bool Write(const W& msg, WriteOptions options) {
+ if (options.is_last_message()) {
+ options.set_buffer_hint();
+ }
+ if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
+ return false;
+ }
+ if (!ctx_->sent_initial_metadata_) {
+ ctx_->pending_ops_.SendInitialMetadata(ctx_->initial_metadata_,
+ ctx_->initial_metadata_flags());
+ if (ctx_->compression_level_set()) {
+ ctx_->pending_ops_.set_compression_level(ctx_->compression_level());
+ }
+ ctx_->sent_initial_metadata_ = true;
+ }
+ call_->PerformOps(&ctx_->pending_ops_);
+ // if this is the last message we defer the pluck until AFTER we start
+ // the trailing md op. This prevents hangs. See
+ // https://github.com/grpc/grpc/issues/11546
+ if (options.is_last_message()) {
+ ctx_->has_pending_ops_ = true;
+ return true;
+ }
+ ctx_->has_pending_ops_ = false;
+ return call_->cq()->Pluck(&ctx_->pending_ops_);
+ }
+
+ private:
+ Call* const call_;
+ ServerContext* const ctx_;
+};
+
+} // namespace internal
+
+/// Synchronous (blocking) server-side API for a bidirectional
+/// streaming call, where the incoming message stream coming from the client has
+/// messages of type \a R, and the outgoing message streaming coming from
+/// the server has messages of type \a W.
+template <class W, class R>
+class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
+ public:
+ /// See the \a ServerStreamingInterface.SendInitialMetadata method
+ /// for semantics. Note that initial metadata will be affected by the
+ /// \a ServerContext associated with this call.
+ void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+
+ bool NextMessageSize(uint32_t* sz) override {
+ return body_.NextMessageSize(sz);
+ }
+
+ bool Read(R* msg) override { return body_.Read(msg); }
+
+ /// See the \a WriterInterface.Write(const W& msg, WriteOptions options)
+ /// method for semantics.
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the \a
+ /// ServerContext associated with this call).
+ using internal::WriterInterface<W>::Write;
+ bool Write(const W& msg, WriteOptions options) override {
+ return body_.Write(msg, options);
+ }
+
+ private:
+ internal::ServerReaderWriterBody<W, R> body_;
+
+ friend class internal::TemplatedBidiStreamingHandler<ServerReaderWriter<W, R>,
+ false>;
+ ServerReaderWriter(internal::Call* call, ServerContext* ctx)
+ : body_(call, ctx) {}
+};
+
+/// A class to represent a flow-controlled unary call. This is something
+/// of a hybrid between conventional unary and streaming. This is invoked
+/// through a unary call on the client side, but the server responds to it
+/// as though it were a single-ping-pong streaming call. The server can use
+/// the \a NextMessageSize method to determine an upper-bound on the size of
+/// the message. A key difference relative to streaming: ServerUnaryStreamer
+/// must have exactly 1 Read and exactly 1 Write, in that order, to function
+/// correctly. Otherwise, the RPC is in error.
+template <class RequestType, class ResponseType>
+class ServerUnaryStreamer final
+ : public ServerReaderWriterInterface<ResponseType, RequestType> {
+ public:
+ /// Block to send initial metadata to client.
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call will be used for
+ /// sending initial metadata.
+ void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+
+ /// Get an upper bound on the request message size from the client.
+ bool NextMessageSize(uint32_t* sz) override {
+ return body_.NextMessageSize(sz);
+ }
+
+ /// Read a message of type \a R into \a msg. Completion will be notified by \a
+ /// tag on the associated completion queue.
+ /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+ /// should not be called concurrently with other streaming APIs
+ /// on the same stream. It is not meaningful to call it concurrently
+ /// with another \a ReaderInterface::Read on the same stream since reads on
+ /// the same stream are delivered in order.
+ ///
+ /// \param[out] msg Where to eventually store the read message.
+ /// \param[in] tag The tag identifying the operation.
+ bool Read(RequestType* request) override {
+ if (read_done_) {
+ return false;
+ }
+ read_done_ = true;
+ return body_.Read(request);
+ }
+
+ /// Block to write \a msg to the stream with WriteOptions \a options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \param msg The message to be written to the stream.
+ /// \param options The WriteOptions affecting the write operation.
+ ///
+ /// \return \a true on success, \a false when the stream has been closed.
+ using internal::WriterInterface<ResponseType>::Write;
+ bool Write(const ResponseType& response, WriteOptions options) override {
+ if (write_done_ || !read_done_) {
+ return false;
+ }
+ write_done_ = true;
+ return body_.Write(response, options);
+ }
+
+ private:
+ internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
+ bool read_done_;
+ bool write_done_;
+
+ friend class internal::TemplatedBidiStreamingHandler<
+ ServerUnaryStreamer<RequestType, ResponseType>, true>;
+ ServerUnaryStreamer(internal::Call* call, ServerContext* ctx)
+ : body_(call, ctx), read_done_(false), write_done_(false) {}
+};
+
+/// A class to represent a flow-controlled server-side streaming call.
+/// This is something of a hybrid between server-side and bidi streaming.
+/// This is invoked through a server-side streaming call on the client side,
+/// but the server responds to it as though it were a bidi streaming call that
+/// must first have exactly 1 Read and then any number of Writes.
+template <class RequestType, class ResponseType>
+class ServerSplitStreamer final
+ : public ServerReaderWriterInterface<ResponseType, RequestType> {
+ public:
+ /// Block to send initial metadata to client.
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call will be used for
+ /// sending initial metadata.
+ void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+
+ /// Get an upper bound on the request message size from the client.
+ bool NextMessageSize(uint32_t* sz) override {
+ return body_.NextMessageSize(sz);
+ }
+
+ /// Read a message of type \a R into \a msg. Completion will be notified by \a
+ /// tag on the associated completion queue.
+ /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+ /// should not be called concurrently with other streaming APIs
+ /// on the same stream. It is not meaningful to call it concurrently
+ /// with another \a ReaderInterface::Read on the same stream since reads on
+ /// the same stream are delivered in order.
+ ///
+ /// \param[out] msg Where to eventually store the read message.
+ /// \param[in] tag The tag identifying the operation.
+ bool Read(RequestType* request) override {
+ if (read_done_) {
+ return false;
+ }
+ read_done_ = true;
+ return body_.Read(request);
+ }
+
+ /// Block to write \a msg to the stream with WriteOptions \a options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \param msg The message to be written to the stream.
+ /// \param options The WriteOptions affecting the write operation.
+ ///
+ /// \return \a true on success, \a false when the stream has been closed.
+ using internal::WriterInterface<ResponseType>::Write;
+ bool Write(const ResponseType& response, WriteOptions options) override {
+ return read_done_ && body_.Write(response, options);
+ }
+
+ private:
+ internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
+ bool read_done_;
+
+ friend class internal::TemplatedBidiStreamingHandler<
+ ServerSplitStreamer<RequestType, ResponseType>, false>;
+ ServerSplitStreamer(internal::Call* call, ServerContext* ctx)
+ : body_(call, ctx), read_done_(false) {}
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_SYNC_STREAM_H
diff --git a/include/grpcpp/impl/codegen/time.h b/include/grpcpp/impl/codegen/time.h
new file mode 100644
index 0000000..c32f254
--- /dev/null
+++ b/include/grpcpp/impl/codegen/time.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_CODEGEN_TIME_H
+#define GRPCPP_IMPL_CODEGEN_TIME_H
+
+#include <chrono>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/config.h>
+
+namespace grpc {
+
+/** If you are trying to use CompletionQueue::AsyncNext with a time class that
+ isn't either gpr_timespec or std::chrono::system_clock::time_point, you
+ will most likely be looking at this comment as your compiler will have
+ fired an error below. In order to fix this issue, you have two potential
+ solutions:
+
+ 1. Use gpr_timespec or std::chrono::system_clock::time_point instead
+ 2. Specialize the TimePoint class with whichever time class that you
+ want to use here. See below for two examples of how to do this.
+ */
+template <typename T>
+class TimePoint {
+ public:
+ TimePoint(const T& time) { you_need_a_specialization_of_TimePoint(); }
+ gpr_timespec raw_time() {
+ gpr_timespec t;
+ return t;
+ }
+
+ private:
+ void you_need_a_specialization_of_TimePoint();
+};
+
+template <>
+class TimePoint<gpr_timespec> {
+ public:
+ TimePoint(const gpr_timespec& time) : time_(time) {}
+ gpr_timespec raw_time() { return time_; }
+
+ private:
+ gpr_timespec time_;
+};
+
+} // namespace grpc
+
+namespace grpc {
+
+// from and to should be absolute time.
+void Timepoint2Timespec(const std::chrono::system_clock::time_point& from,
+ gpr_timespec* to);
+void TimepointHR2Timespec(
+ const std::chrono::high_resolution_clock::time_point& from,
+ gpr_timespec* to);
+
+std::chrono::system_clock::time_point Timespec2Timepoint(gpr_timespec t);
+
+template <>
+class TimePoint<std::chrono::system_clock::time_point> {
+ public:
+ TimePoint(const std::chrono::system_clock::time_point& time) {
+ Timepoint2Timespec(time, &time_);
+ }
+ gpr_timespec raw_time() const { return time_; }
+
+ private:
+ gpr_timespec time_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_CODEGEN_TIME_H
diff --git a/include/grpcpp/impl/grpc_library.h b/include/grpcpp/impl/grpc_library.h
new file mode 100644
index 0000000..d1f3ff1
--- /dev/null
+++ b/include/grpcpp/impl/grpc_library.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_GRPC_LIBRARY_H
+#define GRPCPP_IMPL_GRPC_LIBRARY_H
+
+#include <iostream>
+
+#include <grpc/grpc.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+
+namespace grpc {
+
+namespace internal {
+class GrpcLibrary final : public GrpcLibraryInterface {
+ public:
+ void init() override { grpc_init(); }
+ void shutdown() override { grpc_shutdown(); }
+};
+
+static GrpcLibrary g_gli;
+static CoreCodegen g_core_codegen;
+
+/// Instantiating this class ensures the proper initialization of gRPC.
+class GrpcLibraryInitializer final {
+ public:
+ GrpcLibraryInitializer() {
+ if (grpc::g_glip == nullptr) {
+ grpc::g_glip = &g_gli;
+ }
+ if (grpc::g_core_codegen_interface == nullptr) {
+ grpc::g_core_codegen_interface = &g_core_codegen;
+ }
+ }
+
+ /// A no-op method to force the linker to reference this class, which will
+ /// take care of initializing and shutting down the gRPC runtime.
+ int summon() { return 0; }
+};
+
+} // namespace internal
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_GRPC_LIBRARY_H
diff --git a/include/grpcpp/impl/method_handler_impl.h b/include/grpcpp/impl/method_handler_impl.h
new file mode 100644
index 0000000..7f3be64
--- /dev/null
+++ b/include/grpcpp/impl/method_handler_impl.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_METHOD_HANDLER_IMPL_H
+#define GRPCPP_IMPL_METHOD_HANDLER_IMPL_H
+
+#include <grpcpp/impl/codegen/method_handler_impl.h>
+
+#endif // GRPCPP_IMPL_METHOD_HANDLER_IMPL_H
diff --git a/include/grpcpp/impl/rpc_method.h b/include/grpcpp/impl/rpc_method.h
new file mode 100644
index 0000000..5da7041
--- /dev/null
+++ b/include/grpcpp/impl/rpc_method.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_RPC_METHOD_H
+#define GRPCPP_IMPL_RPC_METHOD_H
+
+#include <grpcpp/impl/codegen/rpc_method.h>
+
+#endif // GRPCPP_IMPL_RPC_METHOD_H
diff --git a/include/grpcpp/impl/rpc_service_method.h b/include/grpcpp/impl/rpc_service_method.h
new file mode 100644
index 0000000..ef70a3a
--- /dev/null
+++ b/include/grpcpp/impl/rpc_service_method.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_RPC_SERVICE_METHOD_H
+#define GRPCPP_IMPL_RPC_SERVICE_METHOD_H
+
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+
+#endif // GRPCPP_IMPL_RPC_SERVICE_METHOD_H
diff --git a/include/grpcpp/impl/serialization_traits.h b/include/grpcpp/impl/serialization_traits.h
new file mode 100644
index 0000000..95194fb
--- /dev/null
+++ b/include/grpcpp/impl/serialization_traits.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SERIALIZATION_TRAITS_H
+#define GRPCPP_IMPL_SERIALIZATION_TRAITS_H
+
+#include <grpcpp/impl/codegen/serialization_traits.h>
+
+#endif // GRPCPP_IMPL_SERIALIZATION_TRAITS_H
diff --git a/include/grpcpp/impl/server_builder_option.h b/include/grpcpp/impl/server_builder_option.h
new file mode 100644
index 0000000..c7b7801
--- /dev/null
+++ b/include/grpcpp/impl/server_builder_option.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SERVER_BUILDER_OPTION_H
+#define GRPCPP_IMPL_SERVER_BUILDER_OPTION_H
+
+#include <map>
+#include <memory>
+
+#include <grpcpp/impl/server_builder_plugin.h>
+#include <grpcpp/support/channel_arguments.h>
+
+namespace grpc {
+
+/// Interface to pass an option to a \a ServerBuilder.
+class ServerBuilderOption {
+ public:
+ virtual ~ServerBuilderOption() {}
+ /// Alter the \a ChannelArguments used to create the gRPC server.
+ virtual void UpdateArguments(ChannelArguments* args) = 0;
+ /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder.
+ virtual void UpdatePlugins(
+ std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) = 0;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_SERVER_BUILDER_OPTION_H
diff --git a/include/grpcpp/impl/server_builder_plugin.h b/include/grpcpp/impl/server_builder_plugin.h
new file mode 100644
index 0000000..d73511e
--- /dev/null
+++ b/include/grpcpp/impl/server_builder_plugin.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SERVER_BUILDER_PLUGIN_H
+#define GRPCPP_IMPL_SERVER_BUILDER_PLUGIN_H
+
+#include <memory>
+
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+
+class ServerBuilder;
+class ServerInitializer;
+class ChannelArguments;
+
+/// This interface is meant for internal usage only. Implementations of this
+/// interface should add themselves to a \a ServerBuilder instance through the
+/// \a InternalAddPluginFactory method.
+class ServerBuilderPlugin {
+ public:
+ virtual ~ServerBuilderPlugin() {}
+ virtual grpc::string name() = 0;
+
+ /// UpdateServerBuilder will be called at the beginning of
+ /// \a ServerBuilder::BuildAndStart().
+ virtual void UpdateServerBuilder(ServerBuilder* builder) {}
+
+ /// InitServer will be called in ServerBuilder::BuildAndStart(), after the
+ /// Server instance is created.
+ virtual void InitServer(ServerInitializer* si) = 0;
+
+ /// Finish will be called at the end of ServerBuilder::BuildAndStart().
+ virtual void Finish(ServerInitializer* si) = 0;
+
+ /// ChangeArguments is an interface that can be used in
+ /// ServerBuilderOption::UpdatePlugins
+ virtual void ChangeArguments(const grpc::string& name, void* value) = 0;
+
+ /// UpdateChannelArguments will be called in ServerBuilder::BuildAndStart(),
+ /// before the Server instance is created.
+ virtual void UpdateChannelArguments(ChannelArguments* args) {}
+
+ virtual bool has_sync_methods() const { return false; }
+ virtual bool has_async_methods() const { return false; }
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_SERVER_BUILDER_PLUGIN_H
diff --git a/include/grpcpp/impl/server_initializer.h b/include/grpcpp/impl/server_initializer.h
new file mode 100644
index 0000000..f949fab
--- /dev/null
+++ b/include/grpcpp/impl/server_initializer.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SERVER_INITIALIZER_H
+#define GRPCPP_IMPL_SERVER_INITIALIZER_H
+
+#include <memory>
+#include <vector>
+
+#include <grpcpp/server.h>
+
+namespace grpc {
+
+class Server;
+class Service;
+
+class ServerInitializer {
+ public:
+ ServerInitializer(Server* server) : server_(server) {}
+
+ bool RegisterService(std::shared_ptr<Service> service) {
+ if (!server_->RegisterService(nullptr, service.get())) {
+ return false;
+ }
+ default_services_.push_back(service);
+ return true;
+ }
+
+ const std::vector<grpc::string>* GetServiceList() {
+ return &server_->services_;
+ }
+
+ private:
+ Server* server_;
+ std::vector<std::shared_ptr<Service> > default_services_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_IMPL_SERVER_INITIALIZER_H
diff --git a/include/grpcpp/impl/service_type.h b/include/grpcpp/impl/service_type.h
new file mode 100644
index 0000000..250bc8c
--- /dev/null
+++ b/include/grpcpp/impl/service_type.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SERVICE_TYPE_H
+#define GRPCPP_IMPL_SERVICE_TYPE_H
+
+#include <grpcpp/impl/codegen/service_type.h>
+
+#endif // GRPCPP_IMPL_SERVICE_TYPE_H
diff --git a/include/grpcpp/impl/sync_cxx11.h b/include/grpcpp/impl/sync_cxx11.h
new file mode 100644
index 0000000..76dcfe3
--- /dev/null
+++ b/include/grpcpp/impl/sync_cxx11.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SYNC_CXX11_H
+#define GRPCPP_IMPL_SYNC_CXX11_H
+
+#include <grpcpp/impl/codegen/sync_cxx11.h>
+
+#endif // GRPCPP_IMPL_SYNC_CXX11_H
diff --git a/include/grpcpp/impl/sync_no_cxx11.h b/include/grpcpp/impl/sync_no_cxx11.h
new file mode 100644
index 0000000..cc2d4f1
--- /dev/null
+++ b/include/grpcpp/impl/sync_no_cxx11.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_IMPL_SYNC_NO_CXX11_H
+#define GRPCPP_IMPL_SYNC_NO_CXX11_H
+
+#include <grpcpp/impl/codegen/sync_no_cxx11.h>
+
+#endif // GRPCPP_IMPL_SYNC_NO_CXX11_H
diff --git a/include/grpcpp/resource_quota.h b/include/grpcpp/resource_quota.h
new file mode 100644
index 0000000..554437a
--- /dev/null
+++ b/include/grpcpp/resource_quota.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_RESOURCE_QUOTA_H
+#define GRPCPP_RESOURCE_QUOTA_H
+
+struct grpc_resource_quota;
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+
+namespace grpc {
+
+/// ResourceQuota represents a bound on memory usage by the gRPC library.
+/// A ResourceQuota can be attached to a server (via \a ServerBuilder),
+/// or a client channel (via \a ChannelArguments).
+/// gRPC will attempt to keep memory used by all attached entities
+/// below the ResourceQuota bound.
+class ResourceQuota final : private GrpcLibraryCodegen {
+ public:
+ /// \param name - a unique name for this ResourceQuota.
+ explicit ResourceQuota(const grpc::string& name);
+ ResourceQuota();
+ ~ResourceQuota();
+
+ /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller
+ /// than the current size of the pool, memory usage will be monotonically
+ /// decreased until it falls under \a new_size.
+ /// No time bound is given for this to occur however.
+ ResourceQuota& Resize(size_t new_size);
+
+ grpc_resource_quota* c_resource_quota() const { return impl_; }
+
+ private:
+ ResourceQuota(const ResourceQuota& rhs);
+ ResourceQuota& operator=(const ResourceQuota& rhs);
+
+ grpc_resource_quota* const impl_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_RESOURCE_QUOTA_H
diff --git a/include/grpcpp/security/auth_context.h b/include/grpcpp/security/auth_context.h
new file mode 100644
index 0000000..7a6f2cb
--- /dev/null
+++ b/include/grpcpp/security/auth_context.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SECURITY_AUTH_CONTEXT_H
+#define GRPCPP_SECURITY_AUTH_CONTEXT_H
+
+#include <grpcpp/impl/codegen/security/auth_context.h>
+
+#endif // GRPCPP_SECURITY_AUTH_CONTEXT_H
diff --git a/include/grpcpp/security/auth_metadata_processor.h b/include/grpcpp/security/auth_metadata_processor.h
new file mode 100644
index 0000000..30e24c9
--- /dev/null
+++ b/include/grpcpp/security/auth_metadata_processor.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H
+#define GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H
+
+#include <map>
+
+#include <grpcpp/security/auth_context.h>
+#include <grpcpp/support/status.h>
+#include <grpcpp/support/string_ref.h>
+
+namespace grpc {
+
+/// Interface allowing custom server-side authorization based on credentials
+/// encoded in metadata. Objects of this type can be passed to
+/// \a ServerCredentials::SetAuthMetadataProcessor().
+class AuthMetadataProcessor {
+ public:
+ typedef std::multimap<grpc::string_ref, grpc::string_ref> InputMetadata;
+ typedef std::multimap<grpc::string, grpc::string> OutputMetadata;
+
+ virtual ~AuthMetadataProcessor() {}
+
+ /// If this method returns true, the \a Process function will be scheduled in
+ /// a different thread from the one processing the call.
+ virtual bool IsBlocking() const { return true; }
+
+ /// context is read/write: it contains the properties of the channel peer and
+ /// it is the job of the Process method to augment it with properties derived
+ /// from the passed-in auth_metadata.
+ /// consumed_auth_metadata needs to be filled with metadata that has been
+ /// consumed by the processor and will be removed from the call.
+ /// response_metadata is the metadata that will be sent as part of the
+ /// response.
+ /// If the return value is not Status::OK, the rpc call will be aborted with
+ /// the error code and error message sent back to the client.
+ virtual Status Process(const InputMetadata& auth_metadata,
+ AuthContext* context,
+ OutputMetadata* consumed_auth_metadata,
+ OutputMetadata* response_metadata) = 0;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H
diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h
new file mode 100644
index 0000000..837a0e4
--- /dev/null
+++ b/include/grpcpp/security/credentials.h
@@ -0,0 +1,224 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SECURITY_CREDENTIALS_H
+#define GRPCPP_SECURITY_CREDENTIALS_H
+
+#include <map>
+#include <memory>
+
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/security/auth_context.h>
+#include <grpcpp/support/status.h>
+#include <grpcpp/support/string_ref.h>
+
+struct grpc_call;
+
+namespace grpc {
+class ChannelArguments;
+class Channel;
+class SecureChannelCredentials;
+class CallCredentials;
+class SecureCallCredentials;
+
+/// A channel credentials object encapsulates all the state needed by a client
+/// to authenticate with a server for a given channel.
+/// It can make various assertions, e.g., about the client’s identity, role
+/// for all the calls on that channel.
+///
+/// \see https://grpc.io/docs/guides/auth.html
+class ChannelCredentials : private GrpcLibraryCodegen {
+ public:
+ ChannelCredentials();
+ ~ChannelCredentials();
+
+ protected:
+ friend std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+ const std::shared_ptr<ChannelCredentials>& channel_creds,
+ const std::shared_ptr<CallCredentials>& call_creds);
+
+ virtual SecureChannelCredentials* AsSecureCredentials() = 0;
+
+ private:
+ friend std::shared_ptr<Channel> CreateCustomChannel(
+ const grpc::string& target,
+ const std::shared_ptr<ChannelCredentials>& creds,
+ const ChannelArguments& args);
+
+ virtual std::shared_ptr<Channel> CreateChannel(
+ const grpc::string& target, const ChannelArguments& args) = 0;
+};
+
+/// A call credentials object encapsulates the state needed by a client to
+/// authenticate with a server for a given call on a channel.
+///
+/// \see https://grpc.io/docs/guides/auth.html
+class CallCredentials : private GrpcLibraryCodegen {
+ public:
+ CallCredentials();
+ ~CallCredentials();
+
+ /// Apply this instance's credentials to \a call.
+ virtual bool ApplyToCall(grpc_call* call) = 0;
+
+ protected:
+ friend std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+ const std::shared_ptr<ChannelCredentials>& channel_creds,
+ const std::shared_ptr<CallCredentials>& call_creds);
+
+ friend std::shared_ptr<CallCredentials> CompositeCallCredentials(
+ const std::shared_ptr<CallCredentials>& creds1,
+ const std::shared_ptr<CallCredentials>& creds2);
+
+ virtual SecureCallCredentials* AsSecureCredentials() = 0;
+};
+
+/// Options used to build SslCredentials.
+struct SslCredentialsOptions {
+ /// The buffer containing the PEM encoding of the server root certificates. If
+ /// this parameter is empty, the default roots will be used. The default
+ /// roots can be overridden using the \a GRPC_DEFAULT_SSL_ROOTS_FILE_PATH
+ /// environment variable pointing to a file on the file system containing the
+ /// roots.
+ grpc::string pem_root_certs;
+
+ /// The buffer containing the PEM encoding of the client's private key. This
+ /// parameter can be empty if the client does not have a private key.
+ grpc::string pem_private_key;
+
+ /// The buffer containing the PEM encoding of the client's certificate chain.
+ /// This parameter can be empty if the client does not have a certificate
+ /// chain.
+ grpc::string pem_cert_chain;
+};
+
+// Factories for building different types of Credentials The functions may
+// return empty shared_ptr when credentials cannot be created. If a
+// Credentials pointer is returned, it can still be invalid when used to create
+// a channel. A lame channel will be created then and all rpcs will fail on it.
+
+/// Builds credentials with reasonable defaults.
+///
+/// \warning Only use these credentials when connecting to a Google endpoint.
+/// Using these credentials to connect to any other service may result in this
+/// service being able to impersonate your client for requests to Google
+/// services.
+std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials();
+
+/// Builds SSL Credentials given SSL specific options
+std::shared_ptr<ChannelCredentials> SslCredentials(
+ const SslCredentialsOptions& options);
+
+/// Builds credentials for use when running in GCE
+///
+/// \warning Only use these credentials when connecting to a Google endpoint.
+/// Using these credentials to connect to any other service may result in this
+/// service being able to impersonate your client for requests to Google
+/// services.
+std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials();
+
+/// Constant for maximum auth token lifetime.
+constexpr long kMaxAuthTokenLifetimeSecs = 3600;
+
+/// Builds Service Account JWT Access credentials.
+/// json_key is the JSON key string containing the client's private key.
+/// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
+/// (JWT) created with this credentials. It should not exceed
+/// \a kMaxAuthTokenLifetimeSecs or will be cropped to this value.
+std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
+ const grpc::string& json_key,
+ long token_lifetime_seconds = kMaxAuthTokenLifetimeSecs);
+
+/// Builds refresh token credentials.
+/// json_refresh_token is the JSON string containing the refresh token along
+/// with a client_id and client_secret.
+///
+/// \warning Only use these credentials when connecting to a Google endpoint.
+/// Using these credentials to connect to any other service may result in this
+/// service being able to impersonate your client for requests to Google
+/// services.
+std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
+ const grpc::string& json_refresh_token);
+
+/// Builds access token credentials.
+/// access_token is an oauth2 access token that was fetched using an out of band
+/// mechanism.
+///
+/// \warning Only use these credentials when connecting to a Google endpoint.
+/// Using these credentials to connect to any other service may result in this
+/// service being able to impersonate your client for requests to Google
+/// services.
+std::shared_ptr<CallCredentials> AccessTokenCredentials(
+ const grpc::string& access_token);
+
+/// Builds IAM credentials.
+///
+/// \warning Only use these credentials when connecting to a Google endpoint.
+/// Using these credentials to connect to any other service may result in this
+/// service being able to impersonate your client for requests to Google
+/// services.
+std::shared_ptr<CallCredentials> GoogleIAMCredentials(
+ const grpc::string& authorization_token,
+ const grpc::string& authority_selector);
+
+/// Combines a channel credentials and a call credentials into a composite
+/// channel credentials.
+std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
+ const std::shared_ptr<ChannelCredentials>& channel_creds,
+ const std::shared_ptr<CallCredentials>& call_creds);
+
+/// Combines two call credentials objects into a composite call credentials.
+std::shared_ptr<CallCredentials> CompositeCallCredentials(
+ const std::shared_ptr<CallCredentials>& creds1,
+ const std::shared_ptr<CallCredentials>& creds2);
+
+/// Credentials for an unencrypted, unauthenticated channel
+std::shared_ptr<ChannelCredentials> InsecureChannelCredentials();
+
+/// Credentials for a channel using Cronet.
+std::shared_ptr<ChannelCredentials> CronetChannelCredentials(void* engine);
+
+/// User defined metadata credentials.
+class MetadataCredentialsPlugin {
+ public:
+ virtual ~MetadataCredentialsPlugin() {}
+
+ /// If this method returns true, the Process function will be scheduled in
+ /// a different thread from the one processing the call.
+ virtual bool IsBlocking() const { return true; }
+
+ /// Type of credentials this plugin is implementing.
+ virtual const char* GetType() const { return ""; }
+
+ /// Gets the auth metatada produced by this plugin.
+ /// The fully qualified method name is:
+ /// service_url + "/" + method_name.
+ /// The channel_auth_context contains (among other things), the identity of
+ /// the server.
+ virtual Status GetMetadata(
+ grpc::string_ref service_url, grpc::string_ref method_name,
+ const AuthContext& channel_auth_context,
+ std::multimap<grpc::string, grpc::string>* metadata) = 0;
+};
+
+std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
+ std::unique_ptr<MetadataCredentialsPlugin> plugin);
+
+} // namespace grpc
+
+#endif // GRPCPP_SECURITY_CREDENTIALS_H
diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h
new file mode 100644
index 0000000..892863e
--- /dev/null
+++ b/include/grpcpp/security/server_credentials.h
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_H
+#define GRPCPP_SECURITY_SERVER_CREDENTIALS_H
+
+#include <memory>
+#include <vector>
+
+#include <grpc/grpc_security_constants.h>
+#include <grpcpp/security/auth_metadata_processor.h>
+#include <grpcpp/support/config.h>
+
+struct grpc_server;
+
+namespace grpc {
+class Server;
+
+/// Wrapper around \a grpc_server_credentials, a way to authenticate a server.
+class ServerCredentials {
+ public:
+ virtual ~ServerCredentials();
+
+ /// This method is not thread-safe and has to be called before the server is
+ /// started. The last call to this function wins.
+ virtual void SetAuthMetadataProcessor(
+ const std::shared_ptr<AuthMetadataProcessor>& processor) = 0;
+
+ private:
+ friend class ::grpc::Server;
+
+ /// Tries to bind \a server to the given \a addr (eg, localhost:1234,
+ /// 192.168.1.1:31416, [::1]:27182, etc.)
+ ///
+ /// \return bound port number on sucess, 0 on failure.
+ // TODO(dgq): the "port" part seems to be a misnomer.
+ virtual int AddPortToServer(const grpc::string& addr,
+ grpc_server* server) = 0;
+};
+
+/// Options to create ServerCredentials with SSL
+struct SslServerCredentialsOptions {
+ /// \warning Deprecated
+ SslServerCredentialsOptions()
+ : force_client_auth(false),
+ client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {}
+ SslServerCredentialsOptions(
+ grpc_ssl_client_certificate_request_type request_type)
+ : force_client_auth(false), client_certificate_request(request_type) {}
+
+ struct PemKeyCertPair {
+ grpc::string private_key;
+ grpc::string cert_chain;
+ };
+ grpc::string pem_root_certs;
+ std::vector<PemKeyCertPair> pem_key_cert_pairs;
+ /// \warning Deprecated
+ bool force_client_auth;
+
+ /// If both \a force_client_auth and \a client_certificate_request
+ /// fields are set, \a force_client_auth takes effect, i.e.
+ /// \a REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+ /// will be enforced.
+ grpc_ssl_client_certificate_request_type client_certificate_request;
+};
+
+/// Builds SSL ServerCredentials given SSL specific options
+std::shared_ptr<ServerCredentials> SslServerCredentials(
+ const SslServerCredentialsOptions& options);
+
+/// Builds insecure server credentials.
+std::shared_ptr<ServerCredentials> InsecureServerCredentials();
+
+} // namespace grpc
+
+#endif // GRPCPP_SECURITY_SERVER_CREDENTIALS_H
diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h
new file mode 100644
index 0000000..f99a6c2
--- /dev/null
+++ b/include/grpcpp/server.h
@@ -0,0 +1,227 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SERVER_H
+#define GRPCPP_SERVER_H
+
+#include <condition_variable>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <grpc/compression.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/impl/call.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/impl/codegen/server_interface.h>
+#include <grpcpp/impl/rpc_service_method.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/support/channel_arguments.h>
+#include <grpcpp/support/config.h>
+#include <grpcpp/support/status.h>
+
+struct grpc_server;
+
+namespace grpc {
+
+class AsyncGenericService;
+class HealthCheckServiceInterface;
+class ServerContext;
+class ServerInitializer;
+
+/// Represents a gRPC server.
+///
+/// Use a \a grpc::ServerBuilder to create, configure, and start
+/// \a Server instances.
+class Server final : public ServerInterface, private GrpcLibraryCodegen {
+ public:
+ ~Server();
+
+ /// Block until the server shuts down.
+ ///
+ /// \warning The server must be either shutting down or some other thread must
+ /// call \a Shutdown for this function to ever return.
+ void Wait() override;
+
+ /// Global callbacks are a set of hooks that are called when server
+ /// events occur. \a SetGlobalCallbacks method is used to register
+ /// the hooks with gRPC. Note that
+ /// the \a GlobalCallbacks instance will be shared among all
+ /// \a Server instances in an application and can be set exactly
+ /// once per application.
+ class GlobalCallbacks {
+ public:
+ virtual ~GlobalCallbacks() {}
+ /// Called before server is created.
+ virtual void UpdateArguments(ChannelArguments* args) {}
+ /// Called before application callback for each synchronous server request
+ virtual void PreSynchronousRequest(ServerContext* context) = 0;
+ /// Called after application callback for each synchronous server request
+ virtual void PostSynchronousRequest(ServerContext* context) = 0;
+ /// Called before server is started.
+ virtual void PreServerStart(Server* server) {}
+ /// Called after a server port is added.
+ virtual void AddPort(Server* server, const grpc::string& addr,
+ ServerCredentials* creds, int port) {}
+ };
+ /// Set the global callback object. Can only be called once per application.
+ /// Does not take ownership of callbacks, and expects the pointed to object
+ /// to be alive until all server objects in the process have been destroyed.
+ /// The same \a GlobalCallbacks object will be used throughout the
+ /// application and is shared among all \a Server objects.
+ static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
+ // Returns a \em raw pointer to the underlying \a grpc_server instance.
+ grpc_server* c_server();
+
+ /// Returns the health check service.
+ HealthCheckServiceInterface* GetHealthCheckService() const {
+ return health_check_service_.get();
+ }
+
+ /// Establish a channel for in-process communication
+ std::shared_ptr<Channel> InProcessChannel(const ChannelArguments& args);
+
+ private:
+ friend class AsyncGenericService;
+ friend class ServerBuilder;
+ friend class ServerInitializer;
+
+ class SyncRequest;
+ class AsyncRequest;
+ class ShutdownRequest;
+
+ /// SyncRequestThreadManager is an implementation of ThreadManager. This class
+ /// is responsible for polling for incoming RPCs and calling the RPC handlers.
+ /// This is only used in case of a Sync server (i.e a server exposing a sync
+ /// interface)
+ class SyncRequestThreadManager;
+
+ class UnimplementedAsyncRequestContext;
+ class UnimplementedAsyncRequest;
+ class UnimplementedAsyncResponse;
+
+ /// Server constructors. To be used by \a ServerBuilder only.
+ ///
+ /// \param max_message_size Maximum message length that the channel can
+ /// receive.
+ ///
+ /// \param args The channel args
+ ///
+ /// \param sync_server_cqs The completion queues to use if the server is a
+ /// synchronous server (or a hybrid server). The server polls for new RPCs on
+ /// these queues
+ ///
+ /// \param min_pollers The minimum number of polling threads per server
+ /// completion queue (in param sync_server_cqs) to use for listening to
+ /// incoming requests (used only in case of sync server)
+ ///
+ /// \param max_pollers The maximum number of polling threads per server
+ /// completion queue (in param sync_server_cqs) to use for listening to
+ /// incoming requests (used only in case of sync server)
+ ///
+ /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on
+ /// server completion queues passed via sync_server_cqs param.
+ Server(int max_message_size, ChannelArguments* args,
+ std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
+ sync_server_cqs,
+ int min_pollers, int max_pollers, int sync_cq_timeout_msec);
+
+ /// Register a service. This call does not take ownership of the service.
+ /// The service must exist for the lifetime of the Server instance.
+ bool RegisterService(const grpc::string* host, Service* service) override;
+
+ /// Register a generic service. This call does not take ownership of the
+ /// service. The service must exist for the lifetime of the Server instance.
+ void RegisterAsyncGenericService(AsyncGenericService* service) override;
+
+ /// Try binding the server to the given \a addr endpoint
+ /// (port, and optionally including IP address to bind to).
+ ///
+ /// It can be invoked multiple times. Should be used before
+ /// starting the server.
+ ///
+ /// \param addr The address to try to bind to the server (eg, localhost:1234,
+ /// 192.168.1.1:31416, [::1]:27182, etc.).
+ /// \param creds The credentials associated with the server.
+ ///
+ /// \return bound port number on success, 0 on failure.
+ ///
+ /// \warning It is an error to call this method on an already started server.
+ int AddListeningPort(const grpc::string& addr,
+ ServerCredentials* creds) override;
+
+ /// Start the server.
+ ///
+ /// \param cqs Completion queues for handling asynchronous services. The
+ /// caller is required to keep all completion queues live until the server is
+ /// destroyed.
+ /// \param num_cqs How many completion queues does \a cqs hold.
+ void Start(ServerCompletionQueue** cqs, size_t num_cqs) override;
+
+ void PerformOpsOnCall(internal::CallOpSetInterface* ops,
+ internal::Call* call) override;
+
+ void ShutdownInternal(gpr_timespec deadline) override;
+
+ int max_receive_message_size() const override {
+ return max_receive_message_size_;
+ };
+
+ grpc_server* server() override { return server_; };
+
+ ServerInitializer* initializer();
+
+ const int max_receive_message_size_;
+
+ /// The following completion queues are ONLY used in case of Sync API
+ /// i.e. if the server has any services with sync methods. The server uses
+ /// these completion queues to poll for new RPCs
+ std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
+ sync_server_cqs_;
+
+ /// List of \a ThreadManager instances (one for each cq in
+ /// the \a sync_server_cqs)
+ std::vector<std::unique_ptr<SyncRequestThreadManager>> sync_req_mgrs_;
+
+ // Sever status
+ std::mutex mu_;
+ bool started_;
+ bool shutdown_;
+ bool shutdown_notified_; // Was notify called on the shutdown_cv_
+
+ std::condition_variable shutdown_cv_;
+
+ std::shared_ptr<GlobalCallbacks> global_callbacks_;
+
+ std::vector<grpc::string> services_;
+ bool has_generic_service_;
+
+ // Pointer to the wrapped grpc_server.
+ grpc_server* server_;
+
+ std::unique_ptr<ServerInitializer> server_initializer_;
+
+ std::unique_ptr<HealthCheckServiceInterface> health_check_service_;
+ bool health_check_service_disabled_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_SERVER_H
diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h
new file mode 100644
index 0000000..c35a6cf
--- /dev/null
+++ b/include/grpcpp/server_builder.h
@@ -0,0 +1,278 @@
+/*
+ *
+ * Copyright 2015-2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SERVER_BUILDER_H
+#define GRPCPP_SERVER_BUILDER_H
+
+#include <climits>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <grpc/compression.h>
+#include <grpc/support/cpu.h>
+#include <grpc/support/workaround_list.h>
+#include <grpcpp/impl/channel_argument_option.h>
+#include <grpcpp/impl/server_builder_option.h>
+#include <grpcpp/impl/server_builder_plugin.h>
+#include <grpcpp/support/config.h>
+
+struct grpc_resource_quota;
+
+namespace grpc {
+
+class AsyncGenericService;
+class ResourceQuota;
+class CompletionQueue;
+class Server;
+class ServerCompletionQueue;
+class ServerCredentials;
+class Service;
+
+namespace testing {
+class ServerBuilderPluginTest;
+} // namespace testing
+
+/// A builder class for the creation and startup of \a grpc::Server instances.
+class ServerBuilder {
+ public:
+ ServerBuilder();
+ ~ServerBuilder();
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Primary API's
+
+ /// Return a running server which is ready for processing calls.
+ /// Before calling, one typically needs to ensure that:
+ /// 1. a service is registered - so that the server knows what to serve
+ /// (via RegisterService, or RegisterAsyncGenericService)
+ /// 2. a listening port has been added - so the server knows where to receive
+ /// traffic (via AddListeningPort)
+ /// 3. [for async api only] completion queues have been added via
+ /// AddCompletionQueue
+ std::unique_ptr<Server> BuildAndStart();
+
+ /// Register a service. This call does not take ownership of the service.
+ /// The service must exist for the lifetime of the \a Server instance returned
+ /// by \a BuildAndStart().
+ /// Matches requests with any :authority
+ ServerBuilder& RegisterService(Service* service);
+
+ /// Enlists an endpoint \a addr (port with an optional IP address) to
+ /// bind the \a grpc::Server object to be created to.
+ ///
+ /// It can be invoked multiple times.
+ ///
+ /// \param addr_uri The address to try to bind to the server in URI form. If
+ /// the scheme name is omitted, "dns:///" is assumed. To bind to any address,
+ /// please use IPv6 any, i.e., [::]:<port>, which also accepts IPv4
+ /// connections. Valid values include dns:///localhost:1234, /
+ /// 192.168.1.1:31416, dns:///[::1]:27182, etc.).
+ /// \param creds The credentials associated with the server.
+ /// \param selected_port[out] If not `nullptr`, gets populated with the port
+ /// number bound to the \a grpc::Server for the corresponding endpoint after
+ /// it is successfully bound, 0 otherwise.
+ ///
+ ServerBuilder& AddListeningPort(const grpc::string& addr_uri,
+ std::shared_ptr<ServerCredentials> creds,
+ int* selected_port = nullptr);
+
+ /// Add a completion queue for handling asynchronous services.
+ ///
+ /// Best performance is typically obtained by using one thread per polling
+ /// completion queue.
+ ///
+ /// Caller is required to shutdown the server prior to shutting down the
+ /// returned completion queue. Caller is also required to drain the
+ /// completion queue after shutting it down. A typical usage scenario:
+ ///
+ /// // While building the server:
+ /// ServerBuilder builder;
+ /// ...
+ /// cq_ = builder.AddCompletionQueue();
+ /// server_ = builder.BuildAndStart();
+ ///
+ /// // While shutting down the server;
+ /// server_->Shutdown();
+ /// cq_->Shutdown(); // Always *after* the associated server's Shutdown()!
+ /// // Drain the cq_ that was created
+ /// void* ignored_tag;
+ /// bool ignored_ok;
+ /// while (cq_->Next(&ignored_tag, &ignored_ok)) { }
+ ///
+ /// \param is_frequently_polled This is an optional parameter to inform gRPC
+ /// library about whether this completion queue would be frequently polled
+ /// (i.e. by calling \a Next() or \a AsyncNext()). The default value is
+ /// 'true' and is the recommended setting. Setting this to 'false' (i.e.
+ /// not polling the completion queue frequently) will have a significantly
+ /// negative performance impact and hence should not be used in production
+ /// use cases.
+ std::unique_ptr<ServerCompletionQueue> AddCompletionQueue(
+ bool is_frequently_polled = true);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Less commonly used RegisterService variants
+
+ /// Register a service. This call does not take ownership of the service.
+ /// The service must exist for the lifetime of the \a Server instance returned
+ /// by \a BuildAndStart().
+ /// Only matches requests with :authority \a host
+ ServerBuilder& RegisterService(const grpc::string& host, Service* service);
+
+ /// Register a generic service.
+ /// Matches requests with any :authority
+ /// This is mostly useful for writing generic gRPC Proxies where the exact
+ /// serialization format is unknown
+ ServerBuilder& RegisterAsyncGenericService(AsyncGenericService* service);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Fine control knobs
+
+ /// Set max receive message size in bytes.
+ ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) {
+ max_receive_message_size_ = max_receive_message_size;
+ return *this;
+ }
+
+ /// Set max send message size in bytes.
+ ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) {
+ max_send_message_size_ = max_send_message_size;
+ return *this;
+ }
+
+ /// \deprecated For backward compatibility.
+ ServerBuilder& SetMaxMessageSize(int max_message_size) {
+ return SetMaxReceiveMessageSize(max_message_size);
+ }
+
+ /// Set the support status for compression algorithms. All algorithms are
+ /// enabled by default.
+ ///
+ /// Incoming calls compressed with an unsupported algorithm will fail with
+ /// \a GRPC_STATUS_UNIMPLEMENTED.
+ ServerBuilder& SetCompressionAlgorithmSupportStatus(
+ grpc_compression_algorithm algorithm, bool enabled);
+
+ /// The default compression level to use for all channel calls in the
+ /// absence of a call-specific level.
+ ServerBuilder& SetDefaultCompressionLevel(grpc_compression_level level);
+
+ /// The default compression algorithm to use for all channel calls in the
+ /// absence of a call-specific level. Note that it overrides any compression
+ /// level set by \a SetDefaultCompressionLevel.
+ ServerBuilder& SetDefaultCompressionAlgorithm(
+ grpc_compression_algorithm algorithm);
+
+ /// Set the attached buffer pool for this server
+ ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota);
+
+ ServerBuilder& SetOption(std::unique_ptr<ServerBuilderOption> option);
+
+ /// Options for synchronous servers.
+ enum SyncServerOption {
+ NUM_CQS, ///< Number of completion queues.
+ MIN_POLLERS, ///< Minimum number of polling threads.
+ MAX_POLLERS, ///< Maximum number of polling threads.
+ CQ_TIMEOUT_MSEC ///< Completion queue timeout in milliseconds.
+ };
+
+ /// Only useful if this is a Synchronous server.
+ ServerBuilder& SetSyncServerOption(SyncServerOption option, int value);
+
+ /// Add a channel argument (an escape hatch to tuning core library parameters
+ /// directly)
+ template <class T>
+ ServerBuilder& AddChannelArgument(const grpc::string& arg, const T& value) {
+ return SetOption(MakeChannelArgumentOption(arg, value));
+ }
+
+ /// For internal use only: Register a ServerBuilderPlugin factory function.
+ static void InternalAddPluginFactory(
+ std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)());
+
+ /// Enable a server workaround. Do not use unless you know what the workaround
+ /// does. For explanation and detailed descriptions of workarounds, see
+ /// doc/workarounds.md.
+ ServerBuilder& EnableWorkaround(grpc_workaround_list id);
+
+ private:
+ friend class ::grpc::testing::ServerBuilderPluginTest;
+
+ struct Port {
+ grpc::string addr;
+ std::shared_ptr<ServerCredentials> creds;
+ int* selected_port;
+ };
+
+ struct SyncServerSettings {
+ SyncServerSettings()
+ : num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {}
+
+ /// Number of server completion queues to create to listen to incoming RPCs.
+ int num_cqs;
+
+ /// Minimum number of threads per completion queue that should be listening
+ /// to incoming RPCs.
+ int min_pollers;
+
+ /// Maximum number of threads per completion queue that can be listening to
+ /// incoming RPCs.
+ int max_pollers;
+
+ /// The timeout for server completion queue's AsyncNext call.
+ int cq_timeout_msec;
+ };
+
+ typedef std::unique_ptr<grpc::string> HostString;
+ struct NamedService {
+ explicit NamedService(Service* s) : service(s) {}
+ NamedService(const grpc::string& h, Service* s)
+ : host(new grpc::string(h)), service(s) {}
+ HostString host;
+ Service* service;
+ };
+
+ int max_receive_message_size_;
+ int max_send_message_size_;
+ std::vector<std::unique_ptr<ServerBuilderOption>> options_;
+ std::vector<std::unique_ptr<NamedService>> services_;
+ std::vector<Port> ports_;
+
+ SyncServerSettings sync_server_settings_;
+
+ /// List of completion queues added via \a AddCompletionQueue method.
+ std::vector<ServerCompletionQueue*> cqs_;
+
+ std::shared_ptr<ServerCredentials> creds_;
+ std::vector<std::unique_ptr<ServerBuilderPlugin>> plugins_;
+ grpc_resource_quota* resource_quota_;
+ AsyncGenericService* generic_service_;
+ struct {
+ bool is_set;
+ grpc_compression_level level;
+ } maybe_default_compression_level_;
+ struct {
+ bool is_set;
+ grpc_compression_algorithm algorithm;
+ } maybe_default_compression_algorithm_;
+ uint32_t enabled_compression_algorithms_bitset_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_SERVER_BUILDER_H
diff --git a/include/grpcpp/server_context.h b/include/grpcpp/server_context.h
new file mode 100644
index 0000000..45f2614
--- /dev/null
+++ b/include/grpcpp/server_context.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SERVER_CONTEXT_H
+#define GRPCPP_SERVER_CONTEXT_H
+
+#include <grpcpp/impl/codegen/server_context.h>
+
+#endif // GRPCPP_SERVER_CONTEXT_H
diff --git a/include/grpcpp/server_posix.h b/include/grpcpp/server_posix.h
new file mode 100644
index 0000000..ef3ee01
--- /dev/null
+++ b/include/grpcpp/server_posix.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SERVER_POSIX_H
+#define GRPCPP_SERVER_POSIX_H
+
+#include <memory>
+
+#include <grpc/support/port_platform.h>
+#include <grpcpp/server.h>
+
+namespace grpc {
+
+#ifdef GPR_SUPPORT_CHANNELS_FROM_FD
+
+/// Add a new client to a \a Server communicating over the given
+/// file descriptor.
+///
+/// \param server The server to add the client to.
+/// \param fd The file descriptor representing a socket.
+void AddInsecureChannelFromFd(Server* server, int fd);
+
+#endif // GPR_SUPPORT_CHANNELS_FROM_FD
+
+} // namespace grpc
+
+#endif // GRPCPP_SERVER_POSIX_H
diff --git a/include/grpcpp/support/async_stream.h b/include/grpcpp/support/async_stream.h
new file mode 100644
index 0000000..ff9e455
--- /dev/null
+++ b/include/grpcpp/support/async_stream.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_ASYNC_STREAM_H
+#define GRPCPP_SUPPORT_ASYNC_STREAM_H
+
+#include <grpcpp/impl/codegen/async_stream.h>
+
+#endif // GRPCPP_SUPPORT_ASYNC_STREAM_H
diff --git a/include/grpcpp/support/async_unary_call.h b/include/grpcpp/support/async_unary_call.h
new file mode 100644
index 0000000..2e5181c
--- /dev/null
+++ b/include/grpcpp/support/async_unary_call.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_ASYNC_UNARY_CALL_H
+#define GRPCPP_SUPPORT_ASYNC_UNARY_CALL_H
+
+#include <grpcpp/impl/codegen/async_unary_call.h>
+
+#endif // GRPCPP_SUPPORT_ASYNC_UNARY_CALL_H
diff --git a/include/grpcpp/support/byte_buffer.h b/include/grpcpp/support/byte_buffer.h
new file mode 100644
index 0000000..53aeff1
--- /dev/null
+++ b/include/grpcpp/support/byte_buffer.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_BYTE_BUFFER_H
+#define GRPCPP_SUPPORT_BYTE_BUFFER_H
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/serialization_traits.h>
+#include <grpcpp/support/config.h>
+#include <grpcpp/support/slice.h>
+#include <grpcpp/support/status.h>
+
+#endif // GRPCPP_SUPPORT_BYTE_BUFFER_H
diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h
new file mode 100644
index 0000000..1eead4e
--- /dev/null
+++ b/include/grpcpp/support/channel_arguments.h
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_CHANNEL_ARGUMENTS_H
+#define GRPCPP_SUPPORT_CHANNEL_ARGUMENTS_H
+
+#include <list>
+#include <vector>
+
+#include <grpc/compression.h>
+#include <grpc/grpc.h>
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+namespace testing {
+class ChannelArgumentsTest;
+} // namespace testing
+
+class ResourceQuota;
+
+/// Options for channel creation. The user can use generic setters to pass
+/// key value pairs down to C channel creation code. For gRPC related options,
+/// concrete setters are provided.
+class ChannelArguments {
+ public:
+ ChannelArguments();
+ ~ChannelArguments();
+
+ ChannelArguments(const ChannelArguments& other);
+ ChannelArguments& operator=(ChannelArguments other) {
+ Swap(other);
+ return *this;
+ }
+
+ void Swap(ChannelArguments& other);
+
+ /// Dump arguments in this instance to \a channel_args. Does not take
+ /// ownership of \a channel_args.
+ ///
+ /// Note that the underlying arguments are shared. Changes made to either \a
+ /// channel_args or this instance would be reflected on both.
+ void SetChannelArgs(grpc_channel_args* channel_args) const;
+
+ // gRPC specific channel argument setters
+ /// Set target name override for SSL host name checking. This option is for
+ /// testing only and should never be used in production.
+ void SetSslTargetNameOverride(const grpc::string& name);
+ // TODO(yangg) add flow control options
+ /// Set the compression algorithm for the channel.
+ void SetCompressionAlgorithm(grpc_compression_algorithm algorithm);
+
+ /// Set the grpclb fallback timeout (in ms) for the channel. If this amount
+ /// of time has passed but we have not gotten any non-empty \a serverlist from
+ /// the balancer, we will fall back to use the backend address(es) returned by
+ /// the resolver.
+ void SetGrpclbFallbackTimeout(int fallback_timeout);
+
+ /// Set the socket mutator for the channel.
+ void SetSocketMutator(grpc_socket_mutator* mutator);
+
+ /// Set the string to prepend to the user agent.
+ void SetUserAgentPrefix(const grpc::string& user_agent_prefix);
+
+ /// Set the buffer pool to be attached to the constructed channel.
+ void SetResourceQuota(const ResourceQuota& resource_quota);
+
+ /// Set the max receive and send message sizes.
+ void SetMaxReceiveMessageSize(int size);
+ void SetMaxSendMessageSize(int size);
+
+ /// Set LB policy name.
+ /// Note that if the name resolver returns only balancer addresses, the
+ /// grpclb LB policy will be used, regardless of what is specified here.
+ void SetLoadBalancingPolicyName(const grpc::string& lb_policy_name);
+
+ /// Set service config in JSON form.
+ /// Primarily meant for use in unit tests.
+ void SetServiceConfigJSON(const grpc::string& service_config_json);
+
+ // Generic channel argument setters. Only for advanced use cases.
+ /// Set an integer argument \a value under \a key.
+ void SetInt(const grpc::string& key, int value);
+
+ // Generic channel argument setter. Only for advanced use cases.
+ /// Set a pointer argument \a value under \a key. Owership is not transferred.
+ void SetPointer(const grpc::string& key, void* value);
+
+ void SetPointerWithVtable(const grpc::string& key, void* value,
+ const grpc_arg_pointer_vtable* vtable);
+
+ /// Set a textual argument \a value under \a key.
+ void SetString(const grpc::string& key, const grpc::string& value);
+
+ /// Return (by value) a C \a grpc_channel_args structure which points to
+ /// arguments owned by this \a ChannelArguments instance
+ grpc_channel_args c_channel_args() const {
+ grpc_channel_args out;
+ out.num_args = args_.size();
+ out.args = args_.empty() ? NULL : const_cast<grpc_arg*>(&args_[0]);
+ return out;
+ }
+
+ private:
+ friend class SecureChannelCredentials;
+ friend class testing::ChannelArgumentsTest;
+
+ /// Default pointer argument operations.
+ struct PointerVtableMembers {
+ static void* Copy(void* in) { return in; }
+ static void Destroy(void* in) {}
+ static int Compare(void* a, void* b) {
+ if (a < b) return -1;
+ if (a > b) return 1;
+ return 0;
+ }
+ };
+
+ // Returns empty string when it is not set.
+ grpc::string GetSslTargetNameOverride() const;
+
+ std::vector<grpc_arg> args_;
+ std::list<grpc::string> strings_;
+};
+
+} // namespace grpc
+
+#endif // GRPCPP_SUPPORT_CHANNEL_ARGUMENTS_H
diff --git a/include/grpcpp/support/config.h b/include/grpcpp/support/config.h
new file mode 100644
index 0000000..16bdab6
--- /dev/null
+++ b/include/grpcpp/support/config.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_CONFIG_H
+#define GRPCPP_SUPPORT_CONFIG_H
+
+#include <grpcpp/impl/codegen/config.h>
+
+#endif // GRPCPP_SUPPORT_CONFIG_H
diff --git a/include/grpcpp/support/error_details.h b/include/grpcpp/support/error_details.h
new file mode 100644
index 0000000..84931d9
--- /dev/null
+++ b/include/grpcpp/support/error_details.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_ERROR_DETAILS_H
+#define GRPCPP_SUPPORT_ERROR_DETAILS_H
+
+#include <grpcpp/support/status.h>
+
+namespace google {
+namespace rpc {
+class Status;
+} // namespace rpc
+} // namespace google
+
+namespace grpc {
+
+/// Map a \a grpc::Status to a \a google::rpc::Status.
+/// The given \a to object will be cleared.
+/// On success, returns status with OK.
+/// Returns status with \a INVALID_ARGUMENT, if failed to deserialize.
+/// Returns status with \a FAILED_PRECONDITION, if \a to is nullptr.
+Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to);
+
+/// Map \a google::rpc::Status to a \a grpc::Status.
+/// Returns OK on success.
+/// Returns status with \a FAILED_PRECONDITION if \a to is nullptr.
+Status SetErrorDetails(const ::google::rpc::Status& from, Status* to);
+
+} // namespace grpc
+
+#endif // GRPCPP_SUPPORT_ERROR_DETAILS_H
diff --git a/include/grpcpp/support/slice.h b/include/grpcpp/support/slice.h
new file mode 100644
index 0000000..eaeb29a
--- /dev/null
+++ b/include/grpcpp/support/slice.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_SLICE_H
+#define GRPCPP_SUPPORT_SLICE_H
+
+#include <grpc/slice.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/support/config.h>
+
+#endif // GRPCPP_SUPPORT_SLICE_H
diff --git a/include/grpcpp/support/status.h b/include/grpcpp/support/status.h
new file mode 100644
index 0000000..91b629f
--- /dev/null
+++ b/include/grpcpp/support/status.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_STATUS_H
+#define GRPCPP_SUPPORT_STATUS_H
+
+#include <grpcpp/impl/codegen/status.h>
+
+#endif // GRPCPP_SUPPORT_STATUS_H
diff --git a/include/grpcpp/support/status_code_enum.h b/include/grpcpp/support/status_code_enum.h
new file mode 100644
index 0000000..bfb47f3
--- /dev/null
+++ b/include/grpcpp/support/status_code_enum.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_STATUS_CODE_ENUM_H
+#define GRPCPP_SUPPORT_STATUS_CODE_ENUM_H
+
+#include <grpcpp/impl/codegen/status_code_enum.h>
+
+#endif // GRPCPP_SUPPORT_STATUS_CODE_ENUM_H
diff --git a/include/grpcpp/support/string_ref.h b/include/grpcpp/support/string_ref.h
new file mode 100644
index 0000000..0e0d3d4
--- /dev/null
+++ b/include/grpcpp/support/string_ref.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_STRING_REF_H
+#define GRPCPP_SUPPORT_STRING_REF_H
+
+#include <grpcpp/impl/codegen/string_ref.h>
+
+#endif // GRPCPP_SUPPORT_STRING_REF_H
diff --git a/include/grpcpp/support/stub_options.h b/include/grpcpp/support/stub_options.h
new file mode 100644
index 0000000..e9700ea
--- /dev/null
+++ b/include/grpcpp/support/stub_options.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_STUB_OPTIONS_H
+#define GRPCPP_SUPPORT_STUB_OPTIONS_H
+
+#include <grpcpp/impl/codegen/stub_options.h>
+
+#endif // GRPCPP_SUPPORT_STUB_OPTIONS_H
diff --git a/include/grpcpp/support/sync_stream.h b/include/grpcpp/support/sync_stream.h
new file mode 100644
index 0000000..ea60b6d
--- /dev/null
+++ b/include/grpcpp/support/sync_stream.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_SYNC_STREAM_H
+#define GRPCPP_SUPPORT_SYNC_STREAM_H
+
+#include <grpcpp/impl/codegen/sync_stream.h>
+
+#endif // GRPCPP_SUPPORT_SYNC_STREAM_H
diff --git a/include/grpcpp/support/time.h b/include/grpcpp/support/time.h
new file mode 100644
index 0000000..c7408ff
--- /dev/null
+++ b/include/grpcpp/support/time.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_SUPPORT_TIME_H
+#define GRPCPP_SUPPORT_TIME_H
+
+#include <grpcpp/impl/codegen/time.h>
+
+#endif // GRPCPP_SUPPORT_TIME_H
diff --git a/include/grpcpp/test/mock_stream.h b/include/grpcpp/test/mock_stream.h
new file mode 100644
index 0000000..93963f7
--- /dev/null
+++ b/include/grpcpp/test/mock_stream.h
@@ -0,0 +1,148 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_TEST_MOCK_STREAM_H
+#define GRPCPP_TEST_MOCK_STREAM_H
+
+#include <stdint.h>
+
+#include <gmock/gmock.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/support/async_stream.h>
+#include <grpcpp/support/async_unary_call.h>
+#include <grpcpp/support/sync_stream.h>
+
+namespace grpc {
+namespace testing {
+
+template <class R>
+class MockClientReader : public ClientReaderInterface<R> {
+ public:
+ MockClientReader() = default;
+
+ /// ClientStreamingInterface
+ MOCK_METHOD0_T(Finish, Status());
+
+ /// ReaderInterface
+ MOCK_METHOD1_T(NextMessageSize, bool(uint32_t*));
+ MOCK_METHOD1_T(Read, bool(R*));
+
+ /// ClientReaderInterface
+ MOCK_METHOD0_T(WaitForInitialMetadata, void());
+};
+
+template <class W>
+class MockClientWriter : public ClientWriterInterface<W> {
+ public:
+ MockClientWriter() = default;
+
+ /// ClientStreamingInterface
+ MOCK_METHOD0_T(Finish, Status());
+
+ /// WriterInterface
+ MOCK_METHOD2_T(Write, bool(const W&, const WriteOptions));
+
+ /// ClientWriterInterface
+ MOCK_METHOD0_T(WritesDone, bool());
+};
+
+template <class W, class R>
+class MockClientReaderWriter : public ClientReaderWriterInterface<W, R> {
+ public:
+ MockClientReaderWriter() = default;
+
+ /// ClientStreamingInterface
+ MOCK_METHOD0_T(Finish, Status());
+
+ /// ReaderInterface
+ MOCK_METHOD1_T(NextMessageSize, bool(uint32_t*));
+ MOCK_METHOD1_T(Read, bool(R*));
+
+ /// WriterInterface
+ MOCK_METHOD2_T(Write, bool(const W&, const WriteOptions));
+
+ /// ClientReaderWriterInterface
+ MOCK_METHOD0_T(WaitForInitialMetadata, void());
+ MOCK_METHOD0_T(WritesDone, bool());
+};
+
+/// TODO: We do not support mocking an async RPC for now.
+
+template <class R>
+class MockClientAsyncResponseReader
+ : public ClientAsyncResponseReaderInterface<R> {
+ public:
+ MockClientAsyncResponseReader() = default;
+
+ MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
+ MOCK_METHOD3_T(Finish, void(R*, Status*, void*));
+};
+
+template <class R>
+class MockClientAsyncReader : public ClientAsyncReaderInterface<R> {
+ public:
+ MockClientAsyncReader() = default;
+
+ /// ClientAsyncStreamingInterface
+ MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
+ MOCK_METHOD2_T(Finish, void(Status*, void*));
+
+ /// AsyncReaderInterface
+ MOCK_METHOD2_T(Read, void(R*, void*));
+};
+
+template <class W>
+class MockClientAsyncWriter : public ClientAsyncWriterInterface<W> {
+ public:
+ MockClientAsyncWriter() = default;
+
+ /// ClientAsyncStreamingInterface
+ MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
+ MOCK_METHOD2_T(Finish, void(Status*, void*));
+
+ /// AsyncWriterInterface
+ MOCK_METHOD2_T(Write, void(const W&, void*));
+
+ /// ClientAsyncWriterInterface
+ MOCK_METHOD1_T(WritesDone, void(void*));
+};
+
+template <class W, class R>
+class MockClientAsyncReaderWriter
+ : public ClientAsyncReaderWriterInterface<W, R> {
+ public:
+ MockClientAsyncReaderWriter() = default;
+
+ /// ClientAsyncStreamingInterface
+ MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
+ MOCK_METHOD2_T(Finish, void(Status*, void*));
+
+ /// AsyncWriterInterface
+ MOCK_METHOD2_T(Write, void(const W&, void*));
+
+ /// AsyncReaderInterface
+ MOCK_METHOD2_T(Read, void(R*, void*));
+
+ /// ClientAsyncReaderWriterInterface
+ MOCK_METHOD1_T(WritesDone, void(void*));
+};
+
+} // namespace testing
+} // namespace grpc
+
+#endif // GRPCPP_TEST_MOCK_STREAM_H
diff --git a/include/grpcpp/test/server_context_test_spouse.h b/include/grpcpp/test/server_context_test_spouse.h
new file mode 100644
index 0000000..f5ca552
--- /dev/null
+++ b/include/grpcpp/test/server_context_test_spouse.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPCPP_TEST_SERVER_CONTEXT_TEST_SPOUSE_H
+#define GRPCPP_TEST_SERVER_CONTEXT_TEST_SPOUSE_H
+
+#include <map>
+
+#include <grpcpp/server_context.h>
+
+namespace grpc {
+namespace testing {
+
+/// A test-only class to access private members and methods of ServerContext.
+class ServerContextTestSpouse {
+ public:
+ explicit ServerContextTestSpouse(ServerContext* ctx) : ctx_(ctx) {}
+
+ /// Inject client metadata to the ServerContext for the test. The test spouse
+ /// must be alive when \a ServerContext::client_metadata is called.
+ void AddClientMetadata(const grpc::string& key, const grpc::string& value) {
+ client_metadata_storage_.insert(
+ std::pair<grpc::string, grpc::string>(key, value));
+ ctx_->client_metadata_.map()->clear();
+ for (auto iter = client_metadata_storage_.begin();
+ iter != client_metadata_storage_.end(); ++iter) {
+ ctx_->client_metadata_.map()->insert(
+ std::pair<grpc::string_ref, grpc::string_ref>(
+ iter->first.c_str(),
+ grpc::string_ref(iter->second.data(), iter->second.size())));
+ }
+ }
+
+ std::multimap<grpc::string, grpc::string> GetInitialMetadata() const {
+ return ctx_->initial_metadata_;
+ }
+
+ std::multimap<grpc::string, grpc::string> GetTrailingMetadata() const {
+ return ctx_->trailing_metadata_;
+ }
+
+ private:
+ ServerContext* ctx_; // not owned
+ std::multimap<grpc::string, grpc::string> client_metadata_storage_;
+};
+
+} // namespace testing
+} // namespace grpc
+
+#endif // GRPCPP_TEST_SERVER_CONTEXT_TEST_SPOUSE_H