Resolved merge conflicts with master

pull/1014/head
murgatroid99 10 years ago
commit 44cfd3eccb
  1. 10
      .travis.yml
  2. 649
      Makefile
  3. 2
      README.md
  4. 208
      build.json
  5. 39
      examples/pubsub/main.cc
  6. 6
      examples/pubsub/publisher_test.cc
  7. 6
      examples/pubsub/subscriber_test.cc
  8. 5
      include/grpc++/async_unary_call.h
  9. 8
      include/grpc++/channel_arguments.h
  10. 6
      include/grpc++/channel_interface.h
  11. 6
      include/grpc++/client_context.h
  12. 4
      include/grpc++/completion_queue.h
  13. 18
      include/grpc++/config.h
  14. 5
      include/grpc++/create_channel.h
  15. 115
      include/grpc++/credentials.h
  16. 14
      include/grpc++/impl/call.h
  17. 10
      include/grpc++/impl/client_unary_call.h
  18. 6
      include/grpc++/impl/rpc_method.h
  19. 22
      include/grpc++/impl/rpc_service_method.h
  20. 12
      include/grpc++/impl/service_type.h
  21. 21
      include/grpc++/server.h
  22. 16
      include/grpc++/server_builder.h
  23. 2
      include/grpc++/server_context.h
  24. 29
      include/grpc++/server_credentials.h
  25. 12
      include/grpc++/stream.h
  26. 3
      include/grpc/grpc.h
  27. 9
      include/grpc/grpc_security.h
  28. 10
      include/grpc/support/histogram.h
  29. 2
      include/grpc/support/slice_buffer.h
  30. 1
      src/compiler/python_plugin.cc
  31. 4
      src/core/iomgr/pollset_posix.c
  32. 15
      src/core/iomgr/resolve_address_posix.c
  33. 17
      src/core/security/auth.c
  34. 12
      src/core/security/credentials.c
  35. 30
      src/core/security/factories.c
  36. 4
      src/core/security/google_default_credentials.c
  37. 2
      src/core/security/json_token.c
  38. 5
      src/core/security/security_context.c
  39. 111
      src/core/security/server_secure_chttp2.c
  40. 35
      src/core/support/histogram.c
  41. 7
      src/core/support/slice_buffer.c
  42. 21
      src/core/surface/call.c
  43. 2
      src/core/surface/channel.c
  44. 16
      src/core/surface/init.c
  45. 1
      src/core/surface/init.h
  46. 2
      src/core/surface/lame_client.c
  47. 4
      src/core/surface/server.c
  48. 7
      src/core/surface/server_chttp2.c
  49. 4
      src/core/tsi/fake_transport_security.c
  50. 5
      src/core/tsi/ssl_transport_security.c
  51. 2
      src/core/tsi/transport_security.c
  52. 41
      src/cpp/client/channel.cc
  53. 7
      src/cpp/client/channel.h
  54. 4
      src/cpp/client/client_unary_call.cc
  55. 8
      src/cpp/client/create_channel.cc
  56. 89
      src/cpp/client/credentials.cc
  57. 44
      src/cpp/client/insecure_credentials.cc
  58. 132
      src/cpp/client/secure_credentials.cc
  59. 5
      src/cpp/common/call.cc
  60. 150
      src/cpp/proto/proto_utils.cc
  61. 11
      src/cpp/proto/proto_utils.h
  62. 6
      src/cpp/server/async_server_context.cc
  63. 52
      src/cpp/server/insecure_server_credentials.cc
  64. 71
      src/cpp/server/secure_server_credentials.cc
  65. 42
      src/cpp/server/server.cc
  66. 23
      src/cpp/server/server_builder.cc
  67. 22
      src/cpp/server/server_credentials.cc
  68. 2
      src/csharp/.gitignore
  69. 2
      src/csharp/Grpc.Core.Tests/PInvokeTest.cs
  70. 55
      src/csharp/Grpc.Core/Channel.cs
  71. 112
      src/csharp/Grpc.Core/ChannelArgs.cs
  72. 77
      src/csharp/Grpc.Core/Credentials.cs
  73. 11
      src/csharp/Grpc.Core/Grpc.Core.csproj
  74. 577
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  75. 407
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  76. 125
      src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
  77. 95
      src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
  78. 56
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  79. 77
      src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
  80. 35
      src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
  81. 41
      src/csharp/Grpc.Core/Internal/ClientStreamingInputObserver.cs
  82. 15
      src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
  83. 64
      src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs
  84. 45
      src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
  85. 48
      src/csharp/Grpc.Core/Internal/Timespec.cs
  86. 48
      src/csharp/Grpc.Core/OperationFailedException.cs
  87. 34
      src/csharp/Grpc.Core/ServerCallHandler.cs
  88. 62
      src/csharp/Grpc.Core/Status.cs
  89. 113
      src/csharp/Grpc.Core/Utils/Preconditions.cs
  90. 27
      src/csharp/Grpc.Examples.MathClient/MathClient.cs
  91. 128
      src/csharp/Grpc.Examples/MathExamples.cs
  92. 13
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  93. 33
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  94. 1
      src/csharp/Grpc.IntegrationTesting/data/README
  95. 15
      src/csharp/Grpc.IntegrationTesting/data/ca.pem
  96. 16
      src/csharp/Grpc.IntegrationTesting/data/server1.key
  97. 16
      src/csharp/Grpc.IntegrationTesting/data/server1.pem
  98. 68
      src/csharp/ext/grpc_csharp_ext.c
  99. 30
      src/node/binding.gyp
  100. 17
      src/node/ext/byte_buffer.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -4,9 +4,11 @@ before_install:
- sudo add-apt-repository ppa:h-rayflood/llvm -y
- sudo apt-get update -qq
- sudo apt-get install -qq libgtest-dev libgflags-dev python-virtualenv clang-3.5
- sudo pip install cpp-coveralls
env:
global:
- RUBY_VERSION=2.1
- COVERALLS_PARALLEL=true
matrix:
- CONFIG=dbg TEST=c
- CONFIG=dbg TEST=c++
@ -15,9 +17,15 @@ env:
- CONFIG=opt TEST=node
- CONFIG=opt TEST=ruby
- CONFIG=opt TEST=python
- CONFIG=gcov TEST=c
- CONFIG=gcov TEST=c++
script:
- rvm use $RUBY_VERSION
- gem install bundler
- ./tools/run_tests/run_tests.py -l $TEST -t -j 16 -c $CONFIG -s 4.0
after_success:
- if [ "$CONFIG" = "gcov" ] ; then coveralls --exclude third_party --exclude gens -b. --gcov-options '\-p' ; fi
notifications:
email: false
email: false
webhooks:
- https://coveralls.io/webhook?repo_token=54IxAHPjJNdQJzJAhPU0MFpCtg7KvcydQ

File diff suppressed because one or more lines are too long

@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.org/grpc/grpc.svg?branch=master)](https://travis-ci.org/grpc/grpc)
[gRPC - An RPC library and framework](http://github.com/grpc/grpc)
===================================

@ -9,6 +9,61 @@
}
},
"filegroups": [
{
"name": "grpc++_base",
"public_headers": [
"include/grpc++/async_unary_call.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
"include/grpc++/client_context.h",
"include/grpc++/completion_queue.h",
"include/grpc++/config.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
"include/grpc++/impl/internal_stub.h",
"include/grpc++/impl/rpc_method.h",
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/server.h",
"include/grpc++/server_builder.h",
"include/grpc++/server_context.h",
"include/grpc++/server_credentials.h",
"include/grpc++/status.h",
"include/grpc++/status_code_enum.h",
"include/grpc++/stream.h",
"include/grpc++/thread_pool_interface.h"
],
"headers": [
"src/cpp/client/channel.h",
"src/cpp/proto/proto_utils.h",
"src/cpp/server/thread_pool.h",
"src/cpp/util/time.h"
],
"src": [
"src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc",
"src/cpp/client/client_context.cc",
"src/cpp/client/client_unary_call.cc",
"src/cpp/client/create_channel.cc",
"src/cpp/client/credentials.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/client/internal_stub.cc",
"src/cpp/common/call.cc",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
"src/cpp/server/thread_pool.cc",
"src/cpp/util/status.cc",
"src/cpp/util/time.cc"
]
},
{
"name": "grpc_base",
"public_headers": [
@ -80,7 +135,6 @@
"src/core/surface/completion_queue.h",
"src/core/surface/event_string.h",
"src/core/surface/init.h",
"src/core/surface/lame_client.h",
"src/core/surface/server.h",
"src/core/surface/surface_trace.h",
"src/core/transport/chttp2/bin_encoder.h",
@ -276,7 +330,7 @@
"src/core/support/time_posix.c",
"src/core/support/time_win32.c"
],
"secure": false,
"secure": "no",
"vs_project_guid": "{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}"
},
{
@ -333,7 +387,6 @@
"src/core/security/server_secure_chttp2.c",
"src/core/surface/init_secure.c",
"src/core/surface/secure_channel_create.c",
"src/core/surface/secure_server_create.c",
"src/core/tsi/fake_transport_security.c",
"src/core/tsi/ssl_transport_security.c",
"src/core/tsi/transport_security.c"
@ -345,7 +398,7 @@
"filegroups": [
"grpc_base"
],
"secure": true,
"secure": "yes",
"vs_project_guid": "{29D16885-7228-4C31-81ED-5F9187C7F2A9}"
},
{
@ -385,68 +438,26 @@
"filegroups": [
"grpc_base"
],
"secure": false,
"secure": "no",
"vs_project_guid": "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
},
{
"name": "grpc++",
"build": "all",
"language": "c++",
"public_headers": [
"include/grpc++/async_unary_call.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
"include/grpc++/client_context.h",
"include/grpc++/completion_queue.h",
"include/grpc++/config.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
"include/grpc++/impl/internal_stub.h",
"include/grpc++/impl/rpc_method.h",
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/server.h",
"include/grpc++/server_builder.h",
"include/grpc++/server_context.h",
"include/grpc++/server_credentials.h",
"include/grpc++/status.h",
"include/grpc++/status_code_enum.h",
"include/grpc++/stream.h",
"include/grpc++/thread_pool_interface.h"
],
"headers": [
"src/cpp/client/channel.h",
"src/cpp/proto/proto_utils.h",
"src/cpp/server/thread_pool.h",
"src/cpp/util/time.h"
],
"src": [
"src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc",
"src/cpp/client/client_context.cc",
"src/cpp/client/client_unary_call.cc",
"src/cpp/client/create_channel.cc",
"src/cpp/client/credentials.cc",
"src/cpp/client/internal_stub.cc",
"src/cpp/common/call.cc",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
"src/cpp/server/thread_pool.cc",
"src/cpp/util/status.cc",
"src/cpp/util/time.cc"
"src/cpp/client/secure_credentials.cc",
"src/cpp/server/secure_server_credentials.cc"
],
"deps": [
"gpr",
"grpc"
],
"secure": true,
"baselib": true,
"filegroups": [
"grpc++_base"
],
"secure": "check",
"vs_project_guid": "{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}"
},
{
@ -460,6 +471,20 @@
"test/cpp/util/create_test_channel.cc"
]
},
{
"name": "grpc++_unsecure",
"build": "all",
"language": "c++",
"deps": [
"gpr",
"grpc_unsecure"
],
"baselib": true,
"filegroups": [
"grpc++_base"
],
"secure": "no"
},
{
"name": "pubsub_client_lib",
"build": "private",
@ -477,6 +502,20 @@
"gpr"
]
},
{
"name": "qps",
"build": "private",
"language": "c++",
"headers": [
"test/cpp/qps/driver.h",
"test/cpp/qps/timer.h"
],
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/driver.cc",
"test/cpp/qps/timer.cc"
]
},
{
"name": "grpc_csharp_ext",
"build": "all",
@ -1672,7 +1711,7 @@
"src/compiler/cpp_plugin.cc"
],
"deps": [],
"secure": false
"secure": "no"
},
{
"name": "grpc_python_plugin",
@ -1686,7 +1725,7 @@
"src/compiler/python_plugin.cc"
],
"deps": [],
"secure": false
"secure": "no"
},
{
"name": "grpc_ruby_plugin",
@ -1697,7 +1736,7 @@
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
"secure": "no"
},
{
"name": "interop_client",
@ -1763,7 +1802,6 @@
],
"deps": [
"pubsub_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
@ -1806,15 +1844,15 @@
]
},
{
"name": "qps_client",
"name": "qps_driver",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/client.cc"
"test/cpp/qps/qps_driver.cc"
],
"deps": [
"qps",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
@ -1824,51 +1862,23 @@
]
},
{
"name": "qps_client_async",
"name": "qps_worker",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/client_async.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "qps_server",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/server.cc"
"headers": [
"test/cpp/qps/client.h",
"test/cpp/qps/server.h"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "qps_server_async",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/server_async.cc"
"test/cpp/qps/client_async.cc",
"test/cpp/qps/client_sync.cc",
"test/cpp/qps/server_async.cc",
"test/cpp/qps/server_sync.cc",
"test/cpp/qps/worker.cc"
],
"deps": [
"qps",
"grpc++_test_util",
"grpc_test_util",
"grpc++",

@ -41,6 +41,7 @@
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <gflags/gflags.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
@ -48,17 +49,11 @@
#include "examples/pubsub/publisher.h"
#include "examples/pubsub/subscriber.h"
#include "test/cpp/util/create_test_channel.h"
DEFINE_int32(server_port, 443, "Server port.");
DEFINE_string(server_host,
"pubsub-staging.googleapis.com", "Server host to connect to");
DEFINE_string(project_id, "", "GCE project id such as stoked-keyword-656");
DEFINE_string(service_account_key_file, "",
"Path to service account json key file.");
DEFINE_string(oauth_scope,
"https://www.googleapis.com/auth/cloud-platform",
"Scope for OAuth tokens.");
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
@ -75,17 +70,6 @@ const char kMessageData[] = "Test Data";
} // namespace
grpc::string GetServiceAccountJsonKey() {
grpc::string json_key;
if (json_key.empty()) {
std::ifstream json_key_file(FLAGS_service_account_key_file);
std::stringstream key_stream;
key_stream << json_key_file.rdbuf();
json_key = key_stream.str();
}
return json_key;
}
int main(int argc, char** argv) {
grpc_init();
ParseCommandLineFlags(&argc, &argv, true);
@ -93,23 +77,11 @@ int main(int argc, char** argv) {
std::ostringstream ss;
std::unique_ptr<grpc::Credentials> creds;
if (FLAGS_service_account_key_file != "") {
grpc::string json_key = GetServiceAccountJsonKey();
creds = grpc::CredentialsFactory::ServiceAccountCredentials(
json_key, FLAGS_oauth_scope, std::chrono::hours(1));
} else {
creds = grpc::CredentialsFactory::ComputeEngineCredentials();
}
ss << FLAGS_server_host << ":" << FLAGS_server_port;
std::shared_ptr<grpc::ChannelInterface> channel(
grpc::CreateTestChannel(
ss.str(),
FLAGS_server_host,
true, // enable SSL
true, // use prod roots
creds));
std::unique_ptr<grpc::Credentials> creds = grpc::GoogleDefaultCredentials();
std::shared_ptr<grpc::ChannelInterface> channel =
grpc::CreateChannel(ss.str(), creds, grpc::ChannelArguments());
grpc::examples::pubsub::Publisher publisher(channel);
grpc::examples::pubsub::Subscriber subscriber(channel);
@ -129,6 +101,7 @@ int main(int argc, char** argv) {
subscription_name, &subscription_topic).IsOk()) {
subscriber.DeleteSubscription(subscription_name);
}
if (publisher.GetTopic(topic).IsOk()) publisher.DeleteTopic(topic);
grpc::Status s = publisher.CreateTopic(topic);

@ -40,6 +40,7 @@
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <gtest/gtest.h>
@ -106,12 +107,11 @@ class PublisherTest : public ::testing::Test {
int port = grpc_pick_unused_port_or_die();
server_address_ << "localhost:" << port;
ServerBuilder builder;
builder.AddPort(server_address_.str());
builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
channel_ =
CreateChannelDeprecated(server_address_.str(), ChannelArguments());
channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(), ChannelArguments());
publisher_.reset(new grpc::examples::pubsub::Publisher(channel_));
}

@ -40,6 +40,7 @@
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <gtest/gtest.h>
@ -104,12 +105,11 @@ class SubscriberTest : public ::testing::Test {
int port = grpc_pick_unused_port_or_die();
server_address_ << "localhost:" << port;
ServerBuilder builder;
builder.AddPort(server_address_.str());
builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
channel_ =
CreateChannelDeprecated(server_address_.str(), ChannelArguments());
channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(), ChannelArguments());
subscriber_.reset(new grpc::examples::pubsub::Subscriber(channel_));
}

@ -49,7 +49,7 @@ class ClientAsyncResponseReader GRPC_FINAL {
public:
ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const google::protobuf::Message& request, void* tag)
const grpc::protobuf::Message& request, void* tag)
: context_(context),
call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
@ -77,7 +77,6 @@ class ClientAsyncResponseReader GRPC_FINAL {
call_.PerformOps(&finish_buf_);
}
private:
ClientContext* context_;
Call call_;
@ -93,7 +92,7 @@ class ServerAsyncResponseWriter GRPC_FINAL
explicit ServerAsyncResponseWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) {
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.Reset(tag);

@ -62,8 +62,11 @@ class ChannelArguments {
void SetInt(const grpc::string& key, int 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:
friend class Channel;
friend class SecureCredentials;
friend class testing::ChannelArgumentsTest;
// TODO(yangg) implement copy and assign
@ -73,9 +76,6 @@ class ChannelArguments {
// Returns empty string when it is not set.
grpc::string GetSslTargetNameOverride() const;
// Populates given channel_args with args_, does not take ownership.
void SetChannelArgs(grpc_channel_args* channel_args) const;
std::vector<grpc_arg> args_;
std::list<grpc::string> strings_;
};

@ -37,12 +37,6 @@
#include <grpc++/status.h>
#include <grpc++/impl/call.h>
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
struct grpc_call;
namespace grpc {

@ -47,12 +47,6 @@ using std::chrono::system_clock;
struct grpc_call;
struct grpc_completion_queue;
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class CallOpBuffer;

@ -106,8 +106,8 @@ class CompletionQueue {
friend Status BlockingUnaryCall(ChannelInterface *channel,
const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
const grpc::protobuf::Message &request,
grpc::protobuf::Message *result);
// Wraps grpc_completion_queue_pluck.
// Cannot be mixed with calls to Next().

@ -34,8 +34,6 @@
#ifndef GRPCXX_CONFIG_H
#define GRPCXX_CONFIG_H
#include <string>
#ifdef GRPC_OLD_CXX
#define GRPC_FINAL
#define GRPC_OVERRIDE
@ -44,9 +42,23 @@
#define GRPC_OVERRIDE override
#endif
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
#ifndef GRPC_CUSTOM_MESSAGE
#include <google/protobuf/message.h>
#define GRPC_CUSTOM_MESSAGE ::google::protobuf::Message
#endif
namespace grpc {
typedef std::string string;
typedef GRPC_CUSTOM_STRING string;
namespace protobuf {
typedef GRPC_CUSTOM_MESSAGE Message;
} // namespace protobuf
} // namespace grpc

@ -43,11 +43,6 @@ namespace grpc {
class ChannelArguments;
class ChannelInterface;
// Deprecation warning: This function will soon be deleted
// (See pull request #711)
std::shared_ptr<ChannelInterface> CreateChannelDeprecated(
const grpc::string& target, const ChannelArguments& args);
// If creds does not hold an object or is invalid, a lame channel is returned.
std::shared_ptr<ChannelInterface> CreateChannel(
const grpc::string& target, const std::unique_ptr<Credentials>& creds,

@ -39,29 +39,29 @@
#include <grpc++/config.h>
struct grpc_credentials;
namespace grpc {
class ChannelArguments;
class ChannelInterface;
class SecureCredentials;
// grpc_credentials wrapper class. Typical use in C++ applications is limited
// to creating an instance using CredentialsFactory, and passing it down
// during channel construction.
class Credentials GRPC_FINAL {
class Credentials {
public:
~Credentials();
virtual ~Credentials();
// TODO(abhikumar): Specify a plugin API here to be implemented by
// credentials that do not have a corresponding implementation in C.
protected:
friend std::unique_ptr<Credentials> CompositeCredentials(
const std::unique_ptr<Credentials>& creds1,
const std::unique_ptr<Credentials>& creds2);
private:
explicit Credentials(grpc_credentials*);
grpc_credentials* GetRawCreds();
virtual SecureCredentials* AsSecureCredentials() = 0;
friend class Channel;
friend class CredentialsFactory;
private:
friend std::shared_ptr<ChannelInterface> CreateChannel(
const grpc::string& target, const std::unique_ptr<Credentials>& creds,
const ChannelArguments& args);
grpc_credentials* creds_;
virtual std::shared_ptr<ChannelInterface> CreateChannel(
const grpc::string& target, const ChannelArguments& args) = 0;
};
// Options used to build SslCredentials
@ -79,57 +79,44 @@ struct SslCredentialsOptions {
grpc::string pem_cert_chain;
};
// Factory for building different types of Credentials
// The methods may return empty unique_ptr when credentials cannot be created.
// Factories for building different types of Credentials
// The functions may return empty unique_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.
class CredentialsFactory {
public:
// Builds google credentials with reasonable defaults.
// WARNING: Do NOT use this credentials to connect to a non-google service as
// this could result in an oauth2 token leak.
static std::unique_ptr<Credentials> GoogleDefaultCredentials();
// Builds SSL Credentials given SSL specific options
static std::unique_ptr<Credentials> SslCredentials(
const SslCredentialsOptions& options);
// Builds credentials for use when running in GCE
// WARNING: Do NOT use this credentials to connect to a non-google service as
// this could result in an oauth2 token leak.
static std::unique_ptr<Credentials> ComputeEngineCredentials();
// Builds service account credentials.
// WARNING: Do NOT use this credentials to connect to a non-google service as
// this could result in an oauth2 token leak.
// json_key is the JSON key string containing the client's private key.
// scope is a space-delimited list of the requested permissions.
// token_lifetime is the lifetime of each token acquired through this service
// account credentials. It should be positive and should not exceed
// grpc_max_auth_token_lifetime or will be cropped to this value.
static std::unique_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope,
std::chrono::seconds token_lifetime);
// Builds JWT credentials.
// json_key is the JSON key string containing the client's private key.
// token_lifetime is the lifetime of each Json Web Token (JWT) created with
// this credentials. It should not exceed grpc_max_auth_token_lifetime or
// will be cropped to this value.
static std::unique_ptr<Credentials> JWTCredentials(
const grpc::string& json_key, std::chrono::seconds token_lifetime);
// Builds IAM credentials.
static std::unique_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,
const grpc::string& authority_selector);
// Combines two credentials objects into a composite credentials
static std::unique_ptr<Credentials> CompositeCredentials(
const std::unique_ptr<Credentials>& creds1,
const std::unique_ptr<Credentials>& creds2);
};
// Builds credentials with reasonable defaults.
std::unique_ptr<Credentials> GoogleDefaultCredentials();
// Builds SSL Credentials given SSL specific options
std::unique_ptr<Credentials> SslCredentials(
const SslCredentialsOptions& options);
// Builds credentials for use when running in GCE
std::unique_ptr<Credentials> ComputeEngineCredentials();
// Builds service account credentials.
// json_key is the JSON key string containing the client's private key.
// scope is a space-delimited list of the requested permissions.
// token_lifetime is the lifetime of each token acquired through this service
// account credentials. It should be positive and should not exceed
// grpc_max_auth_token_lifetime or will be cropped to this value.
std::unique_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope,
std::chrono::seconds token_lifetime);
// Builds IAM credentials.
std::unique_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,
const grpc::string& authority_selector);
// Combines two credentials objects into a composite credentials
std::unique_ptr<Credentials> CompositeCredentials(
const std::unique_ptr<Credentials>& creds1,
const std::unique_ptr<Credentials>& creds2);
// Credentials for an unencrypted, unauthenticated channel
std::unique_ptr<Credentials> InsecureCredentials();
} // namespace grpc

@ -42,12 +42,6 @@
#include <memory>
#include <map>
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
struct grpc_call;
struct grpc_op;
@ -67,8 +61,8 @@ class CallOpBuffer : public CompletionQueueTag {
std::multimap<grpc::string, grpc::string> *metadata);
void AddSendInitialMetadata(ClientContext *ctx);
void AddRecvInitialMetadata(ClientContext *ctx);
void AddSendMessage(const google::protobuf::Message &message);
void AddRecvMessage(google::protobuf::Message *message);
void AddSendMessage(const grpc::protobuf::Message &message);
void AddRecvMessage(grpc::protobuf::Message *message);
void AddClientSendClose();
void AddClientRecvStatus(ClientContext *ctx, Status *status);
void AddServerSendStatus(std::multimap<grpc::string, grpc::string> *metadata,
@ -95,10 +89,10 @@ class CallOpBuffer : public CompletionQueueTag {
std::multimap<grpc::string, grpc::string> *recv_initial_metadata_;
grpc_metadata_array recv_initial_metadata_arr_;
// Send message
const google::protobuf::Message *send_message_;
const grpc::protobuf::Message *send_message_;
grpc_byte_buffer *send_message_buf_;
// Recv message
google::protobuf::Message *recv_message_;
grpc::protobuf::Message *recv_message_;
grpc_byte_buffer *recv_message_buf_;
// Client send close
bool client_send_close_;

@ -34,11 +34,7 @@
#ifndef GRPCXX_IMPL_CLIENT_UNARY_CALL_H
#define GRPCXX_IMPL_CLIENT_UNARY_CALL_H
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
#include <grpc++/config.h>
namespace grpc {
@ -51,8 +47,8 @@ class Status;
// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
const grpc::protobuf::Message &request,
grpc::protobuf::Message *result);
} // namespace grpc

@ -34,12 +34,6 @@
#ifndef GRPCXX_IMPL_RPC_METHOD_H
#define GRPCXX_IMPL_RPC_METHOD_H
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class RpcMethod {

@ -39,10 +39,10 @@
#include <memory>
#include <vector>
#include <grpc++/config.h>
#include <grpc++/impl/rpc_method.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include <google/protobuf/message.h>
namespace grpc {
class ServerContext;
@ -56,13 +56,13 @@ class MethodHandler {
virtual ~MethodHandler() {}
struct HandlerParameter {
HandlerParameter(Call* c, ServerContext* context,
const google::protobuf::Message* req,
google::protobuf::Message* resp)
const grpc::protobuf::Message* req,
grpc::protobuf::Message* resp)
: call(c), server_context(context), request(req), response(resp) {}
Call* call;
ServerContext* server_context;
const google::protobuf::Message* request;
google::protobuf::Message* response;
const grpc::protobuf::Message* request;
grpc::protobuf::Message* response;
};
virtual Status RunHandler(const HandlerParameter& param) = 0;
};
@ -165,8 +165,8 @@ class RpcServiceMethod : public RpcMethod {
// Takes ownership of the handler and two prototype objects.
RpcServiceMethod(const char* name, RpcMethod::RpcType type,
MethodHandler* handler,
google::protobuf::Message* request_prototype,
google::protobuf::Message* response_prototype)
grpc::protobuf::Message* request_prototype,
grpc::protobuf::Message* response_prototype)
: RpcMethod(name, type),
handler_(handler),
request_prototype_(request_prototype),
@ -174,17 +174,17 @@ class RpcServiceMethod : public RpcMethod {
MethodHandler* handler() { return handler_.get(); }
google::protobuf::Message* AllocateRequestProto() {
grpc::protobuf::Message* AllocateRequestProto() {
return request_prototype_->New();
}
google::protobuf::Message* AllocateResponseProto() {
grpc::protobuf::Message* AllocateResponseProto() {
return response_prototype_->New();
}
private:
std::unique_ptr<MethodHandler> handler_;
std::unique_ptr<google::protobuf::Message> request_prototype_;
std::unique_ptr<google::protobuf::Message> response_prototype_;
std::unique_ptr<grpc::protobuf::Message> request_prototype_;
std::unique_ptr<grpc::protobuf::Message> response_prototype_;
};
// This class contains all the method information for an rpc service. It is

@ -34,11 +34,7 @@
#ifndef GRPCXX_IMPL_SERVICE_TYPE_H
#define GRPCXX_IMPL_SERVICE_TYPE_H
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
#include <grpc++/config.h>
namespace grpc {
@ -72,7 +68,7 @@ class AsynchronousService {
public:
virtual void RequestAsyncCall(void* registered_method,
ServerContext* context,
::google::protobuf::Message* request,
::grpc::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) = 0;
};
@ -91,7 +87,7 @@ class AsynchronousService {
protected:
void RequestAsyncUnary(int index, ServerContext* context,
::google::protobuf::Message* request,
grpc::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
dispatch_impl_->RequestAsyncCall(request_args_[index], context, request,
@ -104,7 +100,7 @@ class AsynchronousService {
stream, cq, tag);
}
void RequestServerStreaming(int index, ServerContext* context,
::google::protobuf::Message* request,
grpc::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
dispatch_impl_->RequestAsyncCall(request_args_[index], context, request,

@ -47,12 +47,6 @@
struct grpc_server;
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class AsynchronousService;
class RpcService;
@ -81,15 +75,14 @@ class Server GRPC_FINAL : private CallHook,
class AsyncRequest;
// ServerBuilder use only
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
ServerCredentials* creds);
Server();
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned);
Server() = delete;
// 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(RpcService* service);
bool RegisterAsyncService(AsynchronousService* service);
// Add a listening port. Can be called multiple times.
int AddPort(const grpc::string& addr);
int AddPort(const grpc::string& addr, ServerCredentials* creds);
// Start the server.
bool Start();
@ -101,9 +94,9 @@ class Server GRPC_FINAL : private CallHook,
// DispatchImpl
void RequestAsyncCall(void* registered_method, ServerContext* context,
::google::protobuf::Message* request,
grpc::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag);
CompletionQueue* cq, void* tag) GRPC_OVERRIDE;
// Completion queue.
CompletionQueue cq_;
@ -119,13 +112,11 @@ class Server GRPC_FINAL : private CallHook,
std::list<SyncRequest> sync_methods_;
// Pointer to the c grpc server.
grpc_server* server_;
grpc_server* const server_;
ThreadPoolInterface* thread_pool_;
// Whether the thread pool is created and owned by the server.
bool thread_pool_owned_;
// Whether the server is created with credentials.
bool secure_;
};
} // namespace grpc

@ -65,11 +65,9 @@ class ServerBuilder {
void RegisterAsyncService(AsynchronousService* service);
// Add a listening port. Can be called multiple times.
void AddPort(const grpc::string& addr);
// Set a ServerCredentials. Can only be called once.
// TODO(yangg) move this to be part of AddPort
void SetCredentials(const std::shared_ptr<ServerCredentials>& creds);
void AddPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port = nullptr);
// Set the thread pool used for running appliation rpc handlers.
// Does not take ownership.
@ -79,9 +77,15 @@ class ServerBuilder {
std::unique_ptr<Server> BuildAndStart();
private:
struct Port {
grpc::string addr;
std::shared_ptr<ServerCredentials> creds;
int* selected_port;
};
std::vector<RpcService*> services_;
std::vector<AsynchronousService*> async_services_;
std::vector<grpc::string> ports_;
std::vector<Port> ports_;
std::shared_ptr<ServerCredentials> creds_;
ThreadPoolInterface* thread_pool_;
};

@ -37,7 +37,7 @@
#include <chrono>
#include <map>
#include "config.h"
#include <grpc++/config.h>
struct gpr_timespec;
struct grpc_metadata;

@ -39,24 +39,21 @@
#include <grpc++/config.h>
struct grpc_server_credentials;
struct grpc_server;
namespace grpc {
class Server;
// grpc_server_credentials wrapper class.
class ServerCredentials GRPC_FINAL {
class ServerCredentials {
public:
~ServerCredentials();
virtual ~ServerCredentials();
private:
explicit ServerCredentials(grpc_server_credentials* c_creds);
friend class ::grpc::Server;
grpc_server_credentials* GetRawCreds();
friend class ServerCredentialsFactory;
friend class Server;
grpc_server_credentials* creds_;
virtual int AddPortToServer(const grpc::string& addr,
grpc_server* server) = 0;
};
// Options to create ServerCredentials with SSL
@ -69,13 +66,11 @@ struct SslServerCredentialsOptions {
std::vector<PemKeyCertPair> pem_key_cert_pairs;
};
// Factory for building different types of ServerCredentials
class ServerCredentialsFactory {
public:
// Builds SSL ServerCredentials given SSL specific options
static std::shared_ptr<ServerCredentials> SslCredentials(
const SslServerCredentialsOptions& options);
};
// Builds SSL ServerCredentials given SSL specific options
std::shared_ptr<ServerCredentials> SslServerCredentials(
const SslServerCredentialsOptions& options);
std::shared_ptr<ServerCredentials> InsecureServerCredentials();
} // namespace grpc

@ -88,7 +88,7 @@ class ClientReader GRPC_FINAL : public ClientStreamingInterface,
public:
// Blocking create a stream and write the first request out.
ClientReader(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const google::protobuf::Message& request)
ClientContext* context, const grpc::protobuf::Message& request)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -142,7 +142,7 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface,
public:
// Blocking create a stream.
ClientWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, google::protobuf::Message* response)
ClientContext* context, grpc::protobuf::Message* response)
: context_(context),
response_(response),
call_(channel->CreateCall(method, context, &cq_)) {
@ -179,7 +179,7 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface,
private:
ClientContext* context_;
google::protobuf::Message* const response_;
grpc::protobuf::Message* const response_;
CompletionQueue cq_;
Call call_;
};
@ -386,7 +386,7 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncStreamingInterface,
// Create a stream and write the first request out.
ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const google::protobuf::Message& request, void* tag)
const grpc::protobuf::Message& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
@ -436,7 +436,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface,
public:
ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
google::protobuf::Message* response, void* tag)
grpc::protobuf::Message* response, void* tag)
: context_(context),
response_(response),
call_(channel->CreateCall(method, context, cq)) {
@ -477,7 +477,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface,
private:
ClientContext* context_;
google::protobuf::Message* const response_;
grpc::protobuf::Message* const response_;
Call call_;
CallOpBuffer init_buf_;
CallOpBuffer meta_buf_;

@ -436,6 +436,9 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
grpc_channel *grpc_channel_create(const char *target,
const grpc_channel_args *args);
/* Create a lame client: this client fails every operation attempted on it. */
grpc_channel *grpc_lame_client_channel_create(void);
/* Close and destroy a grpc channel */
void grpc_channel_destroy(grpc_channel *channel);

@ -169,17 +169,12 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
/* --- Secure server creation. --- */
/* Creates a secure server using the passed-in server credentials. */
grpc_server *grpc_secure_server_create(grpc_server_credentials *creds,
grpc_completion_queue *cq,
const grpc_channel_args *args);
/* Add a HTTP2 over an encrypted link over tcp listener.
Server must have been created with grpc_secure_server_create.
Returns bound port number on success, 0 on failure.
REQUIRES: server not started */
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr);
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
grpc_server_credentials *creds);
#ifdef __cplusplus
}

@ -34,6 +34,9 @@
#ifndef GRPC_SUPPORT_HISTOGRAM_H
#define GRPC_SUPPORT_HISTOGRAM_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -59,6 +62,13 @@ double gpr_histogram_count(gpr_histogram *histogram);
double gpr_histogram_sum(gpr_histogram *histogram);
double gpr_histogram_sum_of_squares(gpr_histogram *histogram);
const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *histogram,
size_t *count);
void gpr_histogram_merge_contents(gpr_histogram *histogram,
const gpr_uint32 *data, size_t data_count,
double min_seen, double max_seen, double sum,
double sum_of_squares, double count);
#ifdef __cplusplus
}
#endif

@ -74,6 +74,8 @@ void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *slices, size_t n);
/* add a very small (less than 8 bytes) amount of data to the end of a slice
buffer: returns a pointer into which to add the data */
gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned len);
/* pop the last buffer, but don't unref it */
void gpr_slice_buffer_pop(gpr_slice_buffer *sb);
/* clear a slice buffer, unref all elements */
void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb);

@ -36,6 +36,7 @@
#include <cstring>
#include <memory>
#include <string>
#include <tuple>
#include "src/compiler/python_generator.h"
#include <google/protobuf/compiler/code_generator.h>

@ -66,7 +66,7 @@ static void backup_poller(void *p) {
gpr_timespec next_poll = gpr_time_add(last_poll, delta);
grpc_pollset_work(&g_backup_pollset, gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
gpr_mu_unlock(&g_backup_pollset.mu);
/*gpr_sleep_until(next_poll);*/
gpr_sleep_until(next_poll);
gpr_mu_lock(&g_backup_pollset.mu);
last_poll = next_poll;
}
@ -267,7 +267,6 @@ static void unary_poll_do_promote(void *args, int success) {
* and we don't have any mechanism to unbecome multipoller. */
pollset->in_flight_cbs--;
if (pollset->shutting_down) {
gpr_log(GPR_INFO, "Shutting down");
/* We don't care about this pollset anymore. */
if (pollset->in_flight_cbs == 0) {
do_shutdown_cb = 1;
@ -275,7 +274,6 @@ static void unary_poll_do_promote(void *args, int success) {
} else if (grpc_fd_is_orphaned(fd)) {
/* Don't try to add it to anything, we'll drop our ref on it below */
} else if (pollset->vtable != original_vtable) {
gpr_log(GPR_INFO, "Not original vtable");
pollset->vtable->add_fd(pollset, fd);
} else if (fd != pollset->data.ptr) {
grpc_fd *fds[2];

@ -101,6 +101,21 @@ grpc_resolved_addresses *grpc_blocking_resolve_address(
hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */
s = getaddrinfo(host, port, &hints, &result);
if (s != 0) {
/* Retry if well-known service name is recognized */
char *svc[][2] = {
{"http", "80"},
{"https", "443"}
};
int i;
for (i = 0; i < (int)(sizeof(svc) / sizeof(svc[0])); i++) {
if (strcmp(port, svc[i][0]) == 0) {
s = getaddrinfo(host, svc[i][1], &hints, &result);
break;
}
}
}
if (s != 0) {
gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
goto done;

@ -59,6 +59,7 @@ typedef struct {
grpc_mdstr *authority_string;
grpc_mdstr *path_string;
grpc_mdstr *error_msg_key;
grpc_mdstr *status_key;
} channel_data;
static void do_nothing(void *ignored, grpc_op_error error) {}
@ -66,17 +67,25 @@ static void do_nothing(void *ignored, grpc_op_error error) {}
static void bubbleup_error(grpc_call_element *elem, const char *error_msg) {
grpc_call_op finish_op;
channel_data *channeld = elem->channel_data;
char status[GPR_LTOA_MIN_BUFSIZE];
gpr_log(GPR_ERROR, "%s", error_msg);
finish_op.type = GRPC_RECV_METADATA;
finish_op.dir = GRPC_CALL_UP;
finish_op.flags = 0;
finish_op.data.metadata = grpc_mdelem_from_metadata_strings(
channeld->md_ctx, channeld->error_msg_key,
channeld->md_ctx, grpc_mdstr_ref(channeld->error_msg_key),
grpc_mdstr_from_string(channeld->md_ctx, error_msg));
finish_op.done_cb = do_nothing;
finish_op.user_data = NULL;
grpc_call_next_op(elem, &finish_op);
gpr_ltoa(GRPC_STATUS_UNAUTHENTICATED, status);
finish_op.data.metadata = grpc_mdelem_from_metadata_strings(
channeld->md_ctx, grpc_mdstr_ref(channeld->status_key),
grpc_mdstr_from_string(channeld->md_ctx, status));
grpc_call_next_op(elem, &finish_op);
grpc_call_element_send_cancel(elem);
}
@ -151,6 +160,7 @@ static void on_host_checked(void *user_data, grpc_security_status status) {
grpc_mdstr_as_c_string(calld->host));
bubbleup_error(elem, error_msg);
gpr_free(error_msg);
calld->op.done_cb(calld->op.user_data, GRPC_OP_ERROR);
}
}
@ -193,6 +203,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
call_host);
bubbleup_error(elem, error_msg);
gpr_free(error_msg);
op->done_cb(op->user_data, GRPC_OP_ERROR);
}
break;
}
@ -265,6 +276,7 @@ static void init_channel_elem(grpc_channel_element *elem,
channeld->path_string = grpc_mdstr_from_string(channeld->md_ctx, ":path");
channeld->error_msg_key =
grpc_mdstr_from_string(channeld->md_ctx, "grpc-message");
channeld->status_key = grpc_mdstr_from_string(channeld->md_ctx, "grpc-status");
}
/* Destructor for channel data */
@ -279,6 +291,9 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
if (channeld->error_msg_key != NULL) {
grpc_mdstr_unref(channeld->error_msg_key);
}
if (channeld->status_key != NULL) {
grpc_mdstr_unref(channeld->status_key);
}
if (channeld->path_string != NULL) {
grpc_mdstr_unref(channeld->path_string);
}

@ -348,7 +348,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
{
gpr_mu_lock(&c->cache_mu);
if (c->cached.service_url != NULL &&
!strcmp(c->cached.service_url, service_url) &&
strcmp(c->cached.service_url, service_url) == 0 &&
c->cached.jwt_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()),
refresh_threshold) > 0)) {
@ -957,7 +957,7 @@ static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
grpc_credentials *creds = *creds_addr;
result.creds_array = creds_addr;
result.num_creds = 1;
if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)) {
if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
result = *grpc_composite_credentials_get_credentials(creds);
}
return result;
@ -995,7 +995,7 @@ const grpc_credentials_array *grpc_composite_credentials_get_credentials(
grpc_credentials *creds) {
const grpc_composite_credentials *c =
(const grpc_composite_credentials *)creds;
GPR_ASSERT(!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE));
GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
return &c->inner;
}
@ -1003,14 +1003,14 @@ grpc_credentials *grpc_credentials_contains_type(
grpc_credentials *creds, const char *type,
grpc_credentials **composite_creds) {
size_t i;
if (!strcmp(creds->type, type)) {
if (strcmp(creds->type, type) == 0) {
if (composite_creds != NULL) *composite_creds = NULL;
return creds;
} else if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)) {
} else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
const grpc_credentials_array *inner_creds_array =
grpc_composite_credentials_get_credentials(creds);
for (i = 0; i < inner_creds_array->num_creds; i++) {
if (!strcmp(type, inner_creds_array->creds_array[i]->type)) {
if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
if (composite_creds != NULL) *composite_creds = creds;
return inner_creds_array->creds_array[i];
}

@ -33,9 +33,9 @@
#include <string.h>
#include <grpc/grpc.h>
#include "src/core/security/credentials.h"
#include "src/core/security/security_context.h"
#include "src/core/surface/lame_client.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
@ -50,31 +50,3 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
return grpc_secure_channel_create_with_factories(
factories, GPR_ARRAY_SIZE(factories), creds, target, args);
}
grpc_server *grpc_secure_server_create(grpc_server_credentials *creds,
grpc_completion_queue *cq,
const grpc_channel_args *args) {
grpc_security_status status = GRPC_SECURITY_ERROR;
grpc_security_context *ctx = NULL;
grpc_server *server = NULL;
if (creds == NULL) return NULL; /* TODO(ctiller): Return lame server. */
if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL)) {
status = grpc_ssl_server_security_context_create(
grpc_ssl_server_credentials_get_config(creds), &ctx);
} else if (!strcmp(creds->type,
GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY)) {
ctx = grpc_fake_server_security_context_create();
status = GRPC_SECURITY_OK;
}
if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR,
"Unable to create secure server with credentials of type %s.",
creds->type);
return NULL; /* TODO(ctiller): Return lame server. */
}
server = grpc_secure_server_create_internal(cq, args, ctx);
grpc_security_context_unref(ctx);
return server;
}

@ -75,8 +75,8 @@ static void on_compute_engine_detection_http_response(
size_t i;
for (i = 0; i < response->hdr_count; i++) {
grpc_httpcli_header *header = &response->hdrs[i];
if (!strcmp(header->key, "Metadata-Flavor") &&
!strcmp(header->value, "Google")) {
if (strcmp(header->key, "Metadata-Flavor") == 0 &&
strcmp(header->value, "Google") == 0) {
detector->success = 1;
break;
}

@ -257,7 +257,7 @@ static char *dot_concat_and_free_strings(char *str1, char *str2) {
}
const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) {
if (!strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM)) {
if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) {
return EVP_sha256();
} else {
gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm);

@ -42,7 +42,6 @@
#include "src/core/support/env.h"
#include "src/core/support/file.h"
#include "src/core/support/string.h"
#include "src/core/surface/lame_client.h"
#include "src/core/transport/chttp2/alpn.h"
#include <grpc/support/alloc.h>
@ -422,7 +421,7 @@ static grpc_security_status ssl_channel_check_call_host(
/* If the target name was overridden, then the original target_name was
'checked' transitively during the previous peer check at the end of the
handshake. */
if (c->overridden_target_name != NULL && !strcmp(host, c->target_name)) {
if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) {
return GRPC_SECURITY_OK;
} else {
return GRPC_SECURITY_ERROR;
@ -611,7 +610,7 @@ grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds,
for (i = 0; args && i < args->num_args; i++) {
grpc_arg *arg = &args->args[i];
if (!strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) &&
if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
arg->type == GRPC_ARG_STRING) {
overridden_target_name = arg->value.string;
break;

@ -33,8 +33,11 @@
#include <grpc/grpc.h>
#include <string.h>
#include "src/core/channel/http_filter.h"
#include "src/core/channel/http_server_filter.h"
#include "src/core/iomgr/endpoint.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/tcp_server.h"
#include "src/core/security/security_context.h"
@ -43,8 +46,29 @@
#include "src/core/transport/chttp2_transport.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
typedef struct grpc_server_secure_state {
grpc_server *server;
grpc_tcp_server *tcp;
grpc_security_context *ctx;
int is_shutdown;
gpr_mu mu;
gpr_refcount refcount;
} grpc_server_secure_state;
static void state_ref(grpc_server_secure_state *state) {
gpr_ref(&state->refcount);
}
static void state_unref(grpc_server_secure_state *state) {
if (gpr_unref(&state->refcount)) {
grpc_security_context_unref(state->ctx);
gpr_free(state);
}
}
static grpc_transport_setup_result setup_transport(void *server,
grpc_transport *transport,
grpc_mdctx *mdctx) {
@ -54,49 +78,84 @@ static grpc_transport_setup_result setup_transport(void *server,
GPR_ARRAY_SIZE(extra_filters), mdctx);
}
static void on_secure_transport_setup_done(void *server,
static void on_secure_transport_setup_done(void *statep,
grpc_security_status status,
grpc_endpoint *secure_endpoint) {
grpc_server_secure_state *state = statep;
if (status == GRPC_SECURITY_OK) {
grpc_create_chttp2_transport(
setup_transport, server, grpc_server_get_channel_args(server),
secure_endpoint, NULL, 0, grpc_mdctx_create(), 0);
gpr_mu_lock(&state->mu);
if (!state->is_shutdown) {
grpc_create_chttp2_transport(
setup_transport, state->server,
grpc_server_get_channel_args(state->server),
secure_endpoint, NULL, 0, grpc_mdctx_create(), 0);
} else {
/* We need to consume this here, because the server may already have gone
* away. */
grpc_endpoint_destroy(secure_endpoint);
}
gpr_mu_unlock(&state->mu);
} else {
gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
}
state_unref(state);
}
static void on_accept(void *server, grpc_endpoint *tcp) {
const grpc_channel_args *args = grpc_server_get_channel_args(server);
grpc_security_context *ctx = grpc_find_security_context_in_args(args);
GPR_ASSERT(ctx);
grpc_setup_secure_transport(ctx, tcp, on_secure_transport_setup_done, server);
static void on_accept(void *statep, grpc_endpoint *tcp) {
grpc_server_secure_state *state = statep;
state_ref(state);
grpc_setup_secure_transport(state->ctx, tcp, on_secure_transport_setup_done, state);
}
/* Note: the following code is the same with server_chttp2.c */
/* Server callback: start listening on our ports */
static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets,
static void start(grpc_server *server, void *statep, grpc_pollset **pollsets,
size_t pollset_count) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_start(tcp, pollsets, pollset_count, on_accept, server);
grpc_server_secure_state *state = statep;
grpc_tcp_server_start(state->tcp, pollsets, pollset_count, on_accept, state);
}
/* Server callback: destroy the tcp listener (so we don't generate further
callbacks) */
static void destroy(grpc_server *server, void *tcpp) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_destroy(tcp);
static void destroy(grpc_server *server, void *statep) {
grpc_server_secure_state *state = statep;
gpr_mu_lock(&state->mu);
state->is_shutdown = 1;
grpc_tcp_server_destroy(state->tcp);
gpr_mu_unlock(&state->mu);
state_unref(state);
}
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) {
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) {
grpc_resolved_addresses *resolved = NULL;
grpc_tcp_server *tcp = NULL;
grpc_server_secure_state *state = NULL;
size_t i;
unsigned count = 0;
int port_num = -1;
int port_temp;
grpc_security_status status = GRPC_SECURITY_ERROR;
grpc_security_context *ctx = NULL;
/* create security context */
if (creds == NULL) goto error;
if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL) == 0) {
status = grpc_ssl_server_security_context_create(
grpc_ssl_server_credentials_get_config(creds), &ctx);
} else if (strcmp(creds->type,
GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY) == 0) {
ctx = grpc_fake_server_security_context_create();
status = GRPC_SECURITY_OK;
}
if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR,
"Unable to create secure server with credentials of type %s.",
creds->type);
goto error;
}
/* resolve address */
resolved = grpc_blocking_resolve_address(addr, "https");
if (!resolved) {
goto error;
@ -132,18 +191,32 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) {
}
grpc_resolved_addresses_destroy(resolved);
state = gpr_malloc(sizeof(*state));
state->server = server;
state->tcp = tcp;
state->ctx = ctx;
state->is_shutdown = 0;
gpr_mu_init(&state->mu);
gpr_ref_init(&state->refcount, 1);
/* Register with the server only upon success */
grpc_server_add_listener(server, tcp, start, destroy);
grpc_server_add_listener(server, state, start, destroy);
return port_num;
/* Error path: cleanup and return */
error:
if (ctx) {
grpc_security_context_unref(ctx);
}
if (resolved) {
grpc_resolved_addresses_destroy(resolved);
}
if (tcp) {
grpc_tcp_server_destroy(tcp);
}
if (state) {
gpr_free(state);
}
return 0;
}

@ -126,25 +126,35 @@ void gpr_histogram_add(gpr_histogram *h, double x) {
}
int gpr_histogram_merge(gpr_histogram *dst, gpr_histogram *src) {
size_t i;
if ((dst->num_buckets != src->num_buckets) ||
(dst->multiplier != src->multiplier)) {
/* Fail because these histograms don't match */
return 0;
}
dst->sum += src->sum;
dst->sum_of_squares += src->sum_of_squares;
dst->count += src->count;
if (src->min_seen < dst->min_seen) {
dst->min_seen = src->min_seen;
gpr_histogram_merge_contents(dst, src->buckets, src->num_buckets,
src->min_seen, src->max_seen, src->sum,
src->sum_of_squares, src->count);
return 1;
}
void gpr_histogram_merge_contents(gpr_histogram *dst, const gpr_uint32 *data,
size_t data_count, double min_seen,
double max_seen, double sum,
double sum_of_squares, double count) {
size_t i;
GPR_ASSERT(dst->num_buckets == data_count);
dst->sum += sum;
dst->sum_of_squares += sum_of_squares;
dst->count += count;
if (min_seen < dst->min_seen) {
dst->min_seen = min_seen;
}
if (src->max_seen > dst->max_seen) {
dst->max_seen = src->max_seen;
if (max_seen > dst->max_seen) {
dst->max_seen = max_seen;
}
for (i = 0; i < dst->num_buckets; i++) {
dst->buckets[i] += src->buckets[i];
dst->buckets[i] += data[i];
}
return 1;
}
static double threshold_for_count_below(gpr_histogram *h, double count_below) {
@ -222,3 +232,8 @@ double gpr_histogram_sum(gpr_histogram *h) { return h->sum; }
double gpr_histogram_sum_of_squares(gpr_histogram *h) {
return h->sum_of_squares;
}
const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) {
*size = h->num_buckets;
return h->buckets;
}

@ -143,6 +143,13 @@ void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *s, size_t n) {
}
}
void gpr_slice_buffer_pop(gpr_slice_buffer *sb) {
if (sb->count != 0) {
size_t count = --sb->count;
sb->length -= GPR_SLICE_LENGTH(sb->slices[count]);
}
}
void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) {
size_t i;

@ -140,6 +140,8 @@ struct grpc_call {
gpr_uint8 have_alarm;
/* are we currently performing a send operation */
gpr_uint8 sending;
/* are we currently completing requests */
gpr_uint8 completing;
/* pairs with completed_requests */
gpr_uint8 num_completed_requests;
/* flag that we need to request more data */
@ -357,7 +359,7 @@ static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); }
static void unlock(grpc_call *call) {
send_action sa = SEND_NOTHING;
completed_request completed_requests[GRPC_IOREQ_OP_COUNT];
int num_completed_requests = call->num_completed_requests;
int completing_requests = 0;
int need_more_data =
call->need_more_data &&
(call->write_state >= WRITE_STATE_STARTED || !call->is_client);
@ -367,10 +369,13 @@ static void unlock(grpc_call *call) {
call->need_more_data = 0;
}
if (num_completed_requests != 0) {
if (!call->completing && call->num_completed_requests != 0) {
completing_requests = call->num_completed_requests;
memcpy(completed_requests, call->completed_requests,
sizeof(completed_requests));
call->num_completed_requests = 0;
call->completing = 1;
grpc_call_internal_ref(call);
}
if (!call->sending) {
@ -391,9 +396,15 @@ static void unlock(grpc_call *call) {
enact_send_action(call, sa);
}
for (i = 0; i < num_completed_requests; i++) {
completed_requests[i].on_complete(call, completed_requests[i].status,
completed_requests[i].user_data);
if (completing_requests > 0) {
for (i = 0; i < completing_requests; i++) {
completed_requests[i].on_complete(call, completed_requests[i].status,
completed_requests[i].user_data);
}
lock(call);
call->completing = 0;
unlock(call);
grpc_call_internal_unref(call, 0);
}
}

@ -39,6 +39,7 @@
#include "src/core/iomgr/iomgr.h"
#include "src/core/surface/call.h"
#include "src/core/surface/client.h"
#include "src/core/surface/init.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -63,6 +64,7 @@ grpc_channel *grpc_channel_create_from_filters(
size_t size =
sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
grpc_channel *channel = gpr_malloc(size);
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
channel->is_client = is_client;
/* decremented by grpc_channel_destroy, and grpc_client_channel_closed if is_client */
gpr_ref_init(&channel->refs, 1 + is_client);

@ -40,17 +40,17 @@
#include "src/core/surface/surface_trace.h"
#include "src/core/transport/chttp2_transport.h"
static gpr_once g_init = GPR_ONCE_INIT;
static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
static int g_initializations;
static void do_init(void) {
static void do_basic_init(void) {
gpr_mu_init(&g_init_mu);
g_initializations = 0;
}
void grpc_init(void) {
gpr_once_init(&g_init, do_init);
gpr_once_init(&g_basic_init, do_basic_init);
gpr_mu_lock(&g_init_mu);
if (++g_initializations == 1) {
@ -73,3 +73,13 @@ void grpc_shutdown(void) {
}
gpr_mu_unlock(&g_init_mu);
}
int grpc_is_initialized(void) {
int r;
gpr_once_init(&g_basic_init, do_basic_init);
gpr_mu_lock(&g_init_mu);
r = g_initializations > 0;
gpr_mu_unlock(&g_init_mu);
return r;
}

@ -35,5 +35,6 @@
#define GRPC_INTERNAL_CORE_SURFACE_INIT_H
void grpc_security_pre_init(void);
int grpc_is_initialized(void);
#endif /* GRPC_INTERNAL_CORE_SURFACE_INIT_H */

@ -31,7 +31,7 @@
*
*/
#include "src/core/surface/lame_client.h"
#include <grpc/grpc.h>
#include <string.h>

@ -44,6 +44,7 @@
#include "src/core/surface/call.h"
#include "src/core/surface/channel.h"
#include "src/core/surface/completion_queue.h"
#include "src/core/surface/init.h"
#include "src/core/transport/metadata.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -612,6 +613,9 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
int census_enabled = grpc_channel_args_is_census_enabled(args);
grpc_server *server = gpr_malloc(sizeof(grpc_server));
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
memset(server, 0, sizeof(grpc_server));
if (cq) addcq(server, cq);

@ -53,6 +53,13 @@ static grpc_transport_setup_result setup_transport(void *server,
}
static void new_transport(void *server, grpc_endpoint *tcp) {
/*
* Beware that the call to grpc_create_chttp2_transport() has to happen before
* grpc_tcp_server_destroy(). This is fine here, but similar code
* asynchronously doing a handshake instead of calling grpc_tcp_server_start()
* (as in server_secure_chttp2.c) needs to add synchronization to avoid this
* case.
*/
grpc_create_chttp2_transport(setup_transport, server,
grpc_server_get_channel_args(server), tcp, NULL,
0, grpc_mdctx_create(), 0);

@ -102,8 +102,8 @@ static tsi_result tsi_fake_handshake_message_from_string(
const char* msg_string, tsi_fake_handshake_message* msg) {
int i;
for (i = 0; i < TSI_FAKE_HANDSHAKE_MESSAGE_MAX; i++) {
if (!strncmp(msg_string, tsi_fake_handshake_message_strings[i],
strlen(tsi_fake_handshake_message_strings[i]))) {
if (strncmp(msg_string, tsi_fake_handshake_message_strings[i],
strlen(tsi_fake_handshake_message_strings[i])) == 0) {
*msg = i;
return TSI_OK;
}

@ -1083,7 +1083,8 @@ static int does_entry_match_name(const char* entry, size_t entry_length,
if (entry_length == 0) return 0;
}
if ((name_length == entry_length) && !strncmp(name, entry, entry_length)) {
if ((name_length == entry_length) &&
strncmp(name, entry, entry_length) == 0) {
return 1; /* Perfect match. */
}
if (entry[0] != '*') return 0;
@ -1110,7 +1111,7 @@ static int does_entry_match_name(const char* entry, size_t entry_length,
name_subdomain_length--;
}
return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
!strncmp(entry, name_subdomain, entry_length));
strncmp(entry, name_subdomain, entry_length) == 0);
}
static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap,

@ -208,7 +208,7 @@ const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* self,
return property;
}
if (name != NULL && property->name != NULL &&
!strcmp(property->name, name)) {
strcmp(property->name, name) == 0) {
return property;
}
}

@ -50,47 +50,26 @@
#include <grpc++/impl/call.h>
#include <grpc++/impl/rpc_method.h>
#include <grpc++/status.h>
#include <google/protobuf/message.h>
namespace grpc {
Channel::Channel(const grpc::string &target, const ChannelArguments &args)
: target_(target) {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
c_channel_ = grpc_channel_create(
target_.c_str(), channel_args.num_args > 0 ? &channel_args : nullptr);
}
Channel::Channel(const grpc::string &target,
const std::unique_ptr<Credentials> &creds,
const ChannelArguments &args)
: target_(args.GetSslTargetNameOverride().empty()
? target
: args.GetSslTargetNameOverride()) {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
grpc_credentials *c_creds = creds ? creds->GetRawCreds() : nullptr;
c_channel_ = grpc_secure_channel_create(
c_creds, target.c_str(),
channel_args.num_args > 0 ? &channel_args : nullptr);
}
Channel::Channel(const grpc::string& target, grpc_channel* channel)
: target_(target), c_channel_(channel) {}
Channel::~Channel() { grpc_channel_destroy(c_channel_); }
Call Channel::CreateCall(const RpcMethod &method, ClientContext *context,
CompletionQueue *cq) {
auto c_call =
grpc_channel_create_call(
c_channel_, cq->cq(), method.name(),
context->authority().empty() ? target_.c_str()
: context->authority().c_str(),
context->RawDeadline());
Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) {
auto c_call = grpc_channel_create_call(c_channel_, cq->cq(), method.name(),
context->authority().empty()
? target_.c_str()
: context->authority().c_str(),
context->RawDeadline());
context->set_call(c_call);
return Call(c_call, this, cq);
}
void Channel::PerformOpsOnCall(CallOpBuffer *buf, Call *call) {
void Channel::PerformOpsOnCall(CallOpBuffer* buf, Call* call) {
static const size_t MAX_OPS = 8;
size_t nops = MAX_OPS;
grpc_op ops[MAX_OPS];

@ -51,10 +51,7 @@ class StreamContextInterface;
class Channel GRPC_FINAL : public ChannelInterface {
public:
Channel(const grpc::string &target, const ChannelArguments &args);
Channel(const grpc::string &target, const std::unique_ptr<Credentials> &creds,
const ChannelArguments &args);
Channel(const grpc::string &target, grpc_channel *c_channel);
~Channel() GRPC_OVERRIDE;
virtual Call CreateCall(const RpcMethod &method, ClientContext *context,
@ -63,7 +60,7 @@ class Channel GRPC_FINAL : public ChannelInterface {
private:
const grpc::string target_;
grpc_channel *c_channel_; // owned
grpc_channel *const c_channel_; // owned
};
} // namespace grpc

@ -44,8 +44,8 @@ namespace grpc {
// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result) {
const grpc::protobuf::Message &request,
grpc::protobuf::Message *result) {
CompletionQueue cq;
Call call(channel->CreateCall(method, context, &cq));
CallOpBuffer buf;

@ -40,14 +40,10 @@
namespace grpc {
class ChannelArguments;
std::shared_ptr<ChannelInterface> CreateChannelDeprecated(
const grpc::string &target, const ChannelArguments &args) {
return std::shared_ptr<ChannelInterface>(new Channel(target, args));
}
std::shared_ptr<ChannelInterface> CreateChannel(
const grpc::string &target, const std::unique_ptr<Credentials> &creds,
const ChannelArguments &args) {
return std::shared_ptr<ChannelInterface>(new Channel(target, creds, args));
return creds ? creds->CreateChannel(target, args) :
std::shared_ptr<ChannelInterface>(new Channel(target, grpc_lame_client_channel_create()));
}
} // namespace grpc

@ -31,97 +31,10 @@
*
*/
#include <string>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include <grpc++/credentials.h>
namespace grpc {
Credentials::Credentials(grpc_credentials *c_creds) : creds_(c_creds) {}
Credentials::~Credentials() { grpc_credentials_release(creds_); }
grpc_credentials *Credentials::GetRawCreds() { return creds_; }
std::unique_ptr<Credentials> CredentialsFactory::GoogleDefaultCredentials() {
grpc_credentials *c_creds = grpc_google_default_credentials_create();
std::unique_ptr<Credentials> cpp_creds(new Credentials(c_creds));
return cpp_creds;
}
// Builds SSL Credentials given SSL specific options
std::unique_ptr<Credentials> CredentialsFactory::SslCredentials(
const SslCredentialsOptions &options) {
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
grpc_credentials *c_creds = grpc_ssl_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair);
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
}
// Builds credentials for use when running in GCE
std::unique_ptr<Credentials> CredentialsFactory::ComputeEngineCredentials() {
grpc_credentials *c_creds = grpc_compute_engine_credentials_create();
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
}
// Builds service account credentials.
std::unique_ptr<Credentials> CredentialsFactory::ServiceAccountCredentials(
const grpc::string &json_key, const grpc::string &scope,
std::chrono::seconds token_lifetime) {
gpr_timespec lifetime = gpr_time_from_seconds(
token_lifetime.count() > 0 ? token_lifetime.count() : 0);
grpc_credentials *c_creds = grpc_service_account_credentials_create(
json_key.c_str(), scope.c_str(), lifetime);
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
}
// Builds JWT credentials.
std::unique_ptr<Credentials> CredentialsFactory::JWTCredentials(
const grpc::string &json_key, std::chrono::seconds token_lifetime) {
gpr_timespec lifetime = gpr_time_from_seconds(
token_lifetime.count() > 0 ? token_lifetime.count() : 0);
grpc_credentials *c_creds =
grpc_jwt_credentials_create(json_key.c_str(), lifetime);
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
}
// Builds IAM credentials.
std::unique_ptr<Credentials> CredentialsFactory::IAMCredentials(
const grpc::string &authorization_token,
const grpc::string &authority_selector) {
grpc_credentials *c_creds = grpc_iam_credentials_create(
authorization_token.c_str(), authority_selector.c_str());
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
}
// Combines two credentials objects into a composite credentials.
std::unique_ptr<Credentials> CredentialsFactory::CompositeCredentials(
const std::unique_ptr<Credentials> &creds1,
const std::unique_ptr<Credentials> &creds2) {
// Note that we are not saving unique_ptrs to the two credentials
// passed in here. This is OK because the underlying C objects (i.e.,
// creds1 and creds2) into grpc_composite_credentials_create will see their
// refcounts incremented.
grpc_credentials *c_creds = grpc_composite_credentials_create(
creds1->GetRawCreds(), creds2->GetRawCreds());
std::unique_ptr<Credentials> cpp_creds(
c_creds == nullptr ? nullptr : new Credentials(c_creds));
return cpp_creds;
}
Credentials::~Credentials() {}
} // namespace grpc

@ -31,27 +31,35 @@
*
*/
#include <grpc/grpc.h>
#include <string>
#include "src/core/channel/channel_args.h"
#include "src/core/security/security_context.h"
#include "src/core/surface/completion_queue.h"
#include "src/core/surface/server.h"
#include <grpc/grpc.h>
#include <grpc/support/log.h>
grpc_server *grpc_secure_server_create_internal(
grpc_completion_queue *cq, const grpc_channel_args *args,
grpc_security_context *context) {
grpc_arg context_arg;
grpc_channel_args *args_copy;
grpc_server *server;
if (grpc_find_security_context_in_args(args) != NULL) {
gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
#include <grpc++/channel_arguments.h>
#include <grpc++/config.h>
#include <grpc++/credentials.h>
#include "src/cpp/client/channel.h"
namespace grpc {
namespace {
class InsecureCredentialsImpl GRPC_FINAL : public Credentials {
public:
std::shared_ptr<grpc::ChannelInterface> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
return std::shared_ptr<ChannelInterface>(new Channel(
target, grpc_channel_create(target.c_str(), &channel_args)));
}
context_arg = grpc_security_context_to_arg(context);
args_copy = grpc_channel_args_copy_and_add(args, &context_arg);
server = grpc_server_create_from_filters(cq, NULL, 0, args_copy);
grpc_channel_args_destroy(args_copy);
return server;
SecureCredentials* AsSecureCredentials() { return nullptr; }
};
} // namespace
std::unique_ptr<Credentials> InsecureCredentials() {
return std::unique_ptr<Credentials>(new InsecureCredentialsImpl());
}
} // namespace grpc

@ -0,0 +1,132 @@
/*
*
* 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.
*
*/
#include <string>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/config.h>
#include <grpc++/credentials.h>
#include "src/cpp/client/channel.h"
namespace grpc {
class SecureCredentials GRPC_FINAL : public Credentials {
public:
explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {}
~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); }
grpc_credentials* GetRawCreds() { return c_creds_; }
std::shared_ptr<grpc::ChannelInterface> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
return std::shared_ptr<ChannelInterface>(new Channel(
args.GetSslTargetNameOverride().empty()
? target : args.GetSslTargetNameOverride(),
grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
}
SecureCredentials* AsSecureCredentials() { return this; }
private:
grpc_credentials* const c_creds_;
};
namespace {
std::unique_ptr<Credentials> WrapCredentials(grpc_credentials* creds) {
return creds == nullptr
? nullptr
: std::unique_ptr<Credentials>(new SecureCredentials(creds));
}
} // namespace
std::unique_ptr<Credentials> GoogleDefaultCredentials() {
return WrapCredentials(grpc_google_default_credentials_create());
}
// Builds SSL Credentials given SSL specific options
std::unique_ptr<Credentials> SslCredentials(
const SslCredentialsOptions& options) {
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
grpc_credentials* c_creds = grpc_ssl_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair);
return WrapCredentials(c_creds);
}
// Builds credentials for use when running in GCE
std::unique_ptr<Credentials> ComputeEngineCredentials() {
return WrapCredentials(grpc_compute_engine_credentials_create());
}
// Builds service account credentials.
std::unique_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope,
std::chrono::seconds token_lifetime) {
gpr_timespec lifetime = gpr_time_from_seconds(
token_lifetime.count() > 0 ? token_lifetime.count() : 0);
return WrapCredentials(grpc_service_account_credentials_create(
json_key.c_str(), scope.c_str(), lifetime));
}
// Builds IAM credentials.
std::unique_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,
const grpc::string& authority_selector) {
return WrapCredentials(grpc_iam_credentials_create(
authorization_token.c_str(), authority_selector.c_str()));
}
// Combines two credentials objects into a composite credentials.
std::unique_ptr<Credentials> CompositeCredentials(
const std::unique_ptr<Credentials>& creds1,
const std::unique_ptr<Credentials>& creds2) {
// Note that we are not saving unique_ptrs to the two credentials
// passed in here. This is OK because the underlying C objects (i.e.,
// creds1 and creds2) into grpc_composite_credentials_create will see their
// refcounts incremented.
SecureCredentials* s1 = creds1->AsSecureCredentials();
SecureCredentials* s2 = creds2->AsSecureCredentials();
if (s1 && s2) {
return WrapCredentials(grpc_composite_credentials_create(
s1->GetRawCreds(), s2->GetRawCreds()));
}
return nullptr;
}
} // namespace grpc

@ -31,7 +31,6 @@
*
*/
#include <google/protobuf/message.h>
#include <grpc/support/alloc.h>
#include <grpc++/impl/call.h>
#include <grpc++/client_context.h>
@ -163,11 +162,11 @@ void CallOpBuffer::AddSendInitialMetadata(ClientContext* ctx) {
AddSendInitialMetadata(&ctx->send_initial_metadata_);
}
void CallOpBuffer::AddSendMessage(const google::protobuf::Message& message) {
void CallOpBuffer::AddSendMessage(const grpc::protobuf::Message& message) {
send_message_ = &message;
}
void CallOpBuffer::AddRecvMessage(google::protobuf::Message* message) {
void CallOpBuffer::AddRecvMessage(grpc::protobuf::Message* message) {
recv_message_ = message;
recv_message_->Clear();
}

@ -35,39 +35,135 @@
#include <grpc++/config.h>
#include <grpc/grpc.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/slice.h>
#include <google/protobuf/message.h>
#include <grpc/support/slice_buffer.h>
#include <grpc/support/port_platform.h>
#include <google/protobuf/io/zero_copy_stream.h>
namespace grpc {
const int kMaxBufferLength = 8192;
bool SerializeProto(const google::protobuf::Message &msg,
grpc_byte_buffer **bp) {
grpc::string msg_str;
bool success = msg.SerializeToString(&msg_str);
if (success) {
gpr_slice slice =
gpr_slice_from_copied_buffer(msg_str.data(), msg_str.length());
*bp = grpc_byte_buffer_create(&slice, 1);
gpr_slice_unref(slice);
class GrpcBufferWriter GRPC_FINAL
: public ::google::protobuf::io::ZeroCopyOutputStream {
public:
explicit GrpcBufferWriter(grpc_byte_buffer **bp,
int block_size = kMaxBufferLength)
: block_size_(block_size), byte_count_(0), have_backup_(false) {
*bp = grpc_byte_buffer_create(NULL, 0);
slice_buffer_ = &(*bp)->data.slice_buffer;
}
~GrpcBufferWriter() GRPC_OVERRIDE {
if (have_backup_) {
gpr_slice_unref(backup_slice_);
}
}
bool Next(void **data, int *size) GRPC_OVERRIDE {
if (have_backup_) {
slice_ = backup_slice_;
have_backup_ = false;
} else {
slice_ = gpr_slice_malloc(block_size_);
}
*data = GPR_SLICE_START_PTR(slice_);
byte_count_ += *size = GPR_SLICE_LENGTH(slice_);
gpr_slice_buffer_add(slice_buffer_, slice_);
return true;
}
void BackUp(int count) GRPC_OVERRIDE {
gpr_slice_buffer_pop(slice_buffer_);
if (count == block_size_) {
backup_slice_ = slice_;
} else {
backup_slice_ =
gpr_slice_split_tail(&slice_, GPR_SLICE_LENGTH(slice_) - count);
gpr_slice_buffer_add(slice_buffer_, slice_);
}
have_backup_ = true;
byte_count_ -= count;
}
gpr_int64 ByteCount() const GRPC_OVERRIDE { return byte_count_; }
private:
const int block_size_;
gpr_int64 byte_count_;
gpr_slice_buffer *slice_buffer_;
bool have_backup_;
gpr_slice backup_slice_;
gpr_slice slice_;
};
class GrpcBufferReader GRPC_FINAL
: public ::google::protobuf::io::ZeroCopyInputStream {
public:
explicit GrpcBufferReader(grpc_byte_buffer *buffer)
: byte_count_(0), backup_count_(0) {
reader_ = grpc_byte_buffer_reader_create(buffer);
}
~GrpcBufferReader() GRPC_OVERRIDE {
grpc_byte_buffer_reader_destroy(reader_);
}
return success;
}
bool DeserializeProto(grpc_byte_buffer *buffer,
google::protobuf::Message *msg) {
grpc::string msg_string;
grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer);
gpr_slice slice;
while (grpc_byte_buffer_reader_next(reader, &slice)) {
const char *data = reinterpret_cast<const char *>(
slice.refcount ? slice.data.refcounted.bytes
: slice.data.inlined.bytes);
msg_string.append(data, slice.refcount ? slice.data.refcounted.length
: slice.data.inlined.length);
gpr_slice_unref(slice);
bool Next(const void **data, int *size) GRPC_OVERRIDE {
if (backup_count_ > 0) {
*data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) -
backup_count_;
*size = backup_count_;
backup_count_ = 0;
return true;
}
if (!grpc_byte_buffer_reader_next(reader_, &slice_)) {
return false;
}
gpr_slice_unref(slice_);
*data = GPR_SLICE_START_PTR(slice_);
byte_count_ += *size = GPR_SLICE_LENGTH(slice_);
return true;
}
grpc_byte_buffer_reader_destroy(reader);
return msg->ParseFromString(msg_string);
void BackUp(int count) GRPC_OVERRIDE {
backup_count_ = count;
}
bool Skip(int count) GRPC_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;
}
gpr_int64 ByteCount() const GRPC_OVERRIDE {
return byte_count_ - backup_count_;
}
private:
gpr_int64 byte_count_;
gpr_int64 backup_count_;
grpc_byte_buffer_reader *reader_;
gpr_slice slice_;
};
namespace grpc {
bool SerializeProto(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp) {
GrpcBufferWriter writer(bp);
return msg.SerializeToZeroCopyStream(&writer);
}
bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg) {
GrpcBufferReader reader(buffer);
return msg->ParseFromZeroCopyStream(&reader);
}
} // namespace grpc

@ -34,23 +34,20 @@
#ifndef GRPC_INTERNAL_CPP_PROTO_PROTO_UTILS_H
#define GRPC_INTERNAL_CPP_PROTO_PROTO_UTILS_H
#include <grpc++/config.h>
struct grpc_byte_buffer;
namespace google {
namespace protobuf {
class Message;
}
}
namespace grpc {
// Serialize the msg into a buffer created inside the function. The caller
// should destroy the returned buffer when done with it. If serialization fails,
// false is returned and buffer is left unchanged.
bool SerializeProto(const google::protobuf::Message &msg,
bool SerializeProto(const grpc::protobuf::Message &msg,
grpc_byte_buffer **buffer);
// The caller keeps ownership of buffer and msg.
bool DeserializeProto(grpc_byte_buffer *buffer, google::protobuf::Message *msg);
bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg);
} // namespace grpc

@ -36,7 +36,7 @@
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "src/cpp/proto/proto_utils.h"
#include <google/protobuf/message.h>
#include <grpc++/config.h>
#include <grpc++/status.h>
namespace grpc {
@ -58,14 +58,14 @@ void AsyncServerContext::Accept(grpc_completion_queue *cq) {
call_, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK);
}
bool AsyncServerContext::StartRead(google::protobuf::Message *request) {
bool AsyncServerContext::StartRead(grpc::protobuf::Message *request) {
GPR_ASSERT(request);
request_ = request;
grpc_call_error err = grpc_call_start_read_old(call_, this);
return err == GRPC_CALL_OK;
}
bool AsyncServerContext::StartWrite(const google::protobuf::Message &response,
bool AsyncServerContext::StartWrite(const grpc::protobuf::Message &response,
int flags) {
grpc_byte_buffer *buffer = nullptr;
if (!SerializeProto(response, &buffer)) {

@ -0,0 +1,52 @@
/*
*
* 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.
*
*/
#include <grpc/grpc_security.h>
#include <grpc++/server_credentials.h>
namespace grpc {
namespace {
class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials {
public:
int AddPortToServer(const grpc::string& addr,
grpc_server* server) GRPC_OVERRIDE {
return grpc_server_add_http2_port(server, addr.c_str());
}
};
} // namespace
std::shared_ptr<ServerCredentials> InsecureServerCredentials() {
return std::shared_ptr<ServerCredentials>(new InsecureServerCredentialsImpl());
}
} // namespace grpc

@ -0,0 +1,71 @@
/*
*
* 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.
*
*/
#include <grpc/grpc_security.h>
#include <grpc++/server_credentials.h>
namespace grpc {
namespace {
class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
public:
explicit SecureServerCredentials(grpc_server_credentials* creds) : creds_(creds) {}
~SecureServerCredentials() GRPC_OVERRIDE {
grpc_server_credentials_release(creds_);
}
int AddPortToServer(const grpc::string& addr,
grpc_server* server) GRPC_OVERRIDE {
return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_);
}
private:
grpc_server_credentials* const creds_;
};
} // namespace
std::shared_ptr<ServerCredentials> SslServerCredentials(
const SslServerCredentialsOptions &options) {
std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
for (const auto &key_cert_pair : options.pem_key_cert_pairs) {
pem_key_cert_pairs.push_back(
{key_cert_pair.private_key.c_str(), key_cert_pair.cert_chain.c_str()});
}
grpc_server_credentials *c_creds = grpc_ssl_server_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
&pem_key_cert_pairs[0], pem_key_cert_pairs.size());
return std::shared_ptr<ServerCredentials>(new SecureServerCredentials(c_creds));
}
} // namespace grpc

@ -117,8 +117,8 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
}
void Run() {
std::unique_ptr<google::protobuf::Message> req;
std::unique_ptr<google::protobuf::Message> res;
std::unique_ptr<grpc::protobuf::Message> req;
std::unique_ptr<grpc::protobuf::Message> res;
if (has_request_payload_) {
req.reset(method_->AllocateRequestProto());
if (!DeserializeProto(request_payload_, req.get())) {
@ -170,26 +170,13 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
grpc_completion_queue* cq_;
};
Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
ServerCredentials* creds)
Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned)
: started_(false),
shutdown_(false),
num_running_cb_(0),
server_(grpc_server_create(cq_.cq(), nullptr)),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned),
secure_(creds != nullptr) {
if (creds) {
server_ =
grpc_secure_server_create(creds->GetRawCreds(), cq_.cq(), nullptr);
} else {
server_ = grpc_server_create(cq_.cq(), nullptr);
}
}
Server::Server() {
// Should not be called.
GPR_ASSERT(false);
}
thread_pool_owned_(thread_pool_owned) {}
Server::~Server() {
std::unique_lock<std::mutex> lock(mu_);
@ -239,13 +226,9 @@ bool Server::RegisterAsyncService(AsynchronousService* service) {
return true;
}
int Server::AddPort(const grpc::string& addr) {
int Server::AddPort(const grpc::string& addr, ServerCredentials* creds) {
GPR_ASSERT(!started_);
if (secure_) {
return grpc_server_add_secure_http2_port(server_, addr.c_str());
} else {
return grpc_server_add_http2_port(server_, addr.c_str());
}
return creds->AddPortToServer(addr, server_);
}
bool Server::Start() {
@ -298,7 +281,7 @@ void Server::PerformOpsOnCall(CallOpBuffer* buf, Call* call) {
class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
public:
AsyncRequest(Server* server, void* registered_method, ServerContext* ctx,
::google::protobuf::Message* request,
grpc::protobuf::Message* request,
ServerAsyncStreamingInterface* stream, CompletionQueue* cq,
void* tag)
: tag_(tag),
@ -324,6 +307,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
*tag = tag_;
bool orig_status = *status;
if (*status && request_) {
if (payload_) {
*status = DeserializeProto(payload_, request_);
@ -343,7 +327,9 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
}
ctx_->call_ = call_;
Call call(call_, server_, cq_);
ctx_->BeginCompletionOp(&call);
if (orig_status && call_) {
ctx_->BeginCompletionOp(&call);
}
// just the pointers inside call are copied here
stream_->BindCall(&call);
delete this;
@ -352,7 +338,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
private:
void* const tag_;
::google::protobuf::Message* const request_;
grpc::protobuf::Message* const request_;
ServerAsyncStreamingInterface* const stream_;
CompletionQueue* const cq_;
ServerContext* const ctx_;
@ -364,7 +350,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
};
void Server::RequestAsyncCall(void* registered_method, ServerContext* context,
::google::protobuf::Message* request,
grpc::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
new AsyncRequest(this, registered_method, context, request, stream, cq, tag);

@ -51,14 +51,10 @@ void ServerBuilder::RegisterAsyncService(AsynchronousService* service) {
async_services_.push_back(service);
}
void ServerBuilder::AddPort(const grpc::string& addr) {
ports_.push_back(addr);
}
void ServerBuilder::SetCredentials(
const std::shared_ptr<ServerCredentials>& creds) {
GPR_ASSERT(!creds_);
creds_ = creds;
void ServerBuilder::AddPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port) {
ports_.push_back(Port{addr, creds, selected_port});
}
void ServerBuilder::SetThreadPool(ThreadPoolInterface* thread_pool) {
@ -71,14 +67,13 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
gpr_log(GPR_ERROR, "Mixing async and sync services is unsupported for now");
return nullptr;
}
if (!thread_pool_ && services_.size()) {
if (!thread_pool_ && !services_.empty()) {
int cores = gpr_cpu_num_cores();
if (!cores) cores = 4;
thread_pool_ = new ThreadPool(cores);
thread_pool_owned = true;
}
std::unique_ptr<Server> server(
new Server(thread_pool_, thread_pool_owned, creds_.get()));
std::unique_ptr<Server> server(new Server(thread_pool_, thread_pool_owned));
for (auto* service : services_) {
if (!server->RegisterService(service)) {
return nullptr;
@ -90,8 +85,10 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
}
}
for (auto& port : ports_) {
if (!server->AddPort(port)) {
return nullptr;
int r = server->AddPort(port.addr, port.creds.get());
if (!r) return nullptr;
if (port.selected_port != nullptr) {
*port.selected_port = r;
}
}
if (!server->Start()) {

@ -37,26 +37,6 @@
namespace grpc {
ServerCredentials::ServerCredentials(grpc_server_credentials *c_creds)
: creds_(c_creds) {}
ServerCredentials::~ServerCredentials() {
grpc_server_credentials_release(creds_);
}
grpc_server_credentials *ServerCredentials::GetRawCreds() { return creds_; }
std::shared_ptr<ServerCredentials> ServerCredentialsFactory::SslCredentials(
const SslServerCredentialsOptions &options) {
std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
for (const auto &key_cert_pair : options.pem_key_cert_pairs) {
pem_key_cert_pairs.push_back(
{key_cert_pair.private_key.c_str(), key_cert_pair.cert_chain.c_str()});
}
grpc_server_credentials *c_creds = grpc_ssl_server_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
&pem_key_cert_pairs[0], pem_key_cert_pairs.size());
return std::shared_ptr<ServerCredentials>(new ServerCredentials(c_creds));
}
ServerCredentials::~ServerCredentials() {}
} // namespace grpc

@ -1,4 +1,6 @@
*.userprefs
StyleCop.Cache
test-results
packages
Grpc.v12.suo
TestResult.xml

@ -127,8 +127,6 @@ namespace Grpc.Core.Tests
[Test]
public void NopPInvokeBenchmark()
{
CompletionCallbackDelegate handler = Handler;
BenchmarkUtil.RunBenchmark(
1000000, 100000000,
() => {

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,9 +27,7 @@
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -39,18 +36,32 @@ using Grpc.Core.Internal;
namespace Grpc.Core
{
public class Channel : IDisposable
{
public class Channel : IDisposable
{
readonly ChannelSafeHandle handle;
readonly String target;
// TODO: add way how to create grpc_secure_channel....
// TODO: add support for channel args...
public Channel(string target)
{
this.handle = ChannelSafeHandle.Create(target, IntPtr.Zero);
this.target = target;
}
/// <summary>
/// Creates a channel.
/// </summary>
public Channel(string target, Credentials credentials = null, ChannelArgs channelArgs = null)
{
using (ChannelArgsSafeHandle nativeChannelArgs = CreateNativeChannelArgs(channelArgs))
{
if (credentials != null)
{
using (CredentialsSafeHandle nativeCredentials = credentials.ToNativeCredentials())
{
this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, target, nativeChannelArgs);
}
}
else
{
this.handle = ChannelSafeHandle.Create(target, nativeChannelArgs);
}
}
this.target = GetOverridenTarget(target, channelArgs);
}
internal ChannelSafeHandle Handle
{
@ -81,5 +92,23 @@ namespace Grpc.Core
handle.Dispose();
}
}
}
private static string GetOverridenTarget(string target, ChannelArgs args)
{
if (args != null && !string.IsNullOrEmpty(args.GetSslTargetNameOverride()))
{
return args.GetSslTargetNameOverride();
}
return target;
}
private static ChannelArgsSafeHandle CreateNativeChannelArgs(ChannelArgs args)
{
if (args == null)
{
return ChannelArgsSafeHandle.CreateNull();
}
return args.ToNativeChannelArgs();
}
}
}

@ -0,0 +1,112 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
namespace Grpc.Core
{
// TODO: should we be using the builder pattern?
public class ChannelArgs
{
public const string SslTargetNameOverrideKey = "grpc.ssl_target_name_override";
public class Builder
{
Dictionary<string,string> stringArgs = new Dictionary<string,string>();
// TODO: AddInteger not supported yet.
public Builder AddString(string key, string value)
{
stringArgs.Add(key, value);
return this;
}
public ChannelArgs Build()
{
return new ChannelArgs(stringArgs);
}
}
Dictionary<string,string> stringArgs;
private ChannelArgs(Dictionary<string, string> stringArgs)
{
// TODO: use immutable dict?
this.stringArgs = new Dictionary<string, string>(stringArgs);
}
public string GetSslTargetNameOverride()
{
string result;
if (stringArgs.TryGetValue(SslTargetNameOverrideKey, out result))
{
return result;
}
return null;
}
public static Builder NewBuilder()
{
return new Builder();
}
/// <summary>
/// Creates native object for the channel arguments.
/// </summary>
/// <returns>The native channel arguments.</returns>
internal ChannelArgsSafeHandle ToNativeChannelArgs()
{
ChannelArgsSafeHandle nativeArgs = null;
try
{
nativeArgs = ChannelArgsSafeHandle.Create(stringArgs.Count);
int i = 0;
foreach (var entry in stringArgs)
{
nativeArgs.SetString(i, entry.Key, entry.Value);
i++;
}
return nativeArgs;
}
catch (Exception)
{
if (nativeArgs != null)
{
nativeArgs.Dispose();
}
throw;
}
}
}
}

@ -0,0 +1,77 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using Grpc.Core.Internal;
namespace Grpc.Core
{
public abstract class Credentials
{
/// <summary>
/// Creates native object for the credentials.
/// </summary>
/// <returns>The native credentials.</returns>
internal abstract CredentialsSafeHandle ToNativeCredentials();
}
/// <summary>
/// Client-side SSL credentials.
/// </summary>
public class SslCredentials : Credentials
{
string pemRootCerts;
public SslCredentials(string pemRootCerts)
{
this.pemRootCerts = pemRootCerts;
}
/// <summary>
/// PEM encoding of the server root certificates.
/// </summary>
public string RootCerts
{
get
{
return this.pemRootCerts;
}
}
internal override CredentialsSafeHandle ToNativeCredentials()
{
return CredentialsSafeHandle.CreateSslCredentials(pemRootCerts);
}
}
}

@ -51,7 +51,6 @@
<Compile Include="Internal\SafeHandleZeroIsInvalid.cs" />
<Compile Include="Internal\Timespec.cs" />
<Compile Include="Internal\GrpcThreadPool.cs" />
<Compile Include="Internal\AsyncCall.cs" />
<Compile Include="Internal\ServerSafeHandle.cs" />
<Compile Include="Method.cs" />
<Compile Include="ServerCalls.cs" />
@ -65,6 +64,16 @@
<Compile Include="Internal\BatchContextSafeHandleNotOwned.cs" />
<Compile Include="Utils\BenchmarkUtil.cs" />
<Compile Include="Utils\ExceptionHelper.cs" />
<Compile Include="Internal\CredentialsSafeHandle.cs" />
<Compile Include="Credentials.cs" />
<Compile Include="Internal\ChannelArgsSafeHandle.cs" />
<Compile Include="ChannelArgs.cs" />
<Compile Include="Internal\AsyncCompletion.cs" />
<Compile Include="Internal\AsyncCallBase.cs" />
<Compile Include="Internal\AsyncCallServer.cs" />
<Compile Include="OperationFailedException.cs" />
<Compile Include="Internal\AsyncCall.cs" />
<Compile Include="Utils\Preconditions.cs" />
</ItemGroup>
<Choose>
<!-- Under older versions of Monodevelop, Choose is not supported and is just

@ -43,84 +43,47 @@ using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Handles native call lifecycle and provides convenience methods.
/// Handles client side native call lifecycle.
/// </summary>
internal class AsyncCall<TWrite, TRead>
internal class AsyncCall<TRequest, TResponse> : AsyncCallBase<TRequest, TResponse>
{
readonly Func<TWrite, byte[]> serializer;
readonly Func<byte[], TRead> deserializer;
readonly CompletionCallbackDelegate unaryResponseHandler;
readonly CompletionCallbackDelegate finishedHandler;
readonly CompletionCallbackDelegate writeFinishedHandler;
readonly CompletionCallbackDelegate readFinishedHandler;
readonly CompletionCallbackDelegate halfclosedHandler;
readonly CompletionCallbackDelegate finishedServersideHandler;
object myLock = new object();
GCHandle gchandle;
CallSafeHandle call;
bool disposed;
bool server;
bool started;
bool errorOccured;
bool cancelRequested;
bool readingDone;
bool halfcloseRequested;
bool halfclosed;
bool finished;
// Completion of a pending write if not null.
TaskCompletionSource<object> writeTcs;
// Completion of a pending read if not null.
TaskCompletionSource<TRead> readTcs;
// Completion of a pending halfclose if not null.
TaskCompletionSource<object> halfcloseTcs;
// Completion of a pending unary response if not null.
TaskCompletionSource<TRead> unaryResponseTcs;
TaskCompletionSource<TResponse> unaryResponseTcs;
// Set after status is received on client. Only used for server streaming and duplex streaming calls.
// Set after status is received. Only used for streaming response calls.
Nullable<Status> finishedStatus;
TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>();
// For streaming, the reads will be delivered to this observer.
IObserver<TRead> readObserver;
bool readObserverCompleted; // True if readObserver has already been completed.
public AsyncCall(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer)
public AsyncCall(Func<TRequest, byte[]> serializer, Func<byte[], TResponse> deserializer) : base(serializer, deserializer)
{
this.serializer = serializer;
this.deserializer = deserializer;
this.unaryResponseHandler = HandleUnaryResponse;
this.finishedHandler = HandleFinished;
this.writeFinishedHandler = HandleWriteFinished;
this.readFinishedHandler = HandleReadFinished;
this.halfclosedHandler = HandleHalfclosed;
this.finishedServersideHandler = HandleFinishedServerside;
this.unaryResponseHandler = CreateBatchCompletionCallback(HandleUnaryResponse);
this.finishedHandler = CreateBatchCompletionCallback(HandleFinished);
}
public void Initialize(Channel channel, CompletionQueueSafeHandle cq, String methodName)
{
InitializeInternal(CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture), false);
var call = CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture);
InitializeInternal(call);
}
public void InitializeServer(CallSafeHandle call)
{
InitializeInternal(call, true);
}
public TRead UnaryCall(Channel channel, String methodName, TWrite msg)
// TODO: this method is not Async, so it shouldn't be in AsyncCall class, but
// it is reusing fair amount of code in this class, so we are leaving it here.
// TODO: for other calls, you need to call Initialize, this methods calls initialize
// on its own, so there's a usage inconsistency.
/// <summary>
/// Blocking unary request - unary response call.
/// </summary>
public TResponse UnaryCall(Channel channel, String methodName, TRequest msg)
{
using(CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{
// TODO: handle serialization error...
byte[] payload = serializer(msg);
byte[] payload = UnsafeSerialize(msg);
unaryResponseTcs = new TaskCompletionSource<TRead>();
unaryResponseTcs = new TaskCompletionSource<TResponse>();
lock (myLock)
{
@ -143,508 +106,200 @@ namespace Grpc.Core.Internal
}
}
public Task<TRead> UnaryCallAsync(TWrite msg)
/// <summary>
/// Starts a unary request - unary response call.
/// </summary>
public Task<TResponse> UnaryCallAsync(TRequest msg)
{
lock (myLock)
{
Preconditions.CheckNotNull(call);
started = true;
halfcloseRequested = true;
readingDone = true;
// TODO: handle serialization error...
byte[] payload = serializer(msg);
byte[] payload = UnsafeSerialize(msg);
unaryResponseTcs = new TaskCompletionSource<TRead>();
unaryResponseTcs = new TaskCompletionSource<TResponse>();
call.StartUnary(payload, unaryResponseHandler);
return unaryResponseTcs.Task;
}
}
public Task<TRead> ClientStreamingCallAsync()
/// <summary>
/// Starts a streamed request - unary response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
public Task<TResponse> ClientStreamingCallAsync()
{
lock (myLock)
{
Preconditions.CheckNotNull(call);
started = true;
readingDone = true;
unaryResponseTcs = new TaskCompletionSource<TRead>();
unaryResponseTcs = new TaskCompletionSource<TResponse>();
call.StartClientStreaming(unaryResponseHandler);
return unaryResponseTcs.Task;
}
}
public void StartServerStreamingCall(TWrite msg, IObserver<TRead> readObserver)
/// <summary>
/// Starts a unary request - streamed response call.
/// </summary>
public void StartServerStreamingCall(TRequest msg, IObserver<TResponse> readObserver)
{
lock (myLock)
{
Preconditions.CheckNotNull(call);
started = true;
halfcloseRequested = true;
halfclosed = true; // halfclose not confirmed yet, but it will be once finishedHandler is called.
this.readObserver = readObserver;
// TODO: handle serialization error...
byte[] payload = serializer(msg);
byte[] payload = UnsafeSerialize(msg);
call.StartServerStreaming(payload, finishedHandler);
ReceiveMessageAsync();
StartReceiveMessage();
}
}
public void StartDuplexStreamingCall(IObserver<TRead> readObserver)
/// <summary>
/// Starts a streaming request - streaming response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
public void StartDuplexStreamingCall(IObserver<TResponse> readObserver)
{
lock (myLock)
{
Preconditions.CheckNotNull(call);
started = true;
this.readObserver = readObserver;
call.StartDuplexStreaming(finishedHandler);
ReceiveMessageAsync();
StartReceiveMessage();
}
}
public Task ServerSideUnaryRequestCallAsync()
{
lock (myLock)
{
started = true;
call.StartServerSide(finishedServersideHandler);
return finishedServersideTcs.Task;
}
}
public Task ServerSideStreamingRequestCallAsync(IObserver<TRead> readObserver)
{
lock (myLock)
{
started = true;
call.StartServerSide(finishedServersideHandler);
if (this.readObserver != null)
{
throw new InvalidOperationException("Already registered an observer.");
}
this.readObserver = readObserver;
ReceiveMessageAsync();
return finishedServersideTcs.Task;
}
}
public Task SendMessageAsync(TWrite msg)
/// <summary>
/// Sends a streaming request. Only one pending send action is allowed at any given time.
/// completionDelegate is called when the operation finishes.
/// </summary>
public void StartSendMessage(TRequest msg, AsyncCompletionDelegate completionDelegate)
{
lock (myLock)
{
CheckNotDisposed();
CheckStarted();
CheckNoError();
if (halfcloseRequested)
{
throw new InvalidOperationException("Already halfclosed.");
}
if (writeTcs != null)
{
throw new InvalidOperationException("Only one write can be pending at a time");
}
// TODO: wrap serialization...
byte[] payload = serializer(msg);
call.StartSendMessage(payload, writeFinishedHandler);
writeTcs = new TaskCompletionSource<object>();
return writeTcs.Task;
}
StartSendMessageInternal(msg, completionDelegate);
}
public Task SendCloseFromClientAsync()
/// <summary>
/// Sends halfclose, indicating client is done with streaming requests.
/// Only one pending send action is allowed at any given time.
/// completionDelegate is called when the operation finishes.
/// </summary>
public void StartSendCloseFromClient(AsyncCompletionDelegate completionDelegate)
{
lock (myLock)
{
CheckNotDisposed();
CheckStarted();
CheckNoError();
if (halfcloseRequested)
{
throw new InvalidOperationException("Already halfclosed.");
}
Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
CheckSendingAllowed();
call.StartSendCloseFromClient(halfclosedHandler);
halfcloseRequested = true;
halfcloseTcs = new TaskCompletionSource<object>();
return halfcloseTcs.Task;
}
}
public Task SendStatusFromServerAsync(Status status)
{
lock (myLock)
{
CheckNotDisposed();
CheckStarted();
CheckNoError();
if (halfcloseRequested)
{
throw new InvalidOperationException("Already halfclosed.");
}
call.StartSendStatusFromServer(status, halfclosedHandler);
halfcloseRequested = true;
halfcloseTcs = new TaskCompletionSource<object>();
return halfcloseTcs.Task;
sendCompletionDelegate = completionDelegate;
}
}
public Task<TRead> ReceiveMessageAsync()
/// <summary>
/// On client-side, we only fire readObserver.OnCompleted once all messages have been read
/// and status has been received.
/// </summary>
protected override void CompleteReadObserver()
{
lock (myLock)
if (readingDone && finishedStatus.HasValue)
{
CheckNotDisposed();
CheckStarted();
CheckNoError();
if (readingDone)
{
throw new InvalidOperationException("Already read the last message.");
}
if (readTcs != null)
bool shouldComplete;
lock (myLock)
{
throw new InvalidOperationException("Only one read can be pending at a time");
shouldComplete = !readObserverCompleted;
readObserverCompleted = true;
}
call.StartReceiveMessage(readFinishedHandler);
readTcs = new TaskCompletionSource<TRead>();
return readTcs.Task;
}
}
public void Cancel()
{
lock (myLock)
{
CheckNotDisposed();
CheckStarted();
cancelRequested = true;
}
// grpc_call_cancel is threadsafe
call.Cancel();
}
public void CancelWithStatus(Status status)
{
lock (myLock)
{
CheckNotDisposed();
CheckStarted();
cancelRequested = true;
}
// grpc_call_cancel_with_status is threadsafe
call.CancelWithStatus(status);
}
private void InitializeInternal(CallSafeHandle call, bool server)
{
lock (myLock)
{
// Make sure this object and the delegated held by it will not be garbage collected
// before we release this handle.
gchandle = GCHandle.Alloc(this);
this.call = call;
this.server = server;
}
}
private void CheckStarted()
{
if (!started)
{
throw new InvalidOperationException("Call not started");
}
}
private void CheckNotDisposed()
{
if (disposed)
{
throw new InvalidOperationException("Call has already been disposed.");
}
}
private void CheckNoError()
{
if (errorOccured)
{
throw new InvalidOperationException("Error occured when processing call.");
}
}
private bool ReleaseResourcesIfPossible()
{
if (!disposed && call != null)
{
if (halfclosed && readingDone && finished)
if (shouldComplete)
{
ReleaseResources();
return true;
var status = finishedStatus.Value;
if (status.StatusCode != StatusCode.OK)
{
FireReadObserverOnError(new RpcException(status));
}
else
{
FireReadObserverOnCompleted();
}
}
}
return false;
}
private void ReleaseResources()
{
if (call != null) {
call.Dispose();
}
gchandle.Free();
disposed = true;
}
private void CompleteStreamObserver(Status status)
{
if (status.StatusCode != StatusCode.OK)
{
// TODO: wrap to handle exceptions;
readObserver.OnError(new RpcException(status));
} else {
// TODO: wrap to handle exceptions;
readObserver.OnCompleted();
}
}
/// <summary>
/// Handler for unary response completion.
/// </summary>
private void HandleUnaryResponse(GRPCOpError error, IntPtr batchContextPtr)
private void HandleUnaryResponse(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
try
lock(myLock)
{
TaskCompletionSource<TRead> tcs;
lock(myLock)
{
finished = true;
halfclosed = true;
tcs = unaryResponseTcs;
ReleaseResourcesIfPossible();
}
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
finished = true;
halfclosed = true;
if (error != GRPCOpError.GRPC_OP_OK)
{
tcs.SetException(new RpcException(
new Status(StatusCode.Internal, "Internal error occured.")
));
return;
}
var status = ctx.GetReceivedStatus();
if (status.StatusCode != StatusCode.OK)
{
tcs.SetException(new RpcException(status));
return;
}
// TODO: handle deserialize error...
var msg = deserializer(ctx.GetReceivedMessage());
tcs.SetResult(msg);
}
catch(Exception e)
{
Console.WriteLine("Caught exception in a native handler: " + e);
ReleaseResourcesIfPossible();
}
}
private void HandleWriteFinished(GRPCOpError error, IntPtr batchContextPtr)
{
try
{
TaskCompletionSource<object> oldTcs = null;
lock (myLock)
{
oldTcs = writeTcs;
writeTcs = null;
}
if (errorOccured)
{
// TODO: use the right type of exception...
oldTcs.SetException(new Exception("Write failed"));
}
else
{
// TODO: where does the continuation run?
oldTcs.SetResult(null);
}
}
catch(Exception e)
if (wasError)
{
Console.WriteLine("Caught exception in a native handler: " + e);
unaryResponseTcs.SetException(new RpcException(
new Status(StatusCode.Internal, "Internal error occured.")
));
return;
}
}
private void HandleHalfclosed(GRPCOpError error, IntPtr batchContextPtr)
{
try
{
lock (myLock)
{
halfclosed = true;
ReleaseResourcesIfPossible();
}
if (error != GRPCOpError.GRPC_OP_OK)
{
halfcloseTcs.SetException(new Exception("Halfclose failed"));
}
else
{
halfcloseTcs.SetResult(null);
}
}
catch(Exception e)
var status = ctx.GetReceivedStatus();
if (status.StatusCode != StatusCode.OK)
{
Console.WriteLine("Caught exception in a native handler: " + e);
unaryResponseTcs.SetException(new RpcException(status));
return;
}
}
private void HandleReadFinished(GRPCOpError error, IntPtr batchContextPtr)
{
try
{
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
var payload = ctx.GetReceivedMessage();
TaskCompletionSource<TRead> oldTcs = null;
IObserver<TRead> observer = null;
Nullable<Status> status = null;
lock (myLock)
{
oldTcs = readTcs;
readTcs = null;
if (payload == null)
{
readingDone = true;
}
observer = readObserver;
status = finishedStatus;
ReleaseResourcesIfPossible();
}
// TODO: wrap deserialization...
TRead msg = payload != null ? deserializer(payload) : default(TRead);
oldTcs.SetResult(msg);
// TODO: handle deserialization error
TResponse msg;
TryDeserialize(ctx.GetReceivedMessage(), out msg);
// TODO: make sure we deliver reads in the right order.
if (observer != null)
{
if (payload != null)
{
// TODO: wrap to handle exceptions
observer.OnNext(msg);
// start a new read
ReceiveMessageAsync();
}
else
{
if (!server)
{
if (status.HasValue)
{
CompleteStreamObserver(status.Value);
}
}
else
{
// TODO: wrap to handle exceptions..
observer.OnCompleted();
}
// TODO: completeStreamObserver serverside...
}
}
}
catch(Exception e)
{
Console.WriteLine("Caught exception in a native handler: " + e);
}
unaryResponseTcs.SetResult(msg);
}
private void HandleFinished(GRPCOpError error, IntPtr batchContextPtr)
/// <summary>
/// Handles receive status completion for calls with streaming response.
/// </summary>
private void HandleFinished(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
try
{
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
var status = ctx.GetReceivedStatus();
bool wasReadingDone;
lock (myLock)
{
finished = true;
finishedStatus = status;
wasReadingDone = readingDone;
ReleaseResourcesIfPossible();
}
if (wasReadingDone) {
CompleteStreamObserver(status);
}
}
catch(Exception e)
{
Console.WriteLine("Caught exception in a native handler: " + e);
}
}
var status = ctx.GetReceivedStatus();
private void HandleFinishedServerside(GRPCOpError error, IntPtr batchContextPtr)
{
try
lock (myLock)
{
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
lock(myLock)
{
finished = true;
// TODO: because of the way server calls are implemented, we need to set
// reading done to true here. Should be fixed in the future.
readingDone = true;
ReleaseResourcesIfPossible();
}
// TODO: handle error ...
finishedServersideTcs.SetResult(null);
finished = true;
finishedStatus = status;
ReleaseResourcesIfPossible();
}
catch(Exception e)
{
Console.WriteLine("Caught exception in a native handler: " + e);
}
CompleteReadObserver();
}
}
}

@ -0,0 +1,407 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Base for handling both client side and server side calls.
/// Handles native call lifecycle and provides convenience methods.
/// </summary>
internal abstract class AsyncCallBase<TWrite, TRead>
{
readonly Func<TWrite, byte[]> serializer;
readonly Func<byte[], TRead> deserializer;
protected readonly CompletionCallbackDelegate sendFinishedHandler;
protected readonly CompletionCallbackDelegate readFinishedHandler;
protected readonly CompletionCallbackDelegate halfclosedHandler;
protected readonly object myLock = new object();
protected GCHandle gchandle;
protected CallSafeHandle call;
protected bool disposed;
protected bool started;
protected bool errorOccured;
protected bool cancelRequested;
protected AsyncCompletionDelegate sendCompletionDelegate; // Completion of a pending send or sendclose if not null.
protected bool readPending; // True if there is a read in progress.
protected bool readingDone;
protected bool halfcloseRequested;
protected bool halfclosed;
protected bool finished; // True if close has been received from the peer.
// Streaming reads will be delivered to this observer. For a call that only does unary read it may remain null.
protected IObserver<TRead> readObserver;
public AsyncCallBase(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer)
{
this.serializer = Preconditions.CheckNotNull(serializer);
this.deserializer = Preconditions.CheckNotNull(deserializer);
this.sendFinishedHandler = CreateBatchCompletionCallback(HandleSendFinished);
this.readFinishedHandler = CreateBatchCompletionCallback(HandleReadFinished);
this.halfclosedHandler = CreateBatchCompletionCallback(HandleHalfclosed);
}
/// <summary>
/// Requests cancelling the call.
/// </summary>
public void Cancel()
{
lock (myLock)
{
Preconditions.CheckState(started);
cancelRequested = true;
if (!disposed)
{
call.Cancel();
}
}
}
/// <summary>
/// Requests cancelling the call with given status.
/// </summary>
public void CancelWithStatus(Status status)
{
lock (myLock)
{
Preconditions.CheckState(started);
cancelRequested = true;
if (!disposed)
{
call.CancelWithStatus(status);
}
}
}
protected void InitializeInternal(CallSafeHandle call)
{
lock (myLock)
{
// Make sure this object and the delegated held by it will not be garbage collected
// before we release this handle.
gchandle = GCHandle.Alloc(this);
this.call = call;
}
}
/// <summary>
/// Initiates sending a message. Only once send operation can be active at a time.
/// completionDelegate is invoked upon completion.
/// </summary>
protected void StartSendMessageInternal(TWrite msg, AsyncCompletionDelegate completionDelegate)
{
byte[] payload = UnsafeSerialize(msg);
lock (myLock)
{
Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
CheckSendingAllowed();
call.StartSendMessage(payload, sendFinishedHandler);
sendCompletionDelegate = completionDelegate;
}
}
/// <summary>
/// Requests receiving a next message.
/// </summary>
protected void StartReceiveMessage()
{
lock (myLock)
{
Preconditions.CheckState(started);
Preconditions.CheckState(!disposed);
Preconditions.CheckState(!errorOccured);
Preconditions.CheckState(!readingDone);
Preconditions.CheckState(!readPending);
call.StartReceiveMessage(readFinishedHandler);
readPending = true;
}
}
/// <summary>
/// Default behavior just completes the read observer, but more sofisticated behavior might be required
/// by subclasses.
/// </summary>
protected virtual void CompleteReadObserver()
{
FireReadObserverOnCompleted();
}
/// <summary>
/// If there are no more pending actions and no new actions can be started, releases
/// the underlying native resources.
/// </summary>
protected bool ReleaseResourcesIfPossible()
{
if (!disposed && call != null)
{
if (halfclosed && readingDone && finished)
{
ReleaseResources();
return true;
}
}
return false;
}
private void ReleaseResources()
{
if (call != null)
{
call.Dispose();
}
gchandle.Free();
disposed = true;
}
protected void CheckSendingAllowed()
{
Preconditions.CheckState(started);
Preconditions.CheckState(!disposed);
Preconditions.CheckState(!errorOccured);
Preconditions.CheckState(!halfcloseRequested, "Already halfclosed.");
Preconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time");
}
protected byte[] UnsafeSerialize(TWrite msg)
{
return serializer(msg);
}
protected bool TrySerialize(TWrite msg, out byte[] payload)
{
try
{
payload = serializer(msg);
return true;
}
catch(Exception)
{
Console.WriteLine("Exception occured while trying to serialize message");
payload = null;
return false;
}
}
protected bool TryDeserialize(byte[] payload, out TRead msg)
{
try
{
msg = deserializer(payload);
return true;
}
catch(Exception)
{
Console.WriteLine("Exception occured while trying to deserialize message");
msg = default(TRead);
return false;
}
}
protected void FireReadObserverOnNext(TRead value)
{
try
{
readObserver.OnNext(value);
}
catch(Exception e)
{
Console.WriteLine("Exception occured while invoking readObserver.OnNext: " + e);
}
}
protected void FireReadObserverOnCompleted()
{
try
{
readObserver.OnCompleted();
}
catch(Exception e)
{
Console.WriteLine("Exception occured while invoking readObserver.OnCompleted: " + e);
}
}
protected void FireReadObserverOnError(Exception error)
{
try
{
readObserver.OnError(error);
}
catch(Exception e)
{
Console.WriteLine("Exception occured while invoking readObserver.OnError: " + e);
}
}
protected void FireCompletion(AsyncCompletionDelegate completionDelegate, Exception error)
{
try
{
completionDelegate(error);
}
catch(Exception e)
{
Console.WriteLine("Exception occured while invoking completion delegate: " + e);
}
}
/// <summary>
/// Creates completion callback delegate that wraps the batch completion handler in a try catch block to
/// prevent propagating exceptions accross managed/unmanaged boundary.
/// </summary>
protected CompletionCallbackDelegate CreateBatchCompletionCallback(Action<bool, BatchContextSafeHandleNotOwned> handler)
{
return new CompletionCallbackDelegate( (error, batchContextPtr) => {
try
{
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
bool wasError = (error != GRPCOpError.GRPC_OP_OK);
handler(wasError, ctx);
}
catch(Exception e)
{
Console.WriteLine("Caught exception in a native handler: " + e);
}
});
}
/// <summary>
/// Handles send completion.
/// </summary>
private void HandleSendFinished(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
AsyncCompletionDelegate origCompletionDelegate = null;
lock (myLock)
{
origCompletionDelegate = sendCompletionDelegate;
sendCompletionDelegate = null;
ReleaseResourcesIfPossible();
}
if (wasError)
{
FireCompletion(origCompletionDelegate, new OperationFailedException("Send failed"));
}
else
{
FireCompletion(origCompletionDelegate, null);
}
}
/// <summary>
/// Handles halfclose completion.
/// </summary>
private void HandleHalfclosed(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
AsyncCompletionDelegate origCompletionDelegate = null;
lock (myLock)
{
halfclosed = true;
origCompletionDelegate = sendCompletionDelegate;
sendCompletionDelegate = null;
ReleaseResourcesIfPossible();
}
if (wasError)
{
FireCompletion(origCompletionDelegate, new OperationFailedException("Halfclose failed"));
}
else
{
FireCompletion(origCompletionDelegate, null);
}
}
/// <summary>
/// Handles streaming read completion.
/// </summary>
private void HandleReadFinished(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
var payload = ctx.GetReceivedMessage();
lock (myLock)
{
readPending = false;
if (payload == null)
{
readingDone = true;
}
ReleaseResourcesIfPossible();
}
// TODO: handle the case when error occured...
if (payload != null)
{
// TODO: handle deserialization error
TRead msg;
TryDeserialize(payload, out msg);
FireReadObserverOnNext(msg);
// Start a new read. The current one has already been delivered,
// so correct ordering of reads is assured.
StartReceiveMessage();
}
else
{
CompleteReadObserver();
}
}
}
}

@ -0,0 +1,125 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Handles server side native call lifecycle.
/// </summary>
internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest>
{
readonly CompletionCallbackDelegate finishedServersideHandler;
readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>();
public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer) : base(serializer, deserializer)
{
this.finishedServersideHandler = CreateBatchCompletionCallback(HandleFinishedServerside);
}
public void Initialize(CallSafeHandle call)
{
InitializeInternal(call);
}
/// <summary>
/// Starts a server side call. Currently, all server side calls are implemented as duplex
/// streaming call and they are adapted to the appropriate streaming arity.
/// </summary>
public Task ServerSideCallAsync(IObserver<TRequest> readObserver)
{
lock (myLock)
{
Preconditions.CheckNotNull(call);
started = true;
this.readObserver = readObserver;
call.StartServerSide(finishedServersideHandler);
StartReceiveMessage();
return finishedServersideTcs.Task;
}
}
/// <summary>
/// Sends a streaming response. Only one pending send action is allowed at any given time.
/// completionDelegate is called when the operation finishes.
/// </summary>
public void StartSendMessage(TResponse msg, AsyncCompletionDelegate completionDelegate)
{
StartSendMessageInternal(msg, completionDelegate);
}
/// <summary>
/// Sends call result status, also indicating server is done with streaming responses.
/// Only one pending send action is allowed at any given time.
/// completionDelegate is called when the operation finishes.
/// </summary>
public void StartSendStatusFromServer(Status status, AsyncCompletionDelegate completionDelegate)
{
lock (myLock)
{
Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
CheckSendingAllowed();
call.StartSendStatusFromServer(status, halfclosedHandler);
halfcloseRequested = true;
sendCompletionDelegate = completionDelegate;
}
}
/// <summary>
/// Handles the server side close completion.
/// </summary>
private void HandleFinishedServerside(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
lock (myLock)
{
finished = true;
ReleaseResourcesIfPossible();
}
// TODO: handle error ...
finishedServersideTcs.SetResult(null);
}
}
}

@ -0,0 +1,95 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// If error != null, there's been an error or operation has been cancelled.
/// </summary>
internal delegate void AsyncCompletionDelegate(Exception error);
/// <summary>
/// Helper for transforming AsyncCompletionDelegate into full-fledged Task.
/// </summary>
internal class AsyncCompletionTaskSource
{
readonly TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
readonly AsyncCompletionDelegate completionDelegate;
public AsyncCompletionTaskSource()
{
completionDelegate = new AsyncCompletionDelegate(HandleCompletion);
}
public Task Task
{
get
{
return tcs.Task;
}
}
public AsyncCompletionDelegate CompletionDelegate
{
get
{
return completionDelegate;
}
}
private void HandleCompletion(Exception error)
{
if (error == null)
{
tcs.SetResult(null);
return;
}
if (error is OperationCanceledException)
{
tcs.SetCanceled();
return;
}
tcs.SetException(error);
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -30,7 +29,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
@ -38,14 +36,12 @@ using Grpc.Core;
namespace Grpc.Core.Internal
{
//TODO: rename the delegate
internal delegate void CompletionCallbackDelegate(GRPCOpError error, IntPtr batchContextPtr);
internal delegate void CompletionCallbackDelegate(GRPCOpError error,IntPtr batchContextPtr);
/// <summary>
/// grpc_call from <grpc/grpc.h>
/// </summary>
internal class CallSafeHandle : SafeHandleZeroIsInvalid
{
internal class CallSafeHandle : SafeHandleZeroIsInvalid
{
const UInt32 GRPC_WRITE_BUFFER_HINT = 1;
[DllImport("grpc_csharp_ext.dll")]
@ -59,22 +55,22 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call,
@ -82,28 +78,27 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_send_close_from_client(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_send_status_from_server(CallSafeHandle call, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, StatusCode statusCode, string statusMessage);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_recv_message(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_serverside(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_call_destroy(IntPtr call);
private CallSafeHandle()
{
}
@ -115,12 +110,12 @@ namespace Grpc.Core.Internal
public void StartUnary(byte[] payload, CompletionCallbackDelegate callback)
{
AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong) payload.Length)));
AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length)));
}
public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback)
{
grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong) payload.Length));
grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length));
}
public void StartClientStreaming(CompletionCallbackDelegate callback)
@ -130,7 +125,7 @@ namespace Grpc.Core.Internal
public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback)
{
AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong) payload.Length)));
AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length)));
}
public void StartDuplexStreaming(CompletionCallbackDelegate callback)
@ -140,7 +135,7 @@ namespace Grpc.Core.Internal
public void StartSendMessage(byte[] payload, CompletionCallbackDelegate callback)
{
AssertCallOk(grpcsharp_call_send_message(this, callback, payload, new UIntPtr((ulong) payload.Length)));
AssertCallOk(grpcsharp_call_send_message(this, callback, payload, new UIntPtr((ulong)payload.Length)));
}
public void StartSendCloseFromClient(CompletionCallbackDelegate callback)
@ -173,19 +168,20 @@ namespace Grpc.Core.Internal
AssertCallOk(grpcsharp_call_cancel_with_status(this, status.StatusCode, status.Detail));
}
protected override bool ReleaseHandle()
{
protected override bool ReleaseHandle()
{
grpcsharp_call_destroy(handle);
return true;
}
return true;
}
private static void AssertCallOk(GRPCCallError callError)
{
Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
}
private static UInt32 GetFlags(bool buffered) {
private static UInt32 GetFlags(bool buffered)
{
return buffered ? 0 : GRPC_WRITE_BUFFER_HINT;
}
}
}
}

@ -0,0 +1,77 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace Grpc.Core.Internal
{
/// <summary>
/// grpc_channel_args from <grpc/grpc.h>
/// </summary>
internal class ChannelArgsSafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll")]
static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs);
[DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_channel_args_destroy(IntPtr args);
private ChannelArgsSafeHandle()
{
}
public static ChannelArgsSafeHandle CreateNull()
{
return new ChannelArgsSafeHandle();
}
public static ChannelArgsSafeHandle Create(int size)
{
return grpcsharp_channel_args_create(new UIntPtr((uint)size));
}
public void SetString(int index, string key, string value)
{
grpcsharp_channel_args_set_string(this, new UIntPtr((uint)index), key, value);
}
protected override bool ReleaseHandle()
{
grpcsharp_channel_args_destroy(handle);
return true;
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,9 +27,7 @@
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -41,27 +38,35 @@ namespace Grpc.Core.Internal
/// <summary>
/// grpc_channel from <grpc/grpc.h>
/// </summary>
internal class ChannelSafeHandle : SafeHandleZeroIsInvalid
{
internal class ChannelSafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll")]
static extern ChannelSafeHandle grpcsharp_channel_create(string target, IntPtr channelArgs);
static extern ChannelSafeHandle grpcsharp_channel_create(string target, ChannelArgsSafeHandle channelArgs);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_channel_destroy(IntPtr channel);
[DllImport("grpc_csharp_ext.dll")]
static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_channel_destroy(IntPtr channel);
private ChannelSafeHandle()
{
}
public static ChannelSafeHandle Create(string target, IntPtr channelArgs)
public static ChannelSafeHandle Create(string target, ChannelArgsSafeHandle channelArgs)
{
return grpcsharp_channel_create(target, channelArgs);
}
protected override bool ReleaseHandle()
{
grpcsharp_channel_destroy(handle);
return true;
}
}
public static ChannelSafeHandle CreateSecure(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs)
{
return grpcsharp_secure_channel_create(credentials, target, channelArgs);
}
protected override bool ReleaseHandle()
{
grpcsharp_channel_destroy(handle);
return true;
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,40 +27,40 @@
// 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.
#endregion
using System;
using Grpc.Core.Internal;
namespace Grpc.Core.Internal
{
internal class ClientStreamingInputObserver<TWrite, TRead> : IObserver<TWrite>
{
{
readonly AsyncCall<TWrite, TRead> call;
public ClientStreamingInputObserver(AsyncCall<TWrite, TRead> call)
{
{
this.call = call;
}
public void OnCompleted()
{
}
public void OnCompleted()
{
var taskSource = new AsyncCompletionTaskSource();
call.StartSendCloseFromClient(taskSource.CompletionDelegate);
// TODO: how bad is the Wait here?
call.SendCloseFromClientAsync().Wait();
}
taskSource.Task.Wait();
}
public void OnError(Exception error)
{
throw new InvalidOperationException("This should never be called.");
}
public void OnError(Exception error)
{
throw new InvalidOperationException("This should never be called.");
}
public void OnNext(TWrite value)
{
public void OnNext(TWrite value)
{
var taskSource = new AsyncCompletionTaskSource();
call.StartSendMessage(value, taskSource.CompletionDelegate);
// TODO: how bad is the Wait here?
call.SendMessageAsync(value).Wait();
}
}
taskSource.Task.Wait();
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,9 +27,7 @@
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@ -40,8 +37,8 @@ namespace Grpc.Core.Internal
/// <summary>
/// grpc_completion_queue from <grpc/grpc.h>
/// </summary>
internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid
{
internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll")]
static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create();
@ -73,11 +70,11 @@ namespace Grpc.Core.Internal
grpcsharp_completion_queue_shutdown(this);
}
protected override bool ReleaseHandle()
protected override bool ReleaseHandle()
{
grpcsharp_completion_queue_destroy(handle);
return true;
}
}
return true;
}
}
}

@ -0,0 +1,64 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace Grpc.Core.Internal
{
/// <summary>
/// grpc_credentials from <grpc/grpc_security.h>
/// </summary>
internal class CredentialsSafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_credentials_release(IntPtr credentials);
private CredentialsSafeHandle()
{
}
public static CredentialsSafeHandle CreateSslCredentials(string pemRootCerts)
{
return grpcsharp_ssl_credentials_create(pemRootCerts, null, null);
}
protected override bool ReleaseHandle()
{
grpcsharp_credentials_release(handle);
return true;
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,9 +27,7 @@
// 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.
#endregion
using System;
using Grpc.Core.Internal;
@ -40,32 +37,36 @@ namespace Grpc.Core.Internal
/// Observer that writes all arriving messages to a call abstraction (in blocking fashion)
/// and then halfcloses the call. Used for server-side call handling.
/// </summary>
internal class ServerStreamingOutputObserver<TWrite, TRead> : IObserver<TWrite>
{
readonly AsyncCall<TWrite, TRead> call;
internal class ServerStreamingOutputObserver<TRequest, TResponse> : IObserver<TResponse>
{
readonly AsyncCallServer<TRequest, TResponse> call;
public ServerStreamingOutputObserver(AsyncCall<TWrite, TRead> call)
{
public ServerStreamingOutputObserver(AsyncCallServer<TRequest, TResponse> call)
{
this.call = call;
}
}
public void OnCompleted()
{
public void OnCompleted()
{
var taskSource = new AsyncCompletionTaskSource();
call.StartSendStatusFromServer(new Status(StatusCode.OK, ""), taskSource.CompletionDelegate);
// TODO: how bad is the Wait here?
call.SendStatusFromServerAsync(new Status(StatusCode.OK, "")).Wait();
}
taskSource.Task.Wait();
}
public void OnError(Exception error)
{
public void OnError(Exception error)
{
// TODO: implement this...
throw new InvalidOperationException("This should never be called.");
}
throw new InvalidOperationException("This should never be called.");
}
public void OnNext(TWrite value)
{
public void OnNext(TResponse value)
{
var taskSource = new AsyncCompletionTaskSource();
call.StartSendMessage(value, taskSource.CompletionDelegate);
// TODO: how bad is the Wait here?
call.SendMessageAsync(value).Wait();
}
}
taskSource.Task.Wait();
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,21 +27,19 @@
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Grpc.Core.Internal
{
/// <summary>
/// gpr_timespec from grpc/support/time.h
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct Timespec
{
/// <summary>
/// gpr_timespec from grpc/support/time.h
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct Timespec
{
const int nanosPerSecond = 1000 * 1000 * 1000;
const int nanosPerTick = 100;
@ -54,23 +51,22 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern int gprsharp_sizeof_timespec();
// TODO: revisit this.
// NOTE: on linux 64bit sizeof(gpr_timespec) = 16, on windows 32bit sizeof(gpr_timespec) = 8
// NOTE: on linux 64bit sizeof(gpr_timespec) = 16, on windows 32bit sizeof(gpr_timespec) = 8
// so IntPtr seems to have the right size to work on both.
public System.IntPtr tv_sec;
public System.IntPtr tv_nsec;
public System.IntPtr tv_sec;
public System.IntPtr tv_nsec;
/// <summary>
/// Timespec a long time in the future.
/// </summary>
public static Timespec InfFuture
{
get
{
/// <summary>
/// Timespec a long time in the future.
/// </summary>
public static Timespec InfFuture
{
get
{
return gprsharp_inf_future();
}
}
}
}
public static Timespec Now
{
@ -92,7 +88,8 @@ namespace Grpc.Core.Internal
/// Creates a GPR deadline from current instant and given timeout.
/// </summary>
/// <returns>The from timeout.</returns>
public static Timespec DeadlineFromTimeout(TimeSpan timeout) {
public static Timespec DeadlineFromTimeout(TimeSpan timeout)
{
if (timeout == Timeout.InfiniteTimeSpan)
{
return Timespec.InfFuture;
@ -100,7 +97,8 @@ namespace Grpc.Core.Internal
return Timespec.Now.Add(timeout);
}
public Timespec Add(TimeSpan timeSpan) {
public Timespec Add(TimeSpan timeSpan)
{
long nanos = tv_nsec.ToInt64() + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * nanosPerTick;
long overflow_sec = (nanos > nanosPerSecond) ? 1 : 0;
@ -109,6 +107,6 @@ namespace Grpc.Core.Internal
result.tv_sec = new IntPtr(tv_sec.ToInt64() + (timeSpan.Ticks / TimeSpan.TicksPerSecond) + overflow_sec);
return result;
}
}
}
}

@ -0,0 +1,48 @@
#region Copyright notice and license
// 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.
#endregion
using System;
namespace Grpc.Core
{
/// <summary>
/// Thrown when gRPC operation fails.
/// </summary>
public class OperationFailedException : Exception
{
public OperationFailedException(string message) : base(message)
{
}
}
}

@ -32,7 +32,9 @@
#endregion
using System;
using System.Linq;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
@ -54,17 +56,17 @@ namespace Grpc.Core
public void StartCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
{
var asyncCall = new AsyncCall<TResponse, TRequest>(
var asyncCall = new AsyncCallServer<TRequest, TResponse>(
method.ResponseMarshaller.Serializer,
method.RequestMarshaller.Deserializer);
asyncCall.InitializeServer(call);
asyncCall.Initialize(call);
var finishedTask = asyncCall.ServerSideUnaryRequestCallAsync();
var requestObserver = new RecordingObserver<TRequest>();
var finishedTask = asyncCall.ServerSideCallAsync(requestObserver);
var request = asyncCall.ReceiveMessageAsync().Result;
var responseObserver = new ServerStreamingOutputObserver<TResponse, TRequest>(asyncCall);
var request = requestObserver.ToList().Result.Single();
var responseObserver = new ServerStreamingOutputObserver<TRequest, TResponse>(asyncCall);
handler(request, responseObserver);
finishedTask.Wait();
@ -85,15 +87,15 @@ namespace Grpc.Core
public void StartCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
{
var asyncCall = new AsyncCall<TResponse, TRequest>(
var asyncCall = new AsyncCallServer<TRequest, TResponse>(
method.ResponseMarshaller.Serializer,
method.RequestMarshaller.Deserializer);
asyncCall.InitializeServer(call);
asyncCall.Initialize(call);
var responseObserver = new ServerStreamingOutputObserver<TResponse, TRequest>(asyncCall);
var responseObserver = new ServerStreamingOutputObserver<TRequest,TResponse>(asyncCall);
var requestObserver = handler(responseObserver);
var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(requestObserver);
var finishedTask = asyncCall.ServerSideCallAsync(requestObserver);
finishedTask.Wait();
}
}
@ -103,17 +105,15 @@ namespace Grpc.Core
public void StartCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq)
{
// We don't care about the payload type here.
AsyncCall<byte[], byte[]> asyncCall = new AsyncCall<byte[], byte[]>(
var asyncCall = new AsyncCallServer<byte[], byte[]>(
(payload) => payload, (payload) => payload);
asyncCall.Initialize(call);
asyncCall.InitializeServer(call);
var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>());
var finishedTask = asyncCall.ServerSideCallAsync(new NullObserver<byte[]>());
// TODO: this makes the call finish before all reads can be done which causes trouble
// in AsyncCall.HandleReadFinished callback. Revisit this.
asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait();
// TODO: check result of the completion status.
asyncCall.StartSendStatusFromServer(new Status(StatusCode.Unimplemented, "No such method."), new AsyncCompletionDelegate((error) => {}));
finishedTask.Wait();
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,7 +27,6 @@
// 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.
#endregion
using System;
@ -36,34 +34,40 @@ using System.Runtime.InteropServices;
namespace Grpc.Core
{
/// <summary>
/// Represents RPC result.
/// </summary>
public struct Status
{
readonly StatusCode statusCode;
readonly string detail;
/// <summary>
/// Represents RPC result.
/// </summary>
public struct Status
{
readonly StatusCode statusCode;
readonly string detail;
public Status(StatusCode statusCode, string detail)
{
this.statusCode = statusCode;
this.detail = detail;
}
public Status(StatusCode statusCode, string detail)
{
this.statusCode = statusCode;
this.detail = detail;
}
public StatusCode StatusCode
{
get
{
return statusCode;
}
}
/// <summary>
/// Gets the gRPC status code. OK indicates success, all other values indicate an error.
/// </summary>
public StatusCode StatusCode
{
get
{
return statusCode;
}
}
public string Detail
{
get
{
return detail;
}
}
}
/// <summary>
/// Gets the detail.
/// </summary>
public string Detail
{
get
{
return detail;
}
}
}
}

@ -0,0 +1,113 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace Grpc.Core.Utils
{
public static class Preconditions
{
/// <summary>
/// Throws ArgumentException if condition is false.
/// </summary>
public static void CheckArgument(bool condition)
{
if (!condition)
{
throw new ArgumentException();
}
}
/// <summary>
/// Throws ArgumentException with given message if condition is false.
/// </summary>
public static void CheckArgument(bool condition, string errorMessage)
{
if (!condition)
{
throw new ArgumentException(errorMessage);
}
}
/// <summary>
/// Throws NullReferenceException if reference is null.
/// </summary>
public static T CheckNotNull<T> (T reference)
{
if (reference == null)
{
throw new NullReferenceException();
}
return reference;
}
/// <summary>
/// Throws NullReferenceException with given message if reference is null.
/// </summary>
public static T CheckNotNull<T> (T reference, string errorMessage)
{
if (reference == null)
{
throw new NullReferenceException(errorMessage);
}
return reference;
}
/// <summary>
/// Throws InvalidOperationException if condition is false.
/// </summary>
public static void CheckState(bool condition)
{
if (!condition)
{
throw new InvalidOperationException();
}
}
/// <summary>
/// Throws InvalidOperationException with given message if condition is false.
/// </summary>
public static void CheckState(bool condition, string errorMessage)
{
if (!condition)
{
throw new InvalidOperationException(errorMessage);
}
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,9 +27,7 @@
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -38,25 +35,25 @@ using Grpc.Core;
namespace math
{
class MathClient
class MathClient
{
public static void Main (string[] args)
{
public static void Main(string[] args)
{
GrpcEnvironment.Initialize();
using (Channel channel = new Channel("127.0.0.1:23456"))
{
MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel);
MathExamples.DivExample(stub);
using (Channel channel = new Channel("127.0.0.1:23456"))
{
MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel);
MathExamples.DivExample(stub);
MathExamples.FibExample(stub);
MathExamples.SumExample(stub);
MathExamples.SumExample(stub);
MathExamples.DivManyExample(stub);
}
MathExamples.DivManyExample(stub);
}
GrpcEnvironment.Shutdown();
}
}
}
}
}

@ -1,5 +1,4 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -28,7 +27,6 @@
// 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.
#endregion
using System;
@ -39,59 +37,63 @@ using Grpc.Core.Utils;
namespace math
{
public static class MathExamples
{
public static void DivExample(MathGrpc.IMathServiceClient stub)
{
DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
Console.WriteLine("Div Result: " + result);
}
public static void DivAsyncExample(MathGrpc.IMathServiceClient stub)
{
Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = call.Result;
Console.WriteLine(result);
}
public static void DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub)
{
Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = call.Result;
Console.WriteLine(result);
}
public static void FibExample(MathGrpc.IMathServiceClient stub)
{
public static class MathExamples
{
public static void DivExample(MathGrpc.IMathServiceClient stub)
{
DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
Console.WriteLine("Div Result: " + result);
}
public static void DivAsyncExample(MathGrpc.IMathServiceClient stub)
{
Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = call.Result;
Console.WriteLine(result);
}
public static void DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub)
{
Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = call.Result;
Console.WriteLine(result);
}
public static void FibExample(MathGrpc.IMathServiceClient stub)
{
var recorder = new RecordingObserver<Num>();
stub.Fib(new FibArgs.Builder { Limit = 5 }.Build(), recorder);
List<Num> numbers = recorder.ToList().Result;
List<Num> numbers = recorder.ToList().Result;
Console.WriteLine("Fib Result: " + string.Join("|", recorder.ToList().Result));
}
}
public static void SumExample(MathGrpc.IMathServiceClient stub)
{
List<Num> numbers = new List<Num>{new Num.Builder { Num_ = 1 }.Build(),
new Num.Builder { Num_ = 2 }.Build(),
new Num.Builder { Num_ = 3 }.Build()};
public static void SumExample(MathGrpc.IMathServiceClient stub)
{
List<Num> numbers = new List<Num>
{new Num.Builder { Num_ = 1 }.Build(),
new Num.Builder { Num_ = 2 }.Build(),
new Num.Builder { Num_ = 3 }.Build()
};
var res = stub.Sum();
foreach (var num in numbers) {
foreach (var num in numbers)
{
res.Inputs.OnNext(num);
}
res.Inputs.OnCompleted();
Console.WriteLine("Sum Result: " + res.Task.Result);
}
Console.WriteLine("Sum Result: " + res.Task.Result);
}
public static void DivManyExample(MathGrpc.IMathServiceClient stub)
{
List<DivArgs> divArgsList = new List<DivArgs>{
new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(),
new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build()
};
public static void DivManyExample(MathGrpc.IMathServiceClient stub)
{
List<DivArgs> divArgsList = new List<DivArgs>
{
new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(),
new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build()
};
var recorder = new RecordingObserver<DivReply>();
@ -102,30 +104,30 @@ namespace math
}
inputs.OnCompleted();
Console.WriteLine("DivMany Result: " + string.Join("|", recorder.ToList().Result));
}
Console.WriteLine("DivMany Result: " + string.Join("|", recorder.ToList().Result));
}
public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub)
{
var numberList = new List<Num>
{ new Num.Builder{ Num_ = 1 }.Build(),
new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build()
};
public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub)
{
var numberList = new List<Num>
{ new Num.Builder{ Num_ = 1 }.Build(),
new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build()
};
numberList.ToObservable();
numberList.ToObservable();
//IObserver<Num> numbers;
//Task<Num> call = stub.Sum(out numbers);
//foreach (var num in numberList)
//{
// numbers.OnNext(num);
//}
//numbers.OnCompleted();
//IObserver<Num> numbers;
//Task<Num> call = stub.Sum(out numbers);
//foreach (var num in numberList)
//{
// numbers.OnNext(num);
//}
//numbers.OnCompleted();
//Num sum = call.Result;
//Num sum = call.Result;
//DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build());
}
}
//DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build());
}
}
}

@ -62,8 +62,21 @@
<None Include="proto\test.proto" />
<None Include="proto\empty.proto" />
<None Include="proto\messages.proto" />
<None Include="data\README">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="data\ca.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="data\server1.key">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="data\server1.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="proto\" />
<Folder Include="data\" />
</ItemGroup>
</Project>

@ -34,6 +34,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Google.ProtocolBuffers;
@ -49,10 +50,10 @@ namespace Grpc.IntegrationTesting
private class ClientOptions
{
public bool help;
public string serverHost;
public string serverHostOverride;
public string serverHost= "127.0.0.1";
public string serverHostOverride = "foo.test.google.fr";
public int? serverPort;
public string testCase;
public string testCase = "large_unary";
public bool useTls;
public bool useTestCa;
}
@ -98,10 +99,32 @@ namespace Grpc.IntegrationTesting
GrpcEnvironment.Initialize();
string addr = string.Format("{0}:{1}", options.serverHost, options.serverPort);
using (Channel channel = new Channel(addr))
Credentials credentials = null;
if (options.useTls)
{
TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel);
string caPath = "data/ca.pem"; // Default testing CA
if (!options.useTestCa)
{
caPath = Environment.GetEnvironmentVariable("SSL_CERT_FILE");
if (string.IsNullOrEmpty(caPath))
{
throw new ArgumentException("CA path environment variable is not set.");
}
}
credentials = new SslCredentials(File.ReadAllText(caPath));
}
ChannelArgs channelArgs = null;
if (!string.IsNullOrEmpty(options.serverHostOverride))
{
channelArgs = ChannelArgs.NewBuilder()
.AddString(ChannelArgs.SslTargetNameOverrideKey, options.serverHostOverride).Build();
}
using (Channel channel = new Channel(addr, credentials, channelArgs))
{
TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel);
RunTestCase(options.testCase, client);
}

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla
Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT
BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7
+L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu
g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd
Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau
sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m
oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG
Dfcog5wrJytaQ6UA0wE=
-----END CERTIFICATE-----

@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD
M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf
3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY
AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm
V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY
tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p
dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q
K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR
81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff
DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd
aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2
ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3
XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe
F98XJ7tIFfJq
-----END PRIVATE KEY-----

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
-----END CERTIFICATE-----

@ -39,6 +39,7 @@
#include <grpc/support/slice.h>
#include <grpc/support/thd.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <string.h>
@ -266,6 +267,45 @@ grpcsharp_channel_create_call(grpc_channel *channel, grpc_completion_queue *cq,
return grpc_channel_create_call(channel, cq, method, host, deadline);
}
/* Channel args */
GPR_EXPORT grpc_channel_args *GPR_CALLTYPE
grpcsharp_channel_args_create(size_t num_args) {
grpc_channel_args *args =
(grpc_channel_args *)gpr_malloc(sizeof(grpc_channel_args));
memset(args, 0, sizeof(grpc_channel_args));
args->num_args = num_args;
args->args = (grpc_arg *)gpr_malloc(sizeof(grpc_arg) * num_args);
memset(args->args, 0, sizeof(grpc_arg) * num_args);
return args;
}
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_channel_args_set_string(grpc_channel_args *args, size_t index,
const char *key, const char *value) {
GPR_ASSERT(args);
GPR_ASSERT(index < args->num_args);
args->args[index].type = GRPC_ARG_STRING;
args->args[index].key = gpr_strdup(key);
args->args[index].value.string = gpr_strdup(value);
}
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_channel_args_destroy(grpc_channel_args *args) {
size_t i;
if (args) {
for (i = 0; i < args->num_args; i++) {
gpr_free(args->args[i].key);
if (args->args[i].type == GRPC_ARG_STRING) {
gpr_free(args->args[i].value.string);
}
}
gpr_free(args->args);
gpr_free(args);
}
}
/* Timespec */
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(); }
@ -585,6 +625,34 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
&(ctx->server_rpc_new.request_metadata), cq, ctx);
}
/* Security */
GPR_EXPORT grpc_credentials *GPR_CALLTYPE
grpcsharp_ssl_credentials_create(const char *pem_root_certs,
const char *key_cert_pair_cert_chain,
const char *key_cert_pair_private_key) {
grpc_ssl_pem_key_cert_pair key_cert_pair;
if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
key_cert_pair.cert_chain = key_cert_pair_cert_chain;
key_cert_pair.private_key = key_cert_pair_private_key;
return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair);
} else {
GPR_ASSERT(!key_cert_pair_cert_chain);
GPR_ASSERT(!key_cert_pair_private_key);
return grpc_ssl_credentials_create(pem_root_certs, NULL);
}
}
GPR_EXPORT void grpcsharp_credentials_release(grpc_credentials *creds) {
grpc_credentials_release(creds);
}
GPR_EXPORT grpc_channel *GPR_CALLTYPE
grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target,
const grpc_channel_args *args) {
return grpc_secure_channel_create(creds, target, args);
}
/* Logging */
typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line,

@ -1,9 +1,4 @@
{
"variables" : {
'no_install': "<!(echo $GRPC_NO_INSTALL)",
'grpc_root': "<!(echo $GRPC_ROOT)",
'grpc_lib_subdir': "<!(echo $GRPC_LIB_SUBDIR)"
},
"targets" : [
{
'include_dirs': [
@ -24,7 +19,9 @@
'link_settings': {
'libraries': [
'-lrt',
'-lpthread'
'-lpthread',
'-lgrpc',
'-lgpr'
],
},
"target_name": "grpc",
@ -38,27 +35,6 @@
"ext/server.cc",
"ext/server_credentials.cc",
"ext/timeval.cc"
],
'conditions' : [
['no_install=="yes"', {
'include_dirs': [
"<(grpc_root)/include"
],
'link_settings': {
'libraries': [
'<(grpc_root)/<(grpc_lib_subdir)/libgrpc.a',
'<(grpc_root)/<(grpc_lib_subdir)/libgpr.a'
]
}
}],
['no_install!="yes"', {
'link_settings': {
'libraries': [
'-lgrpc',
'-lgpr'
]
}
}]
]
}
]

@ -44,7 +44,6 @@
namespace grpc {
namespace node {
using ::node::Buffer;
using v8::Context;
using v8::Function;
using v8::Handle;
@ -54,8 +53,8 @@ using v8::Value;
grpc_byte_buffer *BufferToByteBuffer(Handle<Value> buffer) {
NanScope();
int length = Buffer::Length(buffer);
char *data = Buffer::Data(buffer);
int length = ::node::Buffer::Length(buffer);
char *data = ::node::Buffer::Data(buffer);
gpr_slice slice = gpr_slice_malloc(length);
memcpy(GPR_SLICE_START_PTR(slice), data, length);
grpc_byte_buffer *byte_buffer(grpc_byte_buffer_create(&slice, 1));
@ -66,7 +65,7 @@ grpc_byte_buffer *BufferToByteBuffer(Handle<Value> buffer) {
Handle<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
NanEscapableScope();
if (buffer == NULL) {
NanReturnNull();
return NanEscapeScope(NanNull());
}
size_t length = grpc_byte_buffer_length(buffer);
char *result = reinterpret_cast<char *>(calloc(length, sizeof(char)));
@ -82,12 +81,14 @@ Handle<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
Handle<Value> MakeFastBuffer(Handle<Value> slowBuffer) {
NanEscapableScope();
Handle<Object> globalObj = Context::GetCurrent()->Global();
Handle<Object> globalObj = NanGetCurrentContext()->Global();
Handle<Function> bufferConstructor = Handle<Function>::Cast(
globalObj->Get(NanNew("Buffer")));
Handle<Value> consArgs[3] = { slowBuffer,
NanNew<Number>(Buffer::Length(slowBuffer)),
NanNew<Number>(0) };
Handle<Value> consArgs[3] = {
slowBuffer,
NanNew<Number>(::node::Buffer::Length(slowBuffer)),
NanNew<Number>(0)
};
Handle<Object> fastBuffer = bufferConstructor->NewInstance(3, consArgs);
return NanEscapeScope(fastBuffer);
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save