Replicate C++ docs from master to beta branch

Original PR #3074 by @dgquintas
pull/3227/head
Craig Tiller 9 years ago
parent aca3211b0f
commit d6599a39e4
  1. 52
      examples/cpp/helloworld/greeter_async_client.cc
  2. 60
      examples/cpp/helloworld/greeter_async_server.cc
  3. 24
      examples/cpp/helloworld/greeter_client.cc
  4. 15
      examples/cpp/helloworld/greeter_server.cc
  5. 13
      include/grpc++/channel.h
  6. 103
      include/grpc++/client_context.h
  7. 91
      include/grpc++/completion_queue.h
  8. 19
      include/grpc++/create_channel.h
  9. 64
      include/grpc++/grpc++.h
  10. 26
      include/grpc++/security/auth_context.h
  11. 100
      include/grpc++/security/credentials.h
  12. 12
      include/grpc++/security/server_credentials.h
  13. 65
      include/grpc++/server.h
  14. 63
      include/grpc++/server_builder.h
  15. 37
      include/grpc++/support/async_stream.h
  16. 14
      include/grpc++/support/byte_buffer.h
  17. 25
      include/grpc++/support/channel_arguments.h
  18. 26
      include/grpc++/support/slice.h
  19. 12
      include/grpc++/support/status.h
  20. 153
      include/grpc++/support/status_code_enum.h
  21. 13
      include/grpc++/support/string_ref.h
  22. 89
      include/grpc++/support/sync_stream.h
  23. 8
      include/grpc/grpc.h
  24. 2
      src/core/surface/completion_queue.h
  25. 6
      src/cpp/util/byte_buffer.cc

@ -35,13 +35,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <grpc/grpc.h> #include <grpc++/grpc++.h>
#include <grpc/support/log.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include "helloworld.grpc.pb.h" #include "helloworld.grpc.pb.h"
using grpc::Channel; using grpc::Channel;
@ -58,39 +53,72 @@ class GreeterClient {
explicit GreeterClient(std::shared_ptr<Channel> channel) explicit GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {} : stub_(Greeter::NewStub(channel)) {}
// Assambles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) { std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request; HelloRequest request;
request.set_name(user); request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply; HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context; ClientContext context;
// The producer-consumer queue we use to communicate asynchronously with the
// gRPC runtime.
CompletionQueue cq; CompletionQueue cq;
// Storage for the status of the RPC upon completion.
Status status; Status status;
// stub_->AsyncSayHello() perform the RPC call, returning an instance we
// store in "rpc". Because we are using the asynchronous API, we need the
// hold on to the "rpc" instance in order to get updates on the ongoig RPC.
std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc( std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(
stub_->AsyncSayHello(&context, request, &cq)); stub_->AsyncSayHello(&context, request, &cq));
// Request that, upon completion of the RPC, "reply" be updated with the
// server's response; "status" with the indication of whether the operation
// was successful. Tag the request with the integer 1.
rpc->Finish(&reply, &status, (void*)1); rpc->Finish(&reply, &status, (void*)1);
void* got_tag; void* got_tag;
bool ok = false; bool ok = false;
// Block until the next result is available in the completion queue "cq".
cq.Next(&got_tag, &ok); cq.Next(&got_tag, &ok);
GPR_ASSERT(ok);
// Verify that the result from "cq" corresponds, by its tag, our previous
// request.
GPR_ASSERT(got_tag == (void*)1); GPR_ASSERT(got_tag == (void*)1);
// ... and that the request was completed successfully. Note that "ok"
// corresponds solely to the request for updates introduced by Finish().
GPR_ASSERT(ok);
// Act upon the status of the actual RPC.
if (status.ok()) { if (status.ok()) {
return reply.message(); return reply.message();
} else { } else {
return "Rpc failed"; return "RPC failed";
} }
} }
private: private:
// Out of the passed in Channel comes the stub, stored here, our view of the
// server's exposed services.
std::unique_ptr<Greeter::Stub> stub_; std::unique_ptr<Greeter::Stub> stub_;
}; };
int main(int argc, char** argv) { int main(int argc, char** argv) {
GreeterClient greeter(grpc::CreateChannel( // Instantiate the client. It requires a channel, out of which the actual RPCs
"localhost:50051", grpc::InsecureCredentials())); // are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureCredentials()).
GreeterClient greeter(
grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
std::string user("world"); std::string user("world");
std::string reply = greeter.SayHello(user); std::string reply = greeter.SayHello(user); // The actual RPC call!
std::cout << "Greeter received: " << reply << std::endl; std::cout << "Greeter received: " << reply << std::endl;
return 0; return 0;

@ -36,13 +36,8 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include <grpc/grpc.h> #include <grpc++/grpc++.h>
#include <grpc/support/log.h>
#include <grpc++/completion_queue.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include "helloworld.grpc.pb.h" #include "helloworld.grpc.pb.h"
using grpc::Server; using grpc::Server;
@ -59,6 +54,7 @@ class ServerImpl final {
public: public:
~ServerImpl() { ~ServerImpl() {
server_->Shutdown(); server_->Shutdown();
// Always shutdown the completion queue after the server.
cq_->Shutdown(); cq_->Shutdown();
} }
@ -67,56 +63,102 @@ class ServerImpl final {
std::string server_address("0.0.0.0:50051"); std::string server_address("0.0.0.0:50051");
ServerBuilder builder; ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service_" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *asynchronous* service.
builder.RegisterAsyncService(&service_); builder.RegisterAsyncService(&service_);
// Get hold of the completion queue used for the asynchronous communication
// with the gRPC runtime.
cq_ = builder.AddCompletionQueue(); cq_ = builder.AddCompletionQueue();
// Finally assemble the server.
server_ = builder.BuildAndStart(); server_ = builder.BuildAndStart();
std::cout << "Server listening on " << server_address << std::endl; std::cout << "Server listening on " << server_address << std::endl;
// Proceed to the server's main loop.
HandleRpcs(); HandleRpcs();
} }
private: private:
// Class encompasing the state and logic needed to serve a request.
class CallData { class CallData {
public: public:
// Take in the "service" instance (in this case representing an asynchronous
// server) and the completion queue "cq" used for asynchronous communication
// with the gRPC runtime.
CallData(Greeter::AsyncService* service, ServerCompletionQueue* cq) CallData(Greeter::AsyncService* service, ServerCompletionQueue* cq)
: service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) { : service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) {
// Invoke the serving logic right away.
Proceed(); Proceed();
} }
void Proceed() { void Proceed() {
if (status_ == CREATE) { if (status_ == CREATE) {
// As part of the initial CREATE state, we *request* that the system
// start processing SayHello requests. In this request, "this" acts are
// the tag uniquely identifying the request (so that different CallData
// instances can serve different requests concurrently), in this case
// the memory address of this CallData instance.
service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_, service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_,
this); this);
// Make this instance progress to the PROCESS state.
status_ = PROCESS; status_ = PROCESS;
} else if (status_ == PROCESS) { } else if (status_ == PROCESS) {
// Spawn a new CallData instance to serve new clients while we process
// the one for this CallData. The instance will deallocate itself as
// part of its FINISH state.
new CallData(service_, cq_); new CallData(service_, cq_);
// The actual processing.
std::string prefix("Hello "); std::string prefix("Hello ");
reply_.set_message(prefix + request_.name()); reply_.set_message(prefix + request_.name());
// And we are done! Let the gRPC runtime know we've finished, using the
// memory address of this instance as the uniquely identifying tag for
// the event.
responder_.Finish(reply_, Status::OK, this); responder_.Finish(reply_, Status::OK, this);
status_ = FINISH; status_ = FINISH;
} else { } else {
GPR_ASSERT(status_ == FINISH);
// Once in the FINISH state, deallocate ourselves (CallData).
delete this; delete this;
} }
} }
private: private:
// The means of communication with the gRPC runtime for an asynchronous
// server.
Greeter::AsyncService* service_; Greeter::AsyncService* service_;
// The producer-consumer queue where for asynchronous server notifications.
ServerCompletionQueue* cq_; ServerCompletionQueue* cq_;
// Context for the rpc, allowing to tweak aspects of it such as the use
// of compression, authentication, as well as to send metadata back to the
// client.
ServerContext ctx_; ServerContext ctx_;
// What we get from the client.
HelloRequest request_; HelloRequest request_;
// What we send back to the client.
HelloReply reply_; HelloReply reply_;
// The means to get back to the client.
ServerAsyncResponseWriter<HelloReply> responder_; ServerAsyncResponseWriter<HelloReply> responder_;
// Let's implement a tiny state machine with the following states.
enum CallStatus { CREATE, PROCESS, FINISH }; enum CallStatus { CREATE, PROCESS, FINISH };
CallStatus status_; CallStatus status_; // The current serving state.
}; };
// This can be run in multiple threads if needed. // This can be run in multiple threads if needed.
void HandleRpcs() { void HandleRpcs() {
// Spawn a new CallData instance to serve new clients.
new CallData(&service_, cq_.get()); new CallData(&service_, cq_.get());
void* tag; void* tag; // uniquely identifies a request.
bool ok; bool ok;
while (true) { while (true) {
// Block waiting to read the next event from the completion queue. The
// event is uniquely identified by its tag, which in this case is the
// memory address of a CallData instance.
cq_->Next(&tag, &ok); cq_->Next(&tag, &ok);
GPR_ASSERT(ok); GPR_ASSERT(ok);
static_cast<CallData*>(tag)->Proceed(); static_cast<CallData*>(tag)->Proceed();

@ -35,11 +35,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <grpc/grpc.h> #include <grpc++/grpc++.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include "helloworld.grpc.pb.h" #include "helloworld.grpc.pb.h"
using grpc::Channel; using grpc::Channel;
@ -54,17 +51,28 @@ class GreeterClient {
GreeterClient(std::shared_ptr<Channel> channel) GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {} : stub_(Greeter::NewStub(channel)) {}
// Assambles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) { std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request; HelloRequest request;
request.set_name(user); request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply; HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context; ClientContext context;
// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply); Status status = stub_->SayHello(&context, request, &reply);
// Act upon its status.
if (status.ok()) { if (status.ok()) {
return reply.message(); return reply.message();
} else { } else {
return "Rpc failed"; return "RPC failed";
} }
} }
@ -73,6 +81,10 @@ class GreeterClient {
}; };
int main(int argc, char** argv) { int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureCredentials()).
GreeterClient greeter( GreeterClient greeter(
grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials())); grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
std::string user("world"); std::string user("world");

@ -35,11 +35,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <grpc/grpc.h> #include <grpc++/grpc++.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include "helloworld.grpc.pb.h" #include "helloworld.grpc.pb.h"
using grpc::Server; using grpc::Server;
@ -50,6 +47,7 @@ using helloworld::HelloRequest;
using helloworld::HelloReply; using helloworld::HelloReply;
using helloworld::Greeter; using helloworld::Greeter;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service { class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request, Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override { HelloReply* reply) override {
@ -64,10 +62,17 @@ void RunServer() {
GreeterServiceImpl service; GreeterServiceImpl service;
ServerBuilder builder; ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service); builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart()); std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl; std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait(); server->Wait();
} }

@ -65,18 +65,19 @@ class ClientAsyncReaderWriter;
template <class R> template <class R>
class ClientAsyncResponseReader; class ClientAsyncResponseReader;
/// Channels represent a connection to an endpoint. Created by \a CreateChannel.
class Channel GRPC_FINAL : public GrpcLibrary, class Channel GRPC_FINAL : public GrpcLibrary,
public CallHook, public CallHook,
public std::enable_shared_from_this<Channel> { public std::enable_shared_from_this<Channel> {
public: public:
~Channel(); ~Channel();
// Get the current channel state. If the channel is in IDLE and try_to_connect /// Get the current channel state. If the channel is in IDLE and
// is set to true, try to connect. /// \a try_to_connect is set to true, try to connect.
grpc_connectivity_state GetState(bool try_to_connect); grpc_connectivity_state GetState(bool try_to_connect);
// Return the tag on cq when the channel state is changed or deadline expires. /// Return the \a tag on \a cq when the channel state is changed or \a
// GetState needs to called to get the current state. /// deadline expires. \a GetState needs to called to get the current state.
template <typename T> template <typename T>
void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline, void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline,
CompletionQueue* cq, void* tag) { CompletionQueue* cq, void* tag) {
@ -84,8 +85,8 @@ class Channel GRPC_FINAL : public GrpcLibrary,
NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag); NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag);
} }
// Blocking wait for channel state change or deadline expiration. /// Blocking wait for channel state change or \a deadline expiration.
// GetState needs to called to get the current state. /// \a GetState needs to called to get the current state.
template <typename T> template <typename T>
bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) { bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) {
TimePoint<T> deadline_tp(deadline); TimePoint<T> deadline_tp(deadline);

@ -31,6 +31,21 @@
* *
*/ */
/// 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 GRPCXX_CLIENT_CONTEXT_H #ifndef GRPCXX_CLIENT_CONTEXT_H
#define GRPCXX_CLIENT_CONTEXT_H #define GRPCXX_CLIENT_CONTEXT_H
@ -72,6 +87,11 @@ template <class R>
class ClientAsyncResponseReader; class ClientAsyncResponseReader;
class ServerContext; 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 { class PropagationOptions {
public: public:
PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {} PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {}
@ -131,26 +151,66 @@ class ClientContext {
ClientContext(); ClientContext();
~ClientContext(); ~ClientContext();
/// Create a new ClientContext that propagates some or all of its attributes /// 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( static std::unique_ptr<ClientContext> FromServerContext(
const ServerContext& server_context, const ServerContext& server_context,
PropagationOptions options = PropagationOptions()); 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, it must be
/// base64-encoding (see https://tools.ietf.org/html/rfc4648#section-4) and \a
/// meta_key must end in "-bin".
void AddMetadata(const grpc::string& meta_key, void AddMetadata(const grpc::string& meta_key,
const grpc::string& meta_value); 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>& const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerInitialMetadata() { GetServerInitialMetadata() {
GPR_ASSERT(initial_metadata_received_); GPR_ASSERT(initial_metadata_received_);
return recv_initial_metadata_; return recv_initial_metadata_;
} }
/// 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>& const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerTrailingMetadata() { GetServerTrailingMetadata() {
// TODO(yangg) check finished // TODO(yangg) check finished
return trailing_metadata_; return trailing_metadata_;
} }
/// 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> template <typename T>
void set_deadline(const T& deadline) { void set_deadline(const T& deadline) {
TimePoint<T> deadline_tp(deadline); TimePoint<T> deadline_tp(deadline);
@ -158,40 +218,65 @@ class ClientContext {
} }
#ifndef GRPC_CXX0X_NO_CHRONO #ifndef GRPC_CXX0X_NO_CHRONO
/// Return the deadline for the client call.
std::chrono::system_clock::time_point deadline() { std::chrono::system_clock::time_point deadline() {
return Timespec2Timepoint(deadline_); return Timespec2Timepoint(deadline_);
} }
#endif // !GRPC_CXX0X_NO_CHRONO #endif // !GRPC_CXX0X_NO_CHRONO
/// Return a \a gpr_timespec representation of the client call's deadline.
gpr_timespec raw_deadline() { return deadline_; } gpr_timespec raw_deadline() { 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; } void set_authority(const grpc::string& authority) { authority_ = authority; }
// Set credentials for the rpc. /// Return the authentication context for this client call.
///
/// \see grpc::AuthContext.
std::shared_ptr<const AuthContext> auth_context() const;
/// 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://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
void set_credentials(const std::shared_ptr<Credentials>& creds) { void set_credentials(const std::shared_ptr<Credentials>& creds) {
creds_ = creds; creds_ = creds;
} }
/// Return the compression algorithm to be used by the client call.
grpc_compression_algorithm compression_algorithm() const { grpc_compression_algorithm compression_algorithm() const {
return compression_algorithm_; return compression_algorithm_;
} }
/// Set \a algorithm to be the compression algorithm used for the client call.
///
/// \param algorith The compression algorithm used for the client call.
void set_compression_algorithm(grpc_compression_algorithm algorithm); void set_compression_algorithm(grpc_compression_algorithm algorithm);
std::shared_ptr<const AuthContext> auth_context() const; /// Return the peer uri in a string.
///
// Return the peer uri in a string. /// \warning This value is never authenticated or subject to any security
// WARNING: this value is never authenticated or subject to any security /// related code. It must not be used for any authentication related
// related code. It must not be used for any authentication related /// functionality. Instead, use auth_context.
// functionality. Instead, use auth_context. ///
/// \return The call's peer URI.
grpc::string peer() const; grpc::string peer() const;
// Get and set census context /// Get and set census context
void set_census_context(struct census_context* ccp) { census_context_ = ccp; } void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
struct census_context* census_context() const { struct census_context* census_context() const {
return census_context_; return census_context_;
} }
/// Send a best-effort out-of-band cancel. 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.
void TryCancel(); void TryCancel();
private: private:

@ -31,6 +31,8 @@
* *
*/ */
/// A completion queue implements a concurrent producer-consumer queue, with two
/// main methods, \a Next and \a AsyncNext.
#ifndef GRPCXX_COMPLETION_QUEUE_H #ifndef GRPCXX_COMPLETION_QUEUE_H
#define GRPCXX_COMPLETION_QUEUE_H #define GRPCXX_COMPLETION_QUEUE_H
@ -67,53 +69,79 @@ class UnknownMethodHandler;
class Channel; class Channel;
class ClientContext; class ClientContext;
class CompletionQueueTag;
class CompletionQueue; class CompletionQueue;
class RpcMethod; class RpcMethod;
class Server; class Server;
class ServerBuilder; class ServerBuilder;
class ServerContext; class ServerContext;
class CompletionQueueTag { /// A thin wrapper around \a grpc_completion_queue (see / \a
public: /// src/core/surface/completion_queue.h).
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;
};
// grpc_completion_queue wrapper class
class CompletionQueue : public GrpcLibrary { class CompletionQueue : public GrpcLibrary {
public: public:
/// Default constructor. Implicitly creates a \a grpc_completion_queue
/// instance.
CompletionQueue(); CompletionQueue();
/// 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); explicit CompletionQueue(grpc_completion_queue* take);
~CompletionQueue() GRPC_OVERRIDE;
// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT /// Destructor. Destroys the owned wrapped completion queue / instance.
enum NextStatus { SHUTDOWN, GOT_EVENT, TIMEOUT }; ~CompletionQueue() GRPC_OVERRIDE;
// Nonblocking (until deadline) read from queue. /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
// Cannot rely on result of tag or ok if return is TIMEOUT enum NextStatus {
SHUTDOWN, ///< The completion queue has been shutdown.
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 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 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> template <typename T>
NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) {
TimePoint<T> deadline_tp(deadline); TimePoint<T> deadline_tp(deadline);
return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); return AsyncNextInternal(tag, ok, deadline_tp.raw_time());
} }
// Blocking read from queue. /// Read from the queue, blocking until an event is available or the queue is
// Returns false if the queue is ready for destruction, true if event /// shutting down.
///
/// \param tag[out] Updated to point to the read event's tag.
/// \param ok[out] true if read a regular event, false otherwise.
///
/// \return true if read a regular event, false if the queue is shutting down.
bool Next(void** tag, bool* ok) { bool Next(void** tag, bool* ok) {
return (AsyncNextInternal(tag, ok, gpr_inf_future(GPR_CLOCK_REALTIME)) != return (AsyncNextInternal(tag, ok, gpr_inf_future(GPR_CLOCK_REALTIME)) !=
SHUTDOWN); SHUTDOWN);
} }
// Shutdown has to be called, and the CompletionQueue can only be /// Request the shutdown of the queue.
// destructed when false is returned from Next(). ///
/// \warning This method must be called at some point. Once invoked, \a Next
/// will start to return false and \a AsyncNext will return \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.
void Shutdown(); 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_; } grpc_completion_queue* cq() { return cq_; }
private: private:
@ -150,16 +178,29 @@ class CompletionQueue : public GrpcLibrary {
NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline);
// Wraps grpc_completion_queue_pluck. /// Wraps \a grpc_completion_queue_pluck.
// Cannot be mixed with calls to Next(). /// \warning Must not be mixed with calls to \a Next.
bool Pluck(CompletionQueueTag* tag); bool Pluck(CompletionQueueTag* tag);
// Does a single polling pluck on tag /// Performs a single polling pluck on \a tag.
void TryPluck(CompletionQueueTag* tag); void TryPluck(CompletionQueueTag* tag);
grpc_completion_queue* cq_; // owned grpc_completion_queue* cq_; // owned
}; };
/// 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;
};
/// A specific type of completion queue used by the processing of notifications
/// by servers. Instantiated by \a ServerBuilder.
class ServerCompletionQueue : public CompletionQueue { class ServerCompletionQueue : public CompletionQueue {
private: private:
friend class ServerBuilder; friend class ServerBuilder;

@ -42,13 +42,24 @@
namespace grpc { namespace grpc {
// If creds does not hold an object or is invalid, a lame channel is returned. /// 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 is returned.
/// \param args Options for channel creation.
std::shared_ptr<Channel> CreateChannel( std::shared_ptr<Channel> CreateChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds); const grpc::string& target, const std::shared_ptr<Credentials>& creds);
// For advanced use and testing ONLY. Override default channel arguments only /// Create a new \em custom \a Channel pointing to \a target
// if necessary. ///
// If creds does not hold an object or is invalid, a lame channel is returned. /// \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 is returned.
/// \param args Options for channel creation.
std::shared_ptr<Channel> CreateCustomChannel( std::shared_ptr<Channel> CreateCustomChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds, const grpc::string& target, const std::shared_ptr<Credentials>& creds,
const ChannelArguments& args); const ChannelArguments& args);

@ -0,0 +1,64 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/// \mainpage gRPC C++ API
///
/// The gRPC C++ API mainly consists of the following classes:
/// - grpc::Channel, which represents the connection to an endpoint. See [the
/// gRPC Concepts page](http://www.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.
///
/// Refer to the
/// [examples](https://github.com/grpc/grpc/blob/master/examples/cpp)
/// for code putting these pieces into play.
#ifndef GRPCXX_GRPCXX_H
#define GRPCXX_GRPCXX_H
#include <grpc/grpc.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/create_channel.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#endif // GRPCXX_GRPCXX_H

@ -37,6 +37,7 @@
#include <iterator> #include <iterator>
#include <vector> #include <vector>
#include <grpc/grpc_security.h>
#include <grpc++/support/config.h> #include <grpc++/support/config.h>
#include <grpc++/support/string_ref.h> #include <grpc++/support/string_ref.h>
@ -73,26 +74,41 @@ class AuthPropertyIterator
const char* name_; 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 { class AuthContext {
public: public:
virtual ~AuthContext() {} virtual ~AuthContext() {}
// Returns true if the peer is authenticated. /// Returns true if the peer is authenticated.
virtual bool IsPeerAuthenticated() const = 0; virtual bool IsPeerAuthenticated() const = 0;
// A peer identity, in general is one or more properties (in which case they /// A peer identity.
// have the same name). ///
/// 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 std::vector<grpc::string_ref> GetPeerIdentity() const = 0;
virtual grpc::string GetPeerIdentityPropertyName() const = 0; virtual grpc::string GetPeerIdentityPropertyName() const = 0;
// Returns all the property values with the given name. /// Returns all the property values with the given name.
virtual std::vector<grpc::string_ref> FindPropertyValues( virtual std::vector<grpc::string_ref> FindPropertyValues(
const grpc::string& name) const = 0; const grpc::string& name) const = 0;
// Iteration over all the properties. /// Iteration over all the properties.
virtual AuthPropertyIterator begin() const = 0; virtual AuthPropertyIterator begin() const = 0;
virtual AuthPropertyIterator end() const = 0; virtual AuthPropertyIterator end() const = 0;
static string transport_security_type_property_name() {
return GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME;
}
static string ssl_transport_security_type() {
return GRPC_SSL_TRANSPORT_SECURITY_TYPE;
}
static string x509_cn_property_name() { return GRPC_X509_CN_PROPERTY_NAME; }
static string x509_san_property_name() { return GRPC_X509_SAN_PROPERTY_NAME; }
// Mutation functions: should only be used by an AuthMetadataProcessor. // Mutation functions: should only be used by an AuthMetadataProcessor.
virtual void AddProperty(const grpc::string& key, virtual void AddProperty(const grpc::string& key,
const grpc::string_ref& value) = 0; const grpc::string_ref& value) = 0;

@ -44,9 +44,17 @@ class ChannelArguments;
class Channel; class Channel;
class SecureCredentials; class SecureCredentials;
/// 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://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
class Credentials : public GrpcLibrary { class Credentials : public GrpcLibrary {
public: public:
~Credentials() GRPC_OVERRIDE; ~Credentials() GRPC_OVERRIDE;
/// Apply this instance's credentials to \a call.
virtual bool ApplyToCall(grpc_call* call) = 0; virtual bool ApplyToCall(grpc_call* call) = 0;
protected: protected:
@ -65,68 +73,96 @@ class Credentials : public GrpcLibrary {
const grpc::string& target, const ChannelArguments& args) = 0; const grpc::string& target, const ChannelArguments& args) = 0;
}; };
// Options used to build SslCredentials /// Options used to build SslCredentials.
// pem_roots_cert is the buffer containing the PEM encoding of the server root
// certificates. If this parameter is empty, the default roots will be used.
// pem_private_key is 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.
// pem_cert_chain is 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.
struct SslCredentialsOptions { 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; 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; 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; grpc::string pem_cert_chain;
}; };
// Factories for building different types of Credentials // Factories for building different types of Credentials The functions may
// The functions may return empty shared_ptr when credentials cannot be created. // return empty shared_ptr when credentials cannot be created. If a
// If a Credentials pointer is returned, it can still be invalid when used to // Credentials pointer is returned, it can still be invalid when used to create
// create a channel. A lame channel will be created then and all rpcs will // a channel. A lame channel will be created then and all rpcs will fail on it.
// fail on it.
/// Builds credentials with reasonable defaults.
// 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<Credentials> GoogleDefaultCredentials(); std::shared_ptr<Credentials> GoogleDefaultCredentials();
// Builds SSL Credentials given SSL specific options /// Builds SSL Credentials given SSL specific options
std::shared_ptr<Credentials> SslCredentials( std::shared_ptr<Credentials> SslCredentials(
const SslCredentialsOptions& options); const SslCredentialsOptions& options);
// Builds credentials for use when running in GCE /// 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<Credentials> GoogleComputeEngineCredentials(); std::shared_ptr<Credentials> GoogleComputeEngineCredentials();
// Builds Service Account JWT Access credentials. /// Builds Service Account JWT Access credentials.
// json_key is the JSON key string containing the client's private key. /// 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 /// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
// (JWT) created with this credentials. It should not exceed /// (JWT) created with this credentials. It should not exceed
// grpc_max_auth_token_lifetime or will be cropped to this value. /// grpc_max_auth_token_lifetime or will be cropped to this value.
std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials( std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds); const grpc::string& json_key, long token_lifetime_seconds);
// Builds refresh token credentials. /// Builds refresh token credentials.
// json_refresh_token is the JSON string containing the refresh token along /// json_refresh_token is the JSON string containing the refresh token along
// with a client_id and client_secret. /// 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<Credentials> GoogleRefreshTokenCredentials( std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
const grpc::string& json_refresh_token); const grpc::string& json_refresh_token);
// Builds access token credentials. /// Builds access token credentials.
// access_token is an oauth2 access token that was fetched using an out of band /// access_token is an oauth2 access token that was fetched using an out of band
// mechanism. /// 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<Credentials> AccessTokenCredentials( std::shared_ptr<Credentials> AccessTokenCredentials(
const grpc::string& access_token); const grpc::string& access_token);
// Builds IAM credentials. /// 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<Credentials> GoogleIAMCredentials( std::shared_ptr<Credentials> GoogleIAMCredentials(
const grpc::string& authorization_token, const grpc::string& authorization_token,
const grpc::string& authority_selector); const grpc::string& authority_selector);
// Combines two credentials objects into a composite credentials /// Combines two credentials objects into a composite credentials
std::shared_ptr<Credentials> CompositeCredentials( std::shared_ptr<Credentials> CompositeCredentials(
const std::shared_ptr<Credentials>& creds1, const std::shared_ptr<Credentials>& creds1,
const std::shared_ptr<Credentials>& creds2); const std::shared_ptr<Credentials>& creds2);
// Credentials for an unencrypted, unauthenticated channel /// Credentials for an unencrypted, unauthenticated channel
std::shared_ptr<Credentials> InsecureCredentials(); std::shared_ptr<Credentials> InsecureCredentials();
} // namespace grpc } // namespace grpc

@ -45,7 +45,7 @@ struct grpc_server;
namespace grpc { namespace grpc {
class Server; class Server;
// grpc_server_credentials wrapper class. // Wrapper around \a grpc_server_credentials, a way to authenticate a server.
class ServerCredentials { class ServerCredentials {
public: public:
virtual ~ServerCredentials(); virtual ~ServerCredentials();
@ -58,11 +58,16 @@ class ServerCredentials {
private: private:
friend class ::grpc::Server; 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, virtual int AddPortToServer(const grpc::string& addr,
grpc_server* server) = 0; grpc_server* server) = 0;
}; };
// Options to create ServerCredentials with SSL /// Options to create ServerCredentials with SSL
struct SslServerCredentialsOptions { struct SslServerCredentialsOptions {
SslServerCredentialsOptions() : force_client_auth(false) {} SslServerCredentialsOptions() : force_client_auth(false) {}
@ -75,10 +80,11 @@ struct SslServerCredentialsOptions {
bool force_client_auth; bool force_client_auth;
}; };
// Builds SSL ServerCredentials given SSL specific options /// Builds SSL ServerCredentials given SSL specific options
std::shared_ptr<ServerCredentials> SslServerCredentials( std::shared_ptr<ServerCredentials> SslServerCredentials(
const SslServerCredentialsOptions& options); const SslServerCredentialsOptions& options);
/// Builds insecure server credentials.
std::shared_ptr<ServerCredentials> InsecureServerCredentials(); std::shared_ptr<ServerCredentials> InsecureServerCredentials();
} // namespace grpc } // namespace grpc

@ -57,24 +57,30 @@ class RpcServiceMethod;
class ServerAsyncStreamingInterface; class ServerAsyncStreamingInterface;
class ThreadPoolInterface; class ThreadPoolInterface;
// Currently it only supports handling rpcs in a single thread. /// Models a gRPC server.
///
/// Servers are configured and started via \a grpc::ServerBuilder.
class Server GRPC_FINAL : public GrpcLibrary, private CallHook { class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
public: public:
~Server(); ~Server();
// Shutdown the server, block until all rpc processing finishes. /// Shutdown the server, blocking until all rpc processing finishes.
// Forcefully terminate pending calls after deadline expires. /// Forcefully terminate pending calls after \a deadline expires.
///
/// \param deadline How long to wait until pending rpcs are forcefully
/// terminated.
template <class T> template <class T>
void Shutdown(const T& deadline) { void Shutdown(const T& deadline) {
ShutdownInternal(TimePoint<T>(deadline).raw_time()); ShutdownInternal(TimePoint<T>(deadline).raw_time());
} }
// Shutdown the server, waiting for all rpc processing to finish. /// Shutdown the server, waiting for all rpc processing to finish.
void Shutdown() { ShutdownInternal(gpr_inf_future(GPR_CLOCK_MONOTONIC)); } void Shutdown() { ShutdownInternal(gpr_inf_future(GPR_CLOCK_MONOTONIC)); }
// Block waiting for all work to complete (the server must either /// Block waiting for all work to complete.
// be shutting down or some other thread must call Shutdown for this ///
// function to ever return) /// \warning The server must be either shutting down or some other thread must
/// call \a Shutdown for this function to ever return.
void Wait(); void Wait();
private: private:
@ -86,22 +92,57 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
class AsyncRequest; class AsyncRequest;
class ShutdownRequest; class ShutdownRequest;
// ServerBuilder use only /// Server constructors. To be used by \a ServerBuilder only.
///
/// \param thread_pool The threadpool instance to use for call processing.
/// \param thread_pool_owned Does the server own the \a thread_pool instance?
/// \param max_message_size Maximum message length that the channel can
/// receive.
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned, Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
int max_message_size); int max_message_size);
// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance. /// 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, RpcService* service); bool RegisterService(const grpc::string* host, RpcService* service);
/// Register an asynchronous service. This call does not take ownership of the
/// service. The service must exist for the lifetime of the Server instance.
bool RegisterAsyncService(const grpc::string* host, bool RegisterAsyncService(const grpc::string* host,
AsynchronousService* service); AsynchronousService* service);
/// 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); void RegisterAsyncGenericService(AsyncGenericService* service);
// Add a listening port. Can be called multiple times.
/// 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.
int AddListeningPort(const grpc::string& addr, ServerCredentials* creds); int AddListeningPort(const grpc::string& addr, ServerCredentials* creds);
// Start the server.
/// 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.
///
/// \return true on a successful shutdown.
bool Start(ServerCompletionQueue** cqs, size_t num_cqs); bool Start(ServerCompletionQueue** cqs, size_t num_cqs);
void HandleQueueClosed(); void HandleQueueClosed();
/// Process one or more incoming calls.
void RunRpc(); void RunRpc();
/// Schedule \a RunRpc to run in the threadpool.
void ScheduleCallback(); void ScheduleCallback();
void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) GRPC_OVERRIDE; void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) GRPC_OVERRIDE;

@ -51,57 +51,68 @@ class ServerCredentials;
class SynchronousService; class SynchronousService;
class ThreadPoolInterface; class ThreadPoolInterface;
/// A builder class for the creation and startup of \a grpc::Server instances.
class ServerBuilder { class ServerBuilder {
public: public:
ServerBuilder(); ServerBuilder();
// Register a service. This call does not take ownership of the service. /// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance returned by /// The service must exist for the lifetime of the \a Server instance returned
// BuildAndStart(). /// by \a BuildAndStart().
// Matches requests with any :authority /// Matches requests with any :authority
void RegisterService(SynchronousService* service); void RegisterService(SynchronousService* service);
// Register an asynchronous service. /// Register an asynchronous service.
// This call does not take ownership of the service or completion queue. /// This call does not take ownership of the service or completion queue.
// The service and completion queuemust exist for the lifetime of the Server /// The service and completion queuemust exist for the lifetime of the \a
// instance returned by BuildAndStart(). /// Server instance returned by \a BuildAndStart().
// Matches requests with any :authority /// Matches requests with any :authority
void RegisterAsyncService(AsynchronousService* service); void RegisterAsyncService(AsynchronousService* service);
// Register a generic service. /// Register a generic service.
// Matches requests with any :authority /// Matches requests with any :authority
void RegisterAsyncGenericService(AsyncGenericService* service); void RegisterAsyncGenericService(AsyncGenericService* service);
// Register a service. This call does not take ownership of the service. /// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance returned by /// The service must exist for the lifetime of the \a Server instance returned
// BuildAndStart(). /// by BuildAndStart().
// Only matches requests with :authority \a host /// Only matches requests with :authority \a host
void RegisterService(const grpc::string& host, SynchronousService* service); void RegisterService(const grpc::string& host, SynchronousService* service);
// Register an asynchronous service. /// Register an asynchronous service.
// This call does not take ownership of the service or completion queue. /// This call does not take ownership of the service or completion queue.
// The service and completion queuemust exist for the lifetime of the Server /// The service and completion queuemust exist for the lifetime of the \a
// instance returned by BuildAndStart(). /// Server instance returned by \a BuildAndStart().
// Only matches requests with :authority \a host /// Only matches requests with :authority equal to \a host
void RegisterAsyncService(const grpc::string& host, void RegisterAsyncService(const grpc::string& host,
AsynchronousService* service); AsynchronousService* service);
// Set max message size in bytes. /// Set max message size in bytes.
void SetMaxMessageSize(int max_message_size) { void SetMaxMessageSize(int max_message_size) {
max_message_size_ = max_message_size; max_message_size_ = max_message_size;
} }
// Add a listening port. Can be called multiple times. /// 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.
/// \param selected_port[out] Upon success, updated to contain the port
/// number. \a nullptr otherwise.
///
// TODO(dgq): the "port" part seems to be a misnomer.
void AddListeningPort(const grpc::string& addr, void AddListeningPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds, std::shared_ptr<ServerCredentials> creds,
int* selected_port = nullptr); int* selected_port = nullptr);
// Add a completion queue for handling asynchronous services /// Add a completion queue for handling asynchronous services
// Caller is required to keep this completion queue live until /// Caller is required to keep this completion queue live until
// the server is destroyed. /// the server is destroyed.
std::unique_ptr<ServerCompletionQueue> AddCompletionQueue(); std::unique_ptr<ServerCompletionQueue> AddCompletionQueue();
// Return a running server which is ready for processing rpcs. /// Return a running server which is ready for processing calls.
std::unique_ptr<Server> BuildAndStart(); std::unique_ptr<Server> BuildAndStart();
private: private:

@ -45,32 +45,48 @@
namespace grpc { namespace grpc {
// Async interfaces /// Common interface for all client side asynchronous streaming.
// Common interface for all client side streaming.
class ClientAsyncStreamingInterface { class ClientAsyncStreamingInterface {
public: public:
virtual ~ClientAsyncStreamingInterface() {} virtual ~ClientAsyncStreamingInterface() {}
/// Request notification of the reading of the initial metadata. Completion
/// will be notified by \a tag on the associated completion queue.
///
/// \param[in] tag Tag identifying this request.
virtual void ReadInitialMetadata(void* tag) = 0; virtual void ReadInitialMetadata(void* tag) = 0;
/// Request notification completion.
///
/// \param[out] status To be updated with the operation status.
/// \param[in] tag Tag identifying this request.
virtual void Finish(Status* status, void* tag) = 0; virtual void Finish(Status* status, void* tag) = 0;
}; };
// An interface that yields a sequence of R messages. /// An interface that yields a sequence of messages of type \a R.
template <class R> template <class R>
class AsyncReaderInterface { class AsyncReaderInterface {
public: public:
virtual ~AsyncReaderInterface() {} virtual ~AsyncReaderInterface() {}
/// Read a message of type \a R into \a msg. Completion will be notified by \a
/// tag on the associated completion queue.
///
/// \param[out] msg Where to eventually store the read message.
/// \param[in] tag The tag identifying the operation.
virtual void Read(R* msg, void* tag) = 0; virtual void Read(R* msg, void* tag) = 0;
}; };
// An interface that can be fed a sequence of W messages. /// An interface that can be fed a sequence of messages of type \a W.
template <class W> template <class W>
class AsyncWriterInterface { class AsyncWriterInterface {
public: public:
virtual ~AsyncWriterInterface() {} virtual ~AsyncWriterInterface() {}
/// Request the writing of \a msg with identifying tag \a tag.
///
/// \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; virtual void Write(const W& msg, void* tag) = 0;
}; };
@ -81,7 +97,7 @@ class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
template <class R> template <class R>
class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> { class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
public: public:
// Create a stream and write the first request out. /// Create a stream and write the first request out.
template <class W> template <class W>
ClientAsyncReader(Channel* channel, CompletionQueue* cq, ClientAsyncReader(Channel* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context, const RpcMethod& method, ClientContext* context,
@ -131,10 +147,14 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_; CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
}; };
/// Common interface for client side asynchronous writing.
template <class W> template <class W>
class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface, class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> { public AsyncWriterInterface<W> {
public: public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0; virtual void WritesDone(void* tag) = 0;
}; };
@ -194,12 +214,15 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
CallOpClientRecvStatus> finish_ops_; CallOpClientRecvStatus> finish_ops_;
}; };
// Client-side interface for bi-directional streaming. /// Client-side interface for asynchronous bi-directional streaming.
template <class W, class R> template <class W, class R>
class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface, class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>, public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> { public AsyncReaderInterface<R> {
public: public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0; virtual void WritesDone(void* tag) = 0;
}; };
@ -373,7 +396,7 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_; CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
}; };
// Server-side interface for bi-directional streaming. /// Server-side interface for asynchronous bi-directional streaming.
template <class W, class R> template <class W, class R>
class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface, class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W>, public AsyncWriterInterface<W>,

@ -46,21 +46,24 @@
namespace grpc { namespace grpc {
/// A sequence of bytes.
class ByteBuffer GRPC_FINAL { class ByteBuffer GRPC_FINAL {
public: public:
/// Constuct an empty buffer.
ByteBuffer() : buffer_(nullptr) {} ByteBuffer() : buffer_(nullptr) {}
/// Construct buffer from \a slices, of which there are \a nslices.
ByteBuffer(const Slice* slices, size_t nslices); ByteBuffer(const Slice* slices, size_t nslices);
~ByteBuffer() { ~ByteBuffer();
if (buffer_) {
grpc_byte_buffer_destroy(buffer_);
}
}
/// Dump (read) the buffer contents into \a slices.
void Dump(std::vector<Slice>* slices) const; void Dump(std::vector<Slice>* slices) const;
/// Remove all data.
void Clear(); void Clear();
/// Buffer size in bytes.
size_t Length() const; size_t Length() const;
private: private:
@ -78,6 +81,7 @@ class ByteBuffer GRPC_FINAL {
buffer_ = buf; buffer_ = buf;
} }
// For \a SerializationTraits's usage.
grpc_byte_buffer* buffer() const { return buffer_; } grpc_byte_buffer* buffer() const { return buffer_; }
grpc_byte_buffer* buffer_; grpc_byte_buffer* buffer_;

@ -46,9 +46,9 @@ namespace testing {
class ChannelArgumentsTest; class ChannelArgumentsTest;
} // namespace testing } // namespace testing
// Options for channel creation. The user can use generic setters to pass /// 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, /// key value pairs down to c channel creation code. For grpc related options,
// concrete setters are provided. /// concrete setters are provided.
class ChannelArguments { class ChannelArguments {
public: public:
ChannelArguments() {} ChannelArguments() {}
@ -62,21 +62,26 @@ class ChannelArguments {
void Swap(ChannelArguments& other); void Swap(ChannelArguments& other);
// grpc specific channel argument setters /// Populates this instance with the arguments from \a channel_args. Does not
// Set target name override for SSL host name checking. /// 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.
void SetSslTargetNameOverride(const grpc::string& name); void SetSslTargetNameOverride(const grpc::string& name);
// TODO(yangg) add flow control options // TODO(yangg) add flow control options
/// Set the compression algorithm for the channel.
// Set the compression algorithm for the channel.
void SetCompressionAlgorithm(grpc_compression_algorithm algorithm); void SetCompressionAlgorithm(grpc_compression_algorithm algorithm);
// Generic channel argument setters. Only for advanced use cases. // 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); void SetInt(const grpc::string& key, int value);
/// Set a textual argument \a value under \a key.
void SetString(const grpc::string& key, const grpc::string& value); void SetString(const grpc::string& key, const grpc::string& value);
// Populates given channel_args with args_, does not take ownership.
void SetChannelArgs(grpc_channel_args* channel_args) const;
private: private:
friend class SecureCredentials; friend class SecureCredentials;
friend class testing::ChannelArgumentsTest; friend class testing::ChannelArgumentsTest;

@ -39,28 +39,42 @@
namespace grpc { 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 GRPC_FINAL { class Slice GRPC_FINAL {
public: public:
// construct empty slice /// Construct an empty slice.
Slice(); Slice();
// destructor - drops one ref // Destructor - drops one reference.
~Slice(); ~Slice();
// construct slice from grpc slice, adding a ref
enum AddRef { ADD_REF }; enum AddRef { ADD_REF };
/// Construct a slice from \a slice, adding a reference.
Slice(gpr_slice slice, AddRef); Slice(gpr_slice slice, AddRef);
// construct slice from grpc slice, stealing a ref
enum StealRef { STEAL_REF }; enum StealRef { STEAL_REF };
/// Construct a slice from \a slice, stealing a reference.
Slice(gpr_slice slice, StealRef); Slice(gpr_slice slice, StealRef);
// copy constructor - adds a ref
/// Copy constructor, adds a reference.
Slice(const Slice& other); Slice(const Slice& other);
// assignment - ref count is unchanged
/// Assignment, reference count is unchanged.
Slice& operator=(Slice other) { Slice& operator=(Slice other) {
std::swap(slice_, other.slice_); std::swap(slice_, other.slice_);
return *this; return *this;
} }
/// Byte size.
size_t size() const { return GPR_SLICE_LENGTH(slice_); } size_t size() const { return GPR_SLICE_LENGTH(slice_); }
/// Raw pointer to the beginning (first element) of the slice.
const gpr_uint8* begin() const { return GPR_SLICE_START_PTR(slice_); } const gpr_uint8* begin() const { return GPR_SLICE_START_PTR(slice_); }
/// Raw pointer to the end (one byte \em past the last element) of the slice.
const gpr_uint8* end() const { return GPR_SLICE_END_PTR(slice_); } const gpr_uint8* end() const { return GPR_SLICE_END_PTR(slice_); }
private: private:

@ -39,19 +39,31 @@
namespace grpc { 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 { class Status {
public: public:
/// Construct an OK instance.
Status() : code_(StatusCode::OK) {} Status() : code_(StatusCode::OK) {}
/// Construct an instance with associated \a code and \a details (also
// referred to as "error_message").
Status(StatusCode code, const grpc::string& details) Status(StatusCode code, const grpc::string& details)
: code_(code), details_(details) {} : code_(code), details_(details) {}
// Pre-defined special status objects. // Pre-defined special status objects.
/// An OK pre-defined instance.
static const Status& OK; static const Status& OK;
/// A CANCELLED pre-defined instance.
static const Status& CANCELLED; static const Status& CANCELLED;
/// Return the instance's error code.
StatusCode error_code() const { return code_; } StatusCode error_code() const { return code_; }
/// Return the instance's error message.
grpc::string error_message() const { return details_; } grpc::string error_message() const { return details_; }
/// Is the status OK?
bool ok() const { return code_ == StatusCode::OK; } bool ok() const { return code_ == StatusCode::OK; }
private: private:

@ -37,120 +37,113 @@
namespace grpc { namespace grpc {
enum StatusCode { enum StatusCode {
/* Not an error; returned on success */ /// Not an error; returned on success.
OK = 0, OK = 0,
/* The operation was cancelled (typically by the caller). */ /// The operation was cancelled (typically by the caller).
CANCELLED = 1, CANCELLED = 1,
/* Unknown error. An example of where this error may be returned is /// Unknown error. An example of where this error may be returned is if a
if a Status value received from another address space belongs to /// Status value received from another address space belongs to an error-space
an error-space that is not known in this address space. Also /// that is not known in this address space. Also errors raised by APIs that
errors raised by APIs that do not return enough error information /// do not return enough error information may be converted to this error.
may be converted to this error. */
UNKNOWN = 2, UNKNOWN = 2,
/* Client specified an invalid argument. Note that this differs /// Client specified an invalid argument. Note that this differs from
from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments /// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
that are problematic regardless of the state of the system /// problematic regardless of the state of the system (e.g., a malformed file
(e.g., a malformed file name). */ /// name).
INVALID_ARGUMENT = 3, INVALID_ARGUMENT = 3,
/* Deadline expired before operation could complete. For operations /// Deadline expired before operation could complete. For operations that
that change the state of the system, this error may be returned /// change the state of the system, this error may be returned even if the
even if the operation has completed successfully. For example, a /// operation has completed successfully. For example, a successful response
successful response from a server could have been delayed long /// from a server could have been delayed long enough for the deadline to
enough for the deadline to expire. */ /// expire.
DEADLINE_EXCEEDED = 4, DEADLINE_EXCEEDED = 4,
/* Some requested entity (e.g., file or directory) was not found. */ /// Some requested entity (e.g., file or directory) was not found.
NOT_FOUND = 5, NOT_FOUND = 5,
/* Some entity that we attempted to create (e.g., file or directory) /// Some entity that we attempted to create (e.g., file or directory) already
already exists. */ /// exists.
ALREADY_EXISTS = 6, ALREADY_EXISTS = 6,
/* The caller does not have permission to execute the specified /// The caller does not have permission to execute the specified operation.
operation. PERMISSION_DENIED must not be used for rejections /// PERMISSION_DENIED must not be used for rejections caused by exhausting
caused by exhausting some resource (use RESOURCE_EXHAUSTED /// some resource (use RESOURCE_EXHAUSTED instead for those errors).
instead for those errors). PERMISSION_DENIED must not be /// PERMISSION_DENIED must not be used if the caller can not be identified
used if the caller can not be identified (use UNAUTHENTICATED /// (use UNAUTHENTICATED instead for those errors).
instead for those errors). */
PERMISSION_DENIED = 7, PERMISSION_DENIED = 7,
/* The request does not have valid authentication credentials for the /// The request does not have valid authentication credentials for the
operation. */ /// operation.
UNAUTHENTICATED = 16, UNAUTHENTICATED = 16,
/* Some resource has been exhausted, perhaps a per-user quota, or /// Some resource has been exhausted, perhaps a per-user quota, or perhaps the
perhaps the entire file system is out of space. */ /// entire file system is out of space.
RESOURCE_EXHAUSTED = 8, RESOURCE_EXHAUSTED = 8,
/* Operation was rejected because the system is not in a state /// Operation was rejected because the system is not in a state required for
required for the operation's execution. For example, directory /// the operation's execution. For example, directory to be deleted may be
to be deleted may be non-empty, an rmdir operation is applied to /// non-empty, an rmdir operation is applied to a non-directory, etc.
a non-directory, etc. ///
/// A litmus test that may help a service implementor in deciding
A litmus test that may help a service implementor in deciding /// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: /// (a) Use UNAVAILABLE if the client can retry just the failing call.
(a) Use UNAVAILABLE if the client can retry just the failing call. /// (b) Use ABORTED if the client should retry at a higher-level
(b) Use ABORTED if the client should retry at a higher-level /// (e.g., restarting a read-modify-write sequence).
(e.g., restarting a read-modify-write sequence). /// (c) Use FAILED_PRECONDITION if the client should not retry until
(c) Use FAILED_PRECONDITION if the client should not retry until /// the system state has been explicitly fixed. E.g., if an "rmdir"
the system state has been explicitly fixed. E.g., if an "rmdir" /// fails because the directory is non-empty, FAILED_PRECONDITION
fails because the directory is non-empty, FAILED_PRECONDITION /// should be returned since the client should not retry unless
should be returned since the client should not retry unless /// they have first fixed up the directory by deleting files from it.
they have first fixed up the directory by deleting files from it. /// (d) Use FAILED_PRECONDITION if the client performs conditional
(d) Use FAILED_PRECONDITION if the client performs conditional /// REST Get/Update/Delete on a resource and the resource on the
REST Get/Update/Delete on a resource and the resource on the /// server does not match the condition. E.g., conflicting
server does not match the condition. E.g., conflicting /// read-modify-write on the same resource.
read-modify-write on the same resource. */
FAILED_PRECONDITION = 9, FAILED_PRECONDITION = 9,
/* The operation was aborted, typically due to a concurrency issue /// The operation was aborted, typically due to a concurrency issue like
like sequencer check failures, transaction aborts, etc. /// sequencer check failures, transaction aborts, etc.
///
See litmus test above for deciding between FAILED_PRECONDITION, /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
ABORTED, and UNAVAILABLE. */ /// and UNAVAILABLE.
ABORTED = 10, ABORTED = 10,
/* Operation was attempted past the valid range. E.g., seeking or /// Operation was attempted past the valid range. E.g., seeking or reading
reading past end of file. /// past end of file.
///
Unlike INVALID_ARGUMENT, this error indicates a problem that may /// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
be fixed if the system state changes. For example, a 32-bit file /// if the system state changes. For example, a 32-bit file system will
system will generate INVALID_ARGUMENT if asked to read at an /// generate INVALID_ARGUMENT if asked to read at an offset that is not in the
offset that is not in the range [0,2^32-1], but it will generate /// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
OUT_OF_RANGE if asked to read from an offset past the current /// an offset past the current file size.
file size. ///
/// There is a fair bit of overlap between FAILED_PRECONDITION and
There is a fair bit of overlap between FAILED_PRECONDITION and /// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific /// when it applies so that callers who are iterating through a space can
error) when it applies so that callers who are iterating through /// easily look for an OUT_OF_RANGE error to detect when they are done.
a space can easily look for an OUT_OF_RANGE error to detect when
they are done. */
OUT_OF_RANGE = 11, OUT_OF_RANGE = 11,
/* Operation is not implemented or not supported/enabled in this service. */ /// Operation is not implemented or not supported/enabled in this service.
UNIMPLEMENTED = 12, UNIMPLEMENTED = 12,
/* Internal errors. Means some invariants expected by underlying /// Internal errors. Means some invariants expected by underlying System has
system has been broken. If you see one of these errors, /// been broken. If you see one of these errors, Something is very broken.
something is very broken. */
INTERNAL = 13, INTERNAL = 13,
/* The service is currently unavailable. This is a most likely a /// The service is currently unavailable. This is a most likely a transient
transient condition and may be corrected by retrying with /// condition and may be corrected by retrying with a backoff.
a backoff. ///
/// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
See litmus test above for deciding between FAILED_PRECONDITION, /// and UNAVAILABLE.
ABORTED, and UNAVAILABLE. */
UNAVAILABLE = 14, UNAVAILABLE = 14,
/* Unrecoverable data loss or corruption. */ /// Unrecoverable data loss or corruption.
DATA_LOSS = 15, DATA_LOSS = 15,
/* Force users to include a default branch: */ /// Force users to include a default branch:
DO_NOT_USE = -1 DO_NOT_USE = -1
}; };

@ -41,11 +41,14 @@
namespace grpc { namespace grpc {
// This class is a non owning reference to a string. /// 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 /// It should be a strict subset of the upcoming std::string_ref.
// The constexpr is dropped or replaced with const for legacy compiler ///
// compatibility. /// \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 { class string_ref {
public: public:
// types // types

@ -45,60 +45,78 @@
namespace grpc { namespace grpc {
// Common interface for all client side streaming. /// Common interface for all synchronous client side streaming.
class ClientStreamingInterface { class ClientStreamingInterface {
public: public:
virtual ~ClientStreamingInterface() {} virtual ~ClientStreamingInterface() {}
// Wait until the stream finishes, and return the final status. When the /// Wait until the stream finishes, and return the final status. When the
// client side declares it has no more message to send, either implicitly or /// client side declares it has no more message to send, either implicitly or
// by calling WritesDone, it needs to make sure there is no more message to /// by calling \a WritesDone(), it needs to make sure there is no more message
// be received from the server, either implicitly or by getting a false from /// to be received from the server, either implicitly or by getting a false
// a Read(). /// from a \a Read().
// This function will return either: ///
// - when all incoming messages have been read and the server has returned /// This function will return either:
// status /// - when all incoming messages have been read and the server has returned
// - OR when the server has returned a non-OK status /// status.
/// - OR when the server has returned a non-OK status.
virtual Status Finish() = 0; virtual Status Finish() = 0;
}; };
// An interface that yields a sequence of R messages. /// An interface that yields a sequence of messages of type \a R.
template <class R> template <class R>
class ReaderInterface { class ReaderInterface {
public: public:
virtual ~ReaderInterface() {} virtual ~ReaderInterface() {}
// Blocking read a message and parse to msg. Returns true on success. /// Blocking read a message and parse to \a msg. Returns \a true on success.
// The method returns false when there will be no more incoming messages, ///
// either because the other side has called WritesDone or the stream has /// \param[out] msg The read message.
// failed (or been cancelled). ///
/// \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; virtual bool Read(R* msg) = 0;
}; };
// An interface that can be fed a sequence of W messages. /// An interface that can be fed a sequence of messages of type \a W.
template <class W> template <class W>
class WriterInterface { class WriterInterface {
public: public:
virtual ~WriterInterface() {} virtual ~WriterInterface() {}
// Blocking write msg to the stream. Returns true on success. /// Blocking write \a msg to the stream with options.
// Returns false when the stream has been closed. ///
/// \param msg The message to be written to the stream.
/// \param options Options affecting the write operation.
///
/// \return \a true on success, \a false when the stream has been closed.
virtual bool Write(const W& msg, const WriteOptions& options) = 0; virtual bool Write(const W& msg, const WriteOptions& options) = 0;
/// Blocking write \a msg to the stream with default options.
///
/// \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()); } inline bool Write(const W& msg) { return Write(msg, WriteOptions()); }
}; };
/// Client-side interface for streaming reads of message of type \a R.
template <class R> template <class R>
class ClientReaderInterface : public ClientStreamingInterface, class ClientReaderInterface : public ClientStreamingInterface,
public ReaderInterface<R> { public ReaderInterface<R> {
public: public:
/// Blocking 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; virtual void WaitForInitialMetadata() = 0;
}; };
template <class R> template <class R>
class ClientReader GRPC_FINAL : public ClientReaderInterface<R> { class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
public: public:
// Blocking create a stream and write the first request out. /// Blocking create a stream and write the first request out.
template <class W> template <class W>
ClientReader(Channel* channel, const RpcMethod& method, ClientReader(Channel* channel, const RpcMethod& method,
ClientContext* context, const W& request) ClientContext* context, const W& request)
@ -113,17 +131,13 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
cq_.Pluck(&ops); cq_.Pluck(&ops);
} }
// Blocking 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.
void WaitForInitialMetadata() { void WaitForInitialMetadata() {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops; CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_); ops.RecvInitialMetadata(context_);
call_.PerformOps(&ops); call_.PerformOps(&ops);
cq_.Pluck(&ops); // status ignored cq_.Pluck(&ops); /// status ignored
} }
bool Read(R* msg) GRPC_OVERRIDE { bool Read(R* msg) GRPC_OVERRIDE {
@ -151,17 +165,22 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
Call call_; Call call_;
}; };
/// Client-side interface for streaming writes of message of type \a W.
template <class W> template <class W>
class ClientWriterInterface : public ClientStreamingInterface, class ClientWriterInterface : public ClientStreamingInterface,
public WriterInterface<W> { public WriterInterface<W> {
public: public:
/// Half close writing from the client.
/// Block until writes are completed.
///
/// \return Whether the writes were successful.
virtual bool WritesDone() = 0; virtual bool WritesDone() = 0;
}; };
template <class W> template <class W>
class ClientWriter : public ClientWriterInterface<W> { class ClientWriter : public ClientWriterInterface<W> {
public: public:
// Blocking create a stream. /// Blocking create a stream.
template <class R> template <class R>
ClientWriter(Channel* channel, const RpcMethod& method, ClientWriter(Channel* channel, const RpcMethod& method,
ClientContext* context, R* response) ClientContext* context, R* response)
@ -191,7 +210,7 @@ class ClientWriter : public ClientWriterInterface<W> {
return cq_.Pluck(&ops); return cq_.Pluck(&ops);
} }
// Read the final response and wait for the final status. /// Read the final response and wait for the final status.
Status Finish() GRPC_OVERRIDE { Status Finish() GRPC_OVERRIDE {
Status status; Status status;
finish_ops_.ClientRecvStatus(context_, &status); finish_ops_.ClientRecvStatus(context_, &status);
@ -207,20 +226,28 @@ class ClientWriter : public ClientWriterInterface<W> {
Call call_; Call call_;
}; };
// Client-side interface for bi-directional streaming. /// Client-side interface for bi-directional streaming.
template <class W, class R> template <class W, class R>
class ClientReaderWriterInterface : public ClientStreamingInterface, class ClientReaderWriterInterface : public ClientStreamingInterface,
public WriterInterface<W>, public WriterInterface<W>,
public ReaderInterface<R> { public ReaderInterface<R> {
public: public:
/// Blocking 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; virtual void WaitForInitialMetadata() = 0;
/// Block until writes are completed.
///
/// \return Whether the writes were successful.
virtual bool WritesDone() = 0; virtual bool WritesDone() = 0;
}; };
template <class W, class R> template <class W, class R>
class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> { class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
public: public:
// Blocking create a stream. /// Blocking create a stream.
ClientReaderWriter(Channel* channel, const RpcMethod& method, ClientReaderWriter(Channel* channel, const RpcMethod& method,
ClientContext* context) ClientContext* context)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) { : context_(context), call_(channel->CreateCall(method, context, &cq_)) {
@ -230,10 +257,6 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
cq_.Pluck(&ops); cq_.Pluck(&ops);
} }
// Blocking 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.
void WaitForInitialMetadata() { void WaitForInitialMetadata() {
GPR_ASSERT(!context_->initial_metadata_received_); GPR_ASSERT(!context_->initial_metadata_received_);
@ -344,7 +367,7 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
ServerContext* const ctx_; ServerContext* const ctx_;
}; };
// Server-side interface for bi-directional streaming. /// Server-side interface for bi-directional streaming.
template <class W, class R> template <class W, class R>
class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>, class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
public ReaderInterface<R> { public ReaderInterface<R> {

@ -47,11 +47,9 @@ extern "C" {
/*! \mainpage GRPC Core /*! \mainpage GRPC Core
* *
* \section intro_sec The GRPC Core library is a low-level library designed * The GRPC Core library is a low-level library designed to be wrapped by higher
* to be wrapped by higher level libraries. * level libraries. The top-level API is provided in grpc.h. Security related
* * functionality lives in grpc_security.h.
* The top-level API is provided in grpc.h.
* Security related functionality lives in grpc_security.h.
*/ */
/** Completion Queues enable notification of the completion of asynchronous /** Completion Queues enable notification of the completion of asynchronous

@ -34,7 +34,7 @@
#ifndef GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H #ifndef GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H
#define GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H #define GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H
/* Internal API for completion channels */ /* Internal API for completion queues */
#include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>

@ -45,6 +45,12 @@ ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) {
buffer_ = grpc_raw_byte_buffer_create(c_slices.data(), nslices); buffer_ = grpc_raw_byte_buffer_create(c_slices.data(), nslices);
} }
ByteBuffer::~ByteBuffer() {
if (buffer_) {
grpc_byte_buffer_destroy(buffer_);
}
}
void ByteBuffer::Clear() { void ByteBuffer::Clear() {
if (buffer_) { if (buffer_) {
grpc_byte_buffer_destroy(buffer_); grpc_byte_buffer_destroy(buffer_);

Loading…
Cancel
Save