Merge branch 'master' of github.com:grpc/grpc into credentials_refactoring

pull/6436/head
Julien Boeuf 9 years ago
commit a4880374f9
  1. 20
      BUILD
  2. 64
      Makefile
  3. 4
      binding.gyp
  4. 37
      build.yaml
  5. 6
      config.m4
  6. 29
      examples/csharp/helloworld/generate_protos.bat
  7. 29
      examples/csharp/route_guide/generate_protos.bat
  8. 10
      examples/node/README.md
  9. 1
      examples/node/dynamic_codegen/README.md
  10. 2
      examples/node/dynamic_codegen/greeter_client.js
  11. 2
      examples/node/dynamic_codegen/greeter_server.js
  12. 0
      examples/node/dynamic_codegen/route_guide/README.md
  13. 2
      examples/node/dynamic_codegen/route_guide/route_guide_client.js
  14. 0
      examples/node/dynamic_codegen/route_guide/route_guide_db.json
  15. 2
      examples/node/dynamic_codegen/route_guide/route_guide_server.js
  16. 3
      examples/node/package.json
  17. 7
      examples/node/static_codegen/README.md
  18. 55
      examples/node/static_codegen/greeter_client.js
  19. 59
      examples/node/static_codegen/greeter_server.js
  20. 44
      examples/node/static_codegen/helloworld_grpc_pb.js
  21. 332
      examples/node/static_codegen/helloworld_pb.js
  22. 5
      examples/node/static_codegen/route_guide/README.md
  23. 247
      examples/node/static_codegen/route_guide/route_guide_client.js
  24. 601
      examples/node/static_codegen/route_guide/route_guide_db.json
  25. 110
      examples/node/static_codegen/route_guide/route_guide_grpc_pb.js
  26. 1033
      examples/node/static_codegen/route_guide/route_guide_pb.js
  27. 261
      examples/node/static_codegen/route_guide/route_guide_server.js
  28. 9
      gRPC.podspec
  29. 1
      grpc.def
  30. 7
      grpc.gemspec
  31. 7
      include/grpc++/impl/codegen/call.h
  32. 11
      include/grpc++/impl/codegen/proto_utils.h
  33. 8
      include/grpc++/impl/server_builder_option.h
  34. 67
      include/grpc++/impl/server_builder_plugin.h
  35. 58
      include/grpc++/impl/server_initializer.h
  36. 8
      include/grpc++/server.h
  37. 13
      include/grpc++/server_builder.h
  38. 51
      include/grpc/grpc_cronet.h
  39. 29
      include/grpc/impl/codegen/compression_types.h
  40. 2
      package.json
  41. 45
      package.xml
  42. 110
      src/compiler/python_generator.cc
  43. 1
      src/core/ext/client_config/subchannel_call_holder.c
  44. 69
      src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
  45. 85
      src/core/ext/transport/cronet/transport/cronet_api_dummy.c
  46. 640
      src/core/ext/transport/cronet/transport/cronet_transport.c
  47. 9
      src/core/lib/channel/channel_args.c
  48. 12
      src/core/lib/channel/compress_filter.c
  49. 2
      src/core/lib/channel/compress_filter.h
  50. 3
      src/core/lib/http/parser.c
  51. 2
      src/core/lib/iomgr/ev_poll_and_epoll_posix.c
  52. 1212
      src/core/lib/iomgr/ev_poll_posix.c
  53. 41
      src/core/lib/iomgr/ev_poll_posix.h
  54. 93
      src/core/lib/iomgr/ev_posix.c
  55. 17
      src/core/lib/iomgr/exec_ctx.c
  56. 29
      src/core/lib/iomgr/exec_ctx.h
  57. 6
      src/core/lib/iomgr/iomgr_posix.c
  58. 18
      src/core/lib/iomgr/udp_server.c
  59. 6
      src/core/lib/iomgr/udp_server.h
  60. 2
      src/core/lib/support/string_util_win32.c
  61. 19
      src/core/lib/surface/byte_buffer_reader.c
  62. 32
      src/core/lib/surface/call.c
  63. 2
      src/core/lib/surface/init.c
  64. 2
      src/cpp/common/channel_arguments.cc
  65. 19
      src/cpp/server/server.cc
  66. 38
      src/cpp/server/server_builder.cc
  67. 39
      src/csharp/Grpc.Core.Tests/ChannelTest.cs
  68. 51
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
  69. 34
      src/csharp/Grpc.Core/Channel.cs
  70. 15
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  71. 2
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  72. 2
      src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
  73. 38
      src/csharp/Grpc.Examples/MathExamples.cs
  74. 29
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  75. 4
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  76. 2
      src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
  77. 29
      src/csharp/build_packages.bat
  78. 29
      src/csharp/buildall.bat
  79. 7
      src/node/tools/bin/protoc.js
  80. 8
      src/node/tools/bin/protoc_plugin.js
  81. 11
      src/php/ext/grpc/call.c
  82. 4
      src/php/ext/grpc/call.h
  83. 12
      src/php/ext/grpc/call_credentials.c
  84. 4
      src/php/ext/grpc/channel.c
  85. 2
      src/php/ext/grpc/channel.h
  86. 8
      src/php/ext/grpc/channel_credentials.c
  87. 8
      src/php/ext/grpc/server.c
  88. 4
      src/php/ext/grpc/server_credentials.c
  89. 14
      src/php/ext/grpc/timeval.c
  90. 2
      src/php/ext/grpc/timeval.h
  91. 151
      src/proto/grpc/reflection/v1alpha/reflection.proto
  92. 7
      src/proto/grpc/testing/echo_messages.proto
  93. 20
      src/python/grpcio/grpc/_adapter/_low.py
  94. 4
      src/python/grpcio/grpc/_adapter/_types.py
  95. 38
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  96. 4
      src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi
  97. 74
      src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
  98. 2
      src/python/grpcio/grpc/_cython/imports.generated.c
  99. 13
      src/python/grpcio/grpc/_cython/imports.generated.h
  100. 2
      src/python/grpcio/grpc/beta/interfaces.py
  101. Some files were not shown because too many files have changed in this diff Show More

20
BUILD

@ -179,6 +179,7 @@ cc_library(
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.h",
@ -294,6 +295,7 @@ cc_library(
"src/core/ext/client_config/subchannel_call_holder.h",
"src/core/ext/client_config/subchannel_index.h",
"src/core/ext/client_config/uri_parser.h",
"third_party/objective_c/Cronet/cronet_c_for_grpc.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/census/aggregation.h",
@ -321,6 +323,7 @@ cc_library(
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
"src/core/lib/iomgr/ev_posix.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/executor.c",
@ -456,6 +459,9 @@ cc_library(
"src/core/ext/client_config/uri_parser.c",
"src/core/ext/transport/chttp2/server/insecure/server_chttp2.c",
"src/core/ext/transport/chttp2/client/insecure/channel_create.c",
"src/core/ext/transport/cronet/client/secure/cronet_channel_create.c",
"src/core/ext/transport/cronet/transport/cronet_api_dummy.c",
"src/core/ext/transport/cronet/transport/cronet_transport.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/lb_policy/pick_first/pick_first.c",
@ -500,6 +506,7 @@ cc_library(
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"include/grpc/grpc_cronet.h",
"include/grpc/grpc_security.h",
"include/grpc/grpc_security_constants.h",
"include/grpc/census.h",
@ -542,6 +549,7 @@ cc_library(
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.h",
@ -662,6 +670,7 @@ cc_library(
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
"src/core/lib/iomgr/ev_posix.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/executor.c",
@ -909,6 +918,8 @@ cc_library(
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",
@ -1055,6 +1066,8 @@ cc_library(
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",
@ -1350,6 +1363,7 @@ objc_library(
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.c",
"src/core/lib/iomgr/ev_poll_posix.c",
"src/core/lib/iomgr/ev_posix.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/executor.c",
@ -1485,6 +1499,9 @@ objc_library(
"src/core/ext/client_config/uri_parser.c",
"src/core/ext/transport/chttp2/server/insecure/server_chttp2.c",
"src/core/ext/transport/chttp2/client/insecure/channel_create.c",
"src/core/ext/transport/cronet/client/secure/cronet_channel_create.c",
"src/core/ext/transport/cronet/transport/cronet_api_dummy.c",
"src/core/ext/transport/cronet/transport/cronet_transport.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/lb_policy/pick_first/pick_first.c",
@ -1529,6 +1546,7 @@ objc_library(
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"include/grpc/grpc_cronet.h",
"include/grpc/grpc_security.h",
"include/grpc/grpc_security_constants.h",
"include/grpc/census.h",
@ -1550,6 +1568,7 @@ objc_library(
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/ev_poll_and_epoll_posix.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.h",
@ -1665,6 +1684,7 @@ objc_library(
"src/core/ext/client_config/subchannel_call_holder.h",
"src/core/ext/client_config/subchannel_index.h",
"src/core/ext/client_config/uri_parser.h",
"third_party/objective_c/Cronet/cronet_c_for_grpc.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/census/aggregation.h",

@ -187,8 +187,8 @@ CC_ubsan = clang
CXX_ubsan = clang++
LD_ubsan = clang
LDXX_ubsan = clang++
CPPFLAGS_ubsan = -O1 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument
LDFLAGS_ubsan = -fsanitize=undefined
CPPFLAGS_ubsan = -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow -fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
LDFLAGS_ubsan = -fsanitize=undefined,unsigned-integer-overflow
DEFINES_ubsan = NDEBUG
DEFINES_ubsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
@ -1042,6 +1042,7 @@ reconnect_interop_client: $(BINDIR)/$(CONFIG)/reconnect_interop_client
reconnect_interop_server: $(BINDIR)/$(CONFIG)/reconnect_interop_server
secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
secure_sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test
server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test
server_crash_test: $(BINDIR)/$(CONFIG)/server_crash_test
server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client
shutdown_test: $(BINDIR)/$(CONFIG)/shutdown_test
@ -1410,6 +1411,7 @@ buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/reconnect_interop_server \
$(BINDIR)/$(CONFIG)/secure_auth_context_test \
$(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
$(BINDIR)/$(CONFIG)/server_builder_plugin_test \
$(BINDIR)/$(CONFIG)/server_crash_test \
$(BINDIR)/$(CONFIG)/server_crash_test_client \
$(BINDIR)/$(CONFIG)/shutdown_test \
@ -1743,6 +1745,8 @@ test_cxx: test_zookeeper buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 )
$(E) "[RUN] Testing secure_sync_unary_ping_pong_test"
$(Q) $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test || ( echo test secure_sync_unary_ping_pong_test failed ; exit 1 )
$(E) "[RUN] Testing server_builder_plugin_test"
$(Q) $(BINDIR)/$(CONFIG)/server_builder_plugin_test || ( echo test server_builder_plugin_test failed ; exit 1 )
$(E) "[RUN] Testing server_crash_test"
$(Q) $(BINDIR)/$(CONFIG)/server_crash_test || ( echo test server_crash_test failed ; exit 1 )
$(E) "[RUN] Testing shutdown_test"
@ -2507,6 +2511,7 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
@ -2642,6 +2647,9 @@ LIBGRPC_SRC = \
src/core/ext/client_config/uri_parser.c \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \
src/core/ext/transport/cronet/transport/cronet_api_dummy.c \
src/core/ext/transport/cronet/transport/cronet_transport.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
@ -2689,6 +2697,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_win32.h \
include/grpc/impl/codegen/time.h \
include/grpc/grpc_cronet.h \
include/grpc/grpc_security.h \
include/grpc/grpc_security_constants.h \
include/grpc/census.h \
@ -2857,6 +2866,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
@ -3221,6 +3231,8 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \
@ -3525,6 +3537,8 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \
@ -11502,6 +11516,49 @@ endif
endif
SERVER_BUILDER_PLUGIN_TEST_SRC = \
test/cpp/end2end/server_builder_plugin_test.cc \
SERVER_BUILDER_PLUGIN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_BUILDER_PLUGIN_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/server_builder_plugin_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/server_builder_plugin_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/server_builder_plugin_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_PLUGIN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(SERVER_BUILDER_PLUGIN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_builder_plugin_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/end2end/server_builder_plugin_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_server_builder_plugin_test: $(SERVER_BUILDER_PLUGIN_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SERVER_BUILDER_PLUGIN_TEST_OBJS:.o=.dep)
endif
endif
SERVER_CRASH_TEST_SRC = \
test/cpp/end2end/server_crash_test.cc \
@ -14356,6 +14413,9 @@ ifneq ($(OPENSSL_DEP),)
# otherwise parallel compilation will fail if a source is compiled first.
src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP)
src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP)
src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP)
src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP)
src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP)
src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP)
src/core/lib/security/context/security_context.c: $(OPENSSL_DEP)
src/core/lib/security/credentials/composite/composite_credentials.c: $(OPENSSL_DEP)

@ -582,6 +582,7 @@
'src/core/lib/iomgr/endpoint_pair_posix.c',
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
'src/core/lib/iomgr/ev_poll_posix.c',
'src/core/lib/iomgr/ev_posix.c',
'src/core/lib/iomgr/exec_ctx.c',
'src/core/lib/iomgr/executor.c',
@ -717,6 +718,9 @@
'src/core/ext/client_config/uri_parser.c',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
'src/core/ext/transport/cronet/transport/cronet_api_dummy.c',
'src/core/ext/transport/cronet/transport/cronet_transport.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',

@ -166,6 +166,7 @@ filegroups:
- src/core/lib/iomgr/endpoint.h
- src/core/lib/iomgr/endpoint_pair.h
- src/core/lib/iomgr/ev_poll_and_epoll_posix.h
- src/core/lib/iomgr/ev_poll_posix.h
- src/core/lib/iomgr/ev_posix.h
- src/core/lib/iomgr/exec_ctx.h
- src/core/lib/iomgr/executor.h
@ -240,6 +241,7 @@ filegroups:
- src/core/lib/iomgr/endpoint_pair_posix.c
- src/core/lib/iomgr/endpoint_pair_windows.c
- src/core/lib/iomgr/ev_poll_and_epoll_posix.c
- src/core/lib/iomgr/ev_poll_posix.c
- src/core/lib/iomgr/ev_posix.c
- src/core/lib/iomgr/exec_ctx.c
- src/core/lib/iomgr/executor.c
@ -400,6 +402,7 @@ filegroups:
- grpc_client_config
- name: grpc_secure
public_headers:
- include/grpc/grpc_cronet.h
- include/grpc/grpc_security.h
- include/grpc/grpc_security_constants.h
headers:
@ -564,6 +567,16 @@ filegroups:
- grpc_transport_chttp2
- grpc_base
- grpc_secure
- name: grpc_transport_cronet_client_secure
headers:
- third_party/objective_c/Cronet/cronet_c_for_grpc.h
src:
- src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
- src/core/ext/transport/cronet/transport/cronet_api_dummy.c
- src/core/ext/transport/cronet/transport/cronet_transport.c
filegroups:
- grpc_base
- grpc_transport_chttp2
- name: nanopb
headers:
- third_party/nanopb/pb.h
@ -608,6 +621,8 @@ filegroups:
- include/grpc++/impl/rpc_service_method.h
- include/grpc++/impl/serialization_traits.h
- include/grpc++/impl/server_builder_option.h
- include/grpc++/impl/server_builder_plugin.h
- include/grpc++/impl/server_initializer.h
- include/grpc++/impl/service_type.h
- include/grpc++/impl/sync.h
- include/grpc++/impl/sync_cxx11.h
@ -751,6 +766,7 @@ libs:
- grpc_transport_chttp2_client_secure
- grpc_transport_chttp2_server_insecure
- grpc_transport_chttp2_client_insecure
- grpc_transport_cronet_client_secure
- grpc_lb_policy_grpclb
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
@ -2932,6 +2948,19 @@ targets:
- mac
- linux
- posix
- name: server_builder_plugin_test
gtest: true
build: test
language: c++
src:
- test/cpp/end2end/server_builder_plugin_test.cc
deps:
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
- name: server_crash_test
gtest: true
cpu_cost: 0.1
@ -3257,14 +3286,16 @@ configs:
timeout_multiplier: 5
ubsan:
CC: clang
CPPFLAGS: -O1 -fsanitize-coverage=edge -fsanitize=undefined -fno-omit-frame-pointer
-Wno-unused-command-line-argument
CPPFLAGS: -O0 -fsanitize-coverage=edge -fsanitize=undefined,unsigned-integer-overflow
-fno-omit-frame-pointer -Wno-unused-command-line-argument -Wvarargs
CXX: clang++
DEFINES: NDEBUG
LD: clang
LDFLAGS: -fsanitize=undefined
LDFLAGS: -fsanitize=undefined,unsigned-integer-overflow
LDXX: clang++
compile_the_world: true
test_environ:
UBSAN_OPTIONS: print_stacktrace=1
timeout_multiplier: 1.5
defaults:
boringssl:

@ -101,6 +101,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
@ -236,6 +237,9 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_config/uri_parser.c \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \
src/core/ext/transport/cronet/transport/cronet_api_dummy.c \
src/core/ext/transport/cronet/transport/cronet_transport.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
@ -574,6 +578,8 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/client/secure)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/transport)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug)

@ -1,3 +1,32 @@
@rem Copyright 2016, Google Inc.
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions are
@rem met:
@rem
@rem * Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem * Redistributions in binary form must reproduce the above
@rem copyright notice, this list of conditions and the following disclaimer
@rem in the documentation and/or other materials provided with the
@rem distribution.
@rem * Neither the name of Google Inc. nor the names of its
@rem contributors may be used to endorse or promote products derived from
@rem this software without specific prior written permission.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Generate the C# code for .proto files
setlocal

@ -1,3 +1,32 @@
@rem Copyright 2016, Google Inc.
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions are
@rem met:
@rem
@rem * Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem * Redistributions in binary form must reproduce the above
@rem copyright notice, this list of conditions and the following disclaimer
@rem in the documentation and/or other materials provided with the
@rem distribution.
@rem * Neither the name of Google Inc. nor the names of its
@rem contributors may be used to endorse or promote products derived from
@rem this software without specific prior written permission.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Generate the C# code for .proto files
setlocal

@ -22,18 +22,24 @@ INSTALL
TRY IT!
-------
There are two ways to generate the code needed to work with protocol buffers in Node.js - one approach uses [Protobuf.js](https://github.com/dcodeIO/ProtoBuf.js/) to dynamically generate the code at runtime, the other uses code statically generated using the protocol buffer compiler `protoc`. The examples behave identically, and either server can be used with either client.
- Run the server
```sh
$ # from this directory
$ node ./greeter_server.js &
$ node ./dynamic_codegen/greeter_server.js &
$ # OR
$ node ./static_codegen/greeter_server.js &
```
- Run the client
```sh
$ # from this directory
$ node ./greeter_client.js
$ node ./dynamic_codegen/greeter_client.js
$ # OR
$ node ./dynamic_codegen/greeter_client.js
```
TUTORIAL

@ -0,0 +1 @@
This is the dynamic code generation variant of the Node examples. Code in these examples is generated at runtime using Protobuf.js.

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var PROTO_PATH = __dirname + '/../../protos/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var PROTO_PATH = __dirname + '/../../protos/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var PROTO_PATH = __dirname + '/../../../protos/route_guide.proto';
var async = require('async');
var fs = require('fs');

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var PROTO_PATH = __dirname + '/../../../protos/route_guide.proto';
var fs = require('fs');
var parseArgs = require('minimist');

@ -3,7 +3,8 @@
"version": "0.1.0",
"dependencies": {
"async": "^1.5.2",
"grpc": "0.13.0",
"google-protobuf": "^3.0.0-alpha.5",
"grpc": "^0.14.0",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}

@ -0,0 +1,7 @@
This is the static code generation variant of the Node examples. Code in these examples is pre-generated using protoc and the Node gRPC protoc plugin, and the generated code can be found in various `*_pb.js` files. The command line sequence for generating those files is as follows (assuming that `protoc` and `grpc_node_plugin` are present, and starting in the base directory of this package):
```sh
cd ../protos
protoc --js_out=import_style=commonjs,binary:../node/static_codegen/ --grpc_out=../node/static_codegen --plugin=protoc-gen-grpc=grpc_node_plugin helloworld.proto
protoc --js_out=import_style=commonjs,binary:../node/static_codegen/route_guide/ --grpc_out=../node/static_codegen/route_guide/ --plugin=protoc-gen-grpc=grpc_node_plugin route_guide.proto
```

@ -0,0 +1,55 @@
/*
*
* 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.
*
*/
var messages = require('./helloworld_pb');
var services = require('./helloworld_grpc_pb');
var grpc = require('grpc');
function main() {
var client = new services.GreeterClient('localhost:50051',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
var request = new messages.HelloRequest();
request.setName(user);
client.sayHello(request, function(err, response) {
console.log('Greeting:', response.getMessage());
});
}
main();

@ -0,0 +1,59 @@
/*
*
* 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.
*
*/
var messages = require('./helloworld_pb');
var services = require('./helloworld_grpc_pb');
var grpc = require('grpc');
/**
* Implements the SayHello RPC method.
*/
function sayHello(call, callback) {
var reply = new messages.HelloReply();
reply.setMessage('Hello ' + call.request.getName());
callback(null, reply);
}
/**
* Starts an RPC server that receives requests for the Greeter service at the
* sample server port
*/
function main() {
var server = new grpc.Server();
server.addService(services.GreeterService, {sayHello: sayHello});
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start();
}
main();

@ -0,0 +1,44 @@
// GENERATED CODE -- DO NOT EDIT!
'use strict';
var grpc = require('grpc');
var helloworld_pb = require('./helloworld_pb.js');
function serialize_HelloReply(arg) {
if (!(arg instanceof helloworld_pb.HelloReply)) {
throw new Error('Expected argument of type HelloReply');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloReply(buffer_arg) {
return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_HelloRequest(arg) {
if (!(arg instanceof helloworld_pb.HelloRequest)) {
throw new Error('Expected argument of type HelloRequest');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloRequest(buffer_arg) {
return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
var GreeterService = exports.GreeterService = {
sayHello: {
path: '/helloworld.Greeter/SayHello',
requestStream: false,
responseStream: false,
requestType: helloworld_pb.HelloRequest,
responseType: helloworld_pb.HelloReply,
requestSerialize: serialize_HelloRequest,
requestDeserialize: deserialize_HelloRequest,
responseSerialize: serialize_HelloReply,
responseDeserialize: deserialize_HelloReply,
},
};
exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);

@ -0,0 +1,332 @@
/**
* @fileoverview
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.helloworld.HelloReply', null, global);
goog.exportSymbol('proto.helloworld.HelloRequest', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.helloworld.HelloRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.helloworld.HelloRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.helloworld.HelloRequest.prototype.toObject = function(opt_includeInstance) {
return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.helloworld.HelloRequest} msg The msg instance to transform.
* @return {!Object}
*/
proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) {
var f, obj = {
name: msg.getName()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.helloworld.HelloRequest}
*/
proto.helloworld.HelloRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.helloworld.HelloRequest;
return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.helloworld.HelloRequest}
*/
proto.helloworld.HelloRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setName(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.helloworld.HelloRequest} message
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloRequest.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.helloworld.HelloRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getName();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.helloworld.HelloRequest} The clone.
*/
proto.helloworld.HelloRequest.prototype.cloneMessage = function() {
return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage(this));
};
/**
* optional string name = 1;
* @return {string}
*/
proto.helloworld.HelloRequest.prototype.getName = function() {
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
};
/** @param {string} value */
proto.helloworld.HelloRequest.prototype.setName = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.helloworld.HelloReply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.helloworld.HelloReply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.helloworld.HelloReply.prototype.toObject = function(opt_includeInstance) {
return proto.helloworld.HelloReply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.helloworld.HelloReply} msg The msg instance to transform.
* @return {!Object}
*/
proto.helloworld.HelloReply.toObject = function(includeInstance, msg) {
var f, obj = {
message: msg.getMessage()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.helloworld.HelloReply}
*/
proto.helloworld.HelloReply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.helloworld.HelloReply;
return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.helloworld.HelloReply} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.helloworld.HelloReply}
*/
proto.helloworld.HelloReply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setMessage(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.helloworld.HelloReply} message
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloReply.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.helloworld.HelloReply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getMessage();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.helloworld.HelloReply} The clone.
*/
proto.helloworld.HelloReply.prototype.cloneMessage = function() {
return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage(this));
};
/**
* optional string message = 1;
* @return {string}
*/
proto.helloworld.HelloReply.prototype.getMessage = function() {
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
};
/** @param {string} value */
proto.helloworld.HelloReply.prototype.setMessage = function(value) {
jspb.Message.setField(this, 1, value);
};
goog.object.extend(exports, proto.helloworld);

@ -0,0 +1,5 @@
#gRPC Basics: Node.js sample code
The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js.
[gRPC Basics: Node.js]:http://www.grpc.io/docs/tutorials/basic/node.html

@ -0,0 +1,247 @@
/*
*
* 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.
*
*/
var messages = require('./route_guide_pb');
var services = require('./route_guide_grpc_pb');
var async = require('async');
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('lodash');
var grpc = require('grpc');
var client = new services.RouteGuideClient('localhost:50051',
grpc.credentials.createInsecure());
var COORD_FACTOR = 1e7;
/**
* Run the getFeature demo. Calls getFeature with a point known to have a
* feature and a point known not to have a feature.
* @param {function} callback Called when this demo is complete
*/
function runGetFeature(callback) {
var next = _.after(2, callback);
function featureCallback(error, feature) {
if (error) {
callback(error);
}
var latitude = feature.getLocation().getLatitude();
var longitude = feature.getLocation().getLongitude();
if (feature.getName() === '') {
console.log('Found no feature at ' +
latitude/COORD_FACTOR + ', ' + longitude/COORD_FACTOR);
} else {
console.log('Found feature called "' + feature.getName() + '" at ' +
latitude/COORD_FACTOR + ', ' + longitude/COORD_FACTOR);
}
next();
}
var point1 = new messages.Point();
point1.setLatitude(409146138);
point1.setLongitude(-746188906);
var point2 = new messages.Point();
point2.setLatitude(0);
point2.setLongitude(0);
client.getFeature(point1, featureCallback);
client.getFeature(point2, featureCallback);
}
/**
* Run the listFeatures demo. Calls listFeatures with a rectangle containing all
* of the features in the pre-generated database. Prints each response as it
* comes in.
* @param {function} callback Called when this demo is complete
*/
function runListFeatures(callback) {
var rect = new messages.Rectangle();
var lo = new messages.Point();
lo.setLatitude(400000000);
lo.setLongitude(-750000000);
rect.setLo(lo);
var hi = new messages.Point();
hi.setLatitude(420000000);
hi.setLongitude(-730000000);
rect.setHi(hi);
console.log('Looking for features between 40, -75 and 42, -73');
var call = client.listFeatures(rect);
call.on('data', function(feature) {
console.log('Found feature called "' + feature.getName() + '" at ' +
feature.getLocation().getLatitude()/COORD_FACTOR + ', ' +
feature.getLocation().getLongitude()/COORD_FACTOR);
});
call.on('end', callback);
}
/**
* Run the recordRoute demo. Sends several randomly chosen points from the
* pre-generated feature database with a variable delay in between. Prints the
* statistics when they are sent from the server.
* @param {function} callback Called when this demo is complete
*/
function runRecordRoute(callback) {
var argv = parseArgs(process.argv, {
string: 'db_path'
});
fs.readFile(path.resolve(argv.db_path), function(err, data) {
if (err) callback(err);
// Transform the loaded features to Feature objects
var feature_list = _.map(JSON.parse(data), function(value) {
var feature = new messages.Feature();
feature.setName(value.name);
var location = new messages.Point();
location.setLatitude(value.location.latitude);
location.setLongitude(value.location.longitude);
feature.setLocation(location);
return feature;
});
var num_points = 10;
var call = client.recordRoute(function(error, stats) {
if (error) {
callback(error);
}
console.log('Finished trip with', stats.getPointCount(), 'points');
console.log('Passed', stats.getFeatureCount(), 'features');
console.log('Travelled', stats.getDistance(), 'meters');
console.log('It took', stats.getElapsedTime(), 'seconds');
callback();
});
/**
* Constructs a function that asynchronously sends the given point and then
* delays sending its callback
* @param {messages.Point} location The point to send
* @return {function(function)} The function that sends the point
*/
function pointSender(location) {
/**
* Sends the point, then calls the callback after a delay
* @param {function} callback Called when complete
*/
return function(callback) {
console.log('Visiting point ' + location.getLatitude()/COORD_FACTOR +
', ' + location.getLongitude()/COORD_FACTOR);
call.write(location);
_.delay(callback, _.random(500, 1500));
};
}
var point_senders = [];
for (var i = 0; i < num_points; i++) {
var rand_point = feature_list[_.random(0, feature_list.length - 1)];
point_senders[i] = pointSender(rand_point.getLocation());
}
async.series(point_senders, function() {
call.end();
});
});
}
/**
* Run the routeChat demo. Send some chat messages, and print any chat messages
* that are sent from the server.
* @param {function} callback Called when the demo is complete
*/
function runRouteChat(callback) {
var call = client.routeChat();
call.on('data', function(note) {
console.log('Got message "' + note.getMessage() + '" at ' +
note.getLocation().getLatitude() + ', ' +
note.getLocation().getLongitude());
});
call.on('end', callback);
var notes = [{
location: {
latitude: 0,
longitude: 0
},
message: 'First message'
}, {
location: {
latitude: 0,
longitude: 1
},
message: 'Second message'
}, {
location: {
latitude: 1,
longitude: 0
},
message: 'Third message'
}, {
location: {
latitude: 0,
longitude: 0
},
message: 'Fourth message'
}];
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
console.log('Sending message "' + note.message + '" at ' +
note.location.latitude + ', ' + note.location.longitude);
var noteMsg = new messages.RouteNote();
noteMsg.setMessage(note.message);
var location = new messages.Point();
location.setLatitude(note.location.latitude);
location.setLongitude(note.location.longitude);
noteMsg.setLocation(location);
call.write(noteMsg);
}
call.end();
}
/**
* Run all of the demos in order
*/
function main() {
async.series([
runGetFeature,
runListFeatures,
runRecordRoute,
runRouteChat
]);
}
if (require.main === module) {
main();
}
exports.runGetFeature = runGetFeature;
exports.runListFeatures = runListFeatures;
exports.runRecordRoute = runRecordRoute;
exports.runRouteChat = runRouteChat;

@ -0,0 +1,601 @@
[{
"location": {
"latitude": 407838351,
"longitude": -746143763
},
"name": "Patriots Path, Mendham, NJ 07945, USA"
}, {
"location": {
"latitude": 408122808,
"longitude": -743999179
},
"name": "101 New Jersey 10, Whippany, NJ 07981, USA"
}, {
"location": {
"latitude": 413628156,
"longitude": -749015468
},
"name": "U.S. 6, Shohola, PA 18458, USA"
}, {
"location": {
"latitude": 419999544,
"longitude": -740371136
},
"name": "5 Conners Road, Kingston, NY 12401, USA"
}, {
"location": {
"latitude": 414008389,
"longitude": -743951297
},
"name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
}, {
"location": {
"latitude": 419611318,
"longitude": -746524769
},
"name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
}, {
"location": {
"latitude": 406109563,
"longitude": -742186778
},
"name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
}, {
"location": {
"latitude": 416802456,
"longitude": -742370183
},
"name": "352 South Mountain Road, Wallkill, NY 12589, USA"
}, {
"location": {
"latitude": 412950425,
"longitude": -741077389
},
"name": "Bailey Turn Road, Harriman, NY 10926, USA"
}, {
"location": {
"latitude": 412144655,
"longitude": -743949739
},
"name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
}, {
"location": {
"latitude": 415736605,
"longitude": -742847522
},
"name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
}, {
"location": {
"latitude": 413843930,
"longitude": -740501726
},
"name": "162 Merrill Road, Highland Mills, NY 10930, USA"
}, {
"location": {
"latitude": 410873075,
"longitude": -744459023
},
"name": "Clinton Road, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 412346009,
"longitude": -744026814
},
"name": "16 Old Brook Lane, Warwick, NY 10990, USA"
}, {
"location": {
"latitude": 402948455,
"longitude": -747903913
},
"name": "3 Drake Lane, Pennington, NJ 08534, USA"
}, {
"location": {
"latitude": 406337092,
"longitude": -740122226
},
"name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
}, {
"location": {
"latitude": 406421967,
"longitude": -747727624
},
"name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
}, {
"location": {
"latitude": 416318082,
"longitude": -749677716
},
"name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
}, {
"location": {
"latitude": 415301720,
"longitude": -748416257
},
"name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
}, {
"location": {
"latitude": 402647019,
"longitude": -747071791
},
"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
}, {
"location": {
"latitude": 412567807,
"longitude": -741058078
},
"name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
}, {
"location": {
"latitude": 416855156,
"longitude": -744420597
},
"name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
}, {
"location": {
"latitude": 404663628,
"longitude": -744820157
},
"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
}, {
"location": {
"latitude": 407113723,
"longitude": -749746483
},
"name": ""
}, {
"location": {
"latitude": 402133926,
"longitude": -743613249
},
"name": ""
}, {
"location": {
"latitude": 400273442,
"longitude": -741220915
},
"name": ""
}, {
"location": {
"latitude": 411236786,
"longitude": -744070769
},
"name": ""
}, {
"location": {
"latitude": 411633782,
"longitude": -746784970
},
"name": "211-225 Plains Road, Augusta, NJ 07822, USA"
}, {
"location": {
"latitude": 415830701,
"longitude": -742952812
},
"name": ""
}, {
"location": {
"latitude": 413447164,
"longitude": -748712898
},
"name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
}, {
"location": {
"latitude": 405047245,
"longitude": -749800722
},
"name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
}, {
"location": {
"latitude": 418858923,
"longitude": -746156790
},
"name": ""
}, {
"location": {
"latitude": 417951888,
"longitude": -748484944
},
"name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
}, {
"location": {
"latitude": 407033786,
"longitude": -743977337
},
"name": "26 East 3rd Street, New Providence, NJ 07974, USA"
}, {
"location": {
"latitude": 417548014,
"longitude": -740075041
},
"name": ""
}, {
"location": {
"latitude": 410395868,
"longitude": -744972325
},
"name": ""
}, {
"location": {
"latitude": 404615353,
"longitude": -745129803
},
"name": ""
}, {
"location": {
"latitude": 406589790,
"longitude": -743560121
},
"name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
}, {
"location": {
"latitude": 414653148,
"longitude": -740477477
},
"name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
}, {
"location": {
"latitude": 405957808,
"longitude": -743255336
},
"name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
}, {
"location": {
"latitude": 411733589,
"longitude": -741648093
},
"name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
}, {
"location": {
"latitude": 412676291,
"longitude": -742606606
},
"name": "1270 Lakes Road, Monroe, NY 10950, USA"
}, {
"location": {
"latitude": 409224445,
"longitude": -748286738
},
"name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
}, {
"location": {
"latitude": 406523420,
"longitude": -742135517
},
"name": "652 Garden Street, Elizabeth, NJ 07202, USA"
}, {
"location": {
"latitude": 401827388,
"longitude": -740294537
},
"name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
}, {
"location": {
"latitude": 410564152,
"longitude": -743685054
},
"name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 408472324,
"longitude": -740726046
},
"name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
}, {
"location": {
"latitude": 412452168,
"longitude": -740214052
},
"name": "5 White Oak Lane, Stony Point, NY 10980, USA"
}, {
"location": {
"latitude": 409146138,
"longitude": -746188906
},
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
}, {
"location": {
"latitude": 404701380,
"longitude": -744781745
},
"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 409642566,
"longitude": -746017679
},
"name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
}, {
"location": {
"latitude": 408031728,
"longitude": -748645385
},
"name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
}, {
"location": {
"latitude": 413700272,
"longitude": -742135189
},
"name": "367 Prospect Road, Chester, NY 10918, USA"
}, {
"location": {
"latitude": 404310607,
"longitude": -740282632
},
"name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
}, {
"location": {
"latitude": 409319800,
"longitude": -746201391
},
"name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
}, {
"location": {
"latitude": 406685311,
"longitude": -742108603
},
"name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
}, {
"location": {
"latitude": 419018117,
"longitude": -749142781
},
"name": "43 Dreher Road, Roscoe, NY 12776, USA"
}, {
"location": {
"latitude": 412856162,
"longitude": -745148837
},
"name": "Swan Street, Pine Island, NY 10969, USA"
}, {
"location": {
"latitude": 416560744,
"longitude": -746721964
},
"name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
}, {
"location": {
"latitude": 405314270,
"longitude": -749836354
},
"name": ""
}, {
"location": {
"latitude": 414219548,
"longitude": -743327440
},
"name": ""
}, {
"location": {
"latitude": 415534177,
"longitude": -742900616
},
"name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
}, {
"location": {
"latitude": 406898530,
"longitude": -749127080
},
"name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
}, {
"location": {
"latitude": 407586880,
"longitude": -741670168
},
"name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
}, {
"location": {
"latitude": 400106455,
"longitude": -742870190
},
"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
}, {
"location": {
"latitude": 400066188,
"longitude": -746793294
},
"name": ""
}, {
"location": {
"latitude": 418803880,
"longitude": -744102673
},
"name": "40 Mountain Road, Napanoch, NY 12458, USA"
}, {
"location": {
"latitude": 414204288,
"longitude": -747895140
},
"name": ""
}, {
"location": {
"latitude": 414777405,
"longitude": -740615601
},
"name": ""
}, {
"location": {
"latitude": 415464475,
"longitude": -747175374
},
"name": "48 North Road, Forestburgh, NY 12777, USA"
}, {
"location": {
"latitude": 404062378,
"longitude": -746376177
},
"name": ""
}, {
"location": {
"latitude": 405688272,
"longitude": -749285130
},
"name": ""
}, {
"location": {
"latitude": 400342070,
"longitude": -748788996
},
"name": ""
}, {
"location": {
"latitude": 401809022,
"longitude": -744157964
},
"name": ""
}, {
"location": {
"latitude": 404226644,
"longitude": -740517141
},
"name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
}, {
"location": {
"latitude": 410322033,
"longitude": -747871659
},
"name": ""
}, {
"location": {
"latitude": 407100674,
"longitude": -747742727
},
"name": ""
}, {
"location": {
"latitude": 418811433,
"longitude": -741718005
},
"name": "213 Bush Road, Stone Ridge, NY 12484, USA"
}, {
"location": {
"latitude": 415034302,
"longitude": -743850945
},
"name": ""
}, {
"location": {
"latitude": 411349992,
"longitude": -743694161
},
"name": ""
}, {
"location": {
"latitude": 404839914,
"longitude": -744759616
},
"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 414638017,
"longitude": -745957854
},
"name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
}, {
"location": {
"latitude": 412127800,
"longitude": -740173578
},
"name": ""
}, {
"location": {
"latitude": 401263460,
"longitude": -747964303
},
"name": ""
}, {
"location": {
"latitude": 412843391,
"longitude": -749086026
},
"name": ""
}, {
"location": {
"latitude": 418512773,
"longitude": -743067823
},
"name": ""
}, {
"location": {
"latitude": 404318328,
"longitude": -740835638
},
"name": "42-102 Main Street, Belford, NJ 07718, USA"
}, {
"location": {
"latitude": 419020746,
"longitude": -741172328
},
"name": ""
}, {
"location": {
"latitude": 404080723,
"longitude": -746119569
},
"name": ""
}, {
"location": {
"latitude": 401012643,
"longitude": -744035134
},
"name": ""
}, {
"location": {
"latitude": 404306372,
"longitude": -741079661
},
"name": ""
}, {
"location": {
"latitude": 403966326,
"longitude": -748519297
},
"name": ""
}, {
"location": {
"latitude": 405002031,
"longitude": -748407866
},
"name": ""
}, {
"location": {
"latitude": 409532885,
"longitude": -742200683
},
"name": ""
}, {
"location": {
"latitude": 416851321,
"longitude": -742674555
},
"name": ""
}, {
"location": {
"latitude": 406411633,
"longitude": -741722051
},
"name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
}, {
"location": {
"latitude": 413069058,
"longitude": -744597778
},
"name": "261 Van Sickle Road, Goshen, NY 10924, USA"
}, {
"location": {
"latitude": 418465462,
"longitude": -746859398
},
"name": ""
}, {
"location": {
"latitude": 411733222,
"longitude": -744228360
},
"name": ""
}, {
"location": {
"latitude": 410248224,
"longitude": -747127767
},
"name": "3 Hasta Way, Newton, NJ 07860, USA"
}]

@ -0,0 +1,110 @@
// GENERATED CODE -- DO NOT EDIT!
'use strict';
var grpc = require('grpc');
var route_guide_pb = require('./route_guide_pb.js');
function serialize_Feature(arg) {
if (!(arg instanceof route_guide_pb.Feature)) {
throw new Error('Expected argument of type Feature');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Feature(buffer_arg) {
return route_guide_pb.Feature.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_Point(arg) {
if (!(arg instanceof route_guide_pb.Point)) {
throw new Error('Expected argument of type Point');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Point(buffer_arg) {
return route_guide_pb.Point.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_Rectangle(arg) {
if (!(arg instanceof route_guide_pb.Rectangle)) {
throw new Error('Expected argument of type Rectangle');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Rectangle(buffer_arg) {
return route_guide_pb.Rectangle.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_RouteNote(arg) {
if (!(arg instanceof route_guide_pb.RouteNote)) {
throw new Error('Expected argument of type RouteNote');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_RouteNote(buffer_arg) {
return route_guide_pb.RouteNote.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_RouteSummary(arg) {
if (!(arg instanceof route_guide_pb.RouteSummary)) {
throw new Error('Expected argument of type RouteSummary');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_RouteSummary(buffer_arg) {
return route_guide_pb.RouteSummary.deserializeBinary(new Uint8Array(buffer_arg));
}
var RouteGuideService = exports.RouteGuideService = {
getFeature: {
path: '/routeguide.RouteGuide/GetFeature',
requestStream: false,
responseStream: false,
requestType: route_guide_pb.Point,
responseType: route_guide_pb.Feature,
requestSerialize: serialize_Point,
requestDeserialize: deserialize_Point,
responseSerialize: serialize_Feature,
responseDeserialize: deserialize_Feature,
},
listFeatures: {
path: '/routeguide.RouteGuide/ListFeatures',
requestStream: false,
responseStream: true,
requestType: route_guide_pb.Rectangle,
responseType: route_guide_pb.Feature,
requestSerialize: serialize_Rectangle,
requestDeserialize: deserialize_Rectangle,
responseSerialize: serialize_Feature,
responseDeserialize: deserialize_Feature,
},
recordRoute: {
path: '/routeguide.RouteGuide/RecordRoute',
requestStream: true,
responseStream: false,
requestType: route_guide_pb.Point,
responseType: route_guide_pb.RouteSummary,
requestSerialize: serialize_Point,
requestDeserialize: deserialize_Point,
responseSerialize: serialize_RouteSummary,
responseDeserialize: deserialize_RouteSummary,
},
routeChat: {
path: '/routeguide.RouteGuide/RouteChat',
requestStream: true,
responseStream: true,
requestType: route_guide_pb.RouteNote,
responseType: route_guide_pb.RouteNote,
requestSerialize: serialize_RouteNote,
requestDeserialize: deserialize_RouteNote,
responseSerialize: serialize_RouteNote,
responseDeserialize: deserialize_RouteNote,
},
};
exports.RouteGuideClient = grpc.makeGenericClientConstructor(RouteGuideService);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,261 @@
/*
*
* 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.
*
*/
var messages = require('./route_guide_pb');
var services = require('./route_guide_grpc_pb');
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('lodash');
var grpc = require('grpc');
var COORD_FACTOR = 1e7;
/**
* For simplicity, a point is a record type that looks like
* {latitude: number, longitude: number}, and a feature is a record type that
* looks like {name: string, location: point}. feature objects with name===''
* are points with no feature.
*/
/**
* List of feature objects at points that have been requested so far.
*/
var feature_list = [];
/**
* Get a feature object at the given point, or creates one if it does not exist.
* @param {point} point The point to check
* @return {feature} The feature object at the point. Note that an empty name
* indicates no feature
*/
function checkFeature(point) {
var feature;
// Check if there is already a feature object for the given point
for (var i = 0; i < feature_list.length; i++) {
feature = feature_list[i];
if (feature.getLocation().getLatitude() === point.getLatitude() &&
feature.getLocation().getLongitude() === point.getLongitude()) {
return feature;
}
}
var name = '';
feature = new messages.Feature();
feature.setName(name);
feature.setLocation(point);
return feature;
}
/**
* getFeature request handler. Gets a request with a point, and responds with a
* feature object indicating whether there is a feature at that point.
* @param {EventEmitter} call Call object for the handler to process
* @param {function(Error, feature)} callback Response callback
*/
function getFeature(call, callback) {
callback(null, checkFeature(call.request));
}
/**
* listFeatures request handler. Gets a request with two points, and responds
* with a stream of all features in the bounding box defined by those points.
* @param {Writable} call Writable stream for responses with an additional
* request property for the request value.
*/
function listFeatures(call) {
var lo = call.request.getLo();
var hi = call.request.getHi();
var left = _.min([lo.getLongitude(), hi.getLongitude()]);
var right = _.max([lo.getLongitude(), hi.getLongitude()]);
var top = _.max([lo.getLatitude(), hi.getLatitude()]);
var bottom = _.min([lo.getLatitude(), hi.getLatitude()]);
// For each feature, check if it is in the given bounding box
_.each(feature_list, function(feature) {
if (feature.getName() === '') {
return;
}
if (feature.getLocation().getLongitude() >= left &&
feature.getLocation().getLongitude() <= right &&
feature.getLocation().getLatitude() >= bottom &&
feature.getLocation().getLatitude() <= top) {
call.write(feature);
}
});
call.end();
}
/**
* Calculate the distance between two points using the "haversine" formula.
* This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
* @param start The starting point
* @param end The end point
* @return The distance between the points in meters
*/
function getDistance(start, end) {
function toRadians(num) {
return num * Math.PI / 180;
}
var lat1 = start.getLatitude() / COORD_FACTOR;
var lat2 = end.getLatitude() / COORD_FACTOR;
var lon1 = start.getLongitude() / COORD_FACTOR;
var lon2 = end.getLongitude() / COORD_FACTOR;
var R = 6371000; // metres
var φ1 = toRadians(lat1);
var φ2 = toRadians(lat2);
var Δφ = toRadians(lat2-lat1);
var Δλ = toRadians(lon2-lon1);
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
/**
* recordRoute handler. Gets a stream of points, and responds with statistics
* about the "trip": number of points, number of known features visited, total
* distance traveled, and total time spent.
* @param {Readable} call The request point stream.
* @param {function(Error, routeSummary)} callback The callback to pass the
* response to
*/
function recordRoute(call, callback) {
var point_count = 0;
var feature_count = 0;
var distance = 0;
var previous = null;
// Start a timer
var start_time = process.hrtime();
call.on('data', function(point) {
point_count += 1;
if (checkFeature(point).name !== '') {
feature_count += 1;
}
/* For each point after the first, add the incremental distance from the
* previous point to the total distance value */
if (previous != null) {
distance += getDistance(previous, point);
}
previous = point;
});
call.on('end', function() {
var summary = new messages.RouteSummary();
summary.setPointCount(point_count);
summary.setFeatureCount(feature_count);
// Cast the distance to an integer
summary.setDistance(distance|0);
// End the timer
summary.setElapsedTime(process.hrtime(start_time)[0]);
callback(null, summary);
});
}
var route_notes = {};
/**
* Turn the point into a dictionary key.
* @param {point} point The point to use
* @return {string} The key for an object
*/
function pointKey(point) {
return point.getLatitude() + ' ' + point.getLongitude();
}
/**
* routeChat handler. Receives a stream of message/location pairs, and responds
* with a stream of all previous messages at each of those locations.
* @param {Duplex} call The stream for incoming and outgoing messages
*/
function routeChat(call) {
call.on('data', function(note) {
var key = pointKey(note.getLocation());
/* For each note sent, respond with all previous notes that correspond to
* the same point */
if (route_notes.hasOwnProperty(key)) {
_.each(route_notes[key], function(note) {
call.write(note);
});
} else {
route_notes[key] = [];
}
// Then add the new note to the list
route_notes[key].push(note);
});
call.on('end', function() {
call.end();
});
}
/**
* Get a new server with the handler functions in this file bound to the methods
* it serves.
* @return {Server} The new server object
*/
function getServer() {
var server = new grpc.Server();
server.addService(services.RouteGuideService, {
getFeature: getFeature,
listFeatures: listFeatures,
recordRoute: recordRoute,
routeChat: routeChat
});
return server;
}
if (require.main === module) {
// If this is run as a script, start a server on an unused port
var routeServer = getServer();
routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
var argv = parseArgs(process.argv, {
string: 'db_path'
});
fs.readFile(path.resolve(argv.db_path), function(err, data) {
if (err) throw err;
// Transform the loaded features to Feature objects
feature_list = _.map(JSON.parse(data), function(value) {
var feature = new messages.Feature();
feature.setName(value.name);
var location = new messages.Point();
location.setLatitude(value.location.latitude);
location.setLongitude(value.location.longitude);
feature.setLocation(location);
return feature;
});
routeServer.start();
});
}
exports.getServer = getServer;

@ -182,6 +182,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint.h',
'src/core/lib/iomgr/endpoint_pair.h',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h',
'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h',
@ -297,6 +298,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_config/subchannel_call_holder.h',
'src/core/ext/client_config/subchannel_index.h',
'src/core/ext/client_config/uri_parser.h',
'third_party/objective_c/Cronet/cronet_c_for_grpc.h',
'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'third_party/nanopb/pb.h',
@ -335,6 +337,7 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/sync_posix.h',
'include/grpc/impl/codegen/sync_win32.h',
'include/grpc/impl/codegen/time.h',
'include/grpc/grpc_cronet.h',
'include/grpc/grpc_security.h',
'include/grpc/grpc_security_constants.h',
'include/grpc/census.h',
@ -357,6 +360,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint_pair_posix.c',
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
'src/core/lib/iomgr/ev_poll_posix.c',
'src/core/lib/iomgr/ev_posix.c',
'src/core/lib/iomgr/exec_ctx.c',
'src/core/lib/iomgr/executor.c',
@ -492,6 +496,9 @@ Pod::Spec.new do |s|
'src/core/ext/client_config/uri_parser.c',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
'src/core/ext/transport/cronet/transport/cronet_api_dummy.c',
'src/core/ext/transport/cronet/transport/cronet_transport.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
@ -542,6 +549,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/endpoint.h',
'src/core/lib/iomgr/endpoint_pair.h',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.h',
'src/core/lib/iomgr/ev_poll_posix.h',
'src/core/lib/iomgr/ev_posix.h',
'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h',
@ -657,6 +665,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_config/subchannel_call_holder.h',
'src/core/ext/client_config/subchannel_index.h',
'src/core/ext/client_config/uri_parser.h',
'third_party/objective_c/Cronet/cronet_c_for_grpc.h',
'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'third_party/nanopb/pb.h',

@ -87,6 +87,7 @@ EXPORTS
grpc_header_nonbin_value_is_legal
grpc_is_binary_header
grpc_call_error_to_string
grpc_cronet_secure_channel_create
grpc_auth_property_iterator_next
grpc_auth_context_property_iterator
grpc_auth_context_peer_identity

@ -169,6 +169,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/sync_posix.h )
s.files += %w( include/grpc/impl/codegen/sync_win32.h )
s.files += %w( include/grpc/impl/codegen/time.h )
s.files += %w( include/grpc/grpc_cronet.h )
s.files += %w( include/grpc/grpc_security.h )
s.files += %w( include/grpc/grpc_security_constants.h )
s.files += %w( include/grpc/census.h )
@ -190,6 +191,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/endpoint.h )
s.files += %w( src/core/lib/iomgr/endpoint_pair.h )
s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.h )
s.files += %w( src/core/lib/iomgr/ev_posix.h )
s.files += %w( src/core/lib/iomgr/exec_ctx.h )
s.files += %w( src/core/lib/iomgr/executor.h )
@ -305,6 +307,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_config/subchannel_call_holder.h )
s.files += %w( src/core/ext/client_config/subchannel_index.h )
s.files += %w( src/core/ext/client_config/uri_parser.h )
s.files += %w( third_party/objective_c/Cronet/cronet_c_for_grpc.h )
s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h )
s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
s.files += %w( third_party/nanopb/pb.h )
@ -336,6 +339,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c )
s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c )
s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.c )
s.files += %w( src/core/lib/iomgr/ev_posix.c )
s.files += %w( src/core/lib/iomgr/exec_ctx.c )
s.files += %w( src/core/lib/iomgr/executor.c )
@ -471,6 +475,9 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_config/uri_parser.c )
s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c )
s.files += %w( src/core/ext/transport/cronet/client/secure/cronet_channel_create.c )
s.files += %w( src/core/ext/transport/cronet/transport/cronet_api_dummy.c )
s.files += %w( src/core/ext/transport/cronet/transport/cronet_transport.c )
s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c )
s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
s.files += %w( third_party/nanopb/pb_common.c )

@ -329,8 +329,11 @@ class CallOpGenericRecvMessage {
template <class R>
void RecvMessage(R* message) {
deserialize_.reset(
new CallOpGenericRecvMessageHelper::DeserializeFuncType<R>(message));
// Use an explicit base class pointer to avoid resolution error in the
// following unique_ptr::reset for some old implementations.
CallOpGenericRecvMessageHelper::DeserializeFunc* func =
new CallOpGenericRecvMessageHelper::DeserializeFuncType<R>(message);
deserialize_.reset(func);
}
bool got_message;

@ -49,7 +49,7 @@ namespace grpc {
extern CoreCodegenInterface* g_core_codegen_interface;
namespace {
namespace internal {
const int kGrpcBufferWriterMaxBufferLength = 8192;
@ -166,7 +166,7 @@ class GrpcBufferReader GRPC_FINAL
grpc_byte_buffer_reader reader_;
gpr_slice slice_;
};
} // namespace
} // namespace internal
template <class T>
class SerializationTraits<T, typename std::enable_if<std::is_base_of<
@ -176,7 +176,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
grpc_byte_buffer** bp, bool* own_buffer) {
*own_buffer = true;
int byte_size = msg.ByteSize();
if (byte_size <= kGrpcBufferWriterMaxBufferLength) {
if (byte_size <= internal::kGrpcBufferWriterMaxBufferLength) {
gpr_slice slice = g_core_codegen_interface->gpr_slice_malloc(byte_size);
GPR_CODEGEN_ASSERT(
GPR_SLICE_END_PTR(slice) ==
@ -185,7 +185,8 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
g_core_codegen_interface->gpr_slice_unref(slice);
return g_core_codegen_interface->ok();
} else {
GrpcBufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength);
internal::GrpcBufferWriter writer(
bp, internal::kGrpcBufferWriterMaxBufferLength);
return msg.SerializeToZeroCopyStream(&writer)
? g_core_codegen_interface->ok()
: Status(StatusCode::INTERNAL, "Failed to serialize message");
@ -200,7 +201,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
}
Status result = g_core_codegen_interface->ok();
{
GrpcBufferReader reader(buffer);
internal::GrpcBufferReader reader(buffer);
::grpc::protobuf::io::CodedInputStream decoder(&reader);
if (max_message_size > 0) {
decoder.SetTotalBytesLimit(max_message_size, max_message_size);

@ -34,6 +34,10 @@
#ifndef GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
#define GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
#include <map>
#include <memory>
#include <grpc++/impl/server_builder_plugin.h>
#include <grpc++/support/channel_arguments.h>
namespace grpc {
@ -44,6 +48,10 @@ class ServerBuilderOption {
virtual ~ServerBuilderOption() {}
/// Alter the \a ChannelArguments used to create the gRPC server.
virtual void UpdateArguments(ChannelArguments* args) = 0;
/// Alter the ServerBuilderPlugin map that will be added into ServerBuilder.
virtual void UpdatePlugins(
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin> >*
plugins) = 0;
};
} // namespace grpc

@ -0,0 +1,67 @@
/*
*
* Copyright 2016, 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 GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H
#define GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H
#include <memory>
#include <grpc++/support/config.h>
namespace grpc {
class ServerInitializer;
class ServerBuilderPlugin {
public:
virtual ~ServerBuilderPlugin() {}
virtual grpc::string name() = 0;
// InitServer will be called in ServerBuilder::BuildAndStart(), after the
// Server instance is created.
virtual void InitServer(ServerInitializer* si) = 0;
// Finish will be called at the end of ServerBuilder::BuildAndStart().
virtual void Finish(ServerInitializer* si) = 0;
// ChangeArguments is an interface that can be used in
// ServerBuilderOption::UpdatePlugins
virtual void ChangeArguments(const grpc::string& name, void* value) = 0;
virtual bool has_sync_methods() const { return false; }
virtual bool has_async_methods() const { return false; }
};
} // namespace grpc
#endif // GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H

@ -31,40 +31,40 @@
*
*/
#include <ruby/ruby.h>
#include <signal.h>
#include <stdbool.h>
#ifndef GRPCXX_IMPL_SERVER_INITIALIZER_H
#define GRPCXX_IMPL_SERVER_INITIALIZER_H
#include <grpc/support/log.h>
#include <memory>
#include <vector>
#include "rb_grpc.h"
#include <grpc++/server.h>
static void (*old_sigint_handler)(int);
static void (*old_sigterm_handler)(int);
namespace grpc {
static volatile bool signal_received = false;
class Server;
class Service;
/* This has to be handled at the C level instead of Ruby, because Ruby signal
* handlers are constrained to run in the main interpreter thread. If that main
* thread is blocked on grpc_completion_queue_pluck, the signal handlers will
* never run */
static void handle_signal(int signum) {
signal_received = true;
if (signum == SIGINT) {
old_sigint_handler(signum);
} else if (signum == SIGTERM) {
old_sigterm_handler(signum);
class ServerInitializer {
public:
ServerInitializer(Server* server) : server_(server) {}
bool RegisterService(std::shared_ptr<Service> service) {
if (!server_->RegisterService(nullptr, service.get())) {
return false;
}
default_services_.push_back(service);
return true;
}
const std::vector<grpc::string>* GetServiceList() {
return &server_->services_;
}
}
static VALUE grpc_rb_signal_received(VALUE self) {
(void)self;
return signal_received ? Qtrue : Qfalse;
}
private:
Server* server_;
std::vector<std::shared_ptr<Service> > default_services_;
};
} // namespace grpc
void Init_grpc_signals() {
old_sigint_handler = signal(SIGINT, handle_signal);
old_sigterm_handler = signal(SIGTERM, handle_signal);
rb_define_singleton_method(grpc_rb_mGrpcCore, "signal_received?",
grpc_rb_signal_received, 0);
}
#endif // GRPCXX_IMPL_SERVER_INITIALIZER_H

@ -36,6 +36,7 @@
#include <list>
#include <memory>
#include <vector>
#include <grpc++/completion_queue.h>
#include <grpc++/impl/call.h>
@ -57,6 +58,7 @@ class GenericServerContext;
class AsyncGenericService;
class ServerAsyncStreamingInterface;
class ServerContext;
class ServerInitializer;
class ThreadPoolInterface;
/// Models a gRPC server.
@ -94,6 +96,7 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
private:
friend class AsyncGenericService;
friend class ServerBuilder;
friend class ServerInitializer;
class SyncRequest;
class AsyncRequest;
@ -159,6 +162,8 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
grpc_server* server() GRPC_OVERRIDE { return server_; };
ServerInitializer* initializer();
const int max_message_size_;
// Completion queue.
@ -175,6 +180,7 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
std::shared_ptr<GlobalCallbacks> global_callbacks_;
std::list<SyncRequest>* sync_methods_;
std::vector<grpc::string> services_;
std::unique_ptr<RpcServiceMethod> unknown_method_;
bool has_generic_service_;
@ -184,6 +190,8 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
ThreadPoolInterface* thread_pool_;
// Whether the thread pool is created and owned by the server.
bool thread_pool_owned_;
std::unique_ptr<ServerInitializer> server_initializer_;
};
} // namespace grpc

@ -34,10 +34,12 @@
#ifndef GRPCXX_SERVER_BUILDER_H
#define GRPCXX_SERVER_BUILDER_H
#include <map>
#include <memory>
#include <vector>
#include <grpc++/impl/server_builder_option.h>
#include <grpc++/impl/server_builder_plugin.h>
#include <grpc++/support/config.h>
#include <grpc/compression.h>
@ -51,6 +53,10 @@ class ServerCompletionQueue;
class ServerCredentials;
class Service;
namespace testing {
class ServerBuilderPluginTest;
} // namespace testing
/// A builder class for the creation and startup of \a grpc::Server instances.
class ServerBuilder {
public:
@ -107,7 +113,13 @@ class ServerBuilder {
/// Return a running server which is ready for processing calls.
std::unique_ptr<Server> BuildAndStart();
/// For internal use only: Register a ServerBuilderPlugin factory function.
static void InternalAddPluginFactory(
std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)());
private:
friend class ::grpc::testing::ServerBuilderPluginTest;
struct Port {
grpc::string addr;
std::shared_ptr<ServerCredentials> creds;
@ -130,6 +142,7 @@ class ServerBuilder {
std::vector<Port> ports_;
std::vector<ServerCompletionQueue*> cqs_;
std::shared_ptr<ServerCredentials> creds_;
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>> plugins_;
AsyncGenericService* generic_service_;
};

@ -0,0 +1,51 @@
/*
*
* Copyright 2016, 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_GRPC_CRONET_H
#define GRPC_GRPC_CRONET_H
#include <grpc/grpc.h>
#ifdef __cplusplus
extern "C" {
#endif
GRPCAPI grpc_channel *grpc_cronet_secure_channel_create(
void *engine, const char *target, const grpc_channel_args *args,
void *reserved);
#ifdef __cplusplus
}
#endif
#endif /* GRPC_GRPC_CRONET_H */

@ -41,10 +41,13 @@ extern "C" {
#endif
/** To be used in channel arguments */
#define GRPC_COMPRESSION_ALGORITHM_ARG "grpc.compression_algorithm"
#define GRPC_COMPRESSION_ALGORITHM_STATE_ARG "grpc.compression_algorithm_state"
#define GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \
"grpc.default_compression_algorithm"
#define GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL "grpc.default_compression_level"
#define GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET \
"grpc.compression_enabled_algorithms_bitset"
/* The various compression algorithms supported by GRPC */
/* The various compression algorithms supported by gRPC */
typedef enum {
GRPC_COMPRESS_NONE = 0,
GRPC_COMPRESS_DEFLATE,
@ -53,6 +56,10 @@ typedef enum {
GRPC_COMPRESS_ALGORITHMS_COUNT
} grpc_compression_algorithm;
/** Compression levels allow a party with knowledge of its peer's accepted
* encodings to request compression in an abstract way. The level-algorithm
* mapping is performed internally and depends on the peer's supported
* compression algorithms. */
typedef enum {
GRPC_COMPRESS_LEVEL_NONE = 0,
GRPC_COMPRESS_LEVEL_LOW,
@ -62,8 +69,20 @@ typedef enum {
} grpc_compression_level;
typedef struct grpc_compression_options {
uint32_t enabled_algorithms_bitset; /**< All algs are enabled by default */
grpc_compression_algorithm default_compression_algorithm; /**< for channel */
/** All algs are enabled by default. This option corresponds to the channel
* argument key behind \a GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET
*/
uint32_t enabled_algorithms_bitset;
/** The default channel compression algorithm. It'll be used in the absence of
* call specific settings. This option corresponds to the channel argument key
* behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM */
grpc_compression_algorithm default_compression_algorithm;
/** The default channel compression level. It'll be used in the absence of
* call specific settings. This option corresponds to the channel argument key
* behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL */
grpc_compression_algorithm default_compression_level;
} grpc_compression_options;
#ifdef __cplusplus

@ -67,6 +67,8 @@
"src/node/ext",
"include/grpc",
"src/core",
"src/boringssl",
"src/zlib",
"third_party/nanopb",
"third_party/zlib",
"third_party/boringssl",

@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
<date>2016-04-19</date>
<date>2016-05-19</date>
<time>16:06:07</time>
<version>
<release>0.15.0</release>
@ -22,7 +22,7 @@
</stability>
<license>BSD</license>
<notes>
- destroy grpc_byte_buffer after startBatch #6096
- TBD
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@ -176,6 +176,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_win32.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/time.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_cronet.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
<file baseinstalldir="/" name="include/grpc/census.h" role="src" />
@ -197,6 +198,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/executor.h" role="src" />
@ -312,6 +314,7 @@
<file baseinstalldir="/" name="src/core/ext/client_config/subchannel_call_holder.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_config/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_config/uri_parser.h" role="src" />
<file baseinstalldir="/" name="third_party/objective_c/Cronet/cronet_c_for_grpc.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
@ -343,6 +346,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_and_epoll_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/executor.c" role="src" />
@ -478,6 +482,9 @@
<file baseinstalldir="/" name="src/core/ext/client_config/uri_parser.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/cronet/client/secure/cronet_channel_create.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/cronet/transport/cronet_api_dummy.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/cronet/transport/cronet_transport.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
@ -1031,8 +1038,8 @@ Update to wrap gRPC C Core version 0.10.0
</release>
<release>
<version>
<release>0.15.0</release>
<api>0.15.0</api>
<release>0.14.0</release>
<api>0.14.0</api>
</version>
<stability>
<release>beta</release>
@ -1044,5 +1051,35 @@ Update to wrap gRPC C Core version 0.10.0
- destroy grpc_byte_buffer after startBatch #6096
</notes>
</release>
<release>
<version>
<release>0.14.2</release>
<api>0.14.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2016-05-18</date>
<license>BSD</license>
<notes>
- Updated functions with TSRM macros for ZTS support #6607
</notes>
</release>
<release>
<version>
<release>0.15.0</release>
<api>0.15.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2016-05-19</date>
<license>BSD</license>
<notes>
- TBD
</notes>
</release>
</changelog>
</package>

@ -147,7 +147,8 @@ class IndentScope {
// END FORMATTING BOILERPLATE //
////////////////////////////////
// TODO(protobuf team): Export `ModuleName` from protobuf's
// TODO(https://github.com/google/protobuf/issues/888):
// Export `ModuleName` from protobuf's
// `src/google/protobuf/compiler/python/python_generator.cc` file.
grpc::string ModuleName(const grpc::string& filename) {
grpc::string basename = StripProto(filename);
@ -156,8 +157,23 @@ grpc::string ModuleName(const grpc::string& filename) {
return basename + "_pb2";
}
// TODO(https://github.com/google/protobuf/issues/888):
// Export `ModuleAlias` from protobuf's
// `src/google/protobuf/compiler/python/python_generator.cc` file.
grpc::string ModuleAlias(const grpc::string& filename) {
grpc::string module_name = ModuleName(filename);
// We can't have dots in the module name, so we replace each with _dot_.
// But that could lead to a collision between a.b and a_dot_b, so we also
// duplicate each underscore.
module_name = StringReplace(module_name, "_", "__");
module_name = StringReplace(module_name, ".", "_dot_");
return module_name;
}
bool GetModuleAndMessagePath(const Descriptor* type,
pair<grpc::string, grpc::string>* out) {
const ServiceDescriptor* service,
grpc::string* out) {
const Descriptor* path_elem_type = type;
vector<const Descriptor*> message_path;
do {
@ -170,7 +186,9 @@ bool GetModuleAndMessagePath(const Descriptor* type,
file_name.find_last_of(".proto") == file_name.size() - 1)) {
return false;
}
grpc::string module = ModuleName(file_name);
grpc::string service_file_name = service->file()->name();
grpc::string module = service_file_name == file_name ?
"" : ModuleAlias(file_name) + ".";
grpc::string message_type;
for (auto path_iter = message_path.rbegin();
path_iter != message_path.rend(); ++path_iter) {
@ -178,7 +196,7 @@ bool GetModuleAndMessagePath(const Descriptor* type,
}
// no pop_back prior to C++11
message_type.resize(message_type.size() - 1);
*out = make_pair(module, message_type);
*out = module + message_type;
return true;
}
@ -210,7 +228,7 @@ static void PrintAllComments(const DescriptorType* desc, Printer* printer) {
bool PrintBetaServicer(const ServiceDescriptor* service,
Printer* out) {
out->Print("\n");
out->Print("\n\n");
out->Print("class Beta$Service$Servicer(object):\n", "Service",
service->name());
{
@ -234,7 +252,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service,
bool PrintBetaStub(const ServiceDescriptor* service,
Printer* out) {
out->Print("\n");
out->Print("\n\n");
out->Print("class Beta$Service$Stub(object):\n", "Service", service->name());
{
IndentScope raii_class_indent(out);
@ -244,7 +262,7 @@ bool PrintBetaStub(const ServiceDescriptor* service,
grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request";
auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n");
out->Print(methdict, "def $Method$(self, $ArgName$, timeout, metadata=None, with_call=False, protocol_options=None):\n");
{
IndentScope raii_method_indent(out);
PrintAllComments(meth, out);
@ -260,38 +278,31 @@ bool PrintBetaStub(const ServiceDescriptor* service,
bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
out->Print("\n");
out->Print("\n\n");
out->Print("def beta_create_$Service$_server(servicer, pool=None, "
"pool_size=None, default_timeout=None, maximum_timeout=None):\n",
"Service", service->name());
{
IndentScope raii_create_server_indent(out);
map<grpc::string, grpc::string> method_implementation_constructors;
map<grpc::string, pair<grpc::string, grpc::string>>
input_message_modules_and_classes;
map<grpc::string, pair<grpc::string, grpc::string>>
output_message_modules_and_classes;
map<grpc::string, grpc::string> input_message_modules_and_classes;
map<grpc::string, grpc::string> output_message_modules_and_classes;
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
const grpc::string method_implementation_constructor =
grpc::string(method->client_streaming() ? "stream_" : "unary_") +
grpc::string(method->server_streaming() ? "stream_" : "unary_") +
"inline";
pair<grpc::string, grpc::string> input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(),
grpc::string input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
&input_message_module_and_class)) {
return false;
}
pair<grpc::string, grpc::string> output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(),
grpc::string output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service,
&output_message_module_and_class)) {
return false;
}
// Import the modules that define the messages used in RPCs.
out->Print("import $Module$\n", "Module",
input_message_module_and_class.first);
out->Print("import $Module$\n", "Module",
output_message_module_and_class.first);
method_implementation_constructors.insert(
make_pair(method->name(), method_implementation_constructor));
input_message_modules_and_classes.insert(
@ -307,13 +318,11 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
name_and_input_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$InputTypeModule$.$InputTypeClass$.FromString,\n",
"$InputTypeModuleAndClass$.FromString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_input_module_class_pair->first,
"InputTypeModule",
name_and_input_module_class_pair->second.first,
"InputTypeClass",
name_and_input_module_class_pair->second.second);
"InputTypeModuleAndClass",
name_and_input_module_class_pair->second);
}
out->Print("}\n");
out->Print("response_serializers = {\n");
@ -324,13 +333,11 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
name_and_output_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n",
"$OutputTypeModuleAndClass$.SerializeToString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_output_module_class_pair->first,
"OutputTypeModule",
name_and_output_module_class_pair->second.first,
"OutputTypeClass",
name_and_output_module_class_pair->second.second);
"OutputTypeModuleAndClass",
name_and_output_module_class_pair->second);
}
out->Print("}\n");
out->Print("method_implementations = {\n");
@ -366,37 +373,30 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
map<grpc::string, grpc::string> dict = ListToDict({
"Service", service->name(),
});
out->Print("\n");
out->Print("\n\n");
out->Print(dict, "def beta_create_$Service$_stub(channel, host=None,"
" metadata_transformer=None, pool=None, pool_size=None):\n");
{
IndentScope raii_create_server_indent(out);
map<grpc::string, grpc::string> method_cardinalities;
map<grpc::string, pair<grpc::string, grpc::string>>
input_message_modules_and_classes;
map<grpc::string, pair<grpc::string, grpc::string>>
output_message_modules_and_classes;
map<grpc::string, grpc::string> input_message_modules_and_classes;
map<grpc::string, grpc::string> output_message_modules_and_classes;
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
const grpc::string method_cardinality =
grpc::string(method->client_streaming() ? "STREAM" : "UNARY") +
"_" +
grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
pair<grpc::string, grpc::string> input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(),
grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
grpc::string input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
&input_message_module_and_class)) {
return false;
}
pair<grpc::string, grpc::string> output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(),
grpc::string output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service,
&output_message_module_and_class)) {
return false;
}
// Import the modules that define the messages used in RPCs.
out->Print("import $Module$\n", "Module",
input_message_module_and_class.first);
out->Print("import $Module$\n", "Module",
output_message_module_and_class.first);
method_cardinalities.insert(
make_pair(method->name(), method_cardinality));
input_message_modules_and_classes.insert(
@ -412,13 +412,11 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
name_and_input_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$InputTypeModule$.$InputTypeClass$.SerializeToString,\n",
"$InputTypeModuleAndClass$.SerializeToString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_input_module_class_pair->first,
"InputTypeModule",
name_and_input_module_class_pair->second.first,
"InputTypeClass",
name_and_input_module_class_pair->second.second);
"InputTypeModuleAndClass",
name_and_input_module_class_pair->second);
}
out->Print("}\n");
out->Print("response_deserializers = {\n");
@ -429,13 +427,11 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
name_and_output_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$OutputTypeModule$.$OutputTypeClass$.FromString,\n",
"$OutputTypeModuleAndClass$.FromString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_output_module_class_pair->first,
"OutputTypeModule",
name_and_output_module_class_pair->second.first,
"OutputTypeClass",
name_and_output_module_class_pair->second.second);
"OutputTypeModuleAndClass",
name_and_output_module_class_pair->second);
}
out->Print("}\n");
out->Print("cardinalities = {\n");
@ -463,8 +459,6 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
bool PrintPreamble(const FileDescriptor* file,
const GeneratorConfiguration& config, Printer* out) {
out->Print("import abc\n");
out->Print("import six\n");
out->Print("from $Package$ import implementations as beta_implementations\n",
"Package", config.beta_package_root);
out->Print("from $Package$ import interfaces as beta_interfaces\n",

@ -174,6 +174,7 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
if (holder->connected_subchannel == NULL) {
gpr_atm_no_barrier_store(&holder->subchannel_call, 1);
fail_locked(exec_ctx, holder);
} else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
/* already cancelled before subchannel became ready */

@ -0,0 +1,69 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/impl/codegen/port_platform.h>
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/transport_impl.h"
// Cronet transport object
typedef struct cronet_transport {
grpc_transport base; // must be first element in this structure
void *engine;
char *host;
} cronet_transport;
extern grpc_transport_vtable grpc_cronet_vtable;
GRPCAPI grpc_channel *grpc_cronet_secure_channel_create(
void *engine, const char *target, const grpc_channel_args *args,
void *reserved) {
cronet_transport *ct = gpr_malloc(sizeof(cronet_transport));
ct->base.vtable = &grpc_cronet_vtable;
ct->engine = engine;
ct->host = gpr_malloc(strlen(target) + 1);
strcpy(ct->host, target);
gpr_log(GPR_DEBUG,
"grpc_create_cronet_transport: cronet_engine = %p, target=%s", engine,
ct->host);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
return grpc_channel_create(&exec_ctx, target, args,
GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct);
}

@ -0,0 +1,85 @@
/*
*
* Copyright 2016, 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.
*
*/
/* This file has empty implementation of all the functions exposed by the cronet
library, so we can build it in all environments */
#include <stdbool.h>
#include <grpc/support/log.h>
#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h"
#ifdef GRPC_COMPILE_WITH_CRONET
/* link with the real CRONET library in the build system */
#else
/* Dummy implementation of cronet API just to test for build-ability */
cronet_bidirectional_stream* cronet_bidirectional_stream_create(
cronet_engine* engine, void* annotation,
cronet_bidirectional_stream_callback* callback) {
GPR_ASSERT(0);
return NULL;
}
int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream) {
GPR_ASSERT(0);
return 0;
}
int cronet_bidirectional_stream_start(
cronet_bidirectional_stream* stream, const char* url, int priority,
const char* method, const cronet_bidirectional_stream_header_array* headers,
bool end_of_stream) {
GPR_ASSERT(0);
return 0;
}
int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream,
char* buffer, int capacity) {
GPR_ASSERT(0);
return 0;
}
int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream,
const char* buffer, int count,
bool end_of_stream) {
GPR_ASSERT(0);
return 0;
}
int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream) {
GPR_ASSERT(0);
return 0;
}
#endif /* GRPC_COMPILE_WITH_CRONET */

@ -0,0 +1,640 @@
/*
*
* Copyright 2016, 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 <grpc/impl/codegen/port_platform.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/slice_buffer.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport_impl.h"
#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h"
#define GRPC_HEADER_SIZE_IN_BYTES 5
// Global flag that gets set with GRPC_TRACE env variable
int grpc_cronet_trace = 1;
// Cronet transport object
struct grpc_cronet_transport {
grpc_transport base; /* must be first element in this structure */
cronet_engine *engine;
char *host;
};
typedef struct grpc_cronet_transport grpc_cronet_transport;
enum send_state {
CRONET_SEND_IDLE = 0,
CRONET_REQ_STARTED,
CRONET_SEND_HEADER,
CRONET_WRITE,
CRONET_WRITE_COMPLETED,
};
enum recv_state {
CRONET_RECV_IDLE = 0,
CRONET_RECV_READ_LENGTH,
CRONET_RECV_READ_DATA,
CRONET_RECV_CLOSED,
};
static const char *recv_state_name[] = {
"CRONET_RECV_IDLE", "CRONET_RECV_READ_LENGTH", "CRONET_RECV_READ_DATA,",
"CRONET_RECV_CLOSED"};
// Enum that identifies calling function.
enum e_caller {
PERFORM_STREAM_OP,
ON_READ_COMPLETE,
ON_RESPONSE_HEADERS_RECEIVED,
ON_RESPONSE_TRAILERS_RECEIVED
};
enum callback_id {
CB_SEND_INITIAL_METADATA = 0,
CB_SEND_MESSAGE,
CB_SEND_TRAILING_METADATA,
CB_RECV_MESSAGE,
CB_RECV_INITIAL_METADATA,
CB_RECV_TRAILING_METADATA,
CB_NUM_CALLBACKS
};
struct stream_obj {
// we store received bytes here as they trickle in.
gpr_slice_buffer write_slice_buffer;
cronet_bidirectional_stream *cbs;
gpr_slice slice;
gpr_slice_buffer read_slice_buffer;
struct grpc_slice_buffer_stream sbs;
char *read_buffer;
int remaining_read_bytes;
int total_read_bytes;
char *write_buffer;
size_t write_buffer_size;
// Hold the URL
char *url;
bool response_headers_received;
bool read_requested;
bool response_trailers_received;
bool read_closed;
// Recv message stuff
grpc_byte_buffer **recv_message;
// Initial metadata stuff
grpc_metadata_batch *recv_initial_metadata;
// Trailing metadata stuff
grpc_metadata_batch *recv_trailing_metadata;
grpc_chttp2_incoming_metadata_buffer imb;
// This mutex protects receive state machine execution
gpr_mu recv_mu;
// we can queue up up to 2 callbacks for each OP
grpc_closure *callback_list[CB_NUM_CALLBACKS][2];
// storage for header
cronet_bidirectional_stream_header *headers;
uint32_t num_headers;
cronet_bidirectional_stream_header_array header_array;
// state tracking
enum recv_state cronet_recv_state;
enum send_state cronet_send_state;
};
typedef struct stream_obj stream_obj;
static void next_send_step(stream_obj *s);
static void next_recv_step(stream_obj *s, enum e_caller caller);
static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_pollset *pollset) {}
static void enqueue_callbacks(grpc_closure *callback_list[]) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
if (callback_list[0]) {
grpc_exec_ctx_enqueue(&exec_ctx, callback_list[0], true, NULL);
callback_list[0] = NULL;
}
if (callback_list[1]) {
grpc_exec_ctx_enqueue(&exec_ctx, callback_list[1], true, NULL);
callback_list[1] = NULL;
}
grpc_exec_ctx_finish(&exec_ctx);
}
static void on_canceled(cronet_bidirectional_stream *stream) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "on_canceled %p", stream);
}
}
static void on_failed(cronet_bidirectional_stream *stream, int net_error) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "on_failed %p, error = %d", stream, net_error);
}
}
static void on_succeeded(cronet_bidirectional_stream *stream) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "on_succeeded %p", stream);
}
}
static void on_response_trailers_received(
cronet_bidirectional_stream *stream,
const cronet_bidirectional_stream_header_array *trailers) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "R: on_response_trailers_received");
}
stream_obj *s = (stream_obj *)stream->annotation;
memset(&s->imb, 0, sizeof(s->imb));
grpc_chttp2_incoming_metadata_buffer_init(&s->imb);
unsigned int i = 0;
for (i = 0; i < trailers->count; i++) {
grpc_chttp2_incoming_metadata_buffer_add(
&s->imb, grpc_mdelem_from_metadata_strings(
grpc_mdstr_from_string(trailers->headers[i].key),
grpc_mdstr_from_string(trailers->headers[i].value)));
}
s->response_trailers_received = true;
next_recv_step(s, ON_RESPONSE_TRAILERS_RECEIVED);
}
static void on_write_completed(cronet_bidirectional_stream *stream,
const char *data) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "W: on_write_completed");
}
stream_obj *s = (stream_obj *)stream->annotation;
enqueue_callbacks(s->callback_list[CB_SEND_MESSAGE]);
s->cronet_send_state = CRONET_WRITE_COMPLETED;
next_send_step(s);
}
static void process_recv_message(stream_obj *s, const uint8_t *recv_data) {
gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes);
uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
memcpy(dst_p, recv_data, (size_t)s->total_read_bytes);
gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice);
grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0);
*s->recv_message = (grpc_byte_buffer *)&s->sbs;
}
static int parse_grpc_header(const uint8_t *data) {
const uint8_t *p = data + 1;
int length = 0;
length |= ((uint8_t)*p++) << 24;
length |= ((uint8_t)*p++) << 16;
length |= ((uint8_t)*p++) << 8;
length |= ((uint8_t)*p++);
return length;
}
static void on_read_completed(cronet_bidirectional_stream *stream, char *data,
int count) {
stream_obj *s = (stream_obj *)stream->annotation;
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "R: on_read_completed count=%d, total=%d, remaining=%d",
count, s->total_read_bytes, s->remaining_read_bytes);
}
if (count > 0) {
GPR_ASSERT(s->recv_message);
s->remaining_read_bytes -= count;
next_recv_step(s, ON_READ_COMPLETE);
} else {
s->read_closed = true;
next_recv_step(s, ON_READ_COMPLETE);
}
}
static void on_response_headers_received(
cronet_bidirectional_stream *stream,
const cronet_bidirectional_stream_header_array *headers,
const char *negotiated_protocol) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "R: on_response_headers_received");
}
stream_obj *s = (stream_obj *)stream->annotation;
enqueue_callbacks(s->callback_list[CB_RECV_INITIAL_METADATA]);
s->response_headers_received = true;
next_recv_step(s, ON_RESPONSE_HEADERS_RECEIVED);
}
static void on_request_headers_sent(cronet_bidirectional_stream *stream) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "W: on_request_headers_sent");
}
stream_obj *s = (stream_obj *)stream->annotation;
enqueue_callbacks(s->callback_list[CB_SEND_INITIAL_METADATA]);
s->cronet_send_state = CRONET_SEND_HEADER;
next_send_step(s);
}
// Callback function pointers (invoked by cronet in response to events)
static cronet_bidirectional_stream_callback callbacks = {
on_request_headers_sent,
on_response_headers_received,
on_read_completed,
on_write_completed,
on_response_trailers_received,
on_succeeded,
on_failed,
on_canceled};
static void invoke_closing_callback(stream_obj *s) {
grpc_chttp2_incoming_metadata_buffer_publish(&s->imb,
s->recv_trailing_metadata);
if (s->callback_list[CB_RECV_TRAILING_METADATA]) {
enqueue_callbacks(s->callback_list[CB_RECV_TRAILING_METADATA]);
}
}
static void set_recv_state(stream_obj *s, enum recv_state state) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "next_state = %s", recv_state_name[state]);
}
s->cronet_recv_state = state;
}
// This is invoked from perform_stream_op, and all on_xxxx callbacks.
static void next_recv_step(stream_obj *s, enum e_caller caller) {
gpr_mu_lock(&s->recv_mu);
switch (s->cronet_recv_state) {
case CRONET_RECV_IDLE:
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_IDLE");
}
if (caller == PERFORM_STREAM_OP ||
caller == ON_RESPONSE_HEADERS_RECEIVED) {
if (s->read_closed && s->response_trailers_received) {
invoke_closing_callback(s);
set_recv_state(s, CRONET_RECV_CLOSED);
} else if (s->response_headers_received == true &&
s->read_requested == true) {
set_recv_state(s, CRONET_RECV_READ_LENGTH);
s->total_read_bytes = s->remaining_read_bytes =
GRPC_HEADER_SIZE_IN_BYTES;
GPR_ASSERT(s->read_buffer);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
}
cronet_bidirectional_stream_read(s->cbs, s->read_buffer,
s->remaining_read_bytes);
}
}
break;
case CRONET_RECV_READ_LENGTH:
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_LENGTH");
}
if (caller == ON_READ_COMPLETE) {
if (s->read_closed) {
invoke_closing_callback(s);
enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
set_recv_state(s, CRONET_RECV_CLOSED);
} else {
GPR_ASSERT(s->remaining_read_bytes == 0);
set_recv_state(s, CRONET_RECV_READ_DATA);
s->total_read_bytes = s->remaining_read_bytes =
parse_grpc_header((const uint8_t *)s->read_buffer);
s->read_buffer =
gpr_realloc(s->read_buffer, (uint32_t)s->remaining_read_bytes);
GPR_ASSERT(s->read_buffer);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
}
cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer,
s->remaining_read_bytes);
}
}
break;
case CRONET_RECV_READ_DATA:
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_DATA");
}
if (caller == ON_READ_COMPLETE) {
if (s->remaining_read_bytes > 0) {
int offset = s->total_read_bytes - s->remaining_read_bytes;
GPR_ASSERT(s->read_buffer);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
}
cronet_bidirectional_stream_read(
s->cbs, (char *)s->read_buffer + offset, s->remaining_read_bytes);
} else {
gpr_slice_buffer_init(&s->read_slice_buffer);
uint8_t *p = (uint8_t *)s->read_buffer;
process_recv_message(s, p);
set_recv_state(s, CRONET_RECV_IDLE);
enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
}
}
break;
case CRONET_RECV_CLOSED:
break;
default:
GPR_ASSERT(0); // Should not reach here
break;
}
gpr_mu_unlock(&s->recv_mu);
}
// This function takes the data from s->write_slice_buffer and assembles into
// a contiguous byte stream with 5 byte gRPC header prepended.
static void create_grpc_frame(stream_obj *s) {
gpr_slice slice = gpr_slice_buffer_take_first(&s->write_slice_buffer);
uint8_t *raw_data = GPR_SLICE_START_PTR(slice);
size_t length = GPR_SLICE_LENGTH(slice);
s->write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES;
s->write_buffer = gpr_realloc(s->write_buffer, s->write_buffer_size);
uint8_t *p = (uint8_t *)s->write_buffer;
// Append 5 byte header
*p++ = 0;
*p++ = (uint8_t)(length >> 24);
*p++ = (uint8_t)(length >> 16);
*p++ = (uint8_t)(length >> 8);
*p++ = (uint8_t)(length);
// append actual data
memcpy(p, raw_data, length);
}
static void do_write(stream_obj *s) {
gpr_slice_buffer *sb = &s->write_slice_buffer;
GPR_ASSERT(sb->count <= 1);
if (sb->count > 0) {
create_grpc_frame(s);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write");
}
cronet_bidirectional_stream_write(s->cbs, s->write_buffer,
(int)s->write_buffer_size, false);
}
}
//
static void next_send_step(stream_obj *s) {
switch (s->cronet_send_state) {
case CRONET_SEND_IDLE:
GPR_ASSERT(
s->cbs); // cronet_bidirectional_stream is not initialized yet.
s->cronet_send_state = CRONET_REQ_STARTED;
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_start to %s", s->url);
}
cronet_bidirectional_stream_start(s->cbs, s->url, 0, "POST",
&s->header_array, false);
// we no longer need the memory that was allocated earlier.
gpr_free(s->header_array.headers);
break;
case CRONET_SEND_HEADER:
do_write(s);
s->cronet_send_state = CRONET_WRITE;
break;
case CRONET_WRITE_COMPLETED:
do_write(s);
break;
default:
GPR_ASSERT(0);
break;
}
}
static void convert_metadata_to_cronet_headers(grpc_linked_mdelem *head,
const char *host,
stream_obj *s) {
grpc_linked_mdelem *curr = head;
// Walk the linked list and get number of header fields
uint32_t num_headers_available = 0;
while (curr != NULL) {
curr = curr->next;
num_headers_available++;
}
// Allocate enough memory
s->headers = (cronet_bidirectional_stream_header *)gpr_malloc(
sizeof(cronet_bidirectional_stream_header) * num_headers_available);
// Walk the linked list again, this time copying the header fields.
// s->num_headers
// can be less than num_headers_available, as some headers are not used for
// cronet
curr = head;
s->num_headers = 0;
while (s->num_headers < num_headers_available) {
grpc_mdelem *mdelem = curr->md;
curr = curr->next;
const char *key = grpc_mdstr_as_c_string(mdelem->key);
const char *value = grpc_mdstr_as_c_string(mdelem->value);
if (strcmp(key, ":scheme") == 0 || strcmp(key, ":method") == 0 ||
strcmp(key, ":authority") == 0) {
// Cronet populates these fields on its own.
continue;
}
if (strcmp(key, ":path") == 0) {
// Create URL by appending :path value to the hostname
gpr_asprintf(&s->url, "https://%s%s", host, value);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "extracted URL = %s", s->url);
}
continue;
}
s->headers[s->num_headers].key = key;
s->headers[s->num_headers].value = value;
s->num_headers++;
if (curr == NULL) {
break;
}
}
}
static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_transport_stream_op *op) {
grpc_cronet_transport *ct = (grpc_cronet_transport *)gt;
GPR_ASSERT(ct->engine);
stream_obj *s = (stream_obj *)gs;
if (op->recv_trailing_metadata) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG,
"perform_stream_op - recv_trailing_metadata: on_complete=%p",
op->on_complete);
}
s->recv_trailing_metadata = op->recv_trailing_metadata;
GPR_ASSERT(!s->callback_list[CB_RECV_TRAILING_METADATA][0]);
s->callback_list[CB_RECV_TRAILING_METADATA][0] = op->on_complete;
}
if (op->recv_message) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "perform_stream_op - recv_message: on_complete=%p",
op->on_complete);
}
s->recv_message = (grpc_byte_buffer **)op->recv_message;
GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][0]);
GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][1]);
s->callback_list[CB_RECV_MESSAGE][0] = op->recv_message_ready;
s->callback_list[CB_RECV_MESSAGE][1] = op->on_complete;
s->read_requested = true;
next_recv_step(s, PERFORM_STREAM_OP);
}
if (op->recv_initial_metadata) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "perform_stream_op - recv_initial_metadata:=%p",
op->on_complete);
}
s->recv_initial_metadata = op->recv_initial_metadata;
GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][0]);
GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][1]);
s->callback_list[CB_RECV_INITIAL_METADATA][0] =
op->recv_initial_metadata_ready;
s->callback_list[CB_RECV_INITIAL_METADATA][1] = op->on_complete;
}
if (op->send_initial_metadata) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG,
"perform_stream_op - send_initial_metadata: on_complete=%p",
op->on_complete);
}
s->num_headers = 0;
convert_metadata_to_cronet_headers(op->send_initial_metadata->list.head,
ct->host, s);
s->header_array.count = s->num_headers;
s->header_array.capacity = s->num_headers;
s->header_array.headers = s->headers;
GPR_ASSERT(!s->callback_list[CB_SEND_INITIAL_METADATA][0]);
s->callback_list[CB_SEND_INITIAL_METADATA][0] = op->on_complete;
}
if (op->send_message) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "perform_stream_op - send_message: on_complete=%p",
op->on_complete);
}
grpc_byte_stream_next(exec_ctx, op->send_message, &s->slice,
op->send_message->length, NULL);
// Check that compression flag is not ON. We don't support compression yet.
// TODO (makdharma): add compression support
GPR_ASSERT(op->send_message->flags == 0);
gpr_slice_buffer_add(&s->write_slice_buffer, s->slice);
if (s->cbs == NULL) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_create");
}
s->cbs = cronet_bidirectional_stream_create(ct->engine, s, &callbacks);
GPR_ASSERT(s->cbs);
s->read_closed = false;
s->response_trailers_received = false;
s->response_headers_received = false;
s->cronet_send_state = CRONET_SEND_IDLE;
s->cronet_recv_state = CRONET_RECV_IDLE;
}
GPR_ASSERT(!s->callback_list[CB_SEND_MESSAGE][0]);
s->callback_list[CB_SEND_MESSAGE][0] = op->on_complete;
next_send_step(s);
}
if (op->send_trailing_metadata) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG,
"perform_stream_op - send_trailing_metadata: on_complete=%p",
op->on_complete);
}
GPR_ASSERT(!s->callback_list[CB_SEND_TRAILING_METADATA][0]);
s->callback_list[CB_SEND_TRAILING_METADATA][0] = op->on_complete;
if (s->cbs) {
// Send an "empty" write to the far end to signal that we're done.
// This will induce the server to send down trailers.
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write");
}
cronet_bidirectional_stream_write(s->cbs, "abc", 0, true);
} else {
// We never created a stream. This was probably an empty request.
invoke_closing_callback(s);
}
}
}
static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_stream_refcount *refcount,
const void *server_data) {
stream_obj *s = (stream_obj *)gs;
memset(s->callback_list, 0, sizeof(s->callback_list));
s->cbs = NULL;
gpr_mu_init(&s->recv_mu);
s->read_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES);
s->write_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES);
gpr_slice_buffer_init(&s->write_slice_buffer);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "cronet_transport - init_stream");
}
return 0;
}
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, void *and_free_memory) {
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "Destroy stream");
}
stream_obj *s = (stream_obj *)gs;
s->cbs = NULL;
gpr_free(s->read_buffer);
gpr_free(s->write_buffer);
gpr_free(s->url);
gpr_mu_destroy(&s->recv_mu);
if (and_free_memory) {
gpr_free(and_free_memory);
}
}
static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
grpc_cronet_transport *ct = (grpc_cronet_transport *)gt;
gpr_free(ct->host);
if (grpc_cronet_trace) {
gpr_log(GPR_DEBUG, "Destroy transport");
}
}
const grpc_transport_vtable grpc_cronet_vtable = {
sizeof(stream_obj), "cronet_http", init_stream,
set_pollset_do_nothing, perform_stream_op, NULL,
destroy_stream, destroy_transport, NULL};

@ -170,7 +170,7 @@ grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
if (a == NULL) return 0;
for (i = 0; i < a->num_args; ++i) {
if (a->args[i].type == GRPC_ARG_INTEGER &&
!strcmp(GRPC_COMPRESSION_ALGORITHM_ARG, a->args[i].key)) {
!strcmp(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, a->args[i].key)) {
return (grpc_compression_algorithm)a->args[i].value.integer;
break;
}
@ -182,7 +182,7 @@ grpc_channel_args *grpc_channel_args_set_compression_algorithm(
grpc_channel_args *a, grpc_compression_algorithm algorithm) {
grpc_arg tmp;
tmp.type = GRPC_ARG_INTEGER;
tmp.key = GRPC_COMPRESSION_ALGORITHM_ARG;
tmp.key = GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM;
tmp.value.integer = algorithm;
return grpc_channel_args_copy_and_add(a, &tmp, 1);
}
@ -196,7 +196,8 @@ static int find_compression_algorithm_states_bitset(const grpc_channel_args *a,
size_t i;
for (i = 0; i < a->num_args; ++i) {
if (a->args[i].type == GRPC_ARG_INTEGER &&
!strcmp(GRPC_COMPRESSION_ALGORITHM_STATE_ARG, a->args[i].key)) {
!strcmp(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
a->args[i].key)) {
*states_arg = &a->args[i].value.integer;
return 1; /* GPR_TRUE */
}
@ -222,7 +223,7 @@ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
/* create a new arg */
grpc_arg tmp;
tmp.type = GRPC_ARG_INTEGER;
tmp.key = GRPC_COMPRESSION_ALGORITHM_STATE_ARG;
tmp.key = GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET;
/* all enabled by default */
tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
if (state != 0) {

@ -47,7 +47,7 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
int grpc_compress_filter_trace = 0;
int grpc_compression_trace = 0;
typedef struct call_data {
gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */
@ -171,7 +171,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
did_compress =
grpc_msg_compress(calld->compression_algorithm, &calld->slices, &tmp);
if (did_compress) {
if (grpc_compress_filter_trace) {
if (grpc_compression_trace) {
char *algo_name;
const size_t before_size = calld->slices.length;
const size_t after_size = tmp.length;
@ -185,12 +185,14 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
gpr_slice_buffer_swap(&calld->slices, &tmp);
calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
} else {
if (grpc_compress_filter_trace) {
if (grpc_compression_trace) {
char *algo_name;
GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
&algo_name));
gpr_log(GPR_DEBUG, "Algorithm '%s' enabled but decided not to compress.",
algo_name);
gpr_log(
GPR_DEBUG,
"Algorithm '%s' enabled but decided not to compress. Input size: %d",
algo_name, calld->slices.length);
}
}

@ -38,7 +38,7 @@
#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "grpc-internal-encoding-request"
extern int grpc_compress_filter_trace;
extern int grpc_compression_trace;
/** Compression filter for outgoing data.
*

@ -161,8 +161,9 @@ static int add_header(grpc_http_parser *parser) {
cur++;
}
if (cur == end) {
if (grpc_http1_trace)
if (grpc_http1_trace) {
gpr_log(GPR_ERROR, "Didn't find ':' in header string");
}
goto error;
}
GPR_ASSERT(cur >= beg);

@ -790,7 +790,6 @@ static void pollset_kick(grpc_pollset *p,
static void pollset_global_init(void) {
gpr_tls_init(&g_current_thread_poller);
gpr_tls_init(&g_current_thread_worker);
grpc_wakeup_fd_global_init();
grpc_wakeup_fd_init(&grpc_global_wakeup_fd);
}
@ -798,7 +797,6 @@ static void pollset_global_shutdown(void) {
grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd);
gpr_tls_destroy(&g_current_thread_poller);
gpr_tls_destroy(&g_current_thread_worker);
grpc_wakeup_fd_global_destroy();
}
static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }

File diff suppressed because it is too large Load Diff

@ -0,0 +1,41 @@
/*
*
* Copyright 2015-2016, 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_CORE_LIB_IOMGR_EV_POLL_POSIX_H
#define GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H
#include "src/core/lib/iomgr/ev_posix.h"
const grpc_event_engine_vtable *grpc_init_poll_posix(void);
#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */

@ -37,23 +37,104 @@
#include "src/core/lib/iomgr/ev_posix.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h"
#include "src/core/lib/iomgr/ev_poll_posix.h"
#include "src/core/lib/support/env.h"
/** Default poll() function - a pointer so that it can be overridden by some
* tests */
grpc_poll_function_type grpc_poll_function = poll;
static const grpc_event_engine_vtable *g_event_engine;
grpc_poll_function_type grpc_poll_function = poll;
typedef const grpc_event_engine_vtable *(*event_engine_factory_fn)(void);
typedef struct {
const char *name;
event_engine_factory_fn factory;
} event_engine_factory;
static const event_engine_factory g_factories[] = {
{"poll", grpc_init_poll_posix}, {"legacy", grpc_init_poll_and_epoll_posix},
};
static void add(const char *beg, const char *end, char ***ss, size_t *ns) {
size_t n = *ns;
size_t np = n + 1;
char *s;
size_t len;
GPR_ASSERT(end >= beg);
len = (size_t)(end - beg);
s = gpr_malloc(len + 1);
memcpy(s, beg, len);
s[len] = 0;
*ss = gpr_realloc(*ss, sizeof(char **) * np);
(*ss)[n] = s;
*ns = np;
}
static void split(const char *s, char ***ss, size_t *ns) {
const char *c = strchr(s, ',');
if (c == NULL) {
add(s, s + strlen(s), ss, ns);
} else {
add(s, c, ss, ns);
split(c + 1, ss, ns);
}
}
static bool is(const char *want, const char *have) {
return 0 == strcmp(want, "all") || 0 == strcmp(want, have);
}
static void try_engine(const char *engine) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
if (is(engine, g_factories[i].name)) {
if ((g_event_engine = g_factories[i].factory())) {
gpr_log(GPR_DEBUG, "Using polling engine: %s", g_factories[i].name);
return;
}
}
}
}
void grpc_event_engine_init(void) {
if ((g_event_engine = grpc_init_poll_and_epoll_posix())) {
return;
char *s = gpr_getenv("GRPC_POLL_STRATEGY");
if (s == NULL) {
s = gpr_strdup("all");
}
char **strings = NULL;
size_t nstrings = 0;
split(s, &strings, &nstrings);
for (size_t i = 0; g_event_engine == NULL && i < nstrings; i++) {
try_engine(strings[i]);
}
for (size_t i = 0; i < nstrings; i++) {
gpr_free(strings[i]);
}
gpr_free(strings);
gpr_free(s);
if (g_event_engine == NULL) {
gpr_log(GPR_ERROR, "No event engine could be initialized");
abort();
}
gpr_log(GPR_ERROR, "No event engine could be initialized");
abort();
}
void grpc_event_engine_shutdown(void) { g_event_engine->shutdown_engine(); }
void grpc_event_engine_shutdown(void) {
g_event_engine->shutdown_engine();
g_event_engine = NULL;
}
grpc_fd *grpc_fd_create(int fd, const char *name) {
return g_event_engine->fd_create(fd, name);

@ -39,6 +39,22 @@
#include "src/core/lib/profiling/timers.h"
bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx) {
if (!exec_ctx->cached_ready_to_finish) {
exec_ctx->cached_ready_to_finish = exec_ctx->check_ready_to_finish(
exec_ctx, exec_ctx->check_ready_to_finish_arg);
}
return exec_ctx->cached_ready_to_finish;
}
bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) {
return false;
}
bool grpc_always_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) {
return true;
}
#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
bool did_something = 0;
@ -61,6 +77,7 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
}
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
exec_ctx->cached_ready_to_finish = true;
grpc_exec_ctx_flush(exec_ctx);
}

@ -53,6 +53,9 @@ typedef struct grpc_workqueue grpc_workqueue;
* - track a list of work that needs to be delayed until the top of the
* call stack (this provides a convenient mechanism to run callbacks
* without worrying about locking issues)
* - provide a decision maker (via grpc_exec_ctx_ready_to_finish) that provides
* signal as to whether a borrowed thread should continue to do work or
* should actively try to finish up and get this thread back to its owner
*
* CONVENTIONS:
* Instance of this must ALWAYS be constructed on the stack, never
@ -63,18 +66,26 @@ typedef struct grpc_workqueue grpc_workqueue;
*/
struct grpc_exec_ctx {
grpc_closure_list closure_list;
bool cached_ready_to_finish;
void *check_ready_to_finish_arg;
bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
};
#define GRPC_EXEC_CTX_INIT \
{ GRPC_CLOSURE_LIST_INIT }
#define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \
{ GRPC_CLOSURE_LIST_INIT, false, finish_check_arg, finish_check }
#else
struct grpc_exec_ctx {
int unused;
bool cached_ready_to_finish;
void *check_ready_to_finish_arg;
bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg);
};
#define GRPC_EXEC_CTX_INIT \
{ 0 }
#define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \
{ false, finish_check_arg, finish_check }
#endif
#define GRPC_EXEC_CTX_INIT \
GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(grpc_never_ready_to_finish, NULL)
/** Flush any work that has been enqueued onto this grpc_exec_ctx.
* Caller must guarantee that no interfering locks are held.
* Returns true if work was performed, false otherwise. */
@ -86,6 +97,14 @@ void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
bool success,
grpc_workqueue *offload_target_or_null);
/** Returns true if we'd like to leave this execution context as soon as
possible: useful for deciding whether to do something more or not depending
on outside context */
bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx *exec_ctx);
/** A finish check that is never ready to finish */
bool grpc_never_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored);
/** A finish check that is always ready to finish */
bool grpc_always_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored);
/** Add a list of closures to be executed at the next flush/finish point.
* Leaves \a list empty. */
void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,

@ -41,12 +41,16 @@
#include "src/core/lib/iomgr/tcp_posix.h"
void grpc_iomgr_platform_init(void) {
grpc_wakeup_fd_global_init();
grpc_event_engine_init();
grpc_register_tracer("tcp", &grpc_tcp_trace);
}
void grpc_iomgr_platform_flush(void) {}
void grpc_iomgr_platform_shutdown(void) { grpc_event_engine_shutdown(); }
void grpc_iomgr_platform_shutdown(void) {
grpc_event_engine_shutdown();
grpc_wakeup_fd_global_destroy();
}
#endif /* GRPC_POSIX_SOCKET */

@ -81,6 +81,7 @@ typedef struct {
grpc_closure read_closure;
grpc_closure destroyed_closure;
grpc_udp_server_read_cb read_cb;
grpc_udp_server_orphan_cb orphan_cb;
} server_port;
/* the overall server */
@ -168,6 +169,10 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
server_port *sp = &s->ports[i];
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
GPR_ASSERT(sp->orphan_cb);
sp->orphan_cb(sp->emfd);
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
"udp_listener_shutdown");
}
@ -268,7 +273,8 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static int add_socket_to_server(grpc_udp_server *s, int fd,
const struct sockaddr *addr, size_t addr_len,
grpc_udp_server_read_cb read_cb) {
grpc_udp_server_read_cb read_cb,
grpc_udp_server_orphan_cb orphan_cb) {
server_port *sp;
int port;
char *addr_str;
@ -292,6 +298,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
memcpy(sp->addr.untyped, addr, addr_len);
sp->addr_len = addr_len;
sp->read_cb = read_cb;
sp->orphan_cb = orphan_cb;
GPR_ASSERT(sp->emfd);
gpr_mu_unlock(&s->mu);
gpr_free(name);
@ -301,7 +308,8 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
}
int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
size_t addr_len, grpc_udp_server_read_cb read_cb) {
size_t addr_len, grpc_udp_server_read_cb read_cb,
grpc_udp_server_orphan_cb orphan_cb) {
int allocated_port1 = -1;
int allocated_port2 = -1;
unsigned i;
@ -348,7 +356,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
addr = (struct sockaddr *)&wild6;
addr_len = sizeof(wild6);
fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode);
allocated_port1 = add_socket_to_server(s, fd, addr, addr_len, read_cb);
allocated_port1 =
add_socket_to_server(s, fd, addr, addr_len, read_cb, orphan_cb);
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
goto done;
}
@ -370,7 +379,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
addr = (struct sockaddr *)&addr4_copy;
addr_len = sizeof(addr4_copy);
}
allocated_port2 = add_socket_to_server(s, fd, addr, addr_len, read_cb);
allocated_port2 =
add_socket_to_server(s, fd, addr, addr_len, read_cb, orphan_cb);
done:
gpr_free(allocated_addr);

@ -48,6 +48,9 @@ typedef struct grpc_udp_server grpc_udp_server;
typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
struct grpc_server *server);
/* Called when the grpc_fd is about to be orphaned (and the FD closed). */
typedef void (*grpc_udp_server_orphan_cb)(grpc_fd *emfd);
/* Create a server, initially not bound to any ports */
grpc_udp_server *grpc_udp_server_create(void);
@ -69,7 +72,8 @@ int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index);
/* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle
all of the multiple socket port matching logic in one place */
int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
size_t addr_len, grpc_udp_server_read_cb read_cb);
size_t addr_len, grpc_udp_server_read_cb read_cb,
grpc_udp_server_orphan_cb orphan_cb);
void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,
grpc_closure *on_done);

@ -83,7 +83,7 @@ char *gpr_format_message(int messageid) {
DWORD status = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
NULL, (DWORD)messageid, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
(LPTSTR)(&tmessage), 0, NULL);
if (status == 0) return gpr_strdup("Unable to retrieve error string");
message = gpr_tchar_to_char(tmessage);

@ -62,12 +62,19 @@ void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
case GRPC_BB_RAW:
gpr_slice_buffer_init(&decompressed_slices_buffer);
if (is_compressed(reader->buffer_in)) {
grpc_msg_decompress(reader->buffer_in->data.raw.compression,
&reader->buffer_in->data.raw.slice_buffer,
&decompressed_slices_buffer);
reader->buffer_out =
grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
decompressed_slices_buffer.count);
if (grpc_msg_decompress(reader->buffer_in->data.raw.compression,
&reader->buffer_in->data.raw.slice_buffer,
&decompressed_slices_buffer) == 0) {
gpr_log(GPR_ERROR,
"Unexpected error decompressing data for algorithm with enum "
"value '%d'. Reading data as if it were uncompressed.",
reader->buffer_in->data.raw.compression);
reader->buffer_out = reader->buffer_in;
} else { /* all fine */
reader->buffer_out =
grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
decompressed_slices_buffer.count);
}
gpr_slice_buffer_destroy(&decompressed_slices_buffer);
} else { /* not compressed, use the input buffer as output */
reader->buffer_out = reader->buffer_in;

@ -261,6 +261,8 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
call->channel = channel;
call->cq = cq;
call->parent = parent_call;
/* Always support no compression */
GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
call->is_client = server_transport_data == NULL;
if (call->is_client) {
GPR_ASSERT(add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT);
@ -408,6 +410,7 @@ static void set_status_code(grpc_call *call, status_source source,
static void set_compression_algorithm(grpc_call *call,
grpc_compression_algorithm algo) {
GPR_ASSERT(algo < GRPC_COMPRESS_ALGORITHMS_COUNT);
call->compression_algorithm = algo;
}
@ -828,12 +831,16 @@ static uint32_t decode_status(grpc_mdelem *md) {
return status;
}
static uint32_t decode_compression(grpc_mdelem *md) {
static grpc_compression_algorithm decode_compression(grpc_mdelem *md) {
grpc_compression_algorithm algorithm =
grpc_compression_algorithm_from_mdstr(md->value);
if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
const char *md_c_str = grpc_mdstr_as_c_string(md->value);
gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
gpr_log(GPR_ERROR,
"Invalid incoming compression algorithm: '%s'. Interpreting "
"incoming data as uncompressed.",
md_c_str);
return GRPC_COMPRESS_NONE;
}
return algorithm;
}
@ -1087,6 +1094,24 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
&call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
grpc_metadata_batch_filter(md, recv_initial_filter, call);
/* make sure the received grpc-encoding is amongst the ones listed in
* grpc-accept-encoding */
GPR_ASSERT(call->encodings_accepted_by_peer != 0);
if (!GPR_BITGET(call->encodings_accepted_by_peer,
call->compression_algorithm)) {
extern int grpc_compression_trace;
if (grpc_compression_trace) {
char *algo_name;
grpc_compression_algorithm_name(call->compression_algorithm,
&algo_name);
gpr_log(GPR_ERROR,
"Compression algorithm (grpc-encoding = '%s') not present in "
"the bitset of accepted encodings (grpc-accept-encodings: "
"'0x%x')",
algo_name, call->encodings_accepted_by_peer);
}
}
if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
0 &&
!call->is_client) {
@ -1474,7 +1499,8 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
grpc_call_error err;
GRPC_API_TRACE(
"grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, reserved=%p)",
"grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, "
"reserved=%p)",
5, (call, ops, (unsigned long)nops, tag, reserved));
if (reserved != NULL) {

@ -164,7 +164,7 @@ void grpc_init(void) {
grpc_register_tracer("channel_stack_builder",
&grpc_trace_channel_stack_builder);
grpc_register_tracer("http1", &grpc_http1_trace);
grpc_register_tracer("compression", &grpc_compress_filter_trace);
grpc_register_tracer("compression", &grpc_compression_trace);
grpc_security_pre_init();
grpc_iomgr_init();
grpc_executor_init();

@ -85,7 +85,7 @@ void ChannelArguments::Swap(ChannelArguments& other) {
void ChannelArguments::SetCompressionAlgorithm(
grpc_compression_algorithm algorithm) {
SetInt(GRPC_COMPRESSION_ALGORITHM_ARG, algorithm);
SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
}
// Note: a second call to this will add in front the result of the first call.

@ -33,6 +33,7 @@
#include <grpc++/server.h>
#include <sstream>
#include <utility>
#include <grpc++/completion_queue.h>
@ -41,6 +42,7 @@
#include <grpc++/impl/grpc_library.h>
#include <grpc++/impl/method_handler_impl.h>
#include <grpc++/impl/rpc_service_method.h>
#include <grpc++/impl/server_initializer.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server_context.h>
@ -284,7 +286,8 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
has_generic_service_(false),
server_(nullptr),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned) {
thread_pool_owned_(thread_pool_owned),
server_initializer_(new ServerInitializer(this)) {
g_gli_initializer.summon();
gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
global_callbacks_ = g_callbacks;
@ -341,6 +344,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
"Can only register an asynchronous service against one server.");
service->server_ = this;
}
const char* method_name = nullptr;
for (auto it = service->methods_.begin(); it != service->methods_.end();
++it) {
if (it->get() == nullptr) { // Handled by generic service if any.
@ -360,6 +364,17 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
} else {
sync_methods_->emplace_back(method, tag);
}
method_name = method->name();
}
// Parse service name.
if (method_name != nullptr) {
std::stringstream ss(method_name);
grpc::string service_name;
if (std::getline(ss, service_name, '/') &&
std::getline(ss, service_name, '/')) {
services_.push_back(service_name);
}
}
return true;
}
@ -598,4 +613,6 @@ void Server::RunRpc() {
}
}
ServerInitializer* Server::initializer() { return server_initializer_.get(); }
} // namespace grpc

@ -41,9 +41,23 @@
namespace grpc {
static std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>*
g_plugin_factory_list;
static gpr_once once_init_plugin_list = GPR_ONCE_INIT;
static void do_plugin_list_init(void) {
g_plugin_factory_list =
new std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>();
}
ServerBuilder::ServerBuilder()
: max_message_size_(-1), generic_service_(nullptr) {
grpc_compression_options_init(&compression_options_);
gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
for (auto factory : (*g_plugin_factory_list)) {
std::unique_ptr<ServerBuilderPlugin> plugin = factory();
plugins_[plugin->name()] = std::move(plugin);
}
}
std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue() {
@ -96,14 +110,24 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
ChannelArguments args;
for (auto option = options_.begin(); option != options_.end(); ++option) {
(*option)->UpdateArguments(&args);
(*option)->UpdatePlugins(&plugins_);
}
if (thread_pool == nullptr) {
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
if ((*plugin).second->has_sync_methods()) {
thread_pool.reset(CreateDefaultThreadPool());
break;
}
}
}
if (max_message_size_ > 0) {
args.SetInt(GRPC_ARG_MAX_MESSAGE_LENGTH, max_message_size_);
}
args.SetInt(GRPC_COMPRESSION_ALGORITHM_STATE_ARG,
args.SetInt(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
compression_options_.enabled_algorithms_bitset);
std::unique_ptr<Server> server(
new Server(thread_pool.release(), true, max_message_size_, &args));
ServerInitializer* initializer = server->initializer();
for (auto cq = cqs_.begin(); cq != cqs_.end(); ++cq) {
grpc_server_register_completion_queue(server->server_, (*cq)->cq(),
nullptr);
@ -114,6 +138,9 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
return nullptr;
}
}
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin).second->InitServer(initializer);
}
if (generic_service_) {
server->RegisterAsyncGenericService(generic_service_);
} else {
@ -137,7 +164,16 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
if (!server->Start(cqs_data, cqs_.size())) {
return nullptr;
}
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin).second->Finish(initializer);
}
return server;
}
void ServerBuilder::InternalAddPluginFactory(
std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)()) {
gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
(*g_plugin_factory_list).push_back(CreatePlugin);
}
} // namespace grpc

@ -32,6 +32,7 @@
#endregion
using System;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
@ -89,5 +90,43 @@ namespace Grpc.Core.Tests
channel.ShutdownAsync().Wait();
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await channel.ShutdownAsync());
}
[Test]
public async Task ShutdownTokenCancelledAfterShutdown()
{
var channel = new Channel("localhost", ChannelCredentials.Insecure);
Assert.IsFalse(channel.ShutdownToken.IsCancellationRequested);
var shutdownTask = channel.ShutdownAsync();
Assert.IsTrue(channel.ShutdownToken.IsCancellationRequested);
await shutdownTask;
}
[Test]
public async Task StateIsFatalFailureAfterShutdown()
{
var channel = new Channel("localhost", ChannelCredentials.Insecure);
await channel.ShutdownAsync();
Assert.AreEqual(ChannelState.FatalFailure, channel.State);
}
[Test]
public async Task ShutdownFinishesWaitForStateChangedAsync()
{
var channel = new Channel("localhost", ChannelCredentials.Insecure);
var stateChangedTask = channel.WaitForStateChangedAsync(ChannelState.Idle);
var shutdownTask = channel.ShutdownAsync();
await stateChangedTask;
await shutdownTask;
}
[Test]
public async Task OperationsThrowAfterShutdown()
{
var channel = new Channel("localhost", ChannelCredentials.Insecure);
await channel.ShutdownAsync();
Assert.ThrowsAsync(typeof(ObjectDisposedException), async () => await channel.WaitForStateChangedAsync(ChannelState.Idle));
Assert.Throws(typeof(ObjectDisposedException), () => { var x = channel.ResolvedTarget; });
Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await channel.ConnectAsync());
}
}
}

@ -181,13 +181,14 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void ClientStreaming_WriteFailure()
public void ClientStreaming_WriteCompletionFailure()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// TODO: maybe IOException or waiting for RPCException is more appropriate here.
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask);
fakeCall.UnaryResponseClientHandler(true,
@ -199,7 +200,7 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void ClientStreaming_WriteAfterReceivingStatusFails()
public void ClientStreaming_WriteAfterReceivingStatusThrowsRpcException()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
@ -210,7 +211,44 @@ namespace Grpc.Core.Internal.Tests
new Metadata());
AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
var ex = Assert.Throws<RpcException>(() => requestStream.WriteAsync("request1"));
Assert.AreEqual(Status.DefaultSuccess, ex.Status);
}
[Test]
public void ClientStreaming_WriteAfterReceivingStatusThrowsRpcException2()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
fakeCall.UnaryResponseClientHandler(true,
new ClientSideStatus(new Status(StatusCode.OutOfRange, ""), new Metadata()),
CreateResponsePayload(),
new Metadata());
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.OutOfRange);
var ex = Assert.Throws<RpcException>(() => requestStream.WriteAsync("request1"));
Assert.AreEqual(StatusCode.OutOfRange, ex.Status.StatusCode);
}
[Test]
public void ClientStreaming_WriteAfterCompleteThrowsInvalidOperationException()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
requestStream.CompleteAsync();
Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request1"));
fakeCall.SendCompletionHandler(true);
fakeCall.UnaryResponseClientHandler(true,
new ClientSideStatus(Status.DefaultSuccess, new Metadata()),
CreateResponsePayload(),
new Metadata());
AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask);
}
[Test]
@ -229,7 +267,7 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void ClientStreaming_WriteAfterCancellationRequestFails()
public void ClientStreaming_WriteAfterCancellationRequestThrowsOperationCancelledException()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
@ -340,7 +378,7 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void DuplexStreaming_WriteAfterReceivingStatusFails()
public void DuplexStreaming_WriteAfterReceivingStatusThrowsRpcException()
{
asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
@ -352,7 +390,8 @@ namespace Grpc.Core.Internal.Tests
AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask);
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await requestStream.WriteAsync("request1"));
var ex = Assert.ThrowsAsync<RpcException>(async () => await requestStream.WriteAsync("request1"));
Assert.AreEqual(Status.DefaultSuccess, ex.Status);
}
[Test]
@ -372,7 +411,7 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void DuplexStreaming_WriteAfterCancellationRequestFails()
public void DuplexStreaming_WriteAfterCancellationRequestThrowsOperationCancelledException()
{
asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<string, string>(asyncCall);

@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
@ -51,6 +52,7 @@ namespace Grpc.Core
readonly object myLock = new object();
readonly AtomicCounter activeCallCounter = new AtomicCounter();
readonly CancellationTokenSource shutdownTokenSource = new CancellationTokenSource();
readonly string target;
readonly GrpcEnvironment environment;
@ -101,12 +103,13 @@ namespace Grpc.Core
/// <summary>
/// Gets current connectivity state of this channel.
/// After channel is has been shutdown, <c>ChannelState.FatalFailure</c> will be returned.
/// </summary>
public ChannelState State
{
get
{
return handle.CheckConnectivityState(false);
return GetConnectivityState(false);
}
}
@ -154,6 +157,17 @@ namespace Grpc.Core
}
}
/// <summary>
/// Returns a token that gets cancelled once <c>ShutdownAsync</c> is invoked.
/// </summary>
public CancellationToken ShutdownToken
{
get
{
return this.shutdownTokenSource.Token;
}
}
/// <summary>
/// Allows explicitly requesting channel to connect without starting an RPC.
/// Returned task completes once state Ready was seen. If the deadline is reached,
@ -164,7 +178,7 @@ namespace Grpc.Core
/// <param name="deadline">The deadline. <c>null</c> indicates no deadline.</param>
public async Task ConnectAsync(DateTime? deadline = null)
{
var currentState = handle.CheckConnectivityState(true);
var currentState = GetConnectivityState(true);
while (currentState != ChannelState.Ready)
{
if (currentState == ChannelState.FatalFailure)
@ -172,7 +186,7 @@ namespace Grpc.Core
throw new OperationCanceledException("Channel has reached FatalFailure state.");
}
await WaitForStateChangedAsync(currentState, deadline).ConfigureAwait(false);
currentState = handle.CheckConnectivityState(false);
currentState = GetConnectivityState(false);
}
}
@ -188,6 +202,8 @@ namespace Grpc.Core
shutdownRequested = true;
}
shutdownTokenSource.Cancel();
var activeCallCount = activeCallCounter.Count;
if (activeCallCount > 0)
{
@ -231,6 +247,18 @@ namespace Grpc.Core
activeCallCounter.Decrement();
}
private ChannelState GetConnectivityState(bool tryToConnect)
{
try
{
return handle.CheckConnectivityState(tryToConnect);
}
catch (ObjectDisposedException)
{
return ChannelState.FatalFailure;
}
}
private static void EnsureUserAgentChannelOption(Dictionary<string, ChannelOption> options)
{
var key = ChannelOptions.PrimaryUserAgentString;

@ -57,7 +57,7 @@ namespace Grpc.Core.Internal
// Completion of a pending unary response if not null.
TaskCompletionSource<TResponse> unaryResponseTcs;
// Indicates that steaming call has finished.
// Indicates that response streaming call has finished.
TaskCompletionSource<object> streamingCallFinishedTcs = new TaskCompletionSource<object>();
// Response headers set here once received.
@ -443,6 +443,19 @@ namespace Grpc.Core.Internal
}
}
protected override void CheckSendingAllowed(bool allowFinished)
{
base.CheckSendingAllowed(true);
// throwing RpcException if we already received status on client
// side makes the most sense.
// Note that this throws even for StatusCode.OK.
if (!allowFinished && finishedStatus.HasValue)
{
throw new RpcException(finishedStatus.Value.Status);
}
}
/// <summary>
/// Handles receive status completion for calls with streaming response.
/// </summary>

@ -213,7 +213,7 @@ namespace Grpc.Core.Internal
{
}
protected void CheckSendingAllowed(bool allowFinished)
protected virtual void CheckSendingAllowed(bool allowFinished)
{
GrpcPreconditions.CheckState(started);
CheckNotCancelled();

@ -92,7 +92,7 @@ namespace Math.Tests
public void DivByZero()
{
var ex = Assert.Throws<RpcException>(() => client.Div(new DivArgs { Dividend = 0, Divisor = 0 }));
Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode);
Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode);
}
[Test]

@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Math
@ -109,5 +110,42 @@ namespace Math
DivReply result = await client.DivAsync(new DivArgs { Dividend = sum.Num_, Divisor = numbers.Count });
Console.WriteLine("Avg Result: " + result);
}
/// <summary>
/// Shows how to handle a call ending with non-OK status.
/// </summary>
public static async Task HandleErrorExample(Math.MathClient client)
{
try
{
DivReply result = await client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 });
}
catch (RpcException ex)
{
Console.WriteLine(string.Format("RPC ended with status {0}", ex.Status));
}
}
/// <summary>
/// Shows how to send request headers and how to access response headers
/// and response trailers.
/// </summary>
public static async Task MetadataExample(Math.MathClient client)
{
var requestHeaders = new Metadata
{
{ "custom-header", "custom-value" }
};
var call = client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 }, requestHeaders);
// Get response headers
Metadata responseHeaders = await call.ResponseHeadersAsync;
var result = await call;
// Get response trailers after the call has finished.
Metadata responseTrailers = call.GetTrailers();
}
}
}

@ -52,23 +52,15 @@ namespace Math
public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
{
if (request.Limit <= 0)
{
// keep streaming the sequence until cancelled.
IEnumerator<Num> fibEnumerator = FibInternal(long.MaxValue).GetEnumerator();
while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext())
{
await responseStream.WriteAsync(fibEnumerator.Current);
await Task.Delay(100);
}
}
var limit = request.Limit > 0 ? request.Limit : long.MaxValue;
var fibEnumerator = FibInternal(limit).GetEnumerator();
if (request.Limit > 0)
// Keep streaming the sequence until the call is cancelled.
// Use CancellationToken from ServerCallContext to detect the cancellation.
while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext())
{
foreach (var num in FibInternal(request.Limit))
{
await responseStream.WriteAsync(num);
}
await responseStream.WriteAsync(fibEnumerator.Current);
await Task.Delay(100);
}
}
@ -89,6 +81,13 @@ namespace Math
static DivReply DivInternal(DivArgs args)
{
if (args.Divisor == 0)
{
// One can finish the RPC with non-ok status by throwing RpcException instance.
// Alternatively, resulting status can be set using ServerCallContext.Status
throw new RpcException(new Status(StatusCode.InvalidArgument, "Division by zero"));
}
long quotient = args.Dividend / args.Divisor;
long remainder = args.Dividend % args.Divisor;
return new DivReply { Quotient = quotient, Remainder = remainder };

@ -492,6 +492,10 @@ namespace Grpc.IntegrationTesting
{
// Deadline was reached before write has started. Eat the exception and continue.
}
catch (RpcException)
{
// Deadline was reached before write has started. Eat the exception and continue.
}
var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
// We can't guarantee the status code always DeadlineExceeded. See issue #2685.

@ -311,7 +311,7 @@ namespace Grpc.IntegrationTesting
var snapshot = histogram.GetSnapshot(true);
var elapsedSnapshot = wallClockStopwatch.GetElapsedSnapshot(true);
return (long) (snapshot.Count / elapsedSnapshot.Seconds);
return (long) (snapshot.Count / elapsedSnapshot.TotalSeconds);
}
}
}

@ -1,3 +1,32 @@
@rem Copyright 2016, Google Inc.
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions are
@rem met:
@rem
@rem * Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem * Redistributions in binary form must reproduce the above
@rem copyright notice, this list of conditions and the following disclaimer
@rem in the documentation and/or other materials provided with the
@rem distribution.
@rem * Neither the name of Google Inc. nor the names of its
@rem contributors may be used to endorse or promote products derived from
@rem this software without specific prior written permission.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Builds gRPC NuGet packages
@rem Current package versions

@ -1,3 +1,32 @@
@rem Copyright 2016, Google Inc.
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions are
@rem met:
@rem
@rem * Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem * Redistributions in binary form must reproduce the above
@rem copyright notice, this list of conditions and the following disclaimer
@rem in the documentation and/or other materials provided with the
@rem distribution.
@rem * Neither the name of Google Inc. nor the names of its
@rem contributors may be used to endorse or promote products derived from
@rem this software without specific prior written permission.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Convenience script to build gRPC C# from command line
setlocal

@ -47,10 +47,11 @@ var exe_ext = process.platform === 'win32' ? '.exe' : '';
var protoc = path.resolve(__dirname, 'protoc' + exe_ext);
execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
var child_process = execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
if (error) {
throw error;
}
console.log(stdout);
console.log(stderr);
});
child_process.stdout.pipe(process.stdout);
child_process.stderr.pipe(process.stderr);

@ -47,10 +47,12 @@ var exe_ext = process.platform === 'win32' ? '.exe' : '';
var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext);
execFile(plugin, process.argv.slice(2), function(error, stdout, stderr) {
var child_process = execFile(plugin, process.argv.slice(2), {encoding: 'buffer'}, function(error, stdout, stderr) {
if (error) {
throw error;
}
console.log(stdout);
console.log(stderr);
});
process.stdin.pipe(child_process.stdin);
child_process.stdout.pipe(process.stdout);
child_process.stderr.pipe(process.stderr);

@ -89,19 +89,20 @@ zend_object_value create_wrapped_grpc_call(zend_class_entry *class_type
/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the struct
should be destroyed at the end of the object's lifecycle */
zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned) {
zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) {
zval *call_object;
MAKE_STD_ZVAL(call_object);
object_init_ex(call_object, grpc_ce_call);
wrapped_grpc_call *call =
(wrapped_grpc_call *)zend_object_store_get_object(call_object TSRMLS_CC);
call->wrapped = wrapped;
call->owned = owned;
return call_object;
}
/* Creates and returns a PHP array object with the data in a
* grpc_metadata_array. Returns NULL on failure */
zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array) {
zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) {
int count = metadata_array->count;
grpc_metadata *elements = metadata_array->metadata;
int i;
@ -126,7 +127,7 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array) {
if (zend_hash_find(array_hash, str_key, key_len, (void **)data) ==
SUCCESS) {
if (Z_TYPE_P(*data) != IS_ARRAY) {
zend_throw_exception(zend_exception_get_default(),
zend_throw_exception(zend_exception_get_default(TSRMLS_C),
"Metadata hash somehow contains wrong types.",
1 TSRMLS_CC);
efree(str_key);
@ -453,7 +454,7 @@ PHP_METHOD(Call, startBatch) {
add_property_bool(result, "send_status", true);
break;
case GRPC_OP_RECV_INITIAL_METADATA:
array = grpc_parse_metadata_array(&recv_metadata);
array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
add_property_zval(result, "metadata", array);
Z_DELREF_P(array);
break;
@ -469,7 +470,7 @@ PHP_METHOD(Call, startBatch) {
case GRPC_OP_RECV_STATUS_ON_CLIENT:
MAKE_STD_ZVAL(recv_status);
object_init(recv_status);
array = grpc_parse_metadata_array(&recv_trailing_metadata);
array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
add_property_zval(recv_status, "metadata", array);
Z_DELREF_P(array);
add_property_long(recv_status, "code", status);

@ -60,11 +60,11 @@ typedef struct wrapped_grpc_call {
void grpc_init_call(TSRMLS_D);
/* Creates a Call object that wraps the given grpc_call struct */
zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned);
zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC);
/* Creates and returns a PHP associative array of metadata from a C array of
* call metadata */
zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array);
zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC);
/* Populates a grpc_metadata_array with the data in a PHP array object.
Returns true on success and false on failure */

@ -83,7 +83,7 @@ zend_object_value create_wrapped_grpc_call_credentials(
return retval;
}
zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped) {
zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped TSRMLS_DC) {
zval *credentials_object;
MAKE_STD_ZVAL(credentials_object);
object_init_ex(credentials_object, grpc_ce_call_credentials);
@ -122,7 +122,7 @@ PHP_METHOD(CallCredentials, createComposite) {
grpc_call_credentials *creds =
grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped,
NULL);
zval *creds_object = grpc_php_wrap_call_credentials(creds);
zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@ -141,7 +141,7 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
memset(fci_cache, 0, sizeof(zend_fcall_info_cache));
/* "f" == 1 function */
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", fci,
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", fci,
fci_cache,
fci->params,
fci->param_count) == FAILURE) {
@ -167,7 +167,7 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(
plugin, NULL);
zval *creds_object = grpc_php_wrap_call_credentials(creds);
zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@ -175,6 +175,8 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
TSRMLS_FETCH();
plugin_state *state = (plugin_state *)ptr;
/* prepare to call the user callback function with info from the
@ -192,7 +194,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
state->fci->retval_ptr_ptr = &retval;
/* call the user callback function */
zend_call_function(state->fci, state->fci_cache);
zend_call_function(state->fci, state->fci_cache TSRMLS_CC);
if (Z_TYPE_P(retval) != IS_ARRAY) {
zend_throw_exception(spl_ce_InvalidArgumentException,

@ -84,7 +84,7 @@ zend_object_value create_wrapped_grpc_channel(zend_class_entry *class_type
return retval;
}
void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) {
void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC) {
HashTable *array_hash;
HashPosition array_pointer;
int args_index;
@ -168,7 +168,7 @@ PHP_METHOD(Channel, __construct) {
zend_hash_del(array_hash, "credentials", 12);
}
}
php_grpc_read_args_array(args_array, &args);
php_grpc_read_args_array(args_array, &args TSRMLS_CC);
if (creds == NULL) {
channel->wrapped = grpc_insecure_channel_create(target, &args, NULL);
} else {

@ -59,6 +59,6 @@ typedef struct wrapped_grpc_channel {
void grpc_init_channel(TSRMLS_D);
/* Iterates through a PHP array and populates args with the contents */
void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args);
void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC);
#endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */

@ -82,7 +82,7 @@ zend_object_value create_wrapped_grpc_channel_credentials(
return retval;
}
zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped) {
zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS_DC) {
zval *credentials_object;
MAKE_STD_ZVAL(credentials_object);
object_init_ex(credentials_object, grpc_ce_channel_credentials);
@ -99,7 +99,7 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped) {
*/
PHP_METHOD(ChannelCredentials, createDefault) {
grpc_channel_credentials *creds = grpc_google_default_credentials_create();
zval *creds_object = grpc_php_wrap_channel_credentials(creds);
zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@ -134,7 +134,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
grpc_channel_credentials *creds = grpc_ssl_credentials_create(
pem_root_certs,
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds);
zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
@ -165,7 +165,7 @@ PHP_METHOD(ChannelCredentials, createComposite) {
grpc_channel_credentials *creds =
grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds);
zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}

@ -111,7 +111,7 @@ PHP_METHOD(Server, __construct) {
if (args_array == NULL) {
server->wrapped = grpc_server_create(NULL, NULL);
} else {
php_grpc_read_args_array(args_array, &args);
php_grpc_read_args_array(args_array, &args TSRMLS_CC);
server->wrapped = grpc_server_create(&args, NULL);
efree(args.args);
}
@ -154,12 +154,12 @@ PHP_METHOD(Server, requestCall) {
1 TSRMLS_CC);
goto cleanup;
}
add_property_zval(result, "call", grpc_php_wrap_call(call, true));
add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC));
add_property_string(result, "method", details.method, true);
add_property_string(result, "host", details.host, true);
add_property_zval(result, "absolute_deadline",
grpc_php_wrap_timeval(details.deadline));
add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata));
grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata TSRMLS_CC));
cleanup:
grpc_call_details_destroy(&details);
grpc_metadata_array_destroy(&metadata);

@ -81,7 +81,7 @@ zend_object_value create_wrapped_grpc_server_credentials(
return retval;
}
zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped) {
zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_DC) {
zval *server_credentials_object;
MAKE_STD_ZVAL(server_credentials_object);
object_init_ex(server_credentials_object, grpc_ce_server_credentials);
@ -120,7 +120,7 @@ PHP_METHOD(ServerCredentials, createSsl) {
grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex(
pem_root_certs, &pem_key_cert_pair, 1,
GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL);
zval *creds_object = grpc_php_wrap_server_credentials(creds);
zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}

@ -72,7 +72,7 @@ zend_object_value create_wrapped_grpc_timeval(zend_class_entry *class_type
return retval;
}
zval *grpc_php_wrap_timeval(gpr_timespec wrapped) {
zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
zval *timeval_object;
MAKE_STD_ZVAL(timeval_object);
object_init_ex(timeval_object, grpc_ce_timeval);
@ -122,7 +122,7 @@ PHP_METHOD(Timeval, add) {
wrapped_grpc_timeval *other =
(wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC);
zval *sum =
grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped));
grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) TSRMLS_CC);
RETURN_DESTROY_ZVAL(sum);
}
@ -146,7 +146,7 @@ PHP_METHOD(Timeval, subtract) {
wrapped_grpc_timeval *other =
(wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC);
zval *diff =
grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped));
grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) TSRMLS_CC);
RETURN_DESTROY_ZVAL(diff);
}
@ -208,7 +208,7 @@ PHP_METHOD(Timeval, similar) {
* @return Timeval The current time
*/
PHP_METHOD(Timeval, now) {
zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME));
zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_DESTROY_ZVAL(now);
}
@ -218,7 +218,7 @@ PHP_METHOD(Timeval, now) {
*/
PHP_METHOD(Timeval, zero) {
zval *grpc_php_timeval_zero =
grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME));
grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_ZVAL(grpc_php_timeval_zero,
false, /* Copy original before returning? */
true /* Destroy original before returning */);
@ -230,7 +230,7 @@ PHP_METHOD(Timeval, zero) {
*/
PHP_METHOD(Timeval, infFuture) {
zval *grpc_php_timeval_inf_future =
grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME));
grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future);
}
@ -240,7 +240,7 @@ PHP_METHOD(Timeval, infFuture) {
*/
PHP_METHOD(Timeval, infPast) {
zval *grpc_php_timeval_inf_past =
grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME));
grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC);
RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past);
}

@ -63,6 +63,6 @@ void grpc_init_timeval(TSRMLS_D);
void grpc_shutdown_timeval(TSRMLS_D);
/* Creates a Timeval object that wraps the given timeval struct */
zval *grpc_php_wrap_timeval(gpr_timespec wrapped);
zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC);
#endif /* NET_GRPC_PHP_GRPC_TIMEVAL_H_ */

@ -0,0 +1,151 @@
// Copyright 2016, 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.
// Service exported by server reflection
syntax = "proto3";
package grpc.reflection.v1alpha;
service ServerReflection {
// The reflection service is structured as a bidirectional stream, ensuring
// all related requests go to a single server.
rpc ServerReflectionInfo(stream ServerReflectionRequest)
returns (stream ServerReflectionResponse);
}
// The message sent by the client when calling ServerReflectionInfo method.
message ServerReflectionRequest {
string host = 1;
// To use reflection service, the client should set one of the following
// fields in message_request. The server distinguishes requests by their
// defined field and then handles them using corresponding methods.
oneof message_request {
// Find a proto file by the file name.
string file_by_filename = 3;
// Find the proto file that declares the given fully-qualified symbol name.
// This field should be a fully-qualified symbol name
// (e.g. <package>.<service>[.<method>] or <package>.<type>).
string file_containing_symbol = 4;
// Find the proto file which defines an extension extending the given
// message type with the given field number.
ExtensionRequest file_containing_extension = 5;
// Finds the tag numbers used by all known extensions of extendee_type, and
// appends them to ExtensionNumberResponse in an undefined order.
// Its corresponding method is best-effort: it's not guaranteed that the
// reflection service will implement this method, and it's not guaranteed
// that this method will provide all extensions. Returns
// StatusCode::UNIMPLEMENTED if it's not implemented.
// This field should be a fully-qualified type name. The format is
// <package>.<type>
string all_extension_numbers_of_type = 6;
// List the full names of registered services. The content will not be
// checked.
string list_services = 7;
}
}
// The type name and extension number sent by the client when requesting
// file_containing_extension.
message ExtensionRequest {
// Fully-qualified type name. The format should be <package>.<type>
string containing_type = 1;
int32 extension_number = 2;
}
// The message sent by the server to answer ServerReflectionInfo method.
message ServerReflectionResponse {
string valid_host = 1;
ServerReflectionRequest original_request = 2;
// The server set one of the following fields accroding to the message_request
// in the request.
oneof message_response {
// This message is used to answer file_by_filename, file_containing_symbol,
// file_containing_extension requests with transitive dependencies. As
// the repeated label is not allowed in oneof fields, we use a
// FileDescriptorResponse message to encapsulate the repeated fields.
// The reflection service is allowed to avoid sending FileDescriptorProtos
// that were previously sent in response to earlier requests in the stream.
FileDescriptorResponse file_descriptor_response = 4;
// This message is used to answer all_extension_numbers_of_type requst.
ExtensionNumberResponse all_extension_numbers_response = 5;
// This message is used to answer list_services request.
ListServiceResponse list_services_response = 6;
// This message is used when an error occurs.
ErrorResponse error_response = 7;
}
}
// Serialized FileDescriptorProto messages sent by the server answering
// a file_by_filename, file_containing_symbol, or file_containing_extension
// request.
message FileDescriptorResponse {
// Serialized FileDescriptorProto messages. We avoid taking a dependency on
// descriptor.proto, which uses proto2 only features, by making them opaque
// bytes instead.
repeated bytes file_descriptor_proto = 1;
}
// A list of extension numbers sent by the server answering
// all_extension_numbers_of_type request.
message ExtensionNumberResponse {
// Full name of the base type, including the package name. The format
// is <package>.<type>
string base_type_name = 1;
repeated int32 extension_number = 2;
}
// A list of ServiceResponse sent by the server answering list_services request.
message ListServiceResponse {
// The information of each service may be expanded in the future, so we use
// ServiceResponse message to encapsulate it.
repeated ServiceResponse service = 1;
}
// The information of a single service used by ListServiceResponse to answer
// list_services request.
message ServiceResponse {
// Full name of a registered service, including its package name. The format
// is <package>.<service>
string name = 1;
}
// The error code and error message sent by the server when an error occurs.
message ErrorResponse {
// This field uses the error codes defined in grpc::StatusCode.
int32 error_code = 1;
string error_message = 2;
}

@ -32,6 +32,12 @@ syntax = "proto3";
package grpc.testing;
// Message to be echoed back serialized in trailer.
message DebugInfo {
repeated string stack_entries = 1;
string detail = 2;
}
message RequestParams {
bool echo_deadline = 1;
int32 client_cancel_after_us = 2;
@ -43,6 +49,7 @@ message RequestParams {
string expected_client_identity = 8; // will force check_auth_context.
bool skip_cancelled_check = 9;
string expected_transport_security_type = 10;
DebugInfo debug_info = 11;
}
message EchoRequest {

@ -195,26 +195,30 @@ class Call(_types.Call):
translated_op = cygrpc.operation_send_initial_metadata(
cygrpc.Metadata(
cygrpc.Metadatum(key, value)
for key, value in op.initial_metadata))
for key, value in op.initial_metadata),
op.flags)
elif op.type == _types.OpType.SEND_MESSAGE:
translated_op = cygrpc.operation_send_message(op.message)
translated_op = cygrpc.operation_send_message(op.message, op.flags)
elif op.type == _types.OpType.SEND_CLOSE_FROM_CLIENT:
translated_op = cygrpc.operation_send_close_from_client()
translated_op = cygrpc.operation_send_close_from_client(op.flags)
elif op.type == _types.OpType.SEND_STATUS_FROM_SERVER:
translated_op = cygrpc.operation_send_status_from_server(
cygrpc.Metadata(
cygrpc.Metadatum(key, value)
for key, value in op.trailing_metadata),
op.status.code,
op.status.details)
op.status.details,
op.flags)
elif op.type == _types.OpType.RECV_INITIAL_METADATA:
translated_op = cygrpc.operation_receive_initial_metadata()
translated_op = cygrpc.operation_receive_initial_metadata(
op.flags)
elif op.type == _types.OpType.RECV_MESSAGE:
translated_op = cygrpc.operation_receive_message()
translated_op = cygrpc.operation_receive_message(op.flags)
elif op.type == _types.OpType.RECV_STATUS_ON_CLIENT:
translated_op = cygrpc.operation_receive_status_on_client()
translated_op = cygrpc.operation_receive_status_on_client(
op.flags)
elif op.type == _types.OpType.RECV_CLOSE_ON_SERVER:
translated_op = cygrpc.operation_receive_close_on_server()
translated_op = cygrpc.operation_receive_close_on_server(op.flags)
else:
raise ValueError('unexpected operation type {}'.format(op.type))
translated_ops.append(translated_op)

@ -152,7 +152,7 @@ class OpArgs(collections.namedtuple(
'trailing_metadata',
'message',
'status',
'write_flags',
'flags',
])):
"""Arguments passed into a GRPC operation.
@ -165,7 +165,7 @@ class OpArgs(collections.namedtuple(
message (bytes): Only valid if type == OpType.SEND_MESSAGE, else is None.
status (Status): Only valid if type == OpType.SEND_STATUS_FROM_SERVER, else
is None.
write_flags (int): a bit OR'ing of 0 or more OpWriteFlags values.
flags (int): a bitwise OR'ing of 0 or more OpWriteFlags values.
"""
@staticmethod

@ -140,6 +140,9 @@ cdef extern from "grpc/_cython/loader.h":
const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING
const char *GRPC_ARG_SECONDARY_USER_AGENT_STRING
const char *GRPC_SSL_TARGET_NAME_OVERRIDE_ARG
const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM
const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL
const char *GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET
const int GRPC_WRITE_BUFFER_HINT
const int GRPC_WRITE_NO_COMPRESS
@ -425,3 +428,38 @@ cdef extern from "grpc/_cython/loader.h":
grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved) nogil
ctypedef enum grpc_compression_algorithm:
GRPC_COMPRESS_NONE
GRPC_COMPRESS_DEFLATE
GRPC_COMPRESS_GZIP
GRPC_COMPRESS_ALGORITHMS_COUNT
ctypedef enum grpc_compression_level:
GRPC_COMPRESS_LEVEL_NONE
GRPC_COMPRESS_LEVEL_LOW
GRPC_COMPRESS_LEVEL_MED
GRPC_COMPRESS_LEVEL_HIGH
GRPC_COMPRESS_LEVEL_COUNT
ctypedef struct grpc_compression_options:
uint32_t enabled_algorithms_bitset
grpc_compression_algorithm default_compression_algorithm
int grpc_compression_algorithm_parse(
const char *name, size_t name_length,
grpc_compression_algorithm *algorithm) nogil
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
char **name) nogil
grpc_compression_algorithm grpc_compression_algorithm_for_level(
grpc_compression_level level, uint32_t accepted_encodings) nogil
void grpc_compression_options_init(grpc_compression_options *opts) nogil
void grpc_compression_options_enable_algorithm(
grpc_compression_options *opts,
grpc_compression_algorithm algorithm) nogil
void grpc_compression_options_disable_algorithm(
grpc_compression_options *opts,
grpc_compression_algorithm algorithm) nogil
int grpc_compression_options_is_algorithm_enabled(
const grpc_compression_options *opts,
grpc_compression_algorithm algorithm) nogil

@ -124,3 +124,7 @@ cdef class Operations:
cdef size_t c_nops
cdef list operations
cdef class CompressionOptions:
cdef grpc_compression_options c_options

@ -103,6 +103,19 @@ class OperationType:
receive_close_on_server = GRPC_OP_RECV_CLOSE_ON_SERVER
class CompressionAlgorithm:
none = GRPC_COMPRESS_NONE
deflate = GRPC_COMPRESS_DEFLATE
gzip = GRPC_COMPRESS_GZIP
class CompressionLevel:
none = GRPC_COMPRESS_LEVEL_NONE
low = GRPC_COMPRESS_LEVEL_LOW
medium = GRPC_COMPRESS_LEVEL_MED
high = GRPC_COMPRESS_LEVEL_HIGH
cdef class Timespec:
def __cinit__(self, time):
@ -472,6 +485,10 @@ cdef class Operation:
def type(self):
return self.c_op.type
@property
def flags(self):
return self.c_op.flags
@property
def has_status(self):
return self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT
@ -553,9 +570,10 @@ cdef class Operation:
with nogil:
gpr_free(self._received_status_details)
def operation_send_initial_metadata(Metadata metadata):
def operation_send_initial_metadata(Metadata metadata, int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_SEND_INITIAL_METADATA
op.c_op.flags = flags
op.c_op.data.send_initial_metadata.count = metadata.c_metadata_array.count
op.c_op.data.send_initial_metadata.metadata = (
metadata.c_metadata_array.metadata)
@ -563,23 +581,25 @@ def operation_send_initial_metadata(Metadata metadata):
op.is_valid = True
return op
def operation_send_message(data):
def operation_send_message(data, int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_SEND_MESSAGE
op.c_op.flags = flags
byte_buffer = ByteBuffer(data)
op.c_op.data.send_message = byte_buffer.c_byte_buffer
op.references.append(byte_buffer)
op.is_valid = True
return op
def operation_send_close_from_client():
def operation_send_close_from_client(int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_SEND_CLOSE_FROM_CLIENT
op.c_op.flags = flags
op.is_valid = True
return op
def operation_send_status_from_server(
Metadata metadata, grpc_status_code code, details):
Metadata metadata, grpc_status_code code, details, int flags):
if isinstance(details, bytes):
pass
elif isinstance(details, basestring):
@ -588,6 +608,7 @@ def operation_send_status_from_server(
raise TypeError("expected a str or bytes object for details")
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_SEND_STATUS_FROM_SERVER
op.c_op.flags = flags
op.c_op.data.send_status_from_server.trailing_metadata_count = (
metadata.c_metadata_array.count)
op.c_op.data.send_status_from_server.trailing_metadata = (
@ -599,18 +620,20 @@ def operation_send_status_from_server(
op.is_valid = True
return op
def operation_receive_initial_metadata():
def operation_receive_initial_metadata(int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_RECV_INITIAL_METADATA
op.c_op.flags = flags
op._received_metadata = Metadata([])
op.c_op.data.receive_initial_metadata = (
&op._received_metadata.c_metadata_array)
op.is_valid = True
return op
def operation_receive_message():
def operation_receive_message(int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_RECV_MESSAGE
op.c_op.flags = flags
op._received_message = ByteBuffer(None)
# n.b. the c_op.data.receive_message field needs to be deleted by us,
# anyway, so we just let that be handled by the ByteBuffer() we allocated
@ -619,9 +642,10 @@ def operation_receive_message():
op.is_valid = True
return op
def operation_receive_status_on_client():
def operation_receive_status_on_client(int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_RECV_STATUS_ON_CLIENT
op.c_op.flags = flags
op._received_metadata = Metadata([])
op.c_op.data.receive_status_on_client.trailing_metadata = (
&op._received_metadata.c_metadata_array)
@ -634,9 +658,10 @@ def operation_receive_status_on_client():
op.is_valid = True
return op
def operation_receive_close_on_server():
def operation_receive_close_on_server(int flags):
cdef Operation op = Operation()
op.c_op.type = GRPC_OP_RECV_CLOSE_ON_SERVER
op.c_op.flags = flags
op.c_op.data.receive_close_on_server.cancelled = &op._received_cancelled
op.is_valid = True
return op
@ -692,3 +717,36 @@ cdef class Operations:
def __iter__(self):
return _OperationsIterator(self)
cdef class CompressionOptions:
def __cinit__(self):
with nogil:
grpc_compression_options_init(&self.c_options)
def enable_algorithm(self, grpc_compression_algorithm algorithm):
with nogil:
grpc_compression_options_enable_algorithm(&self.c_options, algorithm)
def disable_algorithm(self, grpc_compression_algorithm algorithm):
with nogil:
grpc_compression_options_disable_algorithm(&self.c_options, algorithm)
def is_algorithm_enabled(self, grpc_compression_algorithm algorithm):
cdef int result
with nogil:
result = grpc_compression_options_is_algorithm_enabled(
&self.c_options, algorithm)
return result
def to_channel_arg(self):
return ChannelArg(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
self.c_options.enabled_algorithms_bitset)
def compression_algorithm_name(grpc_compression_algorithm algorithm):
cdef char* name
with nogil:
grpc_compression_algorithm_name(algorithm, &name)
# Let Cython do the right thing with string casting
return name

@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import;
grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import;
grpc_is_binary_header_type grpc_is_binary_header_import;
grpc_call_error_to_string_type grpc_call_error_to_string_import;
grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import;
grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import;
grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import;
grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import;
@ -395,6 +396,7 @@ void pygrpc_load_imports(HMODULE library) {
grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal");
grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header");
grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string");
grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create");
grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next");
grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator");
grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity");

@ -43,6 +43,7 @@
#include <grpc/census.h>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/grpc_cronet.h>
#include <grpc/grpc_security.h>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/byte_buffer.h>
@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import;
typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error);
extern grpc_call_error_to_string_type grpc_call_error_to_string_import;
#define grpc_call_error_to_string grpc_call_error_to_string_import
typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved);
extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import;
#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import
typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it);
extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import;
#define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import
@ -866,14 +870,15 @@ void pygrpc_load_imports(HMODULE library);
#else /* !GPR_WIN32 */
#include <grpc/support/alloc.h>
#include <grpc/support/slice.h>
#include <grpc/support/time.h>
#include <grpc/status.h>
#include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/slice.h>
#include <grpc/support/time.h>
#include <grpc/status.h>
#endif /* !GPR_WIN32 */

@ -235,7 +235,7 @@ class Server(six.with_metaclass(abc.ABCMeta)):
This method may be called at any time and is idempotent. Passing a smaller
grace value than has been passed in a previous call will have the effect of
stopping the Server sooner. Passing a larger grace value than has been
passed in a previous call will not have the effect of stopping the sooner
passed in a previous call will not have the effect of stopping the server
later.
Args:

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

Loading…
Cancel
Save