Merge github.com:grpc/grpc into timeouts-need-logs-too

pull/1560/head
Craig Tiller 10 years ago
commit d8afa09a95
  1. 17
      BUILD
  2. 23
      INSTALL
  3. 836
      Makefile
  4. 59
      build.json
  5. 5
      include/grpc++/async_unary_call.h
  6. 8
      include/grpc++/impl/call.h
  7. 7
      include/grpc/grpc_security.h
  8. 8
      include/grpc/support/tls.h
  9. 2
      include/grpc/support/tls_msvc.h
  10. 61
      src/compiler/cpp_generator.cc
  11. 480
      src/compiler/csharp_generator.cc
  12. 45
      src/compiler/csharp_generator.h
  13. 50
      src/compiler/csharp_generator_helpers.h
  14. 72
      src/compiler/csharp_plugin.cc
  15. 23
      src/compiler/generator_helpers.h
  16. 2
      src/core/iomgr/endpoint_pair_windows.c
  17. 34
      src/core/iomgr/iocp_windows.c
  18. 7
      src/core/iomgr/socket_windows.c
  19. 13
      src/core/iomgr/socket_windows.h
  20. 24
      src/core/iomgr/tcp_client_windows.c
  21. 3
      src/core/iomgr/tcp_server_windows.c
  22. 92
      src/core/iomgr/tcp_windows.c
  23. 131
      src/core/security/auth.c
  24. 79
      src/core/security/security_context.c
  25. 48
      src/core/security/security_context.h
  26. 12
      src/core/surface/call.c
  27. 8
      src/core/surface/call.h
  28. 4
      src/csharp/Grpc.Auth/GoogleCredential.cs
  29. 3
      src/csharp/Grpc.Auth/Grpc.Auth.csproj
  30. 1
      src/csharp/Grpc.Auth/packages.config
  31. 2
      src/csharp/Grpc.Examples.MathClient/MathClient.cs
  32. 2
      src/csharp/Grpc.Examples.MathServer/MathServer.cs
  33. 14
      src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
  34. 7
      src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
  35. 5
      src/csharp/Grpc.Examples.Tests/packages.config
  36. 12
      src/csharp/Grpc.Examples/Grpc.Examples.csproj
  37. 15
      src/csharp/Grpc.Examples/MathExamples.cs
  38. 258
      src/csharp/Grpc.Examples/MathGrpc.cs
  39. 3
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  40. 6
      src/csharp/Grpc.Examples/packages.config
  41. 4
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  42. 26
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  43. 6
      src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
  44. 2
      src/csharp/Grpc.IntegrationTesting/InteropServer.cs
  45. 159
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  46. 2
      src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
  47. 43
      src/csharp/generate_proto_csharp.sh
  48. 14
      src/node/examples/math.proto
  49. 24
      src/node/examples/route_guide.proto
  50. 8
      src/node/examples/stock.proto
  51. 7
      src/node/index.js
  52. 2
      src/node/interop/empty.proto
  53. 4
      src/node/interop/interop_client.js
  54. 36
      src/node/interop/messages.proto
  55. 3
      src/node/interop/test.proto
  56. 4
      src/node/package.json
  57. 35
      src/node/src/client.js
  58. 3
      src/node/test/math_client_test.js
  59. 18
      src/node/test/surface_test.js
  60. 6
      src/node/test/test_service.proto
  61. 2
      src/python/README.md
  62. 4
      src/ruby/bin/math_server.rb
  63. 2
      src/ruby/lib/grpc/core/time_consts.rb
  64. 11
      src/ruby/lib/grpc/generic/rpc_server.rb
  65. 38
      src/ruby/lib/grpc/generic/service.rb
  66. 18
      src/ruby/spec/generic/service_spec.rb
  67. 3
      templates/Makefile.template
  68. 70
      templates/vsprojects/Grpc.mak.template
  69. 33
      templates/vsprojects/generate_debug_projects.sh
  70. 2
      templates/vsprojects/gpr/gpr.vcxproj.filters.template
  71. 2
      templates/vsprojects/gpr/gpr.vcxproj.template
  72. 2
      templates/vsprojects/gpr_test_util/gpr_test_util.vcxproj.template
  73. 2
      templates/vsprojects/grpc++/grpc++.vcxproj.filters.template
  74. 2
      templates/vsprojects/grpc++/grpc++.vcxproj.template
  75. 2
      templates/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters.template
  76. 2
      templates/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.template
  77. 2
      templates/vsprojects/grpc/grpc.vcxproj.filters.template
  78. 2
      templates/vsprojects/grpc/grpc.vcxproj.template
  79. 2
      templates/vsprojects/grpc_csharp_ext/grpc_csharp_ext.vcxproj.template
  80. 2
      templates/vsprojects/grpc_test_util/grpc_test_util.vcxproj.template
  81. 2
      templates/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters.template
  82. 2
      templates/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.template
  83. 2
      templates/vsprojects/vcxproj.filters_defs.include
  84. 40
      templates/vsprojects/vcxproj_defs.include
  85. 1
      test/core/end2end/end2end_tests.h
  86. 4
      test/core/end2end/fixtures/chttp2_fake_security.c
  87. 0
      test/core/end2end/fixtures/chttp2_fullstack_uds_posix.c
  88. 3
      test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
  89. 3
      test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
  90. 93
      test/core/end2end/gen_build_json.py
  91. 1
      test/core/end2end/tests/bad_hostname.c
  92. 1
      test/core/end2end/tests/cancel_after_accept.c
  93. 1
      test/core/end2end/tests/cancel_after_accept_and_writes_closed.c
  94. 1
      test/core/end2end/tests/cancel_after_invoke.c
  95. 1
      test/core/end2end/tests/cancel_before_invoke.c
  96. 1
      test/core/end2end/tests/cancel_in_a_vacuum.c
  97. 1
      test/core/end2end/tests/census_simple_request.c
  98. 1
      test/core/end2end/tests/disappearing_server.c
  99. 1
      test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c
  100. 1
      test/core/end2end/tests/early_server_shutdown_finishes_tags.c
  101. Some files were not shown because too many files have changed in this diff Show More

17
BUILD

@ -135,6 +135,7 @@ cc_library(
"src/core/security/secure_endpoint.h", "src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.h", "src/core/security/secure_transport_setup.h",
"src/core/security/security_connector.h", "src/core/security/security_connector.h",
"src/core/security/security_context.h",
"src/core/tsi/fake_transport_security.h", "src/core/tsi/fake_transport_security.h",
"src/core/tsi/ssl_transport_security.h", "src/core/tsi/ssl_transport_security.h",
"src/core/tsi/transport_security.h", "src/core/tsi/transport_security.h",
@ -240,6 +241,7 @@ cc_library(
"src/core/security/secure_endpoint.c", "src/core/security/secure_endpoint.c",
"src/core/security/secure_transport_setup.c", "src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c", "src/core/security/security_connector.c",
"src/core/security/security_context.c",
"src/core/security/server_secure_chttp2.c", "src/core/security/server_secure_chttp2.c",
"src/core/surface/init_secure.c", "src/core/surface/init_secure.c",
"src/core/surface/secure_channel_create.c", "src/core/surface/secure_channel_create.c",
@ -737,6 +739,8 @@ cc_library(
"src/compiler/config.h", "src/compiler/config.h",
"src/compiler/cpp_generator.h", "src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h", "src/compiler/cpp_generator_helpers.h",
"src/compiler/csharp_generator.h",
"src/compiler/csharp_generator_helpers.h",
"src/compiler/generator_helpers.h", "src/compiler/generator_helpers.h",
"src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator.h",
"src/compiler/objective_c_generator_helpers.h", "src/compiler/objective_c_generator_helpers.h",
@ -746,6 +750,7 @@ cc_library(
"src/compiler/ruby_generator_map-inl.h", "src/compiler/ruby_generator_map-inl.h",
"src/compiler/ruby_generator_string-inl.h", "src/compiler/ruby_generator_string-inl.h",
"src/compiler/cpp_generator.cc", "src/compiler/cpp_generator.cc",
"src/compiler/csharp_generator.cc",
"src/compiler/objective_c_generator.cc", "src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc", "src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc", "src/compiler/ruby_generator.cc",
@ -793,6 +798,18 @@ cc_binary(
) )
cc_binary(
name = "grpc_csharp_plugin",
srcs = [
"src/compiler/csharp_plugin.cc",
],
deps = [
"//external:protobuf_compiler",
":grpc_plugin_support",
],
)
cc_binary( cc_binary(
name = "grpc_objective_c_plugin", name = "grpc_objective_c_plugin",
srcs = [ srcs = [

@ -140,6 +140,29 @@ you will need to install certain modules for python.
$ sudo easy_install simplejson mako $ sudo easy_install simplejson mako
Mingw-specific notes:
---------------------
While gRPC compiles properly under mingw, some more preparation work is needed.
The recommendation is to use msys2. The installation instructions are available
at that address: http://msys2.github.io/
Once this is installed, make sure you are using the following: MinGW-w64 Win64.
You'll be required to install a few more packages:
$ pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-zlib autoconf automake libtool
Please also install OpenSSL from that website:
http://slproweb.com/products/Win32OpenSSL.html
The package Win64 OpenSSL v1.0.2a should do. At that point you should be able
to compile gRPC with the following:
$ export LDFLAGS="-L/mingw64/lib -L/c/OpenSSL-Win64"
$ export CPPFLAGS="-I/mingw64/include -I/c/OpenSSL-Win64/include"
$ make
A word on OpenSSL A word on OpenSSL
----------------- -----------------

File diff suppressed because one or more lines are too long

@ -6,7 +6,7 @@
"#": "The public version number of the library.", "#": "The public version number of the library.",
"version": { "version": {
"major": 0, "major": 0,
"minor": 7, "minor": 8,
"micro": 0, "micro": 0,
"build": 0 "build": 0
} }
@ -410,6 +410,7 @@
"src/core/security/secure_endpoint.h", "src/core/security/secure_endpoint.h",
"src/core/security/secure_transport_setup.h", "src/core/security/secure_transport_setup.h",
"src/core/security/security_connector.h", "src/core/security/security_connector.h",
"src/core/security/security_context.h",
"src/core/tsi/fake_transport_security.h", "src/core/tsi/fake_transport_security.h",
"src/core/tsi/ssl_transport_security.h", "src/core/tsi/ssl_transport_security.h",
"src/core/tsi/transport_security.h", "src/core/tsi/transport_security.h",
@ -430,6 +431,7 @@
"src/core/security/secure_endpoint.c", "src/core/security/secure_endpoint.c",
"src/core/security/secure_transport_setup.c", "src/core/security/secure_transport_setup.c",
"src/core/security/security_connector.c", "src/core/security/security_connector.c",
"src/core/security/security_context.c",
"src/core/security/server_secure_chttp2.c", "src/core/security/server_secure_chttp2.c",
"src/core/surface/init_secure.c", "src/core/surface/init_secure.c",
"src/core/surface/secure_channel_create.c", "src/core/surface/secure_channel_create.c",
@ -553,7 +555,8 @@
"filegroups": [ "filegroups": [
"grpc++_base" "grpc++_base"
], ],
"secure": "no" "secure": "no",
"vs_project_guid": "{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}"
}, },
{ {
"name": "grpc_plugin_support", "name": "grpc_plugin_support",
@ -563,6 +566,8 @@
"src/compiler/config.h", "src/compiler/config.h",
"src/compiler/cpp_generator.h", "src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h", "src/compiler/cpp_generator_helpers.h",
"src/compiler/csharp_generator.h",
"src/compiler/csharp_generator_helpers.h",
"src/compiler/generator_helpers.h", "src/compiler/generator_helpers.h",
"src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator.h",
"src/compiler/objective_c_generator_helpers.h", "src/compiler/objective_c_generator_helpers.h",
@ -574,6 +579,7 @@
], ],
"src": [ "src": [
"src/compiler/cpp_generator.cc", "src/compiler/cpp_generator.cc",
"src/compiler/csharp_generator.cc",
"src/compiler/objective_c_generator.cc", "src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc", "src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc" "src/compiler/ruby_generator.cc"
@ -995,6 +1001,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1039,6 +1048,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1053,6 +1065,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1608,6 +1623,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1664,6 +1682,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1678,6 +1699,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1692,6 +1716,9 @@
"grpc", "grpc",
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
],
"platforms": [
"posix"
] ]
}, },
{ {
@ -1931,6 +1958,18 @@
], ],
"secure": "no" "secure": "no"
}, },
{
"name": "grpc_csharp_plugin",
"build": "protoc",
"language": "c++",
"src": [
"src/compiler/csharp_plugin.cc"
],
"deps": [
"grpc_plugin_support"
],
"secure": "no"
},
{ {
"name": "grpc_objective_c_plugin", "name": "grpc_objective_c_plugin",
"build": "protoc", "build": "protoc",
@ -2208,6 +2247,22 @@
"gpr_test_util", "gpr_test_util",
"gpr" "gpr"
] ]
},
{
"name": "thread_stress_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/thread_stress_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
} }
] ]
} }

@ -60,9 +60,8 @@ class ClientAsyncResponseReader GRPC_FINAL
public: public:
ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq, ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context, const RpcMethod& method, ClientContext* context,
const grpc::protobuf::Message& request, void* tag) const grpc::protobuf::Message& request)
: context_(context), call_(channel->CreateCall(method, context, cq)) { : context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_); init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
init_buf_.AddSendMessage(request); init_buf_.AddSendMessage(request);
init_buf_.AddClientSendClose(); init_buf_.AddClientSendClose();
@ -90,7 +89,7 @@ class ClientAsyncResponseReader GRPC_FINAL
private: private:
ClientContext* context_; ClientContext* context_;
Call call_; Call call_;
CallOpBuffer init_buf_; SneakyCallOpBuffer init_buf_;
CallOpBuffer meta_buf_; CallOpBuffer meta_buf_;
CallOpBuffer finish_buf_; CallOpBuffer finish_buf_;
}; };

@ -123,6 +123,14 @@ class CallOpBuffer : public CompletionQueueTag {
bool* recv_closed_; bool* recv_closed_;
}; };
// SneakyCallOpBuffer does not post completions to the completion queue
class SneakyCallOpBuffer GRPC_FINAL : public CallOpBuffer {
public:
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
return CallOpBuffer::FinalizeResult(tag, status) && false;
}
};
// Channel and Server implement this to allow them to hook performing ops // Channel and Server implement this to allow them to hook performing ops
class CallHook { class CallHook {
public: public:

@ -184,6 +184,13 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
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_server_credentials *creds);
/* --- Call specific credentials. --- */
/* Sets a credentials to a call. Can only be called on the client side before
grpc_call_start_batch. */
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -34,7 +34,7 @@
#ifndef GRPC_SUPPORT_TLS_H #ifndef GRPC_SUPPORT_TLS_H
#define GRPC_SUPPORT_TLS_H #define GRPC_SUPPORT_TLS_H
#include "port_platform.h" #include <grpc/support/port_platform.h>
/* Thread local storage. /* Thread local storage.
@ -63,15 +63,15 @@
ALL functions here may be implemented as macros. */ ALL functions here may be implemented as macros. */
#ifdef GPR_GCC_TLS #ifdef GPR_GCC_TLS
#include "tls_gcc.h" #include <grpc/support/tls_gcc.h>
#endif #endif
#ifdef GPR_MSVC_TLS #ifdef GPR_MSVC_TLS
#include "tls_msvc.h" #include <grpc/support/tls_msvc.h>
#endif #endif
#ifdef GPR_PTHREAD_TLS #ifdef GPR_PTHREAD_TLS
#include "tls_pthread.h" #include <grpc/support/tls_pthread.h>
#endif #endif
#endif #endif

@ -42,7 +42,7 @@ struct gpr_msvc_thread_local {
}; };
#define GPR_TLS_DECL(name) \ #define GPR_TLS_DECL(name) \
static __thread struct gpr_msvc_thread_local name = {0} static __declspec(thread) struct gpr_msvc_thread_local name = {0}
#define gpr_tls_init(tls) do {} while (0) #define gpr_tls_init(tls) do {} while (0)
#define gpr_tls_destroy(tls) do {} while (0) #define gpr_tls_destroy(tls) do {} while (0)

@ -66,50 +66,6 @@ bool BidiStreaming(const grpc::protobuf::MethodDescriptor *method) {
return method->client_streaming() && method->server_streaming(); return method->client_streaming() && method->server_streaming();
} }
bool HasUnaryCalls(const grpc::protobuf::FileDescriptor *file) {
for (int i = 0; i < file->service_count(); i++) {
for (int j = 0; j < file->service(i)->method_count(); j++) {
if (NoStreaming(file->service(i)->method(j))) {
return true;
}
}
}
return false;
}
bool HasClientOnlyStreaming(const grpc::protobuf::FileDescriptor *file) {
for (int i = 0; i < file->service_count(); i++) {
for (int j = 0; j < file->service(i)->method_count(); j++) {
if (ClientOnlyStreaming(file->service(i)->method(j))) {
return true;
}
}
}
return false;
}
bool HasServerOnlyStreaming(const grpc::protobuf::FileDescriptor *file) {
for (int i = 0; i < file->service_count(); i++) {
for (int j = 0; j < file->service(i)->method_count(); j++) {
if (ServerOnlyStreaming(file->service(i)->method(j))) {
return true;
}
}
}
return false;
}
bool HasBidiStreaming(const grpc::protobuf::FileDescriptor *file) {
for (int i = 0; i < file->service_count(); i++) {
for (int j = 0; j < file->service(i)->method_count(); j++) {
if (BidiStreaming(file->service(i)->method(j))) {
return true;
}
}
}
return false;
}
grpc::string FilenameIdentifier(const grpc::string &filename) { grpc::string FilenameIdentifier(const grpc::string &filename) {
grpc::string result; grpc::string result;
for (unsigned i = 0; i < filename.size(); i++) { for (unsigned i = 0; i < filename.size(); i++) {
@ -204,13 +160,13 @@ void PrintHeaderClientMethodInterfaces(grpc::protobuf::io::Printer *printer,
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> " "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
"Async$Method$(::grpc::ClientContext* context, " "Async$Method$(::grpc::ClientContext* context, "
"const $Request$& request, " "const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n"); "::grpc::CompletionQueue* cq) {\n");
printer->Indent(); printer->Indent();
printer->Print( printer->Print(
*vars, *vars,
"return std::unique_ptr< " "return std::unique_ptr< "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>(" "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
"Async$Method$Raw(context, request, cq, tag));\n"); "Async$Method$Raw(context, request, cq));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
@ -301,7 +257,7 @@ void PrintHeaderClientMethodInterfaces(grpc::protobuf::io::Printer *printer,
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* " "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
"Async$Method$Raw(::grpc::ClientContext* context, " "Async$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, " "const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) = 0;\n"); "::grpc::CompletionQueue* cq) = 0;\n");
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -349,7 +305,6 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer,
grpc_cpp_generator::ClassName(method->input_type(), true); grpc_cpp_generator::ClassName(method->input_type(), true);
(*vars)["Response"] = (*vars)["Response"] =
grpc_cpp_generator::ClassName(method->output_type(), true); grpc_cpp_generator::ClassName(method->output_type(), true);
if (is_public) { if (is_public) {
if (NoStreaming(method)) { if (NoStreaming(method)) {
printer->Print( printer->Print(
@ -361,13 +316,13 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer,
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
"Async$Method$(::grpc::ClientContext* context, " "Async$Method$(::grpc::ClientContext* context, "
"const $Request$& request, " "const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n"); "::grpc::CompletionQueue* cq) {\n");
printer->Indent(); printer->Indent();
printer->Print( printer->Print(
*vars, *vars,
"return std::unique_ptr< " "return std::unique_ptr< "
"::grpc::ClientAsyncResponseReader< $Response$>>(" "::grpc::ClientAsyncResponseReader< $Response$>>("
"Async$Method$Raw(context, request, cq, tag));\n"); "Async$Method$Raw(context, request, cq));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
@ -456,7 +411,7 @@ void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer,
"::grpc::ClientAsyncResponseReader< $Response$>* " "::grpc::ClientAsyncResponseReader< $Response$>* "
"Async$Method$Raw(::grpc::ClientContext* context, " "Async$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, " "const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); "::grpc::CompletionQueue* cq) GRPC_OVERRIDE;\n");
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -783,13 +738,13 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
"::grpc::ClientAsyncResponseReader< $Response$>* " "::grpc::ClientAsyncResponseReader< $Response$>* "
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, " "const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n"); "::grpc::CompletionQueue* cq) {\n");
printer->Print(*vars, printer->Print(*vars,
" return new " " return new "
"::grpc::ClientAsyncResponseReader< $Response$>(" "::grpc::ClientAsyncResponseReader< $Response$>("
"channel(), cq, " "channel(), cq, "
"rpcmethod_$Method$_, " "rpcmethod_$Method$_, "
"context, request, tag);\n" "context, request);\n"
"}\n\n"); "}\n\n");
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print(*vars, printer->Print(*vars,

@ -0,0 +1,480 @@
/*
*
* 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 <cctype>
#include <map>
#include <vector>
#include "src/compiler/config.h"
#include "src/compiler/csharp_generator_helpers.h"
#include "src/compiler/csharp_generator.h"
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::Descriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using grpc_generator::MethodType;
using grpc_generator::GetMethodType;
using grpc_generator::METHODTYPE_NO_STREAMING;
using grpc_generator::METHODTYPE_CLIENT_STREAMING;
using grpc_generator::METHODTYPE_SERVER_STREAMING;
using grpc_generator::METHODTYPE_BIDI_STREAMING;
using std::map;
using std::vector;
namespace grpc_csharp_generator {
namespace {
std::string GetCSharpNamespace(const FileDescriptor* file) {
// TODO(jtattermusch): this should be based on csharp_namespace option
return file->package();
}
std::string GetMessageType(const Descriptor* message) {
// TODO(jtattermusch): this has to match with C# protobuf generator
return message->name();
}
std::string GetServiceClassName(const ServiceDescriptor* service) {
return service->name();
}
std::string GetClientInterfaceName(const ServiceDescriptor* service) {
return "I" + service->name() + "Client";
}
std::string GetClientClassName(const ServiceDescriptor* service) {
return service->name() + "Client";
}
std::string GetServerInterfaceName(const ServiceDescriptor* service) {
return "I" + service->name();
}
std::string GetCSharpMethodType(MethodType method_type) {
switch (method_type) {
case METHODTYPE_NO_STREAMING:
return "MethodType.Unary";
case METHODTYPE_CLIENT_STREAMING:
return "MethodType.ClientStreaming";
case METHODTYPE_SERVER_STREAMING:
return "MethodType.ServerStreaming";
case METHODTYPE_BIDI_STREAMING:
return "MethodType.DuplexStreaming";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetServiceNameFieldName() {
return "__ServiceName";
}
std::string GetMarshallerFieldName(const Descriptor *message) {
return "__Marshaller_" + message->name();
}
std::string GetMethodFieldName(const MethodDescriptor *method) {
return "__Method_" + method->name();
}
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
if (method->client_streaming()) {
return "";
}
return GetMessageType(method->input_type()) + " request, ";
}
std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
return "Task<" + GetMessageType(method->output_type()) + ">";
case METHODTYPE_CLIENT_STREAMING:
return "AsyncClientStreamingCall<" + GetMessageType(method->input_type())
+ ", " + GetMessageType(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
return "AsyncServerStreamingCall<" + GetMessageType(method->output_type())
+ ">";
case METHODTYPE_BIDI_STREAMING:
return "AsyncDuplexStreamingCall<" + GetMessageType(method->input_type())
+ ", " + GetMessageType(method->output_type()) + ">";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetMethodRequestParamServer(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_SERVER_STREAMING:
return GetMessageType(method->input_type()) + " request";
case METHODTYPE_CLIENT_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "IAsyncStreamReader<" + GetMessageType(method->input_type())
+ "> requestStream";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetMethodReturnTypeServer(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_CLIENT_STREAMING:
return "Task<" + GetMessageType(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "Task";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_CLIENT_STREAMING:
return "";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return ", IServerStreamWriter<" + GetMessageType(method->output_type())
+ "> responseStream";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
// Gets vector of all messages used as input or output types.
std::vector<const Descriptor*> GetUsedMessages(
const ServiceDescriptor *service) {
std::set<const Descriptor*> descriptor_set;
std::vector<const Descriptor*> result; // vector is to maintain stable ordering
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
if (descriptor_set.find(method->input_type()) == descriptor_set.end()) {
descriptor_set.insert(method->input_type());
result.push_back(method->input_type());
}
if (descriptor_set.find(method->output_type()) == descriptor_set.end()) {
descriptor_set.insert(method->output_type());
result.push_back(method->output_type());
}
}
return result;
}
void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) {
std::vector<const Descriptor*> used_messages = GetUsedMessages(service);
for (size_t i = 0; i < used_messages.size(); i++) {
const Descriptor *message = used_messages[i];
out->Print(
"static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => arg.ToByteArray(), $type$.ParseFrom);\n",
"fieldname", GetMarshallerFieldName(message), "type",
GetMessageType(message));
}
out->Print("\n");
}
void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
out->Print(
"static readonly Method<$request$, $response$> $fieldname$ = new Method<$request$, $response$>(\n",
"fieldname", GetMethodFieldName(method), "request",
GetMessageType(method->input_type()), "response",
GetMessageType(method->output_type()));
out->Indent();
out->Indent();
out->Print("$methodtype$,\n", "methodtype",
GetCSharpMethodType(GetMethodType(method)));
out->Print("\"$methodname$\",\n", "methodname", method->name());
out->Print("$requestmarshaller$,\n", "requestmarshaller",
GetMarshallerFieldName(method->input_type()));
out->Print("$responsemarshaller$);\n", "responsemarshaller",
GetMarshallerFieldName(method->output_type()));
out->Print("\n");
out->Outdent();
out->Outdent();
}
void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// client-side stub interface\n");
out->Print("public interface $name$\n", "name",
GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
MethodType method_type = GetMethodType(method);
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"$response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken));\n",
"methodname", method->name(), "request",
GetMessageType(method->input_type()), "response",
GetMessageType(method->output_type()));
}
std::string method_name = method->name();
if (method_type == METHODTYPE_NO_STREAMING) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"$returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken));\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// server-side interface\n");
out->Print("public interface $name$\n", "name",
GetServerInterfaceName(service));
out->Print("{\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
out->Print("$returntype$ $methodname$(ServerCallContext context, $request$$response_stream_maybe$);\n",
"methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request",
GetMethodRequestParamServer(method), "response_stream_maybe",
GetMethodResponseStreamMaybe(method));
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("// client stub\n");
out->Print(
"public class $name$ : AbstractStub<$name$, StubConfiguration>, $interface$\n",
"name", GetClientClassName(service), "interface",
GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
// constructors
out->Print(
"public $name$(Channel channel) : this(channel, StubConfiguration.Default)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print(
"public $name$(Channel channel, StubConfiguration config) : base(channel, config)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
MethodType method_type = GetMethodType(method);
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"public $response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetMessageType(method->input_type()), "response",
GetMessageType(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request, token);\n");
out->Outdent();
out->Print("}\n");
}
std::string method_name = method->name();
if (method_type == METHODTYPE_NO_STREAMING) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"public $returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request, token);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call, token);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request, token);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call, token);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
out->Outdent();
out->Print("}\n");
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
out->Print(
"// creates service definition that can be registered with a server\n");
out->Print(
"public static ServerServiceDefinition BindService($interface$ serviceImpl)\n",
"interface", GetServerInterfaceName(service));
out->Print("{\n");
out->Indent();
out->Print(
"return ServerServiceDefinition.CreateBuilder($servicenamefield$)\n",
"servicenamefield", GetServiceNameFieldName());
out->Indent();
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
out->Print(".AddMethod($methodfield$, serviceImpl.$methodname$)",
"methodfield", GetMethodFieldName(method), "methodname",
method->name());
if (i == service->method_count() - 1) {
out->Print(".Build();");
}
out->Print("\n");
}
out->Outdent();
out->Outdent();
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) {
out->Print("// creates a new client stub\n");
out->Print("public static $interface$ NewStub(Channel channel)\n",
"interface", GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $classname$(channel);\n", "classname",
GetClientClassName(service));
out->Outdent();
out->Print("}\n");
out->Print("\n");
out->Print("// creates a new client stub\n");
out->Print(
"public static $interface$ NewStub(Channel channel, StubConfiguration config)\n",
"interface", GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $classname$(channel, config);\n", "classname",
GetClientClassName(service));
out->Outdent();
out->Print("}\n");
}
void GenerateService(Printer* out, const ServiceDescriptor *service) {
out->Print("public static class $classname$\n", "classname",
GetServiceClassName(service));
out->Print("{\n");
out->Indent();
out->Print("static readonly string $servicenamefield$ = \"$servicename$\";\n",
"servicenamefield", GetServiceNameFieldName(), "servicename",
service->full_name());
out->Print("\n");
GenerateMarshallerFields(out, service);
for (int i = 0; i < service->method_count(); i++) {
GenerateStaticMethodField(out, service->method(i));
}
GenerateClientInterface(out, service);
GenerateServerInterface(out, service);
GenerateClientStub(out, service);
GenerateBindServiceMethod(out, service);
GenerateNewStubMethods(out, service);
out->Outdent();
out->Print("}\n");
}
} // anonymous namespace
grpc::string GetServices(const FileDescriptor *file) {
grpc::string output;
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
// Don't write out any output if there no services, to avoid empty service
// files being generated for proto files that don't declare any.
if (file->service_count() == 0) {
return output;
}
// Write out a file header.
out.Print("// Generated by the protocol buffer compiler. DO NOT EDIT!\n");
out.Print("// source: $filename$\n", "filename", file->name());
out.Print("#region Designer generated code\n");
out.Print("\n");
out.Print("using System;\n");
out.Print("using System.Threading;\n");
out.Print("using System.Threading.Tasks;\n");
out.Print("using Grpc.Core;\n");
// TODO(jtattermusch): add using for protobuf message classes
out.Print("\n");
out.Print("namespace $namespace$ {\n", "namespace", GetCSharpNamespace(file));
out.Indent();
for (int i = 0; i < file->service_count(); i++) {
GenerateService(&out, file->service(i));
}
out.Outdent();
out.Print("}\n");
out.Print("#endregion\n");
return output;
}
} // namespace grpc_csharp_generator

@ -0,0 +1,45 @@
/*
*
* 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.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H
#include "src/compiler/config.h"
namespace grpc_csharp_generator {
grpc::string GetServices(const grpc::protobuf::FileDescriptor *file);
} // namespace grpc_csharp_generator
#endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H

@ -0,0 +1,50 @@
/*
*
* 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.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H
#define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
namespace grpc_csharp_generator {
inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
grpc::string *file_name_or_error) {
*file_name_or_error = grpc_generator::FileNameInUpperCamel(file) + "Grpc.cs";
return true;
}
} // namespace grpc_csharp_generator
#endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H

@ -0,0 +1,72 @@
/*
*
* 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.
*
*/
// Generates C# gRPC service interface out of Protobuf IDL.
#include <memory>
#include "src/compiler/config.h"
#include "src/compiler/csharp_generator.h"
#include "src/compiler/csharp_generator_helpers.h"
class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
public:
CSharpGrpcGenerator() {}
~CSharpGrpcGenerator() {}
bool Generate(const grpc::protobuf::FileDescriptor *file,
const grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context,
grpc::string *error) const {
grpc::string code = grpc_csharp_generator::GetServices(file);
if (code.size() == 0) {
return true; // don't generate a file if there are no services
}
// Get output file name.
grpc::string file_name;
if (!grpc_csharp_generator::ServicesFilename(file, &file_name)) {
return false;
}
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->Open(file_name));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
coded_out.WriteRaw(code.data(), code.size());
return true;
}
};
int main(int argc, char *argv[]) {
CSharpGrpcGenerator generator;
return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}

@ -116,6 +116,29 @@ inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *f
return LowerUnderscoreToUpperCamel(StripProto(file->name())); return LowerUnderscoreToUpperCamel(StripProto(file->name()));
} }
enum MethodType {
METHODTYPE_NO_STREAMING,
METHODTYPE_CLIENT_STREAMING,
METHODTYPE_SERVER_STREAMING,
METHODTYPE_BIDI_STREAMING
};
inline MethodType GetMethodType(const grpc::protobuf::MethodDescriptor *method) {
if (method->client_streaming()) {
if (method->server_streaming()) {
return METHODTYPE_BIDI_STREAMING;
} else {
return METHODTYPE_CLIENT_STREAMING;
}
} else {
if (method->server_streaming()) {
return METHODTYPE_SERVER_STREAMING;
} else {
return METHODTYPE_NO_STREAMING;
}
}
}
} // namespace grpc_generator } // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H

@ -68,6 +68,8 @@ static void create_sockets(SOCKET sv[2]) {
GPR_ASSERT(svr_sock != INVALID_SOCKET); GPR_ASSERT(svr_sock != INVALID_SOCKET);
closesocket(lst_sock); closesocket(lst_sock);
grpc_tcp_prepare_socket(cli_sock);
grpc_tcp_prepare_socket(svr_sock);
sv[1] = cli_sock; sv[1] = cli_sock;
sv[0] = svr_sock; sv[0] = svr_sock;

@ -53,6 +53,7 @@ static OVERLAPPED g_iocp_custom_overlap;
static gpr_event g_shutdown_iocp; static gpr_event g_shutdown_iocp;
static gpr_event g_iocp_done; static gpr_event g_iocp_done;
static gpr_atm g_orphans = 0; static gpr_atm g_orphans = 0;
static gpr_atm g_custom_events = 0;
static HANDLE g_iocp; static HANDLE g_iocp;
@ -62,20 +63,19 @@ static void do_iocp_work() {
DWORD flags = 0; DWORD flags = 0;
ULONG_PTR completion_key; ULONG_PTR completion_key;
LPOVERLAPPED overlapped; LPOVERLAPPED overlapped;
gpr_timespec wait_time = gpr_inf_future;
grpc_winsocket *socket; grpc_winsocket *socket;
grpc_winsocket_callback_info *info; grpc_winsocket_callback_info *info;
void(*f)(void *, int) = NULL; void(*f)(void *, int) = NULL;
void *opaque = NULL; void *opaque = NULL;
success = GetQueuedCompletionStatus(g_iocp, &bytes, success = GetQueuedCompletionStatus(g_iocp, &bytes,
&completion_key, &overlapped, &completion_key, &overlapped,
gpr_time_to_millis(wait_time)); INFINITE);
if (!success && !overlapped) { /* success = 0 and overlapped = NULL means the deadline got attained.
/* The deadline got attained. */ Which is impossible. since our wait time is +inf */
return; GPR_ASSERT(success || overlapped);
}
GPR_ASSERT(completion_key && overlapped); GPR_ASSERT(completion_key && overlapped);
if (overlapped == &g_iocp_custom_overlap) { if (overlapped == &g_iocp_custom_overlap) {
gpr_atm_full_fetch_add(&g_custom_events, -1);
if (completion_key == (ULONG_PTR) &g_iocp_kick_token) { if (completion_key == (ULONG_PTR) &g_iocp_kick_token) {
/* We were awoken from a kick. */ /* We were awoken from a kick. */
return; return;
@ -93,13 +93,17 @@ static void do_iocp_work() {
gpr_log(GPR_ERROR, "Unknown IOCP operation"); gpr_log(GPR_ERROR, "Unknown IOCP operation");
abort(); abort();
} }
success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, GPR_ASSERT(info->outstanding);
FALSE, &flags);
if (socket->orphan) { if (socket->orphan) {
grpc_winsocket_destroy(socket); info->outstanding = 0;
gpr_atm_full_fetch_add(&g_orphans, -1); if (!socket->read_info.outstanding && !socket->write_info.outstanding) {
grpc_winsocket_destroy(socket);
gpr_atm_full_fetch_add(&g_orphans, -1);
}
return; return;
} }
success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
FALSE, &flags);
info->bytes_transfered = bytes; info->bytes_transfered = bytes;
info->wsa_error = success ? 0 : WSAGetLastError(); info->wsa_error = success ? 0 : WSAGetLastError();
GPR_ASSERT(overlapped == &info->overlapped); GPR_ASSERT(overlapped == &info->overlapped);
@ -117,10 +121,13 @@ static void do_iocp_work() {
} }
static void iocp_loop(void *p) { static void iocp_loop(void *p) {
while (gpr_atm_acq_load(&g_orphans) || !gpr_event_get(&g_shutdown_iocp)) { while (gpr_atm_acq_load(&g_orphans) ||
gpr_atm_acq_load(&g_custom_events) ||
!gpr_event_get(&g_shutdown_iocp)) {
grpc_maybe_call_delayed_callbacks(NULL, 1); grpc_maybe_call_delayed_callbacks(NULL, 1);
do_iocp_work(); do_iocp_work();
} }
gpr_log(GPR_DEBUG, "iocp_loop is done");
gpr_event_set(&g_iocp_done, (void *)1); gpr_event_set(&g_iocp_done, (void *)1);
} }
@ -128,8 +135,8 @@ static void iocp_loop(void *p) {
void grpc_iocp_init(void) { void grpc_iocp_init(void) {
gpr_thd_id id; gpr_thd_id id;
g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
(ULONG_PTR)NULL, 0); NULL, (ULONG_PTR)NULL, 0);
GPR_ASSERT(g_iocp); GPR_ASSERT(g_iocp);
gpr_event_init(&g_iocp_done); gpr_event_init(&g_iocp_done);
@ -140,6 +147,7 @@ void grpc_iocp_init(void) {
void grpc_iocp_kick(void) { void grpc_iocp_kick(void) {
BOOL success; BOOL success;
gpr_atm_full_fetch_add(&g_custom_events, 1);
success = PostQueuedCompletionStatus(g_iocp, 0, success = PostQueuedCompletionStatus(g_iocp, 0,
(ULONG_PTR) &g_iocp_kick_token, (ULONG_PTR) &g_iocp_kick_token,
&g_iocp_custom_overlap); &g_iocp_custom_overlap);

@ -75,15 +75,14 @@ void grpc_winsocket_shutdown(grpc_winsocket *socket) {
/* Abandons a socket. Either we're going to queue it up for garbage collecting /* Abandons a socket. Either we're going to queue it up for garbage collecting
from the IO Completion Port thread, or destroy it immediately. Note that this from the IO Completion Port thread, or destroy it immediately. Note that this
mechanisms assumes that we're either always waiting for an operation, or we mechanisms assumes that we're either always waiting for an operation, or we
explicitely know that we don't. If there is a future case where we can have explicitly know that we don't. If there is a future case where we can have
an "idle" socket which is neither trying to read or write, we'd start leaking an "idle" socket which is neither trying to read or write, we'd start leaking
both memory and sockets. */ both memory and sockets. */
void grpc_winsocket_orphan(grpc_winsocket *winsocket) { void grpc_winsocket_orphan(grpc_winsocket *winsocket) {
SOCKET socket = winsocket->socket; SOCKET socket = winsocket->socket;
if (!winsocket->closed_early) { if (winsocket->read_info.outstanding || winsocket->write_info.outstanding) {
grpc_iocp_socket_orphan(winsocket); grpc_iocp_socket_orphan(winsocket);
} } else {
if (winsocket->closed_early) {
grpc_winsocket_destroy(winsocket); grpc_winsocket_destroy(winsocket);
} }
closesocket(socket); closesocket(socket);

@ -65,12 +65,14 @@ typedef struct grpc_winsocket_callback_info {
/* The results of the overlapped operation. */ /* The results of the overlapped operation. */
DWORD bytes_transfered; DWORD bytes_transfered;
int wsa_error; int wsa_error;
/* A boolean indicating that we started an operation. */
int outstanding;
} grpc_winsocket_callback_info; } grpc_winsocket_callback_info;
/* This is a wrapper to a Windows socket. A socket can have one outstanding /* This is a wrapper to a Windows socket. A socket can have one outstanding
read, and one outstanding write. Doing an asynchronous accept means waiting read, and one outstanding write. Doing an asynchronous accept means waiting
for a read operation. Doing an asynchronous connect means waiting for a for a read operation. Doing an asynchronous connect means waiting for a
write operation. These are completely abitrary ties between the operation write operation. These are completely arbitrary ties between the operation
and the kind of event, because we can have one overlapped per pending and the kind of event, because we can have one overlapped per pending
operation, whichever its nature is. So we could have more dedicated pending operation, whichever its nature is. So we could have more dedicated pending
operation callbacks for connect and listen. But given the scope of listen operation callbacks for connect and listen. But given the scope of listen
@ -87,17 +89,10 @@ typedef struct grpc_winsocket {
/* You can't add the same socket twice to the same IO Completion Port. /* You can't add the same socket twice to the same IO Completion Port.
This prevents that. */ This prevents that. */
int added_to_iocp; int added_to_iocp;
/* A boolean to indicate that the caller has abandonned that socket, but /* A boolean to indicate that the caller has abandoned that socket, but
there is a pending operation that the IO Completion Port will have to there is a pending operation that the IO Completion Port will have to
wait for. The socket will be collected at that time. */ wait for. The socket will be collected at that time. */
int orphan; int orphan;
/* A boolean to indicate that the socket was already closed somehow, and
that no operation is going to be pending. Trying to abandon a socket in
that state won't result in an orphan, but will instead be destroyed
without further delay. We could avoid that boolean by adding one into
grpc_winsocket_callback_info describing that the operation is pending,
but that 1) waste memory more and 2) obfuscate the intent a bit more. */
int closed_early;
} grpc_winsocket; } grpc_winsocket;
/* Create a wrapped windows handle. This takes ownership of it, meaning that /* Create a wrapped windows handle. This takes ownership of it, meaning that

@ -74,7 +74,7 @@ static void async_connect_cleanup(async_connect *ac) {
static void on_alarm(void *acp, int occured) { static void on_alarm(void *acp, int occured) {
async_connect *ac = acp; async_connect *ac = acp;
gpr_mu_lock(&ac->mu); gpr_mu_lock(&ac->mu);
/* If the alarm didn't occor, it got cancelled. */ /* If the alarm didn't occur, it got cancelled. */
if (ac->socket != NULL && occured) { if (ac->socket != NULL && occured) {
grpc_winsocket_shutdown(ac->socket); grpc_winsocket_shutdown(ac->socket);
} }
@ -101,15 +101,14 @@ static void on_connect(void *acp, int from_iocp) {
BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
&transfered_bytes, FALSE, &transfered_bytes, FALSE,
&flags); &flags);
info->outstanding = 0;
GPR_ASSERT(transfered_bytes == 0); GPR_ASSERT(transfered_bytes == 0);
if (!wsa_success) { if (!wsa_success) {
char *utf8_message = gpr_format_message(WSAGetLastError()); char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
gpr_free(utf8_message); gpr_free(utf8_message);
goto finish; } else if (!aborted) {
} else {
ep = grpc_tcp_create(ac->socket); ep = grpc_tcp_create(ac->socket);
goto finish;
} }
} else { } else {
gpr_log(GPR_ERROR, "on_connect is shutting down"); gpr_log(GPR_ERROR, "on_connect is shutting down");
@ -125,20 +124,12 @@ static void on_connect(void *acp, int from_iocp) {
return; return;
} }
abort(); ac->socket->write_info.outstanding = 0;
finish:
/* If we don't have an endpoint, it means the connection failed, /* If we don't have an endpoint, it means the connection failed,
so it doesn't matter if it aborted or failed. We need to orphan so it doesn't matter if it aborted or failed. We need to orphan
that socket. */ that socket. */
if (!ep || aborted) { if (!ep || aborted) grpc_winsocket_orphan(ac->socket);
/* If the connection failed, it means we won't get an IOCP notification,
so let's flag it as already closed. But if the connection was aborted,
while we still got an endpoint, we have to wait for the IOCP to collect
that socket. So let's properly flag that. */
ac->socket->closed_early = !ep;
grpc_winsocket_orphan(ac->socket);
}
async_connect_cleanup(ac); async_connect_cleanup(ac);
/* If the connection was aborted, the callback was already called when /* If the connection was aborted, the callback was already called when
the deadline was met. */ the deadline was met. */
@ -189,7 +180,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp),
&ioctl_num_bytes, NULL, NULL); &ioctl_num_bytes, NULL, NULL);
if (status != 0) { if (status != 0) {
message = "Unable to retreive ConnectEx pointer: %s"; message = "Unable to retrieve ConnectEx pointer: %s";
goto failure; goto failure;
} }
@ -204,6 +195,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp),
socket = grpc_winsocket_create(sock); socket = grpc_winsocket_create(sock);
info = &socket->write_info; info = &socket->write_info;
info->outstanding = 1;
success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped); success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped);
/* It wouldn't be unusual to get a success immediately. But we'll still get /* It wouldn't be unusual to get a success immediately. But we'll still get
@ -225,6 +217,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp),
ac->aborted = 0; ac->aborted = 0;
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
socket->write_info.outstanding = 1;
grpc_socket_notify_on_write(socket, on_connect, ac); grpc_socket_notify_on_write(socket, on_connect, ac);
return; return;
@ -233,7 +226,6 @@ failure:
gpr_log(GPR_ERROR, message, utf8_message); gpr_log(GPR_ERROR, message, utf8_message);
gpr_free(utf8_message); gpr_free(utf8_message);
if (socket) { if (socket) {
socket->closed_early = 1;
grpc_winsocket_orphan(socket); grpc_winsocket_orphan(socket);
} else if (sock != INVALID_SOCKET) { } else if (sock != INVALID_SOCKET) {
closesocket(sock); closesocket(sock);

@ -123,7 +123,6 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s,
closed by the system. */ closed by the system. */
for (i = 0; i < s->nports; i++) { for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i]; server_port *sp = &s->ports[i];
sp->socket->closed_early = 1;
grpc_winsocket_orphan(sp->socket); grpc_winsocket_orphan(sp->socket);
} }
gpr_free(s->ports); gpr_free(s->ports);
@ -249,6 +248,7 @@ static void on_accept(void *arg, int from_iocp) {
if (sp->shutting_down) { if (sp->shutting_down) {
GPR_ASSERT(from_iocp); GPR_ASSERT(from_iocp);
sp->shutting_down = 0; sp->shutting_down = 0;
sp->socket->read_info.outstanding = 0;
gpr_mu_lock(&sp->server->mu); gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) { if (0 == --sp->server->active_ports) {
gpr_cv_broadcast(&sp->server->cv); gpr_cv_broadcast(&sp->server->cv);
@ -420,6 +420,7 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset,
s->cb = cb; s->cb = cb;
s->cb_arg = cb_arg; s->cb_arg = cb_arg;
for (i = 0; i < s->nports; i++) { for (i = 0; i < s->nports; i++) {
s->ports[i].socket->read_info.outstanding = 1;
start_accept(s->ports + i); start_accept(s->ports + i);
s->active_ports++; s->active_ports++;
} }

@ -86,12 +86,10 @@ typedef struct grpc_tcp {
grpc_endpoint_read_cb read_cb; grpc_endpoint_read_cb read_cb;
void *read_user_data; void *read_user_data;
gpr_slice read_slice; gpr_slice read_slice;
int outstanding_read;
grpc_endpoint_write_cb write_cb; grpc_endpoint_write_cb write_cb;
void *write_user_data; void *write_user_data;
gpr_slice_buffer write_slices; gpr_slice_buffer write_slices;
int outstanding_write;
/* The IO Completion Port runs from another thread. We need some mechanism /* The IO Completion Port runs from another thread. We need some mechanism
to protect ourselves when requesting a shutdown. */ to protect ourselves when requesting a shutdown. */
@ -141,14 +139,13 @@ static void on_read(void *tcpp, int from_iocp) {
return; return;
} }
GPR_ASSERT(tcp->outstanding_read); GPR_ASSERT(tcp->socket->read_info.outstanding);
if (socket->read_info.wsa_error != 0) { if (socket->read_info.wsa_error != 0) {
char *utf8_message = gpr_format_message(info->wsa_error); char *utf8_message = gpr_format_message(info->wsa_error);
gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
gpr_free(utf8_message); gpr_free(utf8_message);
status = GRPC_ENDPOINT_CB_ERROR; status = GRPC_ENDPOINT_CB_ERROR;
socket->closed_early = 1;
} else { } else {
if (info->bytes_transfered != 0) { if (info->bytes_transfered != 0) {
sub = gpr_slice_sub(tcp->read_slice, 0, info->bytes_transfered); sub = gpr_slice_sub(tcp->read_slice, 0, info->bytes_transfered);
@ -161,7 +158,7 @@ static void on_read(void *tcpp, int from_iocp) {
} }
} }
tcp->outstanding_read = 0; tcp->socket->read_info.outstanding = 0;
tcp_unref(tcp); tcp_unref(tcp);
cb(opaque, slice, nslices, status); cb(opaque, slice, nslices, status);
@ -175,13 +172,15 @@ static void win_notify_on_read(grpc_endpoint *ep,
int status; int status;
DWORD bytes_read = 0; DWORD bytes_read = 0;
DWORD flags = 0; DWORD flags = 0;
int error;
WSABUF buffer; WSABUF buffer;
GPR_ASSERT(!tcp->outstanding_read); GPR_ASSERT(!tcp->socket->read_info.outstanding);
GPR_ASSERT(!tcp->shutting_down); if (tcp->shutting_down) {
cb(arg, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN);
return;
}
tcp_ref(tcp); tcp_ref(tcp);
tcp->outstanding_read = 1; tcp->socket->read_info.outstanding = 1;
tcp->read_cb = cb; tcp->read_cb = cb;
tcp->read_user_data = arg; tcp->read_user_data = arg;
@ -208,34 +207,13 @@ static void win_notify_on_read(grpc_endpoint *ep,
status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
&info->overlapped, NULL); &info->overlapped, NULL);
if (status == 0) { if (status != 0) {
grpc_socket_notify_on_read(tcp->socket, on_read, tcp); int wsa_error = WSAGetLastError();
return; if (wsa_error != WSA_IO_PENDING) {
} info->wsa_error = wsa_error;
on_read(tcp, 1);
error = WSAGetLastError(); return;
}
if (error != WSA_IO_PENDING) {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "WSARecv error: %s - this means we're going to leak.",
utf8_message);
gpr_free(utf8_message);
/* I'm pretty sure this is a very bad situation there. Hence the log.
What will happen now is that the socket will neither wait for read
or write, unless the caller retry, which is unlikely, but I am not
sure if that's guaranteed. And there might also be a write pending.
This means that the future orphanage of that socket will be in limbo,
and we're going to leak it. I have no idea what could cause this
specific case however, aside from a parameter error from our call.
Normal read errors would actually happen during the overlapped
operation, which is the supported way to go for that. */
tcp->outstanding_read = 0;
tcp_unref(tcp);
cb(arg, NULL, 0, GRPC_ENDPOINT_CB_ERROR);
/* Per the comment above, I'm going to treat that case as a hard failure
for now, and leave the option to catch that and debug. */
__debugbreak();
return;
} }
grpc_socket_notify_on_read(tcp->socket, on_read, tcp); grpc_socket_notify_on_read(tcp->socket, on_read, tcp);
@ -260,7 +238,7 @@ static void on_write(void *tcpp, int from_iocp) {
} }
gpr_mu_unlock(&tcp->mu); gpr_mu_unlock(&tcp->mu);
GPR_ASSERT(tcp->outstanding_write); GPR_ASSERT(tcp->socket->write_info.outstanding);
if (do_abort) { if (do_abort) {
if (from_iocp) gpr_slice_buffer_reset_and_unref(&tcp->write_slices); if (from_iocp) gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
@ -274,13 +252,12 @@ static void on_write(void *tcpp, int from_iocp) {
gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
gpr_free(utf8_message); gpr_free(utf8_message);
status = GRPC_ENDPOINT_CB_ERROR; status = GRPC_ENDPOINT_CB_ERROR;
tcp->socket->closed_early = 1;
} else { } else {
GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length); GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length);
} }
gpr_slice_buffer_reset_and_unref(&tcp->write_slices); gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
tcp->outstanding_write = 0; tcp->socket->write_info.outstanding = 0;
tcp_unref(tcp); tcp_unref(tcp);
cb(opaque, status); cb(opaque, status);
@ -301,11 +278,13 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
WSABUF *allocated = NULL; WSABUF *allocated = NULL;
WSABUF *buffers = local_buffers; WSABUF *buffers = local_buffers;
GPR_ASSERT(!tcp->outstanding_write); GPR_ASSERT(!tcp->socket->write_info.outstanding);
GPR_ASSERT(!tcp->shutting_down); if (tcp->shutting_down) {
return GRPC_ENDPOINT_WRITE_ERROR;
}
tcp_ref(tcp); tcp_ref(tcp);
tcp->outstanding_write = 1; tcp->socket->write_info.outstanding = 1;
tcp->write_cb = cb; tcp->write_cb = cb;
tcp->write_user_data = arg; tcp->write_user_data = arg;
@ -341,7 +320,7 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
} }
if (allocated) gpr_free(allocated); if (allocated) gpr_free(allocated);
gpr_slice_buffer_reset_and_unref(&tcp->write_slices); gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
tcp->outstanding_write = 0; tcp->socket->write_info.outstanding = 0;
tcp_unref(tcp); tcp_unref(tcp);
return ret; return ret;
} }
@ -353,29 +332,12 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
&bytes_sent, 0, &socket->write_info.overlapped, NULL); &bytes_sent, 0, &socket->write_info.overlapped, NULL);
if (allocated) gpr_free(allocated); if (allocated) gpr_free(allocated);
/* It is possible the operation completed then. But we'd still get an IOCP
notification. So let's ignore it and wait for the IOCP. */
if (status != 0) { if (status != 0) {
int error = WSAGetLastError(); int wsa_error = WSAGetLastError();
if (error != WSA_IO_PENDING) { if (wsa_error != WSA_IO_PENDING) {
char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_slice_buffer_reset_and_unref(&tcp->write_slices);
gpr_log(GPR_ERROR, "WSASend error: %s - this means we're going to leak.", tcp->socket->write_info.outstanding = 0;
utf8_message);
gpr_free(utf8_message);
/* I'm pretty sure this is a very bad situation there. Hence the log.
What will happen now is that the socket will neither wait for read
or write, unless the caller retry, which is unlikely, but I am not
sure if that's guaranteed. And there might also be a read pending.
This means that the future orphanage of that socket will be in limbo,
and we're going to leak it. I have no idea what could cause this
specific case however, aside from a parameter error from our call.
Normal read errors would actually happen during the overlapped
operation, which is the supported way to go for that. */
tcp->outstanding_write = 0;
tcp_unref(tcp); tcp_unref(tcp);
/* Per the comment above, I'm going to treat that case as a hard failure
for now, and leave the option to catch that and debug. */
__debugbreak();
return GRPC_ENDPOINT_WRITE_ERROR; return GRPC_ENDPOINT_WRITE_ERROR;
} }
} }

@ -40,6 +40,7 @@
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include "src/core/channel/channel_stack.h" #include "src/core/channel/channel_stack.h"
#include "src/core/security/security_context.h"
#include "src/core/security/security_connector.h" #include "src/core/security/security_connector.h"
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#include "src/core/surface/call.h" #include "src/core/surface/call.h"
@ -67,6 +68,15 @@ typedef struct {
grpc_mdstr *status_key; grpc_mdstr *status_key;
} channel_data; } channel_data;
static void bubble_up_error(grpc_call_element *elem, const char *error_msg) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_transport_op_add_cancellation(
&calld->op, GRPC_STATUS_UNAUTHENTICATED,
grpc_mdstr_from_string(chand->md_ctx, error_msg));
grpc_call_next_op(elem, &calld->op);
}
static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems, static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status) {
@ -75,6 +85,10 @@ static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
grpc_transport_op *op = &calld->op; grpc_transport_op *op = &calld->op;
grpc_metadata_batch *mdb; grpc_metadata_batch *mdb;
size_t i; size_t i;
if (status != GRPC_CREDENTIALS_OK) {
bubble_up_error(elem, "Credentials failed to get metadata.");
return;
}
GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
GPR_ASSERT(op->send_ops && op->send_ops->nops > calld->op_md_idx && GPR_ASSERT(op->send_ops && op->send_ops->nops > calld->op_md_idx &&
op->send_ops->ops[calld->op_md_idx].type == GRPC_OP_METADATA); op->send_ops->ops[calld->op_md_idx].type == GRPC_OP_METADATA);
@ -108,37 +122,48 @@ static char *build_service_url(const char *url_scheme, call_data *calld) {
static void send_security_metadata(grpc_call_element *elem, static void send_security_metadata(grpc_call_element *elem,
grpc_transport_op *op) { grpc_transport_op *op) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_client_security_context *ctx =
(grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY];
char *service_url = NULL;
grpc_credentials *channel_creds = grpc_credentials *channel_creds =
channeld->security_connector->request_metadata_creds; chand->security_connector->request_metadata_creds;
/* TODO(jboeuf): int channel_creds_has_md =
Decide on the policy in this case: (channel_creds != NULL) &&
- populate both channel and call? grpc_credentials_has_request_metadata(channel_creds);
- the call takes precedence over the channel? int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL) &&
- leave this decision up to the channel credentials? */ grpc_credentials_has_request_metadata(ctx->creds);
if (calld->creds != NULL) {
gpr_log(GPR_ERROR, "Ignoring per call credentials for now."); if (!channel_creds_has_md && !call_creds_has_md) {
/* Skip sending metadata altogether. */
grpc_call_next_op(elem, op);
return;
} }
if (channel_creds != NULL &&
grpc_credentials_has_request_metadata(channel_creds)) { if (channel_creds_has_md && call_creds_has_md) {
char *service_url = calld->creds = grpc_composite_credentials_create(channel_creds, ctx->creds);
build_service_url(channeld->security_connector->base.url_scheme, calld); if (calld->creds == NULL) {
calld->op = *op; /* Copy op (originates from the caller's stack). */ bubble_up_error(elem,
grpc_credentials_get_request_metadata(channel_creds, service_url, "Incompatible credentials set on channel and call.");
on_credentials_metadata, elem); return;
gpr_free(service_url); }
} else { } else {
grpc_call_next_op(elem, op); calld->creds =
grpc_credentials_ref(call_creds_has_md ? ctx->creds : channel_creds);
} }
service_url =
build_service_url(chand->security_connector->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
grpc_credentials_get_request_metadata(calld->creds, service_url,
on_credentials_metadata, elem);
gpr_free(service_url);
} }
static void on_host_checked(void *user_data, grpc_security_status status) { static void on_host_checked(void *user_data, grpc_security_status status) {
grpc_call_element *elem = (grpc_call_element *)user_data; grpc_call_element *elem = (grpc_call_element *)user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
if (status == GRPC_SECURITY_OK) { if (status == GRPC_SECURITY_OK) {
send_security_metadata(elem, &calld->op); send_security_metadata(elem, &calld->op);
@ -146,11 +171,8 @@ static void on_host_checked(void *user_data, grpc_security_status status) {
char *error_msg; char *error_msg;
gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
grpc_mdstr_as_c_string(calld->host)); grpc_mdstr_as_c_string(calld->host));
grpc_transport_op_add_cancellation( bubble_up_error(elem, error_msg);
&calld->op, GRPC_STATUS_UNAUTHENTICATED,
grpc_mdstr_from_string(chand->md_ctx, error_msg));
gpr_free(error_msg); gpr_free(error_msg);
grpc_call_next_op(elem, &calld->op);
} }
} }
@ -163,7 +185,7 @@ static void auth_start_transport_op(grpc_call_element *elem,
grpc_transport_op *op) { grpc_transport_op *op) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_linked_mdelem *l; grpc_linked_mdelem *l;
size_t i; size_t i;
@ -179,10 +201,10 @@ static void auth_start_transport_op(grpc_call_element *elem,
grpc_mdelem *md = l->md; grpc_mdelem *md = l->md;
/* Pointer comparison is OK for md_elems created from the same context. /* Pointer comparison is OK for md_elems created from the same context.
*/ */
if (md->key == channeld->authority_string) { if (md->key == chand->authority_string) {
if (calld->host != NULL) grpc_mdstr_unref(calld->host); if (calld->host != NULL) grpc_mdstr_unref(calld->host);
calld->host = grpc_mdstr_ref(md->value); calld->host = grpc_mdstr_ref(md->value);
} else if (md->key == channeld->path_string) { } else if (md->key == chand->path_string) {
if (calld->method != NULL) grpc_mdstr_unref(calld->method); if (calld->method != NULL) grpc_mdstr_unref(calld->method);
calld->method = grpc_mdstr_ref(md->value); calld->method = grpc_mdstr_ref(md->value);
} }
@ -192,18 +214,15 @@ static void auth_start_transport_op(grpc_call_element *elem,
const char *call_host = grpc_mdstr_as_c_string(calld->host); const char *call_host = grpc_mdstr_as_c_string(calld->host);
calld->op = *op; /* Copy op (originates from the caller's stack). */ calld->op = *op; /* Copy op (originates from the caller's stack). */
status = grpc_channel_security_connector_check_call_host( status = grpc_channel_security_connector_check_call_host(
channeld->security_connector, call_host, on_host_checked, elem); chand->security_connector, call_host, on_host_checked, elem);
if (status != GRPC_SECURITY_OK) { if (status != GRPC_SECURITY_OK) {
if (status == GRPC_SECURITY_ERROR) { if (status == GRPC_SECURITY_ERROR) {
char *error_msg; char *error_msg;
gpr_asprintf(&error_msg, gpr_asprintf(&error_msg,
"Invalid host %s set in :authority metadata.", "Invalid host %s set in :authority metadata.",
call_host); call_host);
grpc_transport_op_add_cancellation( bubble_up_error(elem, error_msg);
&calld->op, GRPC_STATUS_UNAUTHENTICATED,
grpc_mdstr_from_string(channeld->md_ctx, error_msg));
gpr_free(error_msg); gpr_free(error_msg);
grpc_call_next_op(elem, &calld->op);
} }
return; /* early exit */ return; /* early exit */
} }
@ -228,8 +247,6 @@ static void channel_op(grpc_channel_element *elem,
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, const void *server_transport_data,
grpc_transport_op *initial_op) { grpc_transport_op *initial_op) {
/* TODO(jboeuf):
Find a way to pass-in the credentials from the caller here. */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
calld->creds = NULL; calld->creds = NULL;
calld->host = NULL; calld->host = NULL;
@ -242,9 +259,7 @@ static void init_call_elem(grpc_call_element *elem,
/* Destructor for call_data */ /* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) { static void destroy_call_elem(grpc_call_element *elem) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (calld->creds != NULL) { grpc_credentials_unref(calld->creds);
grpc_credentials_unref(calld->creds);
}
if (calld->host != NULL) { if (calld->host != NULL) {
grpc_mdstr_unref(calld->host); grpc_mdstr_unref(calld->host);
} }
@ -260,7 +275,7 @@ static void init_channel_elem(grpc_channel_element *elem,
int is_last) { int is_last) {
grpc_security_connector *ctx = grpc_find_security_connector_in_args(args); grpc_security_connector *ctx = grpc_find_security_connector_in_args(args);
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data; channel_data *chand = elem->channel_data;
/* The first and the last filters tend to be implemented differently to /* The first and the last filters tend to be implemented differently to
handle the case that there's no 'next' filter to call on the up or down handle the case that there's no 'next' filter to call on the up or down
@ -271,35 +286,35 @@ static void init_channel_elem(grpc_channel_element *elem,
/* initialize members */ /* initialize members */
GPR_ASSERT(ctx->is_client_side); GPR_ASSERT(ctx->is_client_side);
channeld->security_connector = chand->security_connector =
(grpc_channel_security_connector *)grpc_security_connector_ref(ctx); (grpc_channel_security_connector *)grpc_security_connector_ref(ctx);
channeld->md_ctx = metadata_context; chand->md_ctx = metadata_context;
channeld->authority_string = chand->authority_string =
grpc_mdstr_from_string(channeld->md_ctx, ":authority"); grpc_mdstr_from_string(chand->md_ctx, ":authority");
channeld->path_string = grpc_mdstr_from_string(channeld->md_ctx, ":path"); chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path");
channeld->error_msg_key = chand->error_msg_key =
grpc_mdstr_from_string(channeld->md_ctx, "grpc-message"); grpc_mdstr_from_string(chand->md_ctx, "grpc-message");
channeld->status_key = chand->status_key =
grpc_mdstr_from_string(channeld->md_ctx, "grpc-status"); grpc_mdstr_from_string(chand->md_ctx, "grpc-status");
} }
/* Destructor for channel data */ /* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) { static void destroy_channel_elem(grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */ /* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_channel_security_connector *ctx = channeld->security_connector; grpc_channel_security_connector *ctx = chand->security_connector;
if (ctx != NULL) grpc_security_connector_unref(&ctx->base); if (ctx != NULL) grpc_security_connector_unref(&ctx->base);
if (channeld->authority_string != NULL) { if (chand->authority_string != NULL) {
grpc_mdstr_unref(channeld->authority_string); grpc_mdstr_unref(chand->authority_string);
} }
if (channeld->error_msg_key != NULL) { if (chand->error_msg_key != NULL) {
grpc_mdstr_unref(channeld->error_msg_key); grpc_mdstr_unref(chand->error_msg_key);
} }
if (channeld->status_key != NULL) { if (chand->status_key != NULL) {
grpc_mdstr_unref(channeld->status_key); grpc_mdstr_unref(chand->status_key);
} }
if (channeld->path_string != NULL) { if (chand->path_string != NULL) {
grpc_mdstr_unref(channeld->path_string); grpc_mdstr_unref(chand->path_string);
} }
} }

@ -0,0 +1,79 @@
/*
*
* 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.h>
#include "src/core/security/security_context.h"
#include "src/core/surface/call.h"
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds) {
grpc_client_security_context *ctx = NULL;
if (!grpc_call_is_client(call)) {
gpr_log(GPR_ERROR, "Method is client-side only.");
return GRPC_CALL_ERROR_NOT_ON_SERVER;
}
if (creds != NULL && !grpc_credentials_has_request_metadata_only(creds)) {
gpr_log(GPR_ERROR, "Incompatible credentials to set on a call.");
return GRPC_CALL_ERROR;
}
ctx = (grpc_client_security_context *)grpc_call_context_get(
call, GRPC_CONTEXT_SECURITY);
if (ctx == NULL) {
ctx = grpc_client_security_context_create();
ctx->creds = grpc_credentials_ref(creds);
grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx,
grpc_client_security_context_destroy);
} else {
grpc_credentials_unref(ctx->creds);
ctx->creds = grpc_credentials_ref(creds);
}
return GRPC_CALL_OK;
}
grpc_client_security_context *grpc_client_security_context_create(void) {
grpc_client_security_context *ctx =
gpr_malloc(sizeof(grpc_client_security_context));
memset(ctx, 0, sizeof(grpc_client_security_context));
return ctx;
}
void grpc_client_security_context_destroy(void *ctx) {
grpc_client_security_context *c = (grpc_client_security_context *)ctx;
grpc_credentials_unref(c->creds);
gpr_free(ctx);
}

@ -0,0 +1,48 @@
/*
*
* 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.
*
*/
#ifndef GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H
#define GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H
#include "src/core/security/credentials.h"
/* Security context attached to a client-side call. */
typedef struct {
grpc_credentials *creds;
} grpc_client_security_context;
grpc_client_security_context *grpc_client_security_context_create(void);
void grpc_client_security_context_destroy(void *ctx);
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */

@ -375,18 +375,10 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) {
static void set_status_code(grpc_call *call, status_source source, static void set_status_code(grpc_call *call, status_source source,
gpr_uint32 status) { gpr_uint32 status) {
int flush;
call->status[source].is_set = 1; call->status[source].is_set = 1;
call->status[source].code = status; call->status[source].code = status;
if (call->is_client) { if (status != GRPC_STATUS_OK && !grpc_bbq_empty(&call->incoming_queue)) {
flush = status == GRPC_STATUS_CANCELLED;
} else {
flush = status != GRPC_STATUS_OK;
}
if (flush && !grpc_bbq_empty(&call->incoming_queue)) {
grpc_bbq_flush(&call->incoming_queue); grpc_bbq_flush(&call->incoming_queue);
} }
} }
@ -1310,3 +1302,5 @@ void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value
void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) { void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
return call->context[elem]; return call->context[elem];
} }
gpr_uint8 grpc_call_is_client(grpc_call *call) { return call->is_client; }

@ -98,12 +98,14 @@ grpc_completion_queue *grpc_call_get_completion_queue(grpc_call *call);
void grpc_call_internal_ref(grpc_call *call, const char *reason); void grpc_call_internal_ref(grpc_call *call, const char *reason);
void grpc_call_internal_unref(grpc_call *call, const char *reason, int allow_immediate_deletion); void grpc_call_internal_unref(grpc_call *call, const char *reason, int allow_immediate_deletion);
#define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call, reason) #define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call, reason)
#define GRPC_CALL_INTERNAL_UNREF(call, reason, allow_immediate_deletion) grpc_call_internal_unref(call, reason, allow_immediate_deletion) #define GRPC_CALL_INTERNAL_UNREF(call, reason, allow_immediate_deletion) \
grpc_call_internal_unref(call, reason, allow_immediate_deletion)
#else #else
void grpc_call_internal_ref(grpc_call *call); void grpc_call_internal_ref(grpc_call *call);
void grpc_call_internal_unref(grpc_call *call, int allow_immediate_deletion); void grpc_call_internal_unref(grpc_call *call, int allow_immediate_deletion);
#define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call) #define GRPC_CALL_INTERNAL_REF(call, reason) grpc_call_internal_ref(call)
#define GRPC_CALL_INTERNAL_UNREF(call, reason, allow_immediate_deletion) grpc_call_internal_unref(call, allow_immediate_deletion) #define GRPC_CALL_INTERNAL_UNREF(call, reason, allow_immediate_deletion) \
grpc_call_internal_unref(call, allow_immediate_deletion)
#endif #endif
grpc_call_error grpc_call_start_ioreq_and_call_back( grpc_call_error grpc_call_start_ioreq_and_call_back(
@ -131,4 +133,6 @@ void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
#define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \ #define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \
if (grpc_trace_batch) grpc_call_log_batch(sev, call, ops, nops, tag) if (grpc_trace_batch) grpc_call_log_batch(sev, call, ops, nops, tag)
gpr_uint8 grpc_call_is_client(grpc_call *call);
#endif /* GRPC_INTERNAL_CORE_SURFACE_CALL_H */ #endif /* GRPC_INTERNAL_CORE_SURFACE_CALL_H */

@ -37,7 +37,6 @@ using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2;
using Mono.Security.Cryptography;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security; using Org.BouncyCastle.Security;
@ -113,8 +112,7 @@ namespace Grpc.Auth
{ {
// TODO(jtattermusch): temporary code to create RSACryptoServiceProvider. // TODO(jtattermusch): temporary code to create RSACryptoServiceProvider.
base64PrivateKey = base64PrivateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("\n", "").Replace("-----END PRIVATE KEY-----", ""); base64PrivateKey = base64PrivateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("\n", "").Replace("-----END PRIVATE KEY-----", "");
PKCS8.PrivateKeyInfo PKI = new PKCS8.PrivateKeyInfo(Convert.FromBase64String(base64PrivateKey)); RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(base64PrivateKey));
RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(PKI.GetBytes());
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(key); RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(key);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters); rsa.ImportParameters(rsaParameters);

@ -51,9 +51,6 @@
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop"> <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference> </Reference>
<Reference Include="Mono.Security">
<HintPath>..\packages\Mono.Security.3.2.3.0\lib\net45\Mono.Security.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>

@ -7,6 +7,5 @@
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" /> <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" /> <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" /> <package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
<package id="Mono.Security" version="3.2.3.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" /> <package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
</packages> </packages>

@ -43,7 +43,7 @@ namespace math
using (Channel channel = new Channel("127.0.0.1:23456")) using (Channel channel = new Channel("127.0.0.1:23456"))
{ {
MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel); Math.IMathClient stub = new Math.MathClient(channel);
MathExamples.DivExample(stub); MathExamples.DivExample(stub);
MathExamples.DivAsyncExample(stub).Wait(); MathExamples.DivAsyncExample(stub).Wait();

@ -45,7 +45,7 @@ namespace math
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
Server server = new Server(); Server server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl())); server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host, 23456); int port = server.AddListeningPort(host, 23456);
server.Start(); server.Start();

@ -37,18 +37,6 @@
<Reference Include="Google.ProtocolBuffers"> <Reference Include="Google.ProtocolBuffers">
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath> <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Core">
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices">
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@ -71,4 +59,4 @@
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -33,7 +33,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
@ -50,7 +49,7 @@ namespace math.Tests
string host = "localhost"; string host = "localhost";
Server server; Server server;
Channel channel; Channel channel;
MathGrpc.IMathServiceClient client; Math.IMathClient client;
[TestFixtureSetUp] [TestFixtureSetUp]
public void Init() public void Init()
@ -58,7 +57,7 @@ namespace math.Tests
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
server = new Server(); server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl())); server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host, Server.PickUnusedPort); int port = server.AddListeningPort(host, Server.PickUnusedPort);
server.Start(); server.Start();
channel = new Channel(host + ":" + port); channel = new Channel(host + ":" + port);
@ -69,7 +68,7 @@ namespace math.Tests
{ {
headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef")); headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef"));
}); });
client = MathGrpc.NewStub(channel, stubConfig); client = Math.NewStub(channel, stubConfig);
} }
[TestFixtureTearDown] [TestFixtureTearDown]

@ -2,9 +2,4 @@
<packages> <packages>
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" /> <package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" /> <package id="NUnit" version="2.6.4" targetFramework="net45" />
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
</packages> </packages>

@ -31,19 +31,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Reactive.Core">
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Data.Linq" /> <Reference Include="System.Data.Linq" />
<Reference Include="System.Reactive.Linq">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices">
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.ProtocolBuffers"> <Reference Include="Google.ProtocolBuffers">
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath> <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
</Reference> </Reference>

@ -31,7 +31,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core.Utils; using Grpc.Core.Utils;
@ -39,34 +38,34 @@ namespace math
{ {
public static class MathExamples public static class MathExamples
{ {
public static void DivExample(MathGrpc.IMathServiceClient stub) public static void DivExample(Math.IMathClient stub)
{ {
DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
Console.WriteLine("Div Result: " + result); Console.WriteLine("Div Result: " + result);
} }
public static async Task DivAsyncExample(MathGrpc.IMathServiceClient stub) public static async Task DivAsyncExample(Math.IMathClient stub)
{ {
Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = await resultTask; DivReply result = await resultTask;
Console.WriteLine("DivAsync Result: " + result); Console.WriteLine("DivAsync Result: " + result);
} }
public static async Task DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub) public static async Task DivAsyncWithCancellationExample(Math.IMathClient stub)
{ {
Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = await resultTask; DivReply result = await resultTask;
Console.WriteLine(result); Console.WriteLine(result);
} }
public static async Task FibExample(MathGrpc.IMathServiceClient stub) public static async Task FibExample(Math.IMathClient stub)
{ {
var call = stub.Fib(new FibArgs.Builder { Limit = 5 }.Build()); var call = stub.Fib(new FibArgs.Builder { Limit = 5 }.Build());
List<Num> result = await call.ResponseStream.ToList(); List<Num> result = await call.ResponseStream.ToList();
Console.WriteLine("Fib Result: " + string.Join("|", result)); Console.WriteLine("Fib Result: " + string.Join("|", result));
} }
public static async Task SumExample(MathGrpc.IMathServiceClient stub) public static async Task SumExample(Math.IMathClient stub)
{ {
var numbers = new List<Num> var numbers = new List<Num>
{ {
@ -80,7 +79,7 @@ namespace math
Console.WriteLine("Sum Result: " + await call.Result); Console.WriteLine("Sum Result: " + await call.Result);
} }
public static async Task DivManyExample(MathGrpc.IMathServiceClient stub) public static async Task DivManyExample(Math.IMathClient stub)
{ {
var divArgsList = new List<DivArgs> var divArgsList = new List<DivArgs>
{ {
@ -93,7 +92,7 @@ namespace math
Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToList())); Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToList()));
} }
public static async Task DependendRequestsExample(MathGrpc.IMathServiceClient stub) public static async Task DependendRequestsExample(Math.IMathClient stub)
{ {
var numbers = new List<Num> var numbers = new List<Num>
{ {

@ -1,164 +1,122 @@
#region Copyright notice and license // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto
// Copyright 2015, Google Inc. #region Designer generated code
// 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;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
namespace math namespace math {
{ public static class Math
/// <summary> {
/// Math service definitions (this is handwritten version of code that will normally be generated). static readonly string __ServiceName = "math.Math";
/// </summary>
public class MathGrpc static readonly Marshaller<DivArgs> __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
static readonly Marshaller<DivReply> __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
static readonly Marshaller<FibArgs> __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
static readonly Marshaller<Num> __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
static readonly Method<DivArgs, DivReply> __Method_Div = new Method<DivArgs, DivReply>(
MethodType.Unary,
"Div",
__Marshaller_DivArgs,
__Marshaller_DivReply);
static readonly Method<DivArgs, DivReply> __Method_DivMany = new Method<DivArgs, DivReply>(
MethodType.DuplexStreaming,
"DivMany",
__Marshaller_DivArgs,
__Marshaller_DivReply);
static readonly Method<FibArgs, Num> __Method_Fib = new Method<FibArgs, Num>(
MethodType.ServerStreaming,
"Fib",
__Marshaller_FibArgs,
__Marshaller_Num);
static readonly Method<Num, Num> __Method_Sum = new Method<Num, Num>(
MethodType.ClientStreaming,
"Sum",
__Marshaller_Num,
__Marshaller_Num);
// client-side stub interface
public interface IMathClient
{ {
static readonly string ServiceName = "/math.Math"; DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken));
Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken));
static readonly Marshaller<DivArgs> DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom); AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken));
static readonly Marshaller<DivReply> DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom); AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken));
static readonly Marshaller<Num> NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom); AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken));
static readonly Marshaller<FibArgs> FibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom); }
static readonly Method<DivArgs, DivReply> DivMethod = new Method<DivArgs, DivReply>(
MethodType.Unary,
"Div",
DivArgsMarshaller,
DivReplyMarshaller);
static readonly Method<FibArgs, Num> FibMethod = new Method<FibArgs, Num>(
MethodType.ServerStreaming,
"Fib",
FibArgsMarshaller,
NumMarshaller);
static readonly Method<Num, Num> SumMethod = new Method<Num, Num>(
MethodType.ClientStreaming,
"Sum",
NumMarshaller,
NumMarshaller);
static readonly Method<DivArgs, DivReply> DivManyMethod = new Method<DivArgs, DivReply>(
MethodType.DuplexStreaming,
"DivMany",
DivArgsMarshaller,
DivReplyMarshaller);
public interface IMathServiceClient
{
DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken));
Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken));
AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken));
AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken));
AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken));
}
public class MathServiceClientStub : AbstractStub<MathServiceClientStub, StubConfiguration>, IMathServiceClient
{
public MathServiceClientStub(Channel channel) : this(channel, StubConfiguration.Default)
{
}
public MathServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
{
}
public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, DivMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, DivMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
public AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, FibMethod);
return Calls.AsyncServerStreamingCall(call, request, token);
}
public AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, SumMethod);
return Calls.AsyncClientStreamingCall(call, token);
}
public AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, DivManyMethod);
return Calls.AsyncDuplexStreamingCall(call, token);
}
}
// server-side interface
public interface IMathService
{
Task<DivReply> Div(ServerCallContext context, DivArgs request);
Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream);
Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream); // server-side interface
public interface IMath
{
Task<DivReply> Div(ServerCallContext context, DivArgs request);
Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream);
Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream);
Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream);
}
Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream); // client stub
} public class MathClient : AbstractStub<MathClient, StubConfiguration>, IMathClient
{
public MathClient(Channel channel) : this(channel, StubConfiguration.Default)
{
}
public MathClient(Channel channel, StubConfiguration config) : base(channel, config)
{
}
public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Div);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Div);
return Calls.AsyncUnaryCall(call, request, token);
}
public AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_DivMany);
return Calls.AsyncDuplexStreamingCall(call, token);
}
public AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Fib);
return Calls.AsyncServerStreamingCall(call, request, token);
}
public AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Sum);
return Calls.AsyncClientStreamingCall(call, token);
}
}
public static ServerServiceDefinition BindService(IMathService serviceImpl) // creates service definition that can be registered with a server
{ public static ServerServiceDefinition BindService(IMath serviceImpl)
return ServerServiceDefinition.CreateBuilder(ServiceName) {
.AddMethod(DivMethod, serviceImpl.Div) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(FibMethod, serviceImpl.Fib) .AddMethod(__Method_Div, serviceImpl.Div)
.AddMethod(SumMethod, serviceImpl.Sum) .AddMethod(__Method_DivMany, serviceImpl.DivMany)
.AddMethod(DivManyMethod, serviceImpl.DivMany).Build(); .AddMethod(__Method_Fib, serviceImpl.Fib)
} .AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
public static IMathServiceClient NewStub(Channel channel) // creates a new client stub
{ public static IMathClient NewStub(Channel channel)
return new MathServiceClientStub(channel); {
} return new MathClient(channel);
}
public static IMathServiceClient NewStub(Channel channel, StubConfiguration config) // creates a new client stub
{ public static IMathClient NewStub(Channel channel, StubConfiguration config)
return new MathServiceClientStub(channel, config); {
} return new MathClient(channel, config);
} }
}
} }
#endregion

@ -33,7 +33,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
@ -44,7 +43,7 @@ namespace math
/// <summary> /// <summary>
/// Implementation of MathService server /// Implementation of MathService server
/// </summary> /// </summary>
public class MathServiceImpl : MathGrpc.IMathService public class MathServiceImpl : Math.IMath
{ {
public Task<DivReply> Div(ServerCallContext context, DivArgs request) public Task<DivReply> Div(ServerCallContext context, DivArgs request)
{ {

@ -1,11 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" /> <package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
<package id="Ix-Main" version="1.2.3" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" /> <package id="NUnit" version="2.6.4" targetFramework="net45" />
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
</packages> </packages>

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>10.0.0</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C61154BA-DD4A-4838-8420-0162A28925E0}</ProjectGuid> <ProjectGuid>{C61154BA-DD4A-4838-8420-0162A28925E0}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
@ -72,7 +72,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestServiceGrpc.cs" />
<Compile Include="Empty.cs" /> <Compile Include="Empty.cs" />
<Compile Include="Messages.cs" /> <Compile Include="Messages.cs" />
<Compile Include="InteropClientServerTest.cs" /> <Compile Include="InteropClientServerTest.cs" />
@ -80,6 +79,7 @@
<Compile Include="InteropServer.cs" /> <Compile Include="InteropServer.cs" />
<Compile Include="InteropClient.cs" /> <Compile Include="InteropClient.cs" />
<Compile Include="TestCredentials.cs" /> <Compile Include="TestCredentials.cs" />
<Compile Include="TestGrpc.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>

@ -132,14 +132,14 @@ namespace Grpc.IntegrationTesting
stubConfig = new StubConfiguration(OAuth2InterceptorFactory.Create(credential)); stubConfig = new StubConfiguration(OAuth2InterceptorFactory.Create(credential));
} }
TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel, stubConfig); TestService.ITestServiceClient client = new TestService.TestServiceClient(channel, stubConfig);
RunTestCase(options.testCase, client); RunTestCase(options.testCase, client);
} }
GrpcEnvironment.Shutdown(); GrpcEnvironment.Shutdown();
} }
private void RunTestCase(string testCase, TestServiceGrpc.ITestServiceClient client) private void RunTestCase(string testCase, TestService.ITestServiceClient client)
{ {
switch (testCase) switch (testCase)
{ {
@ -181,7 +181,7 @@ namespace Grpc.IntegrationTesting
} }
} }
public static void RunEmptyUnary(TestServiceGrpc.ITestServiceClient client) public static void RunEmptyUnary(TestService.ITestServiceClient client)
{ {
Console.WriteLine("running empty_unary"); Console.WriteLine("running empty_unary");
var response = client.EmptyCall(Empty.DefaultInstance); var response = client.EmptyCall(Empty.DefaultInstance);
@ -189,7 +189,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }
public static void RunLargeUnary(TestServiceGrpc.ITestServiceClient client) public static void RunLargeUnary(TestService.ITestServiceClient client)
{ {
Console.WriteLine("running large_unary"); Console.WriteLine("running large_unary");
var request = SimpleRequest.CreateBuilder() var request = SimpleRequest.CreateBuilder()
@ -205,7 +205,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }
public static void RunClientStreaming(TestServiceGrpc.ITestServiceClient client) public static void RunClientStreaming(TestService.ITestServiceClient client)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
@ -222,7 +222,7 @@ namespace Grpc.IntegrationTesting
}).Wait(); }).Wait();
} }
public static void RunServerStreaming(TestServiceGrpc.ITestServiceClient client) public static void RunServerStreaming(TestService.ITestServiceClient client)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
@ -248,7 +248,7 @@ namespace Grpc.IntegrationTesting
}).Wait(); }).Wait();
} }
public static void RunPingPong(TestServiceGrpc.ITestServiceClient client) public static void RunPingPong(TestService.ITestServiceClient client)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
@ -303,7 +303,7 @@ namespace Grpc.IntegrationTesting
}).Wait(); }).Wait();
} }
public static void RunEmptyStream(TestServiceGrpc.ITestServiceClient client) public static void RunEmptyStream(TestService.ITestServiceClient client)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
@ -318,7 +318,7 @@ namespace Grpc.IntegrationTesting
}).Wait(); }).Wait();
} }
public static void RunServiceAccountCreds(TestServiceGrpc.ITestServiceClient client) public static void RunServiceAccountCreds(TestService.ITestServiceClient client)
{ {
Console.WriteLine("running service_account_creds"); Console.WriteLine("running service_account_creds");
var request = SimpleRequest.CreateBuilder() var request = SimpleRequest.CreateBuilder()
@ -338,7 +338,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }
public static void RunComputeEngineCreds(TestServiceGrpc.ITestServiceClient client) public static void RunComputeEngineCreds(TestService.ITestServiceClient client)
{ {
Console.WriteLine("running compute_engine_creds"); Console.WriteLine("running compute_engine_creds");
var request = SimpleRequest.CreateBuilder() var request = SimpleRequest.CreateBuilder()
@ -358,7 +358,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }
public static void RunCancelAfterBegin(TestServiceGrpc.ITestServiceClient client) public static void RunCancelAfterBegin(TestService.ITestServiceClient client)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
@ -383,7 +383,7 @@ namespace Grpc.IntegrationTesting
}).Wait(); }).Wait();
} }
public static void RunCancelAfterFirstResponse(TestServiceGrpc.ITestServiceClient client) public static void RunCancelAfterFirstResponse(TestService.ITestServiceClient client)
{ {
Task.Run(async () => Task.Run(async () =>
{ {
@ -419,7 +419,7 @@ namespace Grpc.IntegrationTesting
} }
// This is not an official interop test, but it's useful. // This is not an official interop test, but it's useful.
public static void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client) public static void RunBenchmarkEmptyUnary(TestService.ITestServiceClient client)
{ {
BenchmarkUtil.RunBenchmark(10000, 10000, BenchmarkUtil.RunBenchmark(10000, 10000,
() => { client.EmptyCall(Empty.DefaultInstance); }); () => { client.EmptyCall(Empty.DefaultInstance); });

@ -50,7 +50,7 @@ namespace Grpc.IntegrationTesting
string host = "localhost"; string host = "localhost";
Server server; Server server;
Channel channel; Channel channel;
TestServiceGrpc.ITestServiceClient client; TestService.ITestServiceClient client;
[TestFixtureSetUp] [TestFixtureSetUp]
public void Init() public void Init()
@ -58,7 +58,7 @@ namespace Grpc.IntegrationTesting
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
server = new Server(); server = new Server();
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl())); server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
int port = server.AddListeningPort(host, Server.PickUnusedPort, TestCredentials.CreateTestServerCredentials()); int port = server.AddListeningPort(host, Server.PickUnusedPort, TestCredentials.CreateTestServerCredentials());
server.Start(); server.Start();
@ -66,7 +66,7 @@ namespace Grpc.IntegrationTesting
.AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build(); .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build();
channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs); channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs);
client = TestServiceGrpc.NewStub(channel); client = TestService.NewStub(channel);
} }
[TestFixtureTearDown] [TestFixtureTearDown]

@ -91,7 +91,7 @@ namespace Grpc.IntegrationTesting
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
var server = new Server(); var server = new Server();
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl())); server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
string host = "0.0.0.0"; string host = "0.0.0.0";
int port = options.port.Value; int port = options.port.Value;

@ -0,0 +1,159 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: test.proto
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace grpc.testing {
public static class TestService
{
static readonly string __ServiceName = "grpc.testing.TestService";
static readonly Marshaller<Empty> __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
static readonly Marshaller<SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
static readonly Marshaller<SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
static readonly Marshaller<StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
static readonly Marshaller<StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
static readonly Marshaller<StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
static readonly Marshaller<StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
static readonly Method<Empty, Empty> __Method_EmptyCall = new Method<Empty, Empty>(
MethodType.Unary,
"EmptyCall",
__Marshaller_Empty,
__Marshaller_Empty);
static readonly Method<SimpleRequest, SimpleResponse> __Method_UnaryCall = new Method<SimpleRequest, SimpleResponse>(
MethodType.Unary,
"UnaryCall",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.ServerStreaming,
"StreamingOutputCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> __Method_StreamingInputCall = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
MethodType.ClientStreaming,
"StreamingInputCall",
__Marshaller_StreamingInputCallRequest,
__Marshaller_StreamingInputCallResponse);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
"FullDuplexCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
"HalfDuplexCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
// client-side stub interface
public interface ITestServiceClient
{
Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken));
Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken));
SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken));
Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken));
AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken));
AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken));
AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken));
AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken));
}
// server-side interface
public interface ITestService
{
Task<Empty> EmptyCall(ServerCallContext context, Empty request);
Task<SimpleResponse> UnaryCall(ServerCallContext context, SimpleRequest request);
Task StreamingOutputCall(ServerCallContext context, StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
Task<StreamingInputCallResponse> StreamingInputCall(ServerCallContext context, IAsyncStreamReader<StreamingInputCallRequest> requestStream);
Task FullDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
Task HalfDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
}
// client stub
public class TestServiceClient : AbstractStub<TestServiceClient, StubConfiguration>, ITestServiceClient
{
public TestServiceClient(Channel channel) : this(channel, StubConfiguration.Default)
{
}
public TestServiceClient(Channel channel, StubConfiguration config) : base(channel, config)
{
}
public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_EmptyCall);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_EmptyCall);
return Calls.AsyncUnaryCall(call, request, token);
}
public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_UnaryCall);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_UnaryCall);
return Calls.AsyncUnaryCall(call, request, token);
}
public AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_StreamingOutputCall);
return Calls.AsyncServerStreamingCall(call, request, token);
}
public AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_StreamingInputCall);
return Calls.AsyncClientStreamingCall(call, token);
}
public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_FullDuplexCall);
return Calls.AsyncDuplexStreamingCall(call, token);
}
public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_HalfDuplexCall);
return Calls.AsyncDuplexStreamingCall(call, token);
}
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(ITestService serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall)
.AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall)
.AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall)
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
// creates a new client stub
public static ITestServiceClient NewStub(Channel channel)
{
return new TestServiceClient(channel);
}
// creates a new client stub
public static ITestServiceClient NewStub(Channel channel, StubConfiguration config)
{
return new TestServiceClient(channel, config);
}
}
}
#endregion

@ -44,7 +44,7 @@ namespace grpc.testing
/// <summary> /// <summary>
/// Implementation of TestService server /// Implementation of TestService server
/// </summary> /// </summary>
public class TestServiceImpl : TestServiceGrpc.ITestService public class TestServiceImpl : TestService.ITestService
{ {
public Task<Empty> EmptyCall(ServerCallContext context, Empty request) public Task<Empty> EmptyCall(ServerCallContext context, Empty request)
{ {

@ -0,0 +1,43 @@
#!/bin/sh
# 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.
# Regenerates gRPC service stubs from proto files.
set +e
cd $(dirname $0)
PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin
EXAMPLES_DIR=Grpc.Examples
INTEROP_DIR=Grpc.IntegrationTesting
protoc --plugin=$PLUGIN --grpc_out=$EXAMPLES_DIR \
-I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto
protoc --plugin=$PLUGIN --grpc_out=$INTEROP_DIR \
-I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.proto

@ -33,25 +33,25 @@ syntax = "proto3";
package math; package math;
message DivArgs { message DivArgs {
optional int64 dividend = 1; int64 dividend = 1;
optional int64 divisor = 2; int64 divisor = 2;
} }
message DivReply { message DivReply {
optional int64 quotient = 1; int64 quotient = 1;
optional int64 remainder = 2; int64 remainder = 2;
} }
message FibArgs { message FibArgs {
optional int64 limit = 1; int64 limit = 1;
} }
message Num { message Num {
optional int64 num = 1; int64 num = 1;
} }
message FibReply { message FibReply {
optional int64 count = 1; int64 count = 1;
} }
service Math { service Math {

@ -66,18 +66,18 @@ service RouteGuide {
// Latitudes should be in the range +/- 90 degrees and longitude should be in // Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive). // the range +/- 180 degrees (inclusive).
message Point { message Point {
optional int32 latitude = 1; int32 latitude = 1;
optional int32 longitude = 2; int32 longitude = 2;
} }
// A latitude-longitude rectangle, represented as two diagonally opposite // A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi". // points "lo" and "hi".
message Rectangle { message Rectangle {
// One corner of the rectangle. // One corner of the rectangle.
optional Point lo = 1; Point lo = 1;
// The other corner of the rectangle. // The other corner of the rectangle.
optional Point hi = 2; Point hi = 2;
} }
// A feature names something at a given point. // A feature names something at a given point.
@ -85,19 +85,19 @@ message Rectangle {
// If a feature could not be named, the name is empty. // If a feature could not be named, the name is empty.
message Feature { message Feature {
// The name of the feature. // The name of the feature.
optional string name = 1; string name = 1;
// The point where the feature is detected. // The point where the feature is detected.
optional Point location = 2; Point location = 2;
} }
// A RouteNote is a message sent while at a given point. // A RouteNote is a message sent while at a given point.
message RouteNote { message RouteNote {
// The location from which the message is sent. // The location from which the message is sent.
optional Point location = 1; Point location = 1;
// The message to be sent. // The message to be sent.
optional string message = 2; string message = 2;
} }
// A RouteSummary is received in response to a RecordRoute rpc. // A RouteSummary is received in response to a RecordRoute rpc.
@ -107,14 +107,14 @@ message RouteNote {
// the distance between each point. // the distance between each point.
message RouteSummary { message RouteSummary {
// The number of points received. // The number of points received.
optional int32 point_count = 1; int32 point_count = 1;
// The number of known features passed while traversing the route. // The number of known features passed while traversing the route.
optional int32 feature_count = 2; int32 feature_count = 2;
// The distance covered in metres. // The distance covered in metres.
optional int32 distance = 3; int32 distance = 3;
// The duration of the traversal in seconds. // The duration of the traversal in seconds.
optional int32 elapsed_time = 4; int32 elapsed_time = 4;
} }

@ -33,13 +33,13 @@ package examples;
// Protocol type definitions // Protocol type definitions
message StockRequest { message StockRequest {
optional string symbol = 1; string symbol = 1;
optional int32 num_trades_to_watch = 2 [default=0]; int32 num_trades_to_watch = 2;
} }
message StockReply { message StockReply {
optional float price = 1; float price = 1;
optional string symbol = 2; string symbol = 2;
} }

@ -100,22 +100,23 @@ function load(filename, format) {
function getGoogleAuthDelegate(credential) { function getGoogleAuthDelegate(credential) {
/** /**
* Update a metadata object with authentication information. * Update a metadata object with authentication information.
* @param {string} authURI The uri to authenticate to
* @param {Object} metadata Metadata object * @param {Object} metadata Metadata object
* @param {function(Error, Object)} callback * @param {function(Error, Object)} callback
*/ */
return function updateMetadata(metadata, callback) { return function updateMetadata(authURI, metadata, callback) {
metadata = _.clone(metadata); metadata = _.clone(metadata);
if (metadata.Authorization) { if (metadata.Authorization) {
metadata.Authorization = _.clone(metadata.Authorization); metadata.Authorization = _.clone(metadata.Authorization);
} else { } else {
metadata.Authorization = []; metadata.Authorization = [];
} }
credential.getAccessToken(function(err, token) { credential.getRequestMetadata(authURI, function(err, header) {
if (err) { if (err) {
callback(err); callback(err);
return; return;
} }
metadata.Authorization.push('Bearer ' + token); metadata.Authorization.push(header.Authorization);
callback(null, metadata); callback(null, metadata);
}); });
}; };

@ -28,7 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto2"; syntax = "proto3";
package grpc.testing; package grpc.testing;

@ -260,8 +260,8 @@ function cancelAfterFirstResponse(client, done) {
call.on('data', function(data) { call.on('data', function(data) {
call.cancel(); call.cancel();
}); });
call.on('status', function(status) { call.on('error', function(error) {
assert.strictEqual(status.code, grpc.status.CANCELLED); assert.strictEqual(error.code, grpc.status.CANCELLED);
done(); done();
}); });
} }

@ -30,7 +30,7 @@
// Message definitions to be used by integration test service definitions. // Message definitions to be used by integration test service definitions.
syntax = "proto2"; syntax = "proto3";
package grpc.testing; package grpc.testing;
@ -49,46 +49,46 @@ enum PayloadType {
// A block of data, to simply increase gRPC message size. // A block of data, to simply increase gRPC message size.
message Payload { message Payload {
// The type of data in body. // The type of data in body.
optional PayloadType type = 1 [default = COMPRESSABLE]; PayloadType type = 1;
// Primary contents of payload. // Primary contents of payload.
optional bytes body = 2; bytes body = 2;
} }
// Unary request. // Unary request.
message SimpleRequest { message SimpleRequest {
// Desired payload type in the response from the server. // Desired payload type in the response from the server.
// If response_type is RANDOM, server randomly chooses one from other formats. // If response_type is RANDOM, server randomly chooses one from other formats.
optional PayloadType response_type = 1 [default = COMPRESSABLE]; PayloadType response_type = 1;
// Desired payload size in the response from the server. // Desired payload size in the response from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression. // If response_type is COMPRESSABLE, this denotes the size before compression.
optional int32 response_size = 2; int32 response_size = 2;
// Optional input payload sent along with the request. // Optional input payload sent along with the request.
optional Payload payload = 3; Payload payload = 3;
// Whether SimpleResponse should include username. // Whether SimpleResponse should include username.
optional bool fill_username = 4; bool fill_username = 4;
// Whether SimpleResponse should include OAuth scope. // Whether SimpleResponse should include OAuth scope.
optional bool fill_oauth_scope = 5; bool fill_oauth_scope = 5;
} }
// Unary response, as configured by the request. // Unary response, as configured by the request.
message SimpleResponse { message SimpleResponse {
// Payload to increase message size. // Payload to increase message size.
optional Payload payload = 1; Payload payload = 1;
// The user the request came from, for verifying authentication was // The user the request came from, for verifying authentication was
// successful when the client expected it. // successful when the client expected it.
optional string username = 2; string username = 2;
// OAuth scope. // OAuth scope.
optional string oauth_scope = 3; string oauth_scope = 3;
} }
// Client-streaming request. // Client-streaming request.
message StreamingInputCallRequest { message StreamingInputCallRequest {
// Optional input payload sent along with the request. // Optional input payload sent along with the request.
optional Payload payload = 1; Payload payload = 1;
// Not expecting any payload from the response. // Not expecting any payload from the response.
} }
@ -96,18 +96,18 @@ message StreamingInputCallRequest {
// Client-streaming response. // Client-streaming response.
message StreamingInputCallResponse { message StreamingInputCallResponse {
// Aggregated size of payloads received from the client. // Aggregated size of payloads received from the client.
optional int32 aggregated_payload_size = 1; int32 aggregated_payload_size = 1;
} }
// Configuration for a particular response. // Configuration for a particular response.
message ResponseParameters { message ResponseParameters {
// Desired payload sizes in responses from the server. // Desired payload sizes in responses from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression. // If response_type is COMPRESSABLE, this denotes the size before compression.
optional int32 size = 1; int32 size = 1;
// Desired interval between consecutive responses in the response stream in // Desired interval between consecutive responses in the response stream in
// microseconds. // microseconds.
optional int32 interval_us = 2; int32 interval_us = 2;
} }
// Server-streaming request. // Server-streaming request.
@ -116,17 +116,17 @@ message StreamingOutputCallRequest {
// If response_type is RANDOM, the payload from each response in the stream // If response_type is RANDOM, the payload from each response in the stream
// might be of different types. This is to simulate a mixed type of payload // might be of different types. This is to simulate a mixed type of payload
// stream. // stream.
optional PayloadType response_type = 1 [default = COMPRESSABLE]; PayloadType response_type = 1;
// Configuration for each expected response message. // Configuration for each expected response message.
repeated ResponseParameters response_parameters = 2; repeated ResponseParameters response_parameters = 2;
// Optional input payload sent along with the request. // Optional input payload sent along with the request.
optional Payload payload = 3; Payload payload = 3;
} }
// Server-streaming response, as configured by the request and parameters. // Server-streaming response, as configured by the request and parameters.
message StreamingOutputCallResponse { message StreamingOutputCallResponse {
// Payload to increase response size. // Payload to increase response size.
optional Payload payload = 1; Payload payload = 1;
} }

@ -30,7 +30,8 @@
// An integration test service that covers all the method signature permutations // An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses. // of unary/streaming requests/responses.
syntax = "proto2";
syntax = "proto3";
import "empty.proto"; import "empty.proto";
import "messages.proto"; import "messages.proto";

@ -1,6 +1,6 @@
{ {
"name": "grpc", "name": "grpc",
"version": "0.6.2", "version": "0.7.0",
"author": "Google Inc.", "author": "Google Inc.",
"description": "gRPC Library for Node", "description": "gRPC Library for Node",
"homepage": "http://www.grpc.io/", "homepage": "http://www.grpc.io/",
@ -26,7 +26,7 @@
"dependencies": { "dependencies": {
"bindings": "^1.2.0", "bindings": "^1.2.0",
"nan": "^1.5.0", "nan": "^1.5.0",
"protobufjs": "^4.0.0-b2", "protobufjs": "dcodeIO/ProtoBuf.js",
"underscore": "^1.6.0", "underscore": "^1.6.0",
"underscore.string": "^3.0.0" "underscore.string": "^3.0.0"
}, },

@ -245,6 +245,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
if (response.status.code !== grpc.status.OK) { if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details); var error = new Error(response.status.details);
error.code = response.status.code; error.code = response.status.code;
error.metadata = response.status.metadata;
callback(error); callback(error);
return; return;
} }
@ -316,6 +317,7 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
if (response.status.code !== grpc.status.OK) { if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details); var error = new Error(response.status.details);
error.code = response.status.code; error.code = response.status.code;
error.metadata = response.status.metadata;
callback(error); callback(error);
return; return;
} }
@ -382,6 +384,13 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
throw err; throw err;
} }
stream.emit('status', response.status); stream.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
error.code = response.status.code;
error.metadata = response.status.metadata;
stream.emit('error', error);
return;
}
}); });
}); });
return stream; return stream;
@ -440,6 +449,13 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
throw err; throw err;
} }
stream.emit('status', response.status); stream.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
error.code = response.status.code;
error.metadata = response.status.metadata;
stream.emit('error', error);
return;
}
}); });
}); });
return stream; return stream;
@ -469,27 +485,28 @@ var requester_makers = {
* requestSerialize: function to serialize request objects * requestSerialize: function to serialize request objects
* responseDeserialize: function to deserialize response objects * responseDeserialize: function to deserialize response objects
* @param {Object} methods An object mapping method names to method attributes * @param {Object} methods An object mapping method names to method attributes
* @param {string} serviceName The name of the service
* @return {function(string, Object)} New client constructor * @return {function(string, Object)} New client constructor
*/ */
function makeClientConstructor(methods) { function makeClientConstructor(methods, serviceName) {
/** /**
* Create a client with the given methods * Create a client with the given methods
* @constructor * @constructor
* @param {string} address The address of the server to connect to * @param {string} address The address of the server to connect to
* @param {Object} options Options to pass to the underlying channel * @param {Object} options Options to pass to the underlying channel
* @param {function(Object, function)=} updateMetadata function to update the * @param {function(string, Object, function)=} updateMetadata function to
* metadata for each request * update the metadata for each request
*/ */
function Client(address, options, updateMetadata) { function Client(address, options, updateMetadata) {
if (updateMetadata) { if (!updateMetadata) {
this.updateMetadata = updateMetadata; updateMetadata = function(uri, metadata, callback) {
} else {
this.updateMetadata = function(metadata, callback) {
callback(null, metadata); callback(null, metadata);
}; };
} }
this.server_address = address; this.server_address = address.replace(/\/$/, '');
this.channel = new grpc.Channel(address, options); this.channel = new grpc.Channel(address, options);
this.updateMetadata = _.partial(updateMetadata,
this.server_address + '/' + serviceName);
} }
_.each(methods, function(attrs, name) { _.each(methods, function(attrs, name) {
@ -525,7 +542,7 @@ function makeClientConstructor(methods) {
* @return {function(string, Object)} New client constructor * @return {function(string, Object)} New client constructor
*/ */
function makeProtobufClientConstructor(service) { function makeProtobufClientConstructor(service) {
var method_attrs = common.getProtobufServiceAttrs(service); var method_attrs = common.getProtobufServiceAttrs(service, service.name);
var Client = makeClientConstructor(method_attrs); var Client = makeClientConstructor(method_attrs);
Client.service = service; Client.service = service;

@ -130,8 +130,7 @@ describe('Math client', function() {
}); });
call.write({dividend: 7, divisor: 0}); call.write({dividend: 7, divisor: 0});
call.end(); call.end();
call.on('status', function checkStatus(status) { call.on('error', function checkStatus(status) {
assert.notEqual(status.code, grpc.status.OK);
done(); done();
}); });
}); });

@ -278,9 +278,8 @@ describe('Trailing metadata', function() {
it('should be present when a server stream call fails', function(done) { it('should be present when a server stream call fails', function(done) {
var call = client.serverStream({error: true}); var call = client.serverStream({error: true});
call.on('data', function(){}); call.on('data', function(){});
call.on('status', function(status) { call.on('error', function(error) {
assert.notStrictEqual(status.code, grpc.status.OK); assert.deepEqual(error.metadata.metadata, ['yes']);
assert.deepEqual(status.metadata.metadata, ['yes']);
done(); done();
}); });
}); });
@ -302,9 +301,8 @@ describe('Trailing metadata', function() {
call.write({error: true}); call.write({error: true});
call.end(); call.end();
call.on('data', function(){}); call.on('data', function(){});
call.on('status', function(status) { call.on('error', function(error) {
assert.notStrictEqual(status.code, grpc.status.OK); assert.deepEqual(error.metadata.metadata, ['yes']);
assert.deepEqual(status.metadata.metadata, ['yes']);
done(); done();
}); });
}); });
@ -345,16 +343,16 @@ describe('Cancelling surface client', function() {
}); });
it('Should correctly cancel a server stream call', function(done) { it('Should correctly cancel a server stream call', function(done) {
var call = client.fib({'limit': 5}); var call = client.fib({'limit': 5});
call.on('status', function(status) { call.on('error', function(error) {
assert.strictEqual(status.code, surface_client.status.CANCELLED); assert.strictEqual(error.code, surface_client.status.CANCELLED);
done(); done();
}); });
call.cancel(); call.cancel();
}); });
it('Should correctly cancel a bidi stream call', function(done) { it('Should correctly cancel a bidi stream call', function(done) {
var call = client.divMany(); var call = client.divMany();
call.on('status', function(status) { call.on('error', function(error) {
assert.strictEqual(status.code, surface_client.status.CANCELLED); assert.strictEqual(error.code, surface_client.status.CANCELLED);
done(); done();
}); });
call.cancel(); call.cancel();

@ -27,14 +27,14 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto2"; syntax = "proto3";
message Request { message Request {
optional bool error = 1; bool error = 1;
} }
message Response { message Response {
optional int32 count = 1; int32 count = 1;
} }
service TestService { service TestService {

@ -7,7 +7,7 @@ The Python facility of gRPC.
Status Status
------- -------
Usable with limitations, Pre-Alpha Usable with limitations, Alpha
Prerequisites Prerequisites
----------------------- -----------------------

@ -55,7 +55,7 @@ class Fibber
return enum_for(:generator) unless block_given? return enum_for(:generator) unless block_given?
idx, current, previous = 0, 1, 1 idx, current, previous = 0, 1, 1
until idx == @limit until idx == @limit
if idx == 0 || idx == 1 if idx.zero? || idx == 1
yield Math::Num.new(num: 1) yield Math::Num.new(num: 1)
idx += 1 idx += 1
next next
@ -94,7 +94,7 @@ end
# package. That practice should be avoided by defining real services. # package. That practice should be avoided by defining real services.
class Calculator < Math::Math::Service class Calculator < Math::Math::Service
def div(div_args, _call) def div(div_args, _call)
if div_args.divisor == 0 if div_args.divisor.zero?
# To send non-OK status handlers raise a StatusError with the code and # To send non-OK status handlers raise a StatusError with the code and
# and detail they want sent as a Status. # and detail they want sent as a Status.
fail GRPC::StatusError.new(GRPC::Status::INVALID_ARGUMENT, fail GRPC::StatusError.new(GRPC::Status::INVALID_ARGUMENT,

@ -58,7 +58,7 @@ module GRPC
"Cannot make an absolute deadline from #{timeish.inspect}") "Cannot make an absolute deadline from #{timeish.inspect}")
elsif timeish < 0 elsif timeish < 0
TimeConsts::INFINITE_FUTURE TimeConsts::INFINITE_FUTURE
elsif timeish == 0 elsif timeish.zero?
TimeConsts::ZERO TimeConsts::ZERO
else else
Time.now + timeish Time.now + timeish

@ -146,7 +146,7 @@ module GRPC
def remove_current_thread def remove_current_thread
@stop_mutex.synchronize do @stop_mutex.synchronize do
@workers.delete(Thread.current) @workers.delete(Thread.current)
@stop_cond.signal if @workers.size == 0 @stop_cond.signal if @workers.size.zero?
end end
end end
@ -364,7 +364,7 @@ module GRPC
# - #running? returns true after this is called, until #stop cause the # - #running? returns true after this is called, until #stop cause the
# the server to stop. # the server to stop.
def run def run
if rpc_descs.size == 0 if rpc_descs.size.zero?
logger.warn('did not run as no services were present') logger.warn('did not run as no services were present')
return return
end end
@ -455,7 +455,7 @@ module GRPC
unless cls.include?(GenericService) unless cls.include?(GenericService)
fail "#{cls} must 'include GenericService'" fail "#{cls} must 'include GenericService'"
end end
if cls.rpc_descs.size == 0 if cls.rpc_descs.size.zero?
fail "#{cls} should specify some rpc descriptions" fail "#{cls} should specify some rpc descriptions"
end end
cls.assert_rpc_descs_have_methods cls.assert_rpc_descs_have_methods
@ -468,10 +468,11 @@ module GRPC
route = "/#{cls.service_name}/#{name}".to_sym route = "/#{cls.service_name}/#{name}".to_sym
fail "already registered: rpc #{route} from #{spec}" if specs.key? route fail "already registered: rpc #{route} from #{spec}" if specs.key? route
specs[route] = spec specs[route] = spec
rpc_name = GenericService.underscore(name.to_s).to_sym
if service.is_a?(Class) if service.is_a?(Class)
handlers[route] = cls.new.method(name.to_s.underscore.to_sym) handlers[route] = cls.new.method(rpc_name)
else else
handlers[route] = service.method(name.to_s.underscore.to_sym) handlers[route] = service.method(rpc_name)
end end
logger.info("handling #{route} with #{handlers[route]}") logger.info("handling #{route} with #{handlers[route]}")
end end

@ -30,24 +30,6 @@
require 'grpc/generic/client_stub' require 'grpc/generic/client_stub'
require 'grpc/generic/rpc_desc' require 'grpc/generic/rpc_desc'
# Extend String to add a method underscore
class String
# creates a new string that is the underscore separate version of this one.
#
# E.g,
# PrintHTML -> print_html
# AMethod -> a_method
# AnRpc -> an_rpc
def underscore
word = dup
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
word.tr!('-', '_')
word.downcase!
word
end
end
# GRPC contains the General RPC module. # GRPC contains the General RPC module.
module GRPC module GRPC
# Provides behaviour used to implement schema-derived service classes. # Provides behaviour used to implement schema-derived service classes.
@ -55,6 +37,22 @@ module GRPC
# Is intended to be used to support both client and server # Is intended to be used to support both client and server
# IDL-schema-derived servers. # IDL-schema-derived servers.
module GenericService module GenericService
# creates a new string that is the underscore separate version of s.
#
# E.g,
# PrintHTML -> print_html
# AMethod -> a_method
# AnRpc -> an_rpc
#
# @param s [String] the string to be converted.
def self.underscore(s)
s.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
s.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
s.tr!('-', '_')
s.downcase!
s
end
# Used to indicate that a name has already been specified # Used to indicate that a name has already been specified
class DuplicateRpcName < StandardError class DuplicateRpcName < StandardError
def initialize(name) def initialize(name)
@ -171,7 +169,7 @@ module GRPC
# Used define_method to add a method for each rpc_desc. Each method # Used define_method to add a method for each rpc_desc. Each method
# calls the base class method for the given descriptor. # calls the base class method for the given descriptor.
descs.each_pair do |name, desc| descs.each_pair do |name, desc|
mth_name = name.to_s.underscore.to_sym mth_name = GenericService.underscore(name.to_s).to_sym
marshal = desc.marshal_proc marshal = desc.marshal_proc
unmarshal = desc.unmarshal_proc(:output) unmarshal = desc.unmarshal_proc(:output)
route = "/#{route_prefix}/#{name}" route = "/#{route_prefix}/#{name}"
@ -207,7 +205,7 @@ module GRPC
# implemented. # implemented.
def assert_rpc_descs_have_methods def assert_rpc_descs_have_methods
rpc_descs.each_pair do |m, spec| rpc_descs.each_pair do |m, spec|
mth_name = m.to_s.underscore.to_sym mth_name = GenericService.underscore(m.to_s).to_sym
unless instance_methods.include?(mth_name) unless instance_methods.include?(mth_name)
fail "#{self} does not provide instance method '#{mth_name}'" fail "#{self} does not provide instance method '#{mth_name}'"
end end

@ -56,15 +56,6 @@ end
GenericService = GRPC::GenericService GenericService = GRPC::GenericService
Dsl = GenericService::Dsl Dsl = GenericService::Dsl
describe 'String#underscore' do
it 'should convert CamelCase to underscore separated' do
expect('AnRPC'.underscore).to eq('an_rpc')
expect('AMethod'.underscore).to eq('a_method')
expect('PrintHTML'.underscore).to eq('print_html')
expect('PrintHTMLBooks'.underscore).to eq('print_html_books')
end
end
describe Dsl do describe Dsl do
it 'can be included in new classes' do it 'can be included in new classes' do
blk = proc { Class.new { include Dsl } } blk = proc { Class.new { include Dsl } }
@ -73,6 +64,15 @@ describe Dsl do
end end
describe GenericService do describe GenericService do
context '#underscore' do
it 'should convert CamelCase to underscore separated' do
expect(GenericService.underscore('AnRPC')).to eq('an_rpc')
expect(GenericService.underscore('AMethod')).to eq('a_method')
expect(GenericService.underscore('PrintHTML')).to eq('print_html')
expect(GenericService.underscore('SeeHTMLBooks')).to eq('see_html_books')
end
end
describe 'including it' do describe 'including it' do
it 'adds a class method, rpc' do it 'adds a class method, rpc' do
c = Class.new do c = Class.new do

@ -56,6 +56,9 @@ endif
ifeq ($(SYSTEM),MSYS) ifeq ($(SYSTEM),MSYS)
SYSTEM = MINGW32 SYSTEM = MINGW32
endif endif
ifeq ($(SYSTEM),MINGW64)
SYSTEM = MINGW32
endif
ifndef BUILDDIR ifndef BUILDDIR

@ -33,10 +33,19 @@
<%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\ <%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
<% <%
disallowed_dependencies = set(['end2end_certs']) disallowed_dependencies = set(['end2end_certs'])
buildable_targets = [ target for target in targets build_from_project_file = set(['gpr',
if not disallowed_dependencies.intersection(target.deps) and 'grpc',
'grpc_unsecure',
'gpr_test_util',
'grpc_test_util',
'grpc_test_util_unsecure',
])
buildable_targets = [ target for target in targets + libs
if not disallowed_dependencies.intersection(target.get('deps', [])) and
target.build in ['all', 'test', 'private', 'tool', 'benchmark'] and
target.language in ['c', 'c++'] and
all([src.endswith('.c') for src in target.src]) and all([src.endswith('.c') for src in target.src]) and
'windows' in target.platforms ] 'windows' in target.get('platforms', ['windows']) ]
c_test_targets = [ target for target in buildable_targets if target.build == 'test' and not target.language == 'c++' ] c_test_targets = [ target for target in buildable_targets if target.build == 'test' and not target.language == 'c++' ]
cxx_test_targets = [ target for target in buildable_targets if target.build == 'test' and target.language == 'c++' ] cxx_test_targets = [ target for target in buildable_targets if target.build == 'test' and target.language == 'c++' ]
%>\ %>\
@ -45,31 +54,40 @@
OUT_DIR=test_bin OUT_DIR=test_bin
CC=cl.exe CC=cl.exe /nologo
LINK=link.exe LINK=link.exe /nologo
LIBTOOL=lib.exe /nologo /nodefaultlib
REPO_ROOT=.. REPO_ROOT=..
OPENSSL_INCLUDES = .\packages\${get_openssl()}\build\native\include\v120\Win32\Debug\static OPENSSL_INCLUDES = .\packages\${get_openssl()}\build\native\include
ZLIB_INCLUDES = .\packages\${get_zlib()}\build\native\include ZLIB_INCLUDES = .\packages\${get_zlib()}\build\native\include
INCLUDES=/I$(REPO_ROOT) /I$(REPO_ROOT)\include /I$(OPENSSL_INCLUDES) /I$(ZLIB_INCLUDES) INCLUDES=/I$(REPO_ROOT) /I$(REPO_ROOT)\include /I$(OPENSSL_INCLUDES) /I$(ZLIB_INCLUDES)
DEFINES=/D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /D _CRT_SECURE_NO_WARNINGS DEFINES=/D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /D _CRT_SECURE_NO_WARNINGS
CFLAGS=/c $(INCLUDES) /nologo /Z7 /W3 /WX- /sdl $(DEFINES) /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze- CFLAGS=/c $(INCLUDES) /Z7 /W3 /WX- /sdl $(DEFINES) /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze-
LFLAGS=/DEBUG /INCREMENTAL /NOLOGO /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 LFLAGS=/DEBUG /INCREMENTAL /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86
OPENSSL_LIBS=.\packages\${get_openssl()}\build\native\lib\v120\Win32\Debug\static\ssleay32.lib .\packages\${get_openssl()}\build\native\lib\v120\Win32\Debug\static\libeay32.lib OPENSSL_LIBS=.\packages\${get_openssl()}\build\native\lib\v120\Win32\Debug\static\ssleay32.lib .\packages\${get_openssl()}\build\native\lib\v120\Win32\Debug\static\libeay32.lib
WINSOCK_LIBS=ws2_32.lib WINSOCK_LIBS=ws2_32.lib
GENERAL_LIBS=advapi32.lib comdlg32.lib gdi32.lib kernel32.lib odbc32.lib odbccp32.lib ole32.lib oleaut32.lib shell32.lib user32.lib uuid.lib winspool.lib
ZLIB_LIBS=.\packages\${get_zlib()}\build\native\lib\v120\Win32\Debug\static\cdecl\zlib.lib ZLIB_LIBS=.\packages\${get_zlib()}\build\native\lib\v120\Win32\Debug\static\cdecl\zlib.lib
LIBS=$(OPENSSL_LIBS) $(WINSOCK_LIBS) $(ZLIB_LIBS) LIBS=$(OPENSSL_LIBS) $(ZLIB_LIBS) $(GENERAL_LIBS) $(WINSOCK_LIBS)
build_gpr_test_util: all: buildtests
msbuild grpc.sln /t:gpr_test_util /p:Configuration=Debug
build_grpc_test_util:
msbuild grpc.sln /t:grpc_test_util /p:Configuration=Debug
$(OUT_DIR): $(OUT_DIR):
mkdir $(OUT_DIR) mkdir $(OUT_DIR)
build_libs: \
% for target in buildable_targets:
% if target.build == 'private' or target.build == 'all':
% if target.name in build_from_project_file:
build_${target.name} \
% else:
Debug\${target.name}.lib \
% endif
% endif
% endfor
buildtests: buildtests_c buildtests_cxx buildtests: buildtests_c buildtests_cxx
buildtests_c: \ buildtests_c: \
@ -87,24 +105,42 @@ ${target.name}.exe \
echo All tests built. echo All tests built.
% for target in buildable_targets: % for target in buildable_targets:
${target.name}.exe: build_grpc_test_util $(OUT_DIR) %if target.name in build_from_project_file:
build_${target.name}:
msbuild grpc.sln /t:${target.name} /p:Configuration=Debug /p:Linkage-grpc_dependencies_zlib=static
%else:
%if target.build == 'private':
Debug\${target.name}.lib: \
%else:
${target.name}.exe: build_libs \
%endif
$(OUT_DIR)
echo Building ${target.name} echo Building ${target.name}
$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ \ $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ \
%for source in target.src: %for source in target.src:
$(REPO_ROOT)\${to_windows_path(source)} \ $(REPO_ROOT)\${to_windows_path(source)} \
%endfor %endfor
%if not target.src:
$(REPO_ROOT)\${to_windows_path('vsprojects/dummy.c')} \
%endif
%if target.build == 'private':
$(LIBTOOL) /OUT:"Debug\${target.name}.lib" \
%else:
$(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\${target.name}.exe" \ $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\${target.name}.exe" \
%for dep in target.deps: %for dep in target.get('deps', []):
Debug\${dep}.lib \ Debug\${dep}.lib \
%endfor %endfor
$(LIBS) \ $(LIBS) \
%endif
%for source in target.src: %for source in target.src:
$(OUT_DIR)\${re.search('([^/]+)\.c$', source).group(1)}.obj \ $(OUT_DIR)\${re.search('([^/]+)\.c$', source).group(1)}.obj \
%endfor %endfor
%if target.build != 'private':
${target.name}: ${target.name}.exe ${target.name}: ${target.name}.exe
echo Running ${target.name} echo Running ${target.name}
$(OUT_DIR)\${target.name}.exe $(OUT_DIR)\${target.name}.exe
%endif
%endif
% endfor % endfor

@ -0,0 +1,33 @@
#!/bin/sh
# To properly use this, you'll need to add:
#
# "debug": true
#
# to build.json
cd `dirname $0`/../..
./tools/buildgen/generate_projects.sh
git diff |
grep \\+Project |
cut -d\" -f 4 |
sort -u |
grep _test$ |
while read p ; do
mkdir -p templates/vsprojects/$p
echo '<%namespace file="../vcxproj_defs.include" import="gen_project"/>${gen_project("'$p'", targets)}' > templates/vsprojects/$p/$p.vcxproj.template
done
git diff |
grep \\+Project |
cut -d\" -f 4 |
sort -u |
grep -v _test$ |
while read p ; do
mkdir -p templates/vsprojects/$p
echo '<%namespace file="../vcxproj_defs.include" import="gen_project"/>${gen_project("'$p'", libs)}' > templates/vsprojects/$p/$p.vcxproj.template
done
./tools/buildgen/generate_projects.sh

@ -1,2 +1,2 @@
<%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\ <%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\
${gen_filters('gpr', libs, targets)} ${gen_filters('gpr', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('gpr', libs, targets)} ${gen_project('gpr', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('gpr_test_util', libs, targets)} ${gen_project('gpr_test_util', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\ <%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\
${gen_filters('grpc++', libs, targets)} ${gen_filters('grpc++', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('grpc++', libs, targets)} ${gen_project('grpc++', libs)}

@ -0,0 +1,2 @@
<%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\
${gen_filters('grpc++_unsecure', libs)}

@ -0,0 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('grpc++_unsecure', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\ <%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\
${gen_filters('grpc', libs, targets)} ${gen_filters('grpc', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('grpc', libs, targets, packages=['openssl','zlib'])} ${gen_project('grpc', libs, packages=['openssl','zlib'])}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('grpc_csharp_ext', libs, targets, configuration_type = 'DynamicLibrary', additional_props = ['winsock'], packages=['openssl','zlib'])} ${gen_project('grpc_csharp_ext', libs, configuration_type = 'DynamicLibrary', props = ['winsock'], packages=['openssl','zlib'])}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('grpc_test_util', libs, targets)} ${gen_project('grpc_test_util', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\ <%namespace file="../vcxproj.filters_defs.include" import="gen_filters"/>\
${gen_filters('grpc_unsecure', libs, targets)} ${gen_filters('grpc_unsecure', libs)}

@ -1,2 +1,2 @@
<%namespace file="../vcxproj_defs.include" import="gen_project"/>\ <%namespace file="../vcxproj_defs.include" import="gen_project"/>\
${gen_project('grpc_unsecure', libs, targets, packages=['zlib'])} ${gen_project('grpc_unsecure', libs, packages=['zlib'])}

@ -9,7 +9,7 @@
<%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\ <%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
<%def name="to_filter(path)">${calc_to_filter(path)}</%def>\ <%def name="to_filter(path)">${calc_to_filter(path)}</%def>\
<%def name="filter_to_guid(proj, filter)">${re.sub('(........)(....)(....)(....)', r'\1-\2-\3-\4-', hashlib.md5(''.join([filter, proj])).hexdigest())}</%def>\ <%def name="filter_to_guid(proj, filter)">${re.sub('(........)(....)(....)(....)', r'\1-\2-\3-\4-', hashlib.md5(''.join([filter, proj])).hexdigest())}</%def>\
<%def name="gen_filters(name, libs, targets)">\ <%def name="gen_filters(name, collection)">\
% for project in vsprojects: % for project in vsprojects:
% if project.name == name: % if project.name == name:
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>

@ -2,9 +2,24 @@
<%def name="get_repo_root()">..\..</%def>\ <%def name="get_repo_root()">..\..</%def>\
<%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\ <%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
<%def name="get_subsystem(is_library)">${'Windows' if is_library else 'Console'}</%def>\ <%def name="get_subsystem(is_library)">${'Windows' if is_library else 'Console'}</%def>\
<%def name="gen_project(name, libs, targets, configuration_type = 'StaticLibrary', project_guid = None, additional_props = [], packages = [])">\ <%def name="gen_project(name, collection, configuration_type = None, project_guid = None, props = [], packages = [])">\
% for project in vsprojects: <%
% if project.name == name: for p in vsprojects:
if p.name == name:
project = p
for t in collection:
if t.name == name:
target = t
if not configuration_type:
configuration_type = 'StaticLibrary'
if not project_guid:
project_guid = project.vs_project_guid
if configuration_type == 'Application':
props.extend(['winsock', 'protobuf', 'zlib', 'openssl'])
if target.language == 'c++':
props.extend(['protobuf'])
props.extend(['global'])
%>\
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
${gen_package_props(packages)}\ ${gen_package_props(packages)}\
@ -66,29 +81,25 @@ ${gen_package_props(packages)}\
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\global.props" /> % for prop in props:
% for prop in additional_props:
<Import Project="..\${prop}.props" /> <Import Project="..\${prop}.props" />
% endfor % endfor
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\global.props" /> % for prop in props:
% for prop in additional_props:
<Import Project="..\${prop}.props" /> <Import Project="..\${prop}.props" />
% endfor % endfor
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\global.props" /> % for prop in props:
% for prop in additional_props:
<Import Project="..\${prop}.props" /> <Import Project="..\${prop}.props" />
% endfor % endfor
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\global.props" /> % for prop in props:
% for prop in additional_props:
<Import Project="..\${prop}.props" /> <Import Project="..\${prop}.props" />
% endfor % endfor
</ImportGroup> </ImportGroup>
@ -186,6 +197,11 @@ ${gen_package_props(packages)}\
</ClCompile> </ClCompile>
% endfor % endfor
</ItemGroup> </ItemGroup>
% elif configuration_type != 'StaticLibrary':
<ItemGroup>
<ClCompile Include="${get_repo_root()}\${to_windows_path('vsprojects/dummy.c')}">
</ClCompile>
</ItemGroup>
% endif % endif
% if project.get('deps',[]): % if project.get('deps',[]):
<ItemGroup> <ItemGroup>
@ -207,6 +223,4 @@ ${gen_package_targets(packages)}\
</ImportGroup> </ImportGroup>
${gen_package_ensure(packages)}\ ${gen_package_ensure(packages)}\
</Project> </Project>
% endif
% endfor
</%def>\ </%def>\

@ -41,6 +41,7 @@ typedef struct grpc_end2end_test_config grpc_end2end_test_config;
#define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1 #define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1
#define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2 #define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2
#define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS 4
struct grpc_end2end_test_fixture { struct grpc_end2end_test_fixture {
grpc_completion_queue *server_cq; grpc_completion_queue *server_cq;

@ -112,7 +112,9 @@ static void chttp2_init_server_fake_secure_fullstack(
/* All test configurations */ /* All test configurations */
static grpc_end2end_test_config configs[] = { static grpc_end2end_test_config configs[] = {
{"chttp2/fake_secure_fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, {"chttp2/fake_secure_fullstack",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
chttp2_create_fixture_secure_fullstack, chttp2_create_fixture_secure_fullstack,
chttp2_init_client_fake_secure_fullstack, chttp2_init_client_fake_secure_fullstack,
chttp2_init_server_fake_secure_fullstack, chttp2_init_server_fake_secure_fullstack,

@ -124,7 +124,8 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
static grpc_end2end_test_config configs[] = { static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_fullstack", {"chttp2/simple_ssl_fullstack",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION, FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
chttp2_create_fixture_secure_fullstack, chttp2_create_fixture_secure_fullstack,
chttp2_init_client_simple_ssl_secure_fullstack, chttp2_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack,

@ -129,7 +129,8 @@ static void chttp2_init_server_simple_ssl_secure_fullstack(
static grpc_end2end_test_config configs[] = { static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_with_oauth2_fullstack", {"chttp2/simple_ssl_with_oauth2_fullstack",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION, FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
chttp2_create_fixture_secure_fullstack, chttp2_create_fixture_secure_fullstack,
chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack, chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack,

@ -33,48 +33,56 @@
import simplejson import simplejson
import collections
FixtureOptions = collections.namedtuple('FixtureOptions', 'secure platforms')
default_unsecure_fixture_options = FixtureOptions(False, ['windows', 'posix'])
default_secure_fixture_options = FixtureOptions(True, ['windows', 'posix'])
# maps fixture name to whether it requires the security library # maps fixture name to whether it requires the security library
END2END_FIXTURES = { END2END_FIXTURES = {
'chttp2_fake_security': True, 'chttp2_fake_security': default_secure_fixture_options,
'chttp2_fullstack': False, 'chttp2_fullstack': default_unsecure_fixture_options,
'chttp2_fullstack_uds': False, 'chttp2_fullstack_uds_posix': FixtureOptions(False, ['posix']),
'chttp2_simple_ssl_fullstack': True, 'chttp2_simple_ssl_fullstack': default_secure_fixture_options,
'chttp2_simple_ssl_with_oauth2_fullstack': True, 'chttp2_simple_ssl_with_oauth2_fullstack': default_secure_fixture_options,
'chttp2_socket_pair': False, 'chttp2_socket_pair': default_unsecure_fixture_options,
'chttp2_socket_pair_one_byte_at_a_time': False, 'chttp2_socket_pair_one_byte_at_a_time': default_unsecure_fixture_options,
} }
# maps tests names to whether they run fine or not (aka, not flaky) TestOptions = collections.namedtuple('TestOptions', 'flaky secure')
default_test_options = TestOptions(False, False)
# maps test names to options
END2END_TESTS = { END2END_TESTS = {
'bad_hostname': True, 'bad_hostname': default_test_options,
'cancel_after_accept': False, 'cancel_after_accept': TestOptions(flaky=True, secure=False),
'cancel_after_accept_and_writes_closed': True, 'cancel_after_accept_and_writes_closed': default_test_options,
'cancel_after_invoke': True, 'cancel_after_invoke': default_test_options,
'cancel_before_invoke': True, 'cancel_before_invoke': default_test_options,
'cancel_in_a_vacuum': True, 'cancel_in_a_vacuum': default_test_options,
'census_simple_request': True, 'census_simple_request': default_test_options,
'disappearing_server': True, 'disappearing_server': default_test_options,
'early_server_shutdown_finishes_inflight_calls': True, 'early_server_shutdown_finishes_inflight_calls': default_test_options,
'early_server_shutdown_finishes_tags': True, 'early_server_shutdown_finishes_tags': default_test_options,
'empty_batch': True, 'empty_batch': default_test_options,
'graceful_server_shutdown': True, 'graceful_server_shutdown': default_test_options,
'invoke_large_request': False, 'invoke_large_request': TestOptions(flaky=True, secure=False),
'max_concurrent_streams': True, 'max_concurrent_streams': default_test_options,
'max_message_length': True, 'max_message_length': default_test_options,
'no_op': True, 'no_op': default_test_options,
'ping_pong_streaming': True, 'ping_pong_streaming': default_test_options,
'registered_call': True, 'registered_call': default_test_options,
'request_response_with_binary_metadata_and_payload': True, 'request_response_with_binary_metadata_and_payload': default_test_options,
'request_response_with_metadata_and_payload': True, 'request_response_with_metadata_and_payload': default_test_options,
'request_response_with_payload': True, 'request_response_with_payload': default_test_options,
'request_response_with_trailing_metadata_and_payload': True, 'request_response_with_payload_and_call_creds': TestOptions(flaky=False, secure=True),
'request_with_large_metadata': True, 'request_with_large_metadata': default_test_options,
'request_with_payload': True, 'request_with_payload': default_test_options,
'simple_delayed_request': True, 'simple_delayed_request': default_test_options,
'simple_request': True, 'simple_request': default_test_options,
'simple_request_with_high_initial_sequence_number': True, 'simple_request_with_high_initial_sequence_number': default_test_options,
} }
@ -86,15 +94,16 @@ def main():
'name': 'end2end_fixture_%s' % f, 'name': 'end2end_fixture_%s' % f,
'build': 'private', 'build': 'private',
'language': 'c', 'language': 'c',
'secure': 'check' if END2END_FIXTURES[f] else 'no', 'secure': 'check' if END2END_FIXTURES[f].secure else 'no',
'src': ['test/core/end2end/fixtures/%s.c' % f] 'src': ['test/core/end2end/fixtures/%s.c' % f],
'platforms': [ 'posix' ] if f.endswith('_posix') else [ 'windows', 'posix' ],
} }
for f in sorted(END2END_FIXTURES.keys())] + [ for f in sorted(END2END_FIXTURES.keys())] + [
{ {
'name': 'end2end_test_%s' % t, 'name': 'end2end_test_%s' % t,
'build': 'private', 'build': 'private',
'language': 'c', 'language': 'c',
'secure': 'no', 'secure': 'check' if END2END_TESTS[t].secure else 'no',
'src': ['test/core/end2end/tests/%s.c' % t], 'src': ['test/core/end2end/tests/%s.c' % t],
'headers': ['test/core/end2end/tests/cancel_test_helpers.h'] 'headers': ['test/core/end2end/tests/cancel_test_helpers.h']
} }
@ -116,7 +125,8 @@ def main():
'build': 'test', 'build': 'test',
'language': 'c', 'language': 'c',
'src': [], 'src': [],
'flaky': not END2END_TESTS[t], 'flaky': END2END_TESTS[t].flaky,
'platforms': END2END_FIXTURES[f].platforms,
'deps': [ 'deps': [
'end2end_fixture_%s' % f, 'end2end_fixture_%s' % f,
'end2end_test_%s' % t, 'end2end_test_%s' % t,
@ -136,6 +146,7 @@ def main():
'secure': 'no', 'secure': 'no',
'src': [], 'src': [],
'flaky': 'invoke_large_request' in t, 'flaky': 'invoke_large_request' in t,
'platforms': END2END_FIXTURES[f].platforms,
'deps': [ 'deps': [
'end2end_fixture_%s' % f, 'end2end_fixture_%s' % f,
'end2end_test_%s' % t, 'end2end_test_%s' % t,
@ -145,8 +156,8 @@ def main():
'gpr' 'gpr'
] ]
} }
for f in sorted(END2END_FIXTURES.keys()) if not END2END_FIXTURES[f] for f in sorted(END2END_FIXTURES.keys()) if not END2END_FIXTURES[f].secure
for t in sorted(END2END_TESTS.keys())]} for t in sorted(END2END_TESTS.keys()) if not END2END_TESTS[t].secure]}
print simplejson.dumps(json, sort_keys=True, indent=2 * ' ') print simplejson.dumps(json, sort_keys=True, indent=2 * ' ')

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

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

Loading…
Cancel
Save