Merge github.com:grpc/grpc into bm_perf

pull/9522/head
Craig Tiller 8 years ago
commit d52b76de44
  1. 2
      BUILD
  2. 7313
      CMakeLists.txt
  3. 91
      Makefile
  4. 1
      binding.gyp
  5. 42
      build.yaml
  6. 14
      cmake/msvc_static_runtime.cmake
  7. 2
      composer.json
  8. 1
      config.m4
  9. 9
      doc/PROTOCOL-WEB.md
  10. 1
      doc/environment_variables.md
  11. 2
      examples/csharp/helloworld/generate_protos.bat
  12. 8
      examples/php/composer.json
  13. 10
      examples/php/greeter_client.php
  14. 58
      examples/php/helloworld.pb.php
  15. 168
      examples/php/helloworld.php
  16. 64
      examples/php/helloworld_grpc_pb.php
  17. 209
      examples/php/route_guide/route_guide.pb.php
  18. 789
      examples/php/route_guide/route_guide.php
  19. 120
      examples/php/route_guide/route_guide.proto
  20. 22
      examples/php/route_guide/route_guide_client.php
  21. 116
      examples/php/route_guide/route_guide_grpc_pb.php
  22. 35
      gRPC-Core.podspec
  23. 10
      gRPC-ProtoRPC.podspec
  24. 10
      gRPC-RxLibrary.podspec
  25. 9
      gRPC.podspec
  26. 2
      grpc.gemspec
  27. 14
      include/grpc/census.h
  28. 9
      include/grpc/impl/codegen/grpc_types.h
  29. 2
      package.xml
  30. 45
      src/core/ext/census/gen/trace_context.pb.c
  31. 48
      src/core/ext/census/gen/trace_context.pb.h
  32. 2
      src/core/ext/census/trace_context.c
  33. 3
      src/core/ext/census/trace_context.h
  34. 6
      src/core/ext/client_channel/client_channel.c
  35. 4
      src/core/ext/client_channel/client_channel.h
  36. 390
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  37. 22
      src/core/ext/transport/chttp2/transport/frame_ping.c
  38. 4
      src/core/ext/transport/chttp2/transport/frame_ping.h
  39. 7
      src/core/ext/transport/chttp2/transport/frame_settings.c
  40. 11
      src/core/ext/transport/chttp2/transport/frame_window_update.c
  41. 122
      src/core/ext/transport/chttp2/transport/internal.h
  42. 30
      src/core/ext/transport/chttp2/transport/parsing.c
  43. 43
      src/core/ext/transport/chttp2/transport/stream_lists.c
  44. 120
      src/core/ext/transport/chttp2/transport/writing.c
  45. 6
      src/core/lib/channel/connected_channel.c
  46. 5
      src/core/lib/channel/connected_channel.h
  47. 8
      src/core/lib/iomgr/closure.c
  48. 5
      src/core/lib/iomgr/closure.h
  49. 32
      src/core/lib/iomgr/resource_quota.c
  50. 6
      src/core/lib/iomgr/resource_quota.h
  51. 27
      src/core/lib/iomgr/tcp_client_windows.c
  52. 38
      src/core/lib/iomgr/udp_server.c
  53. 5
      src/core/lib/iomgr/udp_server.h
  54. 12
      src/core/lib/support/log_posix.c
  55. 8
      src/core/lib/support/time_windows.c
  56. 2
      src/core/lib/surface/init.c
  57. 104
      src/core/lib/transport/bdp_estimator.c
  58. 76
      src/core/lib/transport/bdp_estimator.h
  59. 36
      src/core/lib/transport/pid_controller.c
  60. 17
      src/core/lib/transport/pid_controller.h
  61. 2
      src/csharp/Grpc.Core.Testing/.gitignore
  62. 68
      src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj
  63. 8
      src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.project.json
  64. 18
      src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.xproj
  65. 32
      src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs
  66. 10
      src/csharp/Grpc.Core.Testing/Settings.StyleCop
  67. 91
      src/csharp/Grpc.Core.Testing/TestCalls.cs
  68. 4
      src/csharp/Grpc.Core.Testing/packages.config
  69. 39
      src/csharp/Grpc.Core.Testing/project.json
  70. 6
      src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
  71. 6
      src/csharp/Grpc.sln
  72. 1
      src/csharp/build_packages_dotnetcli.bat
  73. 1
      src/csharp/build_packages_dotnetcli.sh
  74. 15
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  75. 382
      src/objective-c/BoringSSL.podspec
  76. 2
      src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
  77. 5
      src/objective-c/GRPCClient/private/GRPCHost.m
  78. 41
      src/objective-c/GRPCClient/private/version.h
  79. 2
      src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
  80. 19
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
  81. 49
      src/php/README.md
  82. 8
      src/php/composer.json
  83. 15
      src/php/tests/generated_code/math_client.php
  84. 20
      src/proto/census/trace_context.proto
  85. 4
      src/python/grpcio/commands.py
  86. 57
      src/python/grpcio/grpc/__init__.py
  87. 51
      src/python/grpcio/grpc/_channel.py
  88. 12
      src/python/grpcio/grpc/_common.py
  89. 3
      src/python/grpcio/grpc/_plugin_wrapping.py
  90. 29
      src/python/grpcio/grpc/_server.py
  91. 11
      src/python/grpcio/grpc/_utilities.py
  92. 90
      src/python/grpcio/grpc/beta/_client_adaptations.py
  93. 4
      src/python/grpcio/grpc/beta/_connectivity_channel.py
  94. 11
      src/python/grpcio/grpc/beta/_server_adaptations.py
  95. 11
      src/python/grpcio/grpc/framework/interfaces/base/utilities.py
  96. 13
      src/python/grpcio/grpc/framework/interfaces/face/face.py
  97. 1
      src/python/grpcio/grpc_core_dependencies.py
  98. 4
      src/python/grpcio/support.py
  99. 9
      src/python/grpcio_health_checking/setup.py
  100. 9
      src/python/grpcio_reflection/setup.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -526,6 +526,7 @@ grpc_cc_library(
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/bdp_estimator.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/status_conversion.c",
@ -633,6 +634,7 @@ grpc_cc_library(
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/bdp_estimator.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/status_conversion.h",

File diff suppressed because it is too large Load Diff

@ -899,6 +899,7 @@ alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test
bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
@ -1090,6 +1091,7 @@ streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
stress_test: $(BINDIR)/$(CONFIG)/stress_test
thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test
thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test
public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
boringssl_aes_test: $(BINDIR)/$(CONFIG)/boringssl_aes_test
boringssl_asn1_test: $(BINDIR)/$(CONFIG)/boringssl_asn1_test
@ -1259,6 +1261,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/alloc_test \
$(BINDIR)/$(CONFIG)/alpn_test \
$(BINDIR)/$(CONFIG)/bad_server_response_test \
$(BINDIR)/$(CONFIG)/bdp_estimator_test \
$(BINDIR)/$(CONFIG)/bin_decoder_test \
$(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/census_context_test \
@ -1485,6 +1488,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/stress_test \
$(BINDIR)/$(CONFIG)/thread_manager_test \
$(BINDIR)/$(CONFIG)/thread_stress_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \
$(BINDIR)/$(CONFIG)/boringssl_aes_test \
$(BINDIR)/$(CONFIG)/boringssl_asn1_test \
$(BINDIR)/$(CONFIG)/boringssl_base64_test \
@ -1587,6 +1591,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/stress_test \
$(BINDIR)/$(CONFIG)/thread_manager_test \
$(BINDIR)/$(CONFIG)/thread_stress_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \
endif
@ -1606,6 +1611,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 )
$(E) "[RUN] Testing bad_server_response_test"
$(Q) $(BINDIR)/$(CONFIG)/bad_server_response_test || ( echo test bad_server_response_test failed ; exit 1 )
$(E) "[RUN] Testing bdp_estimator_test"
$(Q) $(BINDIR)/$(CONFIG)/bdp_estimator_test || ( echo test bdp_estimator_test failed ; exit 1 )
$(E) "[RUN] Testing bin_decoder_test"
$(Q) $(BINDIR)/$(CONFIG)/bin_decoder_test || ( echo test bin_decoder_test failed ; exit 1 )
$(E) "[RUN] Testing bin_encoder_test"
@ -1918,6 +1925,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/thread_manager_test || ( echo test thread_manager_test failed ; exit 1 )
$(E) "[RUN] Testing thread_stress_test"
$(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 )
$(E) "[RUN] Testing writes_per_rpc_test"
$(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 )
flaky_test_cxx: buildtests_cxx
@ -2729,6 +2738,7 @@ LIBGRPC_SRC = \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
@ -3037,6 +3047,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
@ -3220,6 +3231,7 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/end2end/fixtures/http_proxy.c \
test/core/end2end/fixtures/proxy.c \
test/core/iomgr/endpoint_tests.c \
test/core/util/debugger_macros.c \
test/core/util/grpc_profiler.c \
test/core/util/memory_counters.c \
test/core/util/mock_endpoint.c \
@ -3335,6 +3347,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
@ -3418,6 +3431,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
test/core/end2end/fixtures/http_proxy.c \
test/core/end2end/fixtures/proxy.c \
test/core/iomgr/endpoint_tests.c \
test/core/util/debugger_macros.c \
test/core/util/grpc_profiler.c \
test/core/util/memory_counters.c \
test/core/util/mock_endpoint.c \
@ -3559,6 +3573,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
@ -4150,6 +4165,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \
@ -7965,6 +7981,38 @@ endif
endif
BDP_ESTIMATOR_TEST_SRC = \
test/core/transport/bdp_estimator_test.c \
BDP_ESTIMATOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BDP_ESTIMATOR_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bdp_estimator_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/bdp_estimator_test: $(BDP_ESTIMATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(BDP_ESTIMATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/bdp_estimator_test
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/bdp_estimator_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_bdp_estimator_test: $(BDP_ESTIMATOR_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BDP_ESTIMATOR_TEST_OBJS:.o=.dep)
endif
endif
BIN_DECODER_TEST_SRC = \
test/core/transport/chttp2/bin_decoder_test.c \
@ -14725,6 +14773,49 @@ endif
endif
WRITES_PER_RPC_TEST_SRC = \
test/cpp/performance/writes_per_rpc_test.cc \
WRITES_PER_RPC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WRITES_PER_RPC_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/writes_per_rpc_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)/writes_per_rpc_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/writes_per_rpc_test: $(PROTOBUF_DEP) $(WRITES_PER_RPC_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) $(WRITES_PER_RPC_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)/writes_per_rpc_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/performance/writes_per_rpc_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_writes_per_rpc_test: $(WRITES_PER_RPC_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(WRITES_PER_RPC_TEST_OBJS:.o=.dep)
endif
endif
PUBLIC_HEADERS_MUST_BE_C89_SRC = \
test/core/surface/public_headers_must_be_c89.c \

@ -707,6 +707,7 @@
'src/core/lib/surface/server.c',
'src/core/lib/surface/validate_metadata.c',
'src/core/lib/surface/version.c',
'src/core/lib/transport/bdp_estimator.c',
'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c',
'src/core/lib/transport/error_utils.c',

@ -256,6 +256,7 @@ filegroups:
- src/core/lib/surface/lame_client.h
- src/core/lib/surface/server.h
- src/core/lib/surface/validate_metadata.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/byte_stream.h
- src/core/lib/transport/connectivity_state.h
- src/core/lib/transport/error_utils.h
@ -375,6 +376,7 @@ filegroups:
- src/core/lib/surface/server.c
- src/core/lib/surface/validate_metadata.c
- src/core/lib/surface/version.c
- src/core/lib/transport/bdp_estimator.c
- src/core/lib/transport/byte_stream.c
- src/core/lib/transport/connectivity_state.c
- src/core/lib/transport/error_utils.c
@ -560,6 +562,7 @@ filegroups:
- test/core/end2end/fixtures/http_proxy.h
- test/core/end2end/fixtures/proxy.h
- test/core/iomgr/endpoint_tests.h
- test/core/util/debugger_macros.h
- test/core/util/grpc_profiler.h
- test/core/util/memory_counters.h
- test/core/util/mock_endpoint.h
@ -574,6 +577,7 @@ filegroups:
- test/core/end2end/fixtures/http_proxy.c
- test/core/end2end/fixtures/proxy.c
- test/core/iomgr/endpoint_tests.c
- test/core/util/debugger_macros.c
- test/core/util/grpc_profiler.c
- test/core/util/memory_counters.c
- test/core/util/mock_endpoint.c
@ -1440,6 +1444,16 @@ targets:
- gpr
exclude_iomgrs:
- uv
- name: bdp_estimator_test
build: test
language: c
src:
- test/core/transport/bdp_estimator_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: bin_decoder_test
build: test
language: c
@ -2943,6 +2957,12 @@ targets:
- grpc
- gpr_test_util
- gpr
args:
- --benchmark_min_time=0
platforms:
- mac
- linux
- posix
- name: channel_arguments_test
gtest: true
build: test
@ -3369,6 +3389,10 @@ targets:
- gpr_test_util
- gpr
- grpc++_test_config
platforms:
- mac
- linux
- posix
- name: metrics_client
build: test
run: false
@ -3717,6 +3741,24 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: writes_per_rpc_test
gtest: true
cpu_cost: 0.5
build: test
language: c++
src:
- test/cpp/performance/writes_per_rpc_test.cc
deps:
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
platforms:
- mac
- linux
- posix
- name: public_headers_must_be_c89
build: test
language: c89

@ -0,0 +1,14 @@
option(gRPC_MSVC_STATIC_RUNTIME "Link with static msvc runtime libraries" OFF)
if(gRPC_MSVC_STATIC_RUNTIME)
# switch from dynamic to static linking of msvcrt
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif()

@ -7,7 +7,7 @@
"license": "BSD-3-Clause",
"require": {
"php": ">=5.5.0",
"google/protobuf": "v3.1.0-alpha-1"
"google/protobuf": "v3.1.0"
},
"require-dev": {
"google/auth": "v0.9"

@ -186,6 +186,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/bdp_estimator.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/error_utils.c \

@ -60,21 +60,22 @@ HTTP/2 related behavior (specified in [gRPC over HTTP2](http://www.grpc.io/docs/
Message framing (vs. [http2-transport-mapping](http://www.grpc.io/docs/guides/wire.html#http2-transport-mapping))
1. Response status encoded as part of the response body
* Key-value pairs encoded in the HTTP/2 [literal header format](https://tools.ietf.org/html/rfc7541#section-6.2) as a single header block.
* Key-value pairs encoded as a HTTP/1 headers block (without the terminating newline).
2. 8th (MSB) bit of the 1st gRPC frame byte
* 0: data
* 1: trailers
3. Trailers must be the last message of the response, as enforced
by the implementation
4. Trailers-only responses: no change to the gRPC protocol spec.
Trailers will be sent together with response headers, with no message
Trailers may be sent together with response headers, with no message
in the body.
---
User Agent
User Agent and Server headers
* grpc-web-javascript/0.1
* U-A: grpc-web-javascript/0.1
* Server: grpc-web-gateway/0.1
---

@ -35,6 +35,7 @@ some configuration as environment variables that can be set.
A comma separated list of tracers that provide additional insight into how
gRPC C core is processing requests via debug logs. Available tracers include:
- api - traces api calls to the C core
- bdp_estimator - traces behavior of bdp estimation logic
- call_error - traces the possible errors contributing to final call status
- channel - traces operations on the C core channel stack
- combiner - traces combiner lock state

@ -34,7 +34,7 @@ setlocal
@rem enter this directory
cd /d %~dp0
set TOOLS_PATH=packages\Grpc.Tools.1.0.0\tools\windows_x86
set TOOLS_PATH=packages\Grpc.Tools.1.0.1\tools\windows_x86
%TOOLS_PATH%\protoc.exe -I../../protos --csharp_out Greeter ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe

@ -2,7 +2,11 @@
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"require": {
"ext-grpc": "*",
"grpc/grpc": "v1.0.0"
"grpc/grpc": "v1.1.0"
},
"autoload": {
"psr-4": {
"": "route_guide/"
}
}
}

@ -33,14 +33,18 @@
*/
require dirname(__FILE__).'/vendor/autoload.php';
require dirname(__FILE__).'/helloworld.php';
// The following includes are needed when using protobuf 3.1.0
// and will suppress warnings when using protobuf 3.2.0+
@include_once dirname(__FILE__).'/helloworld.pb.php';
@include_once dirname(__FILE__).'/helloworld_grpc_pb.php';
function greet($name)
{
$client = new helloworld\GreeterClient('localhost:50051', [
$client = new Helloworld\GreeterClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
$request = new helloworld\HelloRequest();
$request = new Helloworld\HelloRequest();
$request->setName($name);
list($reply, $status) = $client->SayHello($request)->wait();
$message = $reply->getMessage();

@ -0,0 +1,58 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: helloworld.proto
namespace Helloworld;
use Google\Protobuf\Internal\DescriptorPool;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
class HelloRequest extends \Google\Protobuf\Internal\Message
{
private $name = '';
public function getName()
{
return $this->name;
}
public function setName($var)
{
GPBUtil::checkString($var, True);
$this->name = $var;
}
}
class HelloReply extends \Google\Protobuf\Internal\Message
{
private $message = '';
public function getMessage()
{
return $this->message;
}
public function setMessage($var)
{
GPBUtil::checkString($var, True);
$this->message = $var;
}
}
$pool = DescriptorPool::getGeneratedPool();
$pool->internalAddGeneratedFile(hex2bin(
"0ae6010a1068656c6c6f776f726c642e70726f746f120a68656c6c6f776f" .
"726c64221c0a0c48656c6c6f52657175657374120c0a046e616d65180120" .
"012809221d0a0a48656c6c6f5265706c79120f0a076d6573736167651801" .
"2001280932490a0747726565746572123e0a0853617948656c6c6f12182e" .
"68656c6c6f776f726c642e48656c6c6f526571756573741a162e68656c6c" .
"6f776f726c642e48656c6c6f5265706c79220042360a1b696f2e67727063" .
"2e6578616d706c65732e68656c6c6f776f726c64420f48656c6c6f576f72" .
"6c6450726f746f5001a20203484c57620670726f746f33"
));

@ -1,168 +0,0 @@
<?php
// DO NOT EDIT! Generated by Protobuf-PHP protoc plugin 1.0
// Source: helloworld.proto
// Date: 2015-09-24 20:40:14
namespace helloworld {
class HelloRequest extends \DrSlump\Protobuf\Message
{
/** @var string */
public $name = null;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloRequest');
// OPTIONAL STRING name = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'name';
$f->type = \DrSlump\Protobuf::TYPE_STRING;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <name> has a value.
*
* @return bool
*/
public function hasName()
{
return $this->_has(1);
}
/**
* Clear <name> value.
*
* @return \helloworld\HelloRequest
*/
public function clearName()
{
return $this->_clear(1);
}
/**
* Get <name> value.
*
* @return string
*/
public function getName()
{
return $this->_get(1);
}
/**
* Set <name> value.
*
* @param string $value
*
* @return \helloworld\HelloRequest
*/
public function setName($value)
{
return $this->_set(1, $value);
}
}
}
namespace helloworld {
class HelloReply extends \DrSlump\Protobuf\Message
{
/** @var string */
public $message = null;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloReply');
// OPTIONAL STRING message = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'message';
$f->type = \DrSlump\Protobuf::TYPE_STRING;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <message> has a value.
*
* @return bool
*/
public function hasMessage()
{
return $this->_has(1);
}
/**
* Clear <message> value.
*
* @return \helloworld\HelloReply
*/
public function clearMessage()
{
return $this->_clear(1);
}
/**
* Get <message> value.
*
* @return string
*/
public function getMessage()
{
return $this->_get(1);
}
/**
* Set <message> value.
*
* @param string $value
*
* @return \helloworld\HelloReply
*/
public function setMessage($value)
{
return $this->_set(1, $value);
}
}
}
namespace helloworld {
class GreeterClient extends \Grpc\BaseStub
{
public function __construct($hostname, $opts)
{
parent::__construct($hostname, $opts);
}
/**
* @param helloworld\HelloRequest $input
*/
public function SayHello(\helloworld\HelloRequest $argument, $metadata = array(), $options = array())
{
return $this->_simpleRequest('/helloworld.Greeter/SayHello', $argument, '\helloworld\HelloReply::deserialize', $metadata, $options);
}
}
}

@ -0,0 +1,64 @@
<?php
// GENERATED CODE -- DO NOT EDIT!
// Original file comments:
// 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.
//
namespace Helloworld {
// The greeting service definition.
class GreeterClient extends \Grpc\BaseStub {
/**
* @param string $hostname hostname
* @param array $opts channel options
* @param Grpc\Channel $channel (optional) re-use channel object
*/
public function __construct($hostname, $opts, $channel = null) {
parent::__construct($hostname, $opts, $channel);
}
/**
* Sends a greeting
* @param \Helloworld\HelloRequest $argument input argument
* @param array $metadata metadata
* @param array $options call options
*/
public function SayHello(\Helloworld\HelloRequest $argument,
$metadata = [], $options = []) {
return $this->_simpleRequest('/helloworld.Greeter/SayHello',
$argument,
['\Helloworld\HelloReply', 'decode'],
$metadata, $options);
}
}
}

@ -0,0 +1,209 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: route_guide.proto
namespace Routeguide;
use Google\Protobuf\Internal\DescriptorPool;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
class Point extends \Google\Protobuf\Internal\Message
{
private $latitude = 0;
private $longitude = 0;
public function getLatitude()
{
return $this->latitude;
}
public function setLatitude($var)
{
GPBUtil::checkInt32($var);
$this->latitude = $var;
}
public function getLongitude()
{
return $this->longitude;
}
public function setLongitude($var)
{
GPBUtil::checkInt32($var);
$this->longitude = $var;
}
}
class Rectangle extends \Google\Protobuf\Internal\Message
{
private $lo = null;
private $hi = null;
public function getLo()
{
return $this->lo;
}
public function setLo(&$var)
{
GPBUtil::checkMessage($var, \Routeguide\Point::class);
$this->lo = $var;
}
public function getHi()
{
return $this->hi;
}
public function setHi(&$var)
{
GPBUtil::checkMessage($var, \Routeguide\Point::class);
$this->hi = $var;
}
}
class Feature extends \Google\Protobuf\Internal\Message
{
private $name = '';
private $location = null;
public function getName()
{
return $this->name;
}
public function setName($var)
{
GPBUtil::checkString($var, True);
$this->name = $var;
}
public function getLocation()
{
return $this->location;
}
public function setLocation(&$var)
{
GPBUtil::checkMessage($var, \Routeguide\Point::class);
$this->location = $var;
}
}
class RouteNote extends \Google\Protobuf\Internal\Message
{
private $location = null;
private $message = '';
public function getLocation()
{
return $this->location;
}
public function setLocation(&$var)
{
GPBUtil::checkMessage($var, \Routeguide\Point::class);
$this->location = $var;
}
public function getMessage()
{
return $this->message;
}
public function setMessage($var)
{
GPBUtil::checkString($var, True);
$this->message = $var;
}
}
class RouteSummary extends \Google\Protobuf\Internal\Message
{
private $point_count = 0;
private $feature_count = 0;
private $distance = 0;
private $elapsed_time = 0;
public function getPointCount()
{
return $this->point_count;
}
public function setPointCount($var)
{
GPBUtil::checkInt32($var);
$this->point_count = $var;
}
public function getFeatureCount()
{
return $this->feature_count;
}
public function setFeatureCount($var)
{
GPBUtil::checkInt32($var);
$this->feature_count = $var;
}
public function getDistance()
{
return $this->distance;
}
public function setDistance($var)
{
GPBUtil::checkInt32($var);
$this->distance = $var;
}
public function getElapsedTime()
{
return $this->elapsed_time;
}
public function setElapsedTime($var)
{
GPBUtil::checkInt32($var);
$this->elapsed_time = $var;
}
}
$pool = DescriptorPool::getGeneratedPool();
$pool->internalAddGeneratedFile(hex2bin(
"0ac5050a11726f7574655f67756964652e70726f746f120a726f75746567" .
"75696465222c0a05506f696e7412100a086c617469747564651801200128" .
"0512110a096c6f6e67697475646518022001280522490a0952656374616e" .
"676c65121d0a026c6f18012001280b32112e726f75746567756964652e50" .
"6f696e74121d0a02686918022001280b32112e726f75746567756964652e" .
"506f696e74223c0a0746656174757265120c0a046e616d65180120012809" .
"12230a086c6f636174696f6e18022001280b32112e726f75746567756964" .
"652e506f696e7422410a09526f7574654e6f746512230a086c6f63617469" .
"6f6e18012001280b32112e726f75746567756964652e506f696e74120f0a" .
"076d65737361676518022001280922620a0c526f75746553756d6d617279" .
"12130a0b706f696e745f636f756e7418012001280512150a0d6665617475" .
"72655f636f756e7418022001280512100a0864697374616e636518032001" .
"280512140a0c656c61707365645f74696d651804200128053285020a0a52" .
"6f757465477569646512360a0a4765744665617475726512112e726f7574" .
"6567756964652e506f696e741a132e726f75746567756964652e46656174" .
"7572652200123e0a0c4c697374466561747572657312152e726f75746567" .
"756964652e52656374616e676c651a132e726f75746567756964652e4665" .
"617475726522003001123e0a0b5265636f7264526f75746512112e726f75" .
"746567756964652e506f696e741a182e726f75746567756964652e526f75" .
"746553756d6d61727922002801123f0a09526f7574654368617412152e72" .
"6f75746567756964652e526f7574654e6f74651a152e726f757465677569" .
"64652e526f7574654e6f746522002801300142360a1b696f2e677270632e" .
"6578616d706c65732e726f7574656775696465420f526f75746547756964" .
"6550726f746f5001a20203525447620670726f746f33"
));

@ -1,789 +0,0 @@
<?php
// DO NOT EDIT! Generated by Protobuf-PHP protoc plugin 1.0
// Source: route_guide.proto
// Date: 2015-09-24 21:21:51
namespace routeguide {
class Point extends \DrSlump\Protobuf\Message
{
/** @var int */
public $latitude = 0;
/** @var int */
public $longitude = 0;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.Point');
// OPTIONAL INT32 latitude = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'latitude';
$f->type = \DrSlump\Protobuf::TYPE_INT32;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->default = 0;
$descriptor->addField($f);
// OPTIONAL INT32 longitude = 2
$f = new \DrSlump\Protobuf\Field();
$f->number = 2;
$f->name = 'longitude';
$f->type = \DrSlump\Protobuf::TYPE_INT32;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->default = 0;
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <latitude> has a value.
*
* @return bool
*/
public function hasLatitude()
{
return $this->_has(1);
}
/**
* Clear <latitude> value.
*
* @return \routeguide\Point
*/
public function clearLatitude()
{
return $this->_clear(1);
}
/**
* Get <latitude> value.
*
* @return int
*/
public function getLatitude()
{
return $this->_get(1);
}
/**
* Set <latitude> value.
*
* @param int $value
*
* @return \routeguide\Point
*/
public function setLatitude($value)
{
return $this->_set(1, $value);
}
/**
* Check if <longitude> has a value.
*
* @return bool
*/
public function hasLongitude()
{
return $this->_has(2);
}
/**
* Clear <longitude> value.
*
* @return \routeguide\Point
*/
public function clearLongitude()
{
return $this->_clear(2);
}
/**
* Get <longitude> value.
*
* @return int
*/
public function getLongitude()
{
return $this->_get(2);
}
/**
* Set <longitude> value.
*
* @param int $value
*
* @return \routeguide\Point
*/
public function setLongitude($value)
{
return $this->_set(2, $value);
}
}
}
namespace routeguide {
class Rectangle extends \DrSlump\Protobuf\Message
{
/** @var \routeguide\Point */
public $lo = null;
/** @var \routeguide\Point */
public $hi = null;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.Rectangle');
// OPTIONAL MESSAGE lo = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'lo';
$f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->reference = '\routeguide\Point';
$descriptor->addField($f);
// OPTIONAL MESSAGE hi = 2
$f = new \DrSlump\Protobuf\Field();
$f->number = 2;
$f->name = 'hi';
$f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->reference = '\routeguide\Point';
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <lo> has a value.
*
* @return bool
*/
public function hasLo()
{
return $this->_has(1);
}
/**
* Clear <lo> value.
*
* @return \routeguide\Rectangle
*/
public function clearLo()
{
return $this->_clear(1);
}
/**
* Get <lo> value.
*
* @return \routeguide\Point
*/
public function getLo()
{
return $this->_get(1);
}
/**
* Set <lo> value.
*
* @param \routeguide\Point $value
*
* @return \routeguide\Rectangle
*/
public function setLo(\routeguide\Point $value)
{
return $this->_set(1, $value);
}
/**
* Check if <hi> has a value.
*
* @return bool
*/
public function hasHi()
{
return $this->_has(2);
}
/**
* Clear <hi> value.
*
* @return \routeguide\Rectangle
*/
public function clearHi()
{
return $this->_clear(2);
}
/**
* Get <hi> value.
*
* @return \routeguide\Point
*/
public function getHi()
{
return $this->_get(2);
}
/**
* Set <hi> value.
*
* @param \routeguide\Point $value
*
* @return \routeguide\Rectangle
*/
public function setHi(\routeguide\Point $value)
{
return $this->_set(2, $value);
}
}
}
namespace routeguide {
class Feature extends \DrSlump\Protobuf\Message
{
/** @var string */
public $name = null;
/** @var \routeguide\Point */
public $location = null;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.Feature');
// OPTIONAL STRING name = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'name';
$f->type = \DrSlump\Protobuf::TYPE_STRING;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$descriptor->addField($f);
// OPTIONAL MESSAGE location = 2
$f = new \DrSlump\Protobuf\Field();
$f->number = 2;
$f->name = 'location';
$f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->reference = '\routeguide\Point';
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <name> has a value.
*
* @return bool
*/
public function hasName()
{
return $this->_has(1);
}
/**
* Clear <name> value.
*
* @return \routeguide\Feature
*/
public function clearName()
{
return $this->_clear(1);
}
/**
* Get <name> value.
*
* @return string
*/
public function getName()
{
return $this->_get(1);
}
/**
* Set <name> value.
*
* @param string $value
*
* @return \routeguide\Feature
*/
public function setName($value)
{
return $this->_set(1, $value);
}
/**
* Check if <location> has a value.
*
* @return bool
*/
public function hasLocation()
{
return $this->_has(2);
}
/**
* Clear <location> value.
*
* @return \routeguide\Feature
*/
public function clearLocation()
{
return $this->_clear(2);
}
/**
* Get <location> value.
*
* @return \routeguide\Point
*/
public function getLocation()
{
return $this->_get(2);
}
/**
* Set <location> value.
*
* @param \routeguide\Point $value
*
* @return \routeguide\Feature
*/
public function setLocation(\routeguide\Point $value)
{
return $this->_set(2, $value);
}
}
}
namespace routeguide {
class RouteNote extends \DrSlump\Protobuf\Message
{
/** @var \routeguide\Point */
public $location = null;
/** @var string */
public $message = null;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.RouteNote');
// OPTIONAL MESSAGE location = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'location';
$f->type = \DrSlump\Protobuf::TYPE_MESSAGE;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->reference = '\routeguide\Point';
$descriptor->addField($f);
// OPTIONAL STRING message = 2
$f = new \DrSlump\Protobuf\Field();
$f->number = 2;
$f->name = 'message';
$f->type = \DrSlump\Protobuf::TYPE_STRING;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <location> has a value.
*
* @return bool
*/
public function hasLocation()
{
return $this->_has(1);
}
/**
* Clear <location> value.
*
* @return \routeguide\RouteNote
*/
public function clearLocation()
{
return $this->_clear(1);
}
/**
* Get <location> value.
*
* @return \routeguide\Point
*/
public function getLocation()
{
return $this->_get(1);
}
/**
* Set <location> value.
*
* @param \routeguide\Point $value
*
* @return \routeguide\RouteNote
*/
public function setLocation(\routeguide\Point $value)
{
return $this->_set(1, $value);
}
/**
* Check if <message> has a value.
*
* @return bool
*/
public function hasMessage()
{
return $this->_has(2);
}
/**
* Clear <message> value.
*
* @return \routeguide\RouteNote
*/
public function clearMessage()
{
return $this->_clear(2);
}
/**
* Get <message> value.
*
* @return string
*/
public function getMessage()
{
return $this->_get(2);
}
/**
* Set <message> value.
*
* @param string $value
*
* @return \routeguide\RouteNote
*/
public function setMessage($value)
{
return $this->_set(2, $value);
}
}
}
namespace routeguide {
class RouteSummary extends \DrSlump\Protobuf\Message
{
/** @var int */
public $point_count = 0;
/** @var int */
public $feature_count = 0;
/** @var int */
public $distance = 0;
/** @var int */
public $elapsed_time = 0;
/** @var \Closure[] */
protected static $__extensions = array();
public static function descriptor()
{
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'routeguide.RouteSummary');
// OPTIONAL INT32 point_count = 1
$f = new \DrSlump\Protobuf\Field();
$f->number = 1;
$f->name = 'point_count';
$f->type = \DrSlump\Protobuf::TYPE_INT32;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->default = 0;
$descriptor->addField($f);
// OPTIONAL INT32 feature_count = 2
$f = new \DrSlump\Protobuf\Field();
$f->number = 2;
$f->name = 'feature_count';
$f->type = \DrSlump\Protobuf::TYPE_INT32;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->default = 0;
$descriptor->addField($f);
// OPTIONAL INT32 distance = 3
$f = new \DrSlump\Protobuf\Field();
$f->number = 3;
$f->name = 'distance';
$f->type = \DrSlump\Protobuf::TYPE_INT32;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->default = 0;
$descriptor->addField($f);
// OPTIONAL INT32 elapsed_time = 4
$f = new \DrSlump\Protobuf\Field();
$f->number = 4;
$f->name = 'elapsed_time';
$f->type = \DrSlump\Protobuf::TYPE_INT32;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$f->default = 0;
$descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor;
}
/**
* Check if <point_count> has a value.
*
* @return bool
*/
public function hasPointCount()
{
return $this->_has(1);
}
/**
* Clear <point_count> value.
*
* @return \routeguide\RouteSummary
*/
public function clearPointCount()
{
return $this->_clear(1);
}
/**
* Get <point_count> value.
*
* @return int
*/
public function getPointCount()
{
return $this->_get(1);
}
/**
* Set <point_count> value.
*
* @param int $value
*
* @return \routeguide\RouteSummary
*/
public function setPointCount($value)
{
return $this->_set(1, $value);
}
/**
* Check if <feature_count> has a value.
*
* @return bool
*/
public function hasFeatureCount()
{
return $this->_has(2);
}
/**
* Clear <feature_count> value.
*
* @return \routeguide\RouteSummary
*/
public function clearFeatureCount()
{
return $this->_clear(2);
}
/**
* Get <feature_count> value.
*
* @return int
*/
public function getFeatureCount()
{
return $this->_get(2);
}
/**
* Set <feature_count> value.
*
* @param int $value
*
* @return \routeguide\RouteSummary
*/
public function setFeatureCount($value)
{
return $this->_set(2, $value);
}
/**
* Check if <distance> has a value.
*
* @return bool
*/
public function hasDistance()
{
return $this->_has(3);
}
/**
* Clear <distance> value.
*
* @return \routeguide\RouteSummary
*/
public function clearDistance()
{
return $this->_clear(3);
}
/**
* Get <distance> value.
*
* @return int
*/
public function getDistance()
{
return $this->_get(3);
}
/**
* Set <distance> value.
*
* @param int $value
*
* @return \routeguide\RouteSummary
*/
public function setDistance($value)
{
return $this->_set(3, $value);
}
/**
* Check if <elapsed_time> has a value.
*
* @return bool
*/
public function hasElapsedTime()
{
return $this->_has(4);
}
/**
* Clear <elapsed_time> value.
*
* @return \routeguide\RouteSummary
*/
public function clearElapsedTime()
{
return $this->_clear(4);
}
/**
* Get <elapsed_time> value.
*
* @return int
*/
public function getElapsedTime()
{
return $this->_get(4);
}
/**
* Set <elapsed_time> value.
*
* @param int $value
*
* @return \routeguide\RouteSummary
*/
public function setElapsedTime($value)
{
return $this->_set(4, $value);
}
}
}
namespace routeguide {
class RouteGuideClient extends \Grpc\BaseStub
{
public function __construct($hostname, $opts)
{
parent::__construct($hostname, $opts);
}
/**
* @param routeguide\Point $input
*/
public function GetFeature(\routeguide\Point $argument, $metadata = array(), $options = array())
{
return $this->_simpleRequest('/routeguide.RouteGuide/GetFeature', $argument, '\routeguide\Feature::deserialize', $metadata, $options);
}
/**
* @param routeguide\Rectangle $input
*/
public function ListFeatures($argument, $metadata = array(), $options = array())
{
return $this->_serverStreamRequest('/routeguide.RouteGuide/ListFeatures', $argument, '\routeguide\Feature::deserialize', $metadata, $options);
}
/**
* @param routeguide\Point $input
*/
public function RecordRoute($metadata = array())
{
return $this->_clientStreamRequest('/routeguide.RouteGuide/RecordRoute', '\routeguide\RouteSummary::deserialize', $metadata);
}
/**
* @param routeguide\RouteNote $input
*/
public function RouteChat($metadata = array())
{
return $this->_bidiRequest('/routeguide.RouteGuide/RouteChat', '\routeguide\RouteNote::deserialize', $metadata);
}
}
}

@ -1,120 +0,0 @@
// 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.
syntax = "proto2";
option java_package = "io.grpc.examples";
package routeguide;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
optional int32 latitude = 1 [default = 0];
optional int32 longitude = 2 [default = 0];
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
optional Point lo = 1;
// The other corner of the rectangle.
optional Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
optional string name = 1;
// The point where the feature is detected.
optional Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
optional Point location = 1;
// The message to be sent.
optional string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
optional int32 point_count = 1 [default = 0];
// The number of known features passed while traversing the route.
optional int32 feature_count = 2 [default = 0];
// The distance covered in metres.
optional int32 distance = 3 [default = 0];
// The duration of the traversal in seconds.
optional int32 elapsed_time = 4 [default = 0];
}

@ -33,11 +33,15 @@
*/
require dirname(__FILE__).'/../vendor/autoload.php';
require dirname(__FILE__).'/route_guide.php';
// The following includes are needed when using protobuf 3.1.0
// and will suppress warnings when using protobuf 3.2.0+
@include_once dirname(__FILE__).'/route_guide.pb.php';
@include_once dirname(__FILE__).'/route_guide_grpc_pb.php';
define('COORD_FACTOR', 1e7);
$client = new routeguide\RouteGuideClient('localhost:50051', [
$client = new Routeguide\RouteGuideClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
@ -63,7 +67,7 @@ function runGetFeature()
echo "Running GetFeature...\n";
global $client;
$point = new routeguide\Point();
$point = new Routeguide\Point();
$points = array(
array(409146138, -746188906),
array(0, 0),
@ -88,15 +92,15 @@ function runListFeatures()
echo "Running ListFeatures...\n";
global $client;
$lo_point = new routeguide\Point();
$hi_point = new routeguide\Point();
$lo_point = new Routeguide\Point();
$hi_point = new Routeguide\Point();
$lo_point->setLatitude(400000000);
$lo_point->setLongitude(-750000000);
$hi_point->setLatitude(420000000);
$hi_point->setLongitude(-730000000);
$rectangle = new routeguide\Rectangle();
$rectangle = new Routeguide\Rectangle();
$rectangle->setLo($lo_point);
$rectangle->setHi($hi_point);
@ -126,7 +130,7 @@ function runRecordRoute()
$num_points_in_db = count($db);
$num_points = 10;
for ($i = 0; $i < $num_points; ++$i) {
$point = new routeguide\Point();
$point = new Routeguide\Point();
$index = rand(0, $num_points_in_db - 1);
$lat = $db[$index]['location']['latitude'];
$long = $db[$index]['location']['longitude'];
@ -169,11 +173,11 @@ function runRouteChat()
);
foreach ($notes as $n) {
$point = new routeguide\Point();
$point = new Routeguide\Point();
$point->setLatitude($lat = $n[0]);
$point->setLongitude($long = $n[1]);
$route_note = new routeguide\RouteNote();
$route_note = new Routeguide\RouteNote();
$route_note->setLocation($point);
$route_note->setMessage($message = $n[2]);

@ -0,0 +1,116 @@
<?php
// GENERATED CODE -- DO NOT EDIT!
// Original file comments:
// 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.
//
namespace Routeguide {
// Interface exported by the server.
class RouteGuideClient extends \Grpc\BaseStub {
/**
* @param string $hostname hostname
* @param array $opts channel options
* @param Grpc\Channel $channel (optional) re-use channel object
*/
public function __construct($hostname, $opts, $channel = null) {
parent::__construct($hostname, $opts, $channel);
}
/**
* A simple RPC.
*
* Obtains the feature at a given position.
*
* A feature with an empty name is returned if there's no feature at the given
* position.
* @param \Routeguide\Point $argument input argument
* @param array $metadata metadata
* @param array $options call options
*/
public function GetFeature(\Routeguide\Point $argument,
$metadata = [], $options = []) {
return $this->_simpleRequest('/routeguide.RouteGuide/GetFeature',
$argument,
['\Routeguide\Feature', 'decode'],
$metadata, $options);
}
/**
* A server-to-client streaming RPC.
*
* Obtains the Features available within the given Rectangle. Results are
* streamed rather than returned at once (e.g. in a response message with a
* repeated field), as the rectangle may cover a large area and contain a
* huge number of features.
* @param \Routeguide\Rectangle $argument input argument
* @param array $metadata metadata
* @param array $options call options
*/
public function ListFeatures(\Routeguide\Rectangle $argument,
$metadata = [], $options = []) {
return $this->_serverStreamRequest('/routeguide.RouteGuide/ListFeatures',
$argument,
['\Routeguide\Feature', 'decode'],
$metadata, $options);
}
/**
* A client-to-server streaming RPC.
*
* Accepts a stream of Points on a route being traversed, returning a
* RouteSummary when traversal is completed.
* @param array $metadata metadata
* @param array $options call options
*/
public function RecordRoute($metadata = [], $options = []) {
return $this->_clientStreamRequest('/routeguide.RouteGuide/RecordRoute',
['\Routeguide\RouteSummary','decode'],
$metadata, $options);
}
/**
* A Bidirectional streaming RPC.
*
* Accepts a stream of RouteNotes sent while a route is being traversed,
* while receiving other RouteNotes (e.g. from other users).
* @param array $metadata metadata
* @param array $options call options
*/
public function RouteChat($metadata = [], $options = []) {
return $this->_bidiRequest('/routeguide.RouteGuide/RouteChat',
['\Routeguide\RouteNote','decode'],
$metadata, $options);
}
}
}

@ -1,8 +1,10 @@
# GRPC CocoaPods podspec
# This file has been automatically generated from a template file. Please make modifications to
# `templates/gRPC-Core.podspec.template` instead. This file can be regenerated from the template by
# running `tools/buildgen/generate_projects.sh`.
# This file has been automatically generated from a template file.
# Please make modifications to `templates/gRPC-Core.podspec.template`
# instead. This file can be regenerated from the template by running
# `tools/buildgen/generate_projects.sh`.
# gRPC Core CocoaPods podspec
#
# Copyright 2015, Google Inc.
# All rights reserved.
#
@ -35,7 +37,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '1.0.2'
version = '1.2.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'http://www.grpc.io'
@ -44,9 +46,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
# TODO(mxyan): Change back to "v#{version}" for next release
#:tag => "v#{version}",
:tag => "objective-c-v#{version}",
:tag => "v#{version}",
# TODO(jcanizales): Depend explicitly on the nanopb pod, and disable submodules.
:submodules => true,
}
@ -191,7 +191,7 @@ Pod::Spec.new do |s|
ss.header_mappings_dir = '.'
ss.libraries = 'z'
ss.dependency "#{s.name}/Interface", version
ss.dependency 'BoringSSL', '~> 7.0'
ss.dependency 'BoringSSL', '~> 8.0'
# To save you from scrolling, this is the last part of the podspec.
ss.source_files = 'src/core/lib/profiling/timers.h',
@ -342,6 +342,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/lame_client.h',
'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/byte_stream.h',
'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/error_utils.h',
@ -544,6 +545,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/server.c',
'src/core/lib/surface/validate_metadata.c',
'src/core/lib/surface/version.c',
'src/core/lib/transport/bdp_estimator.c',
'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c',
'src/core/lib/transport/error_utils.c',
@ -765,6 +767,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/lame_client.h',
'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/byte_stream.h',
'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/error_utils.h',
@ -870,23 +873,31 @@ Pod::Spec.new do |s|
s.subspec 'Cronet-Implementation' do |ss|
ss.header_mappings_dir = '.'
ss.dependency "#{s.name}/Interface", version
ss.dependency "#{s.name}/Implementation", version
ss.dependency "#{s.name}/Cronet-Interface", version
ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
'src/core/ext/transport/cronet/transport/cronet_transport.c'
'src/core/ext/transport/cronet/transport/cronet_transport.c',
'third_party/objective_c/Cronet/bidirectional_stream_c.h'
end
s.subspec 'Tests' do |ss|
ss.header_mappings_dir = '.'
ss.dependency "#{s.name}/Interface", version
ss.dependency "#{s.name}/Implementation", version
ss.source_files = 'test/core/end2end/cq_verifier.{c,h}',
'test/core/end2end/end2end_tests.{c,h}',
'test/core/end2end/end2end_test_utils.c',
'test/core/end2end/tests/*.{c,h}',
'test/core/end2end/data/*.{c,h}',
'test/core/util/debugger_macros.c',
'test/core/util/test_config.{c,h}',
'test/core/util/port.h',
'test/core/util/port_posix.c',
'test/core/util/port_server_client.{c,h}'
ss.dependency 'CronetFramework'
end
end

@ -1,3 +1,9 @@
# This file has been automatically generated from a template file.
# Please make modifications to
# `templates/gRPC-ProtoRPC.podspec.template` instead. This file can be
# regenerated from the template by running
# `tools/buildgen/generate_projects.sh`.
# Copyright 2015, Google Inc.
# All rights reserved.
#
@ -30,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '1.0.2'
version = '1.2.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'http://www.grpc.io'
@ -39,7 +45,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "objective-c-v#{version}",
:tag => "v#{version}",
}
s.ios.deployment_target = '7.1'

@ -1,3 +1,9 @@
# This file has been automatically generated from a template file.
# Please make modifications to
# `templates/gRPC-RxLibrary.podspec.template` instead. This file can be
# regenerated from the template by running
# `tools/buildgen/generate_projects.sh`.
# Copyright 2015, Google Inc.
# All rights reserved.
#
@ -30,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '1.0.2'
version = '1.2.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'http://www.grpc.io'
@ -39,7 +45,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "objective-c-v#{version}",
:tag => "v#{version}",
}
s.ios.deployment_target = '7.1'

@ -1,3 +1,8 @@
# This file has been automatically generated from a template file.
# Please make modifications to `templates/gRPC.podspec.template`
# instead. This file can be regenerated from the template by running
# `tools/buildgen/generate_projects.sh`.
# Copyright 2015, Google Inc.
# All rights reserved.
#
@ -30,7 +35,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '1.0.2'
version = '1.2.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
@ -39,7 +44,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "objective-c-v#{version}",
:tag => "v#{version}",
}
s.ios.deployment_target = '7.1'

@ -259,6 +259,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/lame_client.h )
s.files += %w( src/core/lib/surface/server.h )
s.files += %w( src/core/lib/surface/validate_metadata.h )
s.files += %w( src/core/lib/transport/bdp_estimator.h )
s.files += %w( src/core/lib/transport/byte_stream.h )
s.files += %w( src/core/lib/transport/connectivity_state.h )
s.files += %w( src/core/lib/transport/error_utils.h )
@ -461,6 +462,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/server.c )
s.files += %w( src/core/lib/surface/validate_metadata.c )
s.files += %w( src/core/lib/surface/version.c )
s.files += %w( src/core/lib/transport/bdp_estimator.c )
s.files += %w( src/core/lib/transport/byte_stream.c )
s.files += %w( src/core/lib/transport/connectivity_state.c )
s.files += %w( src/core/lib/transport/error_utils.c )

@ -156,7 +156,7 @@ CENSUSAPI void census_context_destroy(census_context *context);
CENSUSAPI const census_context_status *census_context_get_status(
const census_context *context);
/* Structure used for iterating over the tegs in a context. API clients should
/* Structure used for iterating over the tags in a context. API clients should
not use or reference internal fields - neither their contents or
presence/absence are guaranteed. */
typedef struct {
@ -180,7 +180,7 @@ CENSUSAPI int census_context_next_tag(census_context_iterator *iterator,
CENSUSAPI int census_context_get_tag(const census_context *context,
const char *key, census_tag *tag);
/* Tag set encode/decode functionality. These functionas are intended
/* Tag set encode/decode functionality. These functions are intended
for use by RPC systems only, for purposes of transmitting/receiving contexts.
*/
@ -205,14 +205,14 @@ enum census_trace_mask_values {
};
/** Get the current trace mask associated with this context. The value returned
will be the logical or of census_trace_mask_values values. */
will be the logical OR of census_trace_mask_values values. */
CENSUSAPI int census_trace_mask(const census_context *context);
/** Set the trace mask associated with a context. */
CENSUSAPI void census_set_trace_mask(int trace_mask);
/* The concept of "operation" is a fundamental concept for Census. In an RPC
system, and operation typcially represents a single RPC, or a significant
system, an operation typically represents a single RPC, or a significant
sub-part thereof (e.g. a single logical "read" RPC to a distributed storage
system might do several other actions in parallel, from looking up metadata
indices to making requests of other services - each of these could be a
@ -362,7 +362,7 @@ CENSUSAPI census_context *census_start_server_rpc_op(
@param context The base context. Can be NULL.
@param family Family name to associate with the trace
@param name Name within family to associated with traces/stats
@param name Name within family to associate with traces/stats
@param trace_mask An OR of census_trace_mask_values values. Only used if
context is NULL.
@ -454,7 +454,7 @@ CENSUSAPI void census_trace_scan_end();
protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve
value on error, or a positive (>= 0) resource id (for use in
census_delete_resource() and census_record_values()). In order to be valid, a
resource must have a name, and at least one numerator in it's unit type. The
resource must have a name, and at least one numerator in its unit type. The
resource name must be unique, and an error will be returned if it is not. */
CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
size_t resource_pb_size);
@ -462,7 +462,7 @@ CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
/* Delete a resource created by census_define_resource(). */
CENSUSAPI void census_delete_resource(int32_t resource_id);
/* Determine the id of a resource, given it's name. returns -1 if the resource
/* Determine the id of a resource, given its name. returns -1 if the resource
does not exist. */
CENSUSAPI int32_t census_resource_id(const char *name);

@ -179,6 +179,15 @@ typedef struct {
Larger values give lower CPU usage for large messages, but more head of line
blocking for small messages. */
#define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size"
/** Minimum time (in milliseconds) between successive ping frames being sent */
#define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \
"grpc.http2.min_time_between_pings_ms"
/** How many pings can we send before needing to send a data frame or header
frame?
(0 indicates that an infinite number of pings can be sent without sending
a data frame or header frame) */
#define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \
"grpc.http2.max_pings_without_data"
/** How much data are we willing to queue up per stream if
GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */
#define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size"

@ -268,6 +268,7 @@
<file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/server.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/byte_stream.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.h" role="src" />
@ -470,6 +471,7 @@
<file baseinstalldir="/" name="src/core/lib/surface/server.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/validate_metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/version.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/byte_stream.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.c" role="src" />

@ -1,6 +1,6 @@
/*
*
* Copyright 2016, Google Inc.
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,51 +31,24 @@
*
*/
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.5-dev */
/* Generated by nanopb-0.3.7-dev at Fri Jan 20 16:14:22 2017. */
#include "src/core/ext/census/gen/trace_context.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t google_trace_TraceId_fields[3] = {
PB_FIELD( 1, FIXED64 , OPTIONAL, STATIC , FIRST, google_trace_TraceId, hi, hi, 0),
PB_FIELD( 2, FIXED64 , OPTIONAL, STATIC , OTHER, google_trace_TraceId, lo, hi, 0),
const pb_field_t google_trace_TraceContext_fields[5] = {
PB_FIELD( 1, FIXED64 , OPTIONAL, STATIC , FIRST, google_trace_TraceContext, trace_id_hi, trace_id_hi, 0),
PB_FIELD( 2, FIXED64 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, trace_id_lo, trace_id_hi, 0),
PB_FIELD( 3, FIXED64 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, span_id, trace_id_lo, 0),
PB_FIELD( 4, FIXED32 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, span_options, span_id, 0),
PB_LAST_FIELD
};
const pb_field_t google_trace_TraceContext_fields[4] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, google_trace_TraceContext, trace_id, trace_id, &google_trace_TraceId_fields),
PB_FIELD( 2, FIXED64 , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, span_id, trace_id, 0),
PB_FIELD( 3, BOOL , OPTIONAL, STATIC , OTHER, google_trace_TraceContext, is_sampled, span_id, 0),
PB_LAST_FIELD
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(google_trace_TraceContext, trace_id) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_trace_TraceId_google_trace_TraceContext)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(google_trace_TraceContext, trace_id) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_trace_TraceId_google_trace_TraceContext)
#endif
/* @@protoc_insertion_point(eof) */

@ -1,6 +1,6 @@
/*
*
* Copyright 2016, Google Inc.
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,11 +31,13 @@
*
*/
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.5-dev */
/* Generated by nanopb-0.3.7-dev at Fri Jan 20 16:14:22 2017. */
#ifndef GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H
#define GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H
#include "third_party/nanopb/pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
@ -45,44 +47,35 @@ extern "C" {
#endif
/* Struct definitions */
typedef struct _google_trace_TraceId {
bool has_hi;
uint64_t hi;
bool has_lo;
uint64_t lo;
} google_trace_TraceId;
typedef struct _google_trace_TraceContext {
bool has_trace_id;
google_trace_TraceId trace_id;
bool has_trace_id_hi;
uint64_t trace_id_hi;
bool has_trace_id_lo;
uint64_t trace_id_lo;
bool has_span_id;
uint64_t span_id;
bool has_is_sampled;
bool is_sampled;
bool has_span_options;
uint32_t span_options;
/* @@protoc_insertion_point(struct:google_trace_TraceContext) */
} google_trace_TraceContext;
/* Default values for struct fields */
/* Initializer values for message structs */
#define google_trace_TraceId_init_default {false, 0, false, 0}
#define google_trace_TraceContext_init_default {false, google_trace_TraceId_init_default, false, 0, false, 0}
#define google_trace_TraceId_init_zero {false, 0, false, 0}
#define google_trace_TraceContext_init_zero {false, google_trace_TraceId_init_zero, false, 0, false, 0}
#define google_trace_TraceContext_init_default {false, 0, false, 0, false, 0, false, 0}
#define google_trace_TraceContext_init_zero {false, 0, false, 0, false, 0, false, 0}
/* Field tags (for use in manual encoding/decoding) */
#define google_trace_TraceId_hi_tag 1
#define google_trace_TraceId_lo_tag 2
#define google_trace_TraceContext_trace_id_tag 1
#define google_trace_TraceContext_span_id_tag 2
#define google_trace_TraceContext_is_sampled_tag 3
#define google_trace_TraceContext_trace_id_hi_tag 1
#define google_trace_TraceContext_trace_id_lo_tag 2
#define google_trace_TraceContext_span_id_tag 3
#define google_trace_TraceContext_span_options_tag 4
/* Struct field encoding specification for nanopb */
extern const pb_field_t google_trace_TraceId_fields[3];
extern const pb_field_t google_trace_TraceContext_fields[4];
extern const pb_field_t google_trace_TraceContext_fields[5];
/* Maximum encoded size of messages (where known) */
#define google_trace_TraceId_size 18
#define google_trace_TraceContext_size 31
#define google_trace_TraceContext_size 32
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
@ -95,5 +88,6 @@ extern const pb_field_t google_trace_TraceContext_fields[4];
#ifdef __cplusplus
} /* extern "C" */
#endif
/* @@protoc_insertion_point(eof) */
#endif /* GRPC_CORE_EXT_CENSUS_GEN_TRACE_CONTEXT_PB_H */
#endif

@ -73,7 +73,7 @@ bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
}
// check fields
if (!ctxt->has_trace_id) {
if (!ctxt->has_trace_id_hi || !ctxt->has_trace_id_lo) {
gpr_log(GPR_DEBUG, "Invalid TraceContext: missing trace_id");
return false;
}

@ -38,6 +38,9 @@
#include "src/core/ext/census/gen/trace_context.pb.h"
/* Span option flags. */
#define SPAN_OPTIONS_IS_SAMPLED 0x01
/* Maximum number of bytes required to encode a TraceContext (31)
1 byte for trace_id field
1 byte for trace_id length

@ -644,6 +644,12 @@ typedef struct client_channel_call_data {
grpc_linked_mdelem lb_token_mdelem;
} call_data;
grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
grpc_call_element *call_elem) {
grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
return scc == CANCELLED_CALL ? NULL : scc;
}
static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
GPR_TIMER_BEGIN("add_waiting_locked", 0);
if (calld->waiting_ops_count == calld->waiting_ops_capacity) {

@ -57,4 +57,8 @@ void grpc_client_channel_watch_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
grpc_connectivity_state *state, grpc_closure *on_complete);
/* Debug helper: pull the subchannel call from a call stack element */
grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
grpc_call_element *elem);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CLIENT_CHANNEL_H */

@ -124,6 +124,21 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_error *error);
static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error);
static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error);
static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_error *error);
static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_ping_type ping_type,
grpc_closure *on_initiate,
grpc_closure *on_complete);
#define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
#define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
/*******************************************************************************
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
*/
@ -155,16 +170,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
grpc_combiner_destroy(exec_ctx, t->combiner);
/* callback remaining pings: they're not allowed to call into the transpot,
and maybe they hold resources that need to be freed */
while (t->pings.next != &t->pings) {
grpc_chttp2_outstanding_ping *ping = t->pings.next;
grpc_closure_sched(exec_ctx, ping->on_recv,
GRPC_ERROR_CREATE("Transport closed"));
ping->next->prev = ping->prev;
ping->prev->next = ping->next;
gpr_free(ping);
}
cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
while (t->write_cb_pool) {
grpc_chttp2_write_cb *next = t->write_cb_pool->next;
@ -172,6 +178,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
t->write_cb_pool = next;
}
gpr_free(t->ping_acks);
gpr_free(t->peer_string);
gpr_free(t);
}
@ -224,10 +231,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->is_client = is_client;
t->outgoing_window = DEFAULT_WINDOW;
t->incoming_window = DEFAULT_WINDOW;
t->stream_lookahead = DEFAULT_WINDOW;
t->connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
t->ping_counter = 1;
t->pings.next = t->pings.prev = &t->pings;
t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
t->is_first_frame = true;
grpc_connectivity_state_init(
@ -248,6 +251,22 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure_init(&t->destructive_reclaimer_locked,
destructive_reclaimer_locked, t,
grpc_combiner_scheduler(t->combiner, false));
grpc_closure_init(&t->start_bdp_ping_locked, start_bdp_ping_locked, t,
grpc_combiner_scheduler(t->combiner, false));
grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
grpc_combiner_scheduler(t->combiner, false));
grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string);
t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC);
grpc_pid_controller_init(
&t->pid_controller,
(grpc_pid_controller_args){.gain_p = 4,
.gain_i = 8,
.gain_d = 0,
.initial_control_value = log2(DEFAULT_WINDOW),
.min_control_value = -1,
.max_control_value = 22,
.integral_range = 10});
grpc_chttp2_goaway_parser_init(&t->goaway_parser);
grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser);
@ -290,6 +309,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
DEFAULT_MAX_HEADER_LIST_SIZE);
t->ping_policy = (grpc_chttp2_repeated_ping_policy){
.max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA,
.min_time_between_pings =
gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN),
};
if (channel_args) {
for (i = 0; i < channel_args->num_args; i++) {
if (0 == strcmp(channel_args->args[i].key,
@ -306,14 +331,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->next_stream_id = (uint32_t)value;
}
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
const grpc_integer_options options = {-1, 5, INT_MAX};
const int value =
grpc_channel_arg_get_integer(&channel_args->args[i], options);
if (value >= 0) {
t->stream_lookahead = (uint32_t)value;
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
const grpc_integer_options options = {-1, 0, INT_MAX};
@ -323,6 +340,19 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor,
(uint32_t)value);
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer(
&channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX});
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) {
t->ping_policy.min_time_between_pings = gpr_time_from_millis(
grpc_channel_arg_get_integer(
&channel_args->args[i],
(grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0,
INT_MAX}),
GPR_TIMESPAN);
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
@ -334,24 +364,26 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_setting_id setting_id;
grpc_integer_options integer_options;
bool availability[2] /* server, client */;
} settings_map[] = {
{GRPC_ARG_MAX_CONCURRENT_STREAMS,
GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
{-1, 0, INT_MAX},
{true, false}},
{GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
{-1, 0, INT_MAX},
{true, true}},
{GRPC_ARG_MAX_METADATA_SIZE,
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
{-1, 0, INT_MAX},
{true, true}},
{GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
{-1, 16384, 16777215},
{true, true}},
};
} settings_map[] = {{GRPC_ARG_MAX_CONCURRENT_STREAMS,
GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
{-1, 0, INT32_MAX},
{true, false}},
{GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
{-1, 0, INT32_MAX},
{true, true}},
{GRPC_ARG_MAX_METADATA_SIZE,
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
{-1, 0, INT32_MAX},
{true, true}},
{GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
{-1, 16384, 16777215},
{true, true}},
{GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
{-1, 5, INT32_MAX},
{true, true}}};
for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) {
if (0 == strcmp(channel_args->args[i].key,
settings_map[j].channel_arg_name)) {
@ -374,6 +406,9 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
}
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
grpc_chttp2_initiate_write(exec_ctx, t, false, "init");
post_benign_reclaimer(exec_ctx, t);
}
@ -425,6 +460,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:close");
}
end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error));
cancel_pings(exec_ctx, t, GRPC_ERROR_REF(error));
}
GRPC_ERROR_UNREF(error);
}
@ -475,11 +511,6 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
if (server_data) {
s->id = (uint32_t)(uintptr_t)server_data;
s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
s->incoming_window = s->max_recv_bytes =
t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
*t->accepting_stream = s;
grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
post_destructive_reclaimer(exec_ctx, t);
@ -508,6 +539,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
}
grpc_chttp2_list_remove_stalled_by_transport(t, s);
grpc_chttp2_list_remove_stalled_by_stream(t, s);
for (int i = 0; i < STREAM_LIST_COUNT; i++) {
if (s->included[i]) {
@ -647,13 +679,21 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
}
void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s, bool covered_by_poller,
const char *reason) {
void grpc_chttp2_become_writable(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
grpc_chttp2_stream_write_type stream_write_type, const char *reason) {
if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
grpc_chttp2_initiate_write(exec_ctx, t, covered_by_poller, reason);
}
switch (stream_write_type) {
case GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK:
break;
case GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED:
grpc_chttp2_initiate_write(exec_ctx, t, true, reason);
break;
case GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED:
grpc_chttp2_initiate_write(exec_ctx, t, false, reason);
break;
}
}
@ -781,7 +821,6 @@ void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx,
static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
grpc_chttp2_stream *s;
uint32_t stream_incoming_window;
/* start streams where we have free grpc_chttp2_stream ids and free
* concurrency */
while (t->next_stream_id <= MAX_CLIENT_STREAM_ID &&
@ -804,15 +843,11 @@ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
"no_more_stream_ids");
}
s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
s->incoming_window = stream_incoming_window =
t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
s->max_recv_bytes = GPR_MAX(stream_incoming_window, s->max_recv_bytes);
grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
post_destructive_reclaimer(exec_ctx, t);
grpc_chttp2_become_writable(exec_ctx, t, s, true, "new_stream");
grpc_chttp2_become_writable(exec_ctx, t, s,
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
"new_stream");
}
/* cancel out streams that will never be started */
while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@ -907,7 +942,9 @@ static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s) {
if (s->id != 0 && (!s->write_buffering ||
s->flow_controlled_buffer.length > t->write_buffer_size)) {
grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message");
grpc_chttp2_become_writable(exec_ctx, t, s,
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
"op.send_message");
}
}
@ -1069,7 +1106,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
}
} else {
GPR_ASSERT(s->id != 0);
grpc_chttp2_become_writable(exec_ctx, t, s, true,
grpc_chttp2_become_writable(exec_ctx, t, s,
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
"op.send_initial_metadata");
}
} else {
@ -1160,7 +1198,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
} else if (s->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
grpc_chttp2_become_writable(exec_ctx, t, s, true,
grpc_chttp2_become_writable(exec_ctx, t, s,
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
"op.send_trailing_metadata");
}
}
@ -1179,8 +1218,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
s->recv_message = op->recv_message;
if (s->id != 0 &&
(s->incoming_frames.head == NULL || s->incoming_frames.head->is_tail)) {
incoming_byte_stream_update_flow_control(exec_ctx, t, s,
t->stream_lookahead, 0);
incoming_byte_stream_update_flow_control(exec_ctx, t, s, 5, 0);
}
grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
}
@ -1224,43 +1262,46 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
GPR_TIMER_END("perform_stream_op", 0);
}
static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_error *error) {
/* callback remaining pings: they're not allowed to call into the transpot,
and maybe they hold resources that need to be freed */
for (size_t i = 0; i < GRPC_CHTTP2_PING_TYPE_COUNT; i++) {
grpc_chttp2_ping_queue *pq = &t->ping_queues[i];
for (size_t j = 0; j < GRPC_CHTTP2_PCL_COUNT; j++) {
grpc_closure_list_fail_all(&pq->lists[j], GRPC_ERROR_REF(error));
grpc_closure_list_sched(exec_ctx, &pq->lists[j]);
}
}
GRPC_ERROR_UNREF(error);
}
static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure *on_recv) {
grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
p->next = &t->pings;
p->prev = p->next->prev;
p->prev->next = p->next->prev = p;
p->id[0] = (uint8_t)((t->ping_counter >> 56) & 0xff);
p->id[1] = (uint8_t)((t->ping_counter >> 48) & 0xff);
p->id[2] = (uint8_t)((t->ping_counter >> 40) & 0xff);
p->id[3] = (uint8_t)((t->ping_counter >> 32) & 0xff);
p->id[4] = (uint8_t)((t->ping_counter >> 24) & 0xff);
p->id[5] = (uint8_t)((t->ping_counter >> 16) & 0xff);
p->id[6] = (uint8_t)((t->ping_counter >> 8) & 0xff);
p->id[7] = (uint8_t)(t->ping_counter & 0xff);
t->ping_counter++;
p->on_recv = on_recv;
grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_ping_create(0, p->id));
grpc_chttp2_initiate_write(exec_ctx, t, true, "send_ping");
grpc_chttp2_ping_type ping_type,
grpc_closure *on_initiate, grpc_closure *on_ack) {
grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
GRPC_ERROR_NONE);
if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
GRPC_ERROR_NONE)) {
grpc_chttp2_initiate_write(exec_ctx, t, false, "send_ping");
}
}
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
const uint8_t *opaque_8bytes) {
grpc_chttp2_outstanding_ping *ping;
for (ping = t->pings.next; ping != &t->pings; ping = ping->next) {
if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
grpc_closure_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE);
ping->next->prev = ping->prev;
ping->prev->next = ping->next;
gpr_free(ping);
return;
}
uint64_t id) {
grpc_chttp2_ping_queue *pq =
&t->ping_queues[id % GRPC_CHTTP2_PING_TYPE_COUNT];
if (pq->inflight_id != id) {
char *from = grpc_endpoint_get_peer(t->ep);
gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64, from, id);
gpr_free(from);
return;
}
grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
grpc_chttp2_initiate_write(exec_ctx, t, false, "continue_pings");
}
char *msg = gpr_dump((const char *)opaque_8bytes, 8, GPR_DUMP_HEX);
char *from = grpc_endpoint_get_peer(t->ep);
gpr_log(GPR_DEBUG, "Unknown ping response from %s: %s", from, msg);
gpr_free(from);
gpr_free(msg);
}
static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@ -1308,7 +1349,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
}
if (op->send_ping) {
send_ping_locked(exec_ctx, t, op->send_ping);
send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL,
op->send_ping);
}
if (close_transport != GRPC_ERROR_NONE) {
@ -1733,34 +1775,28 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GRPC_ERROR_UNREF(error);
}
/** update window from a settings change */
typedef struct {
grpc_chttp2_transport *t;
grpc_exec_ctx *exec_ctx;
} update_global_window_args;
/*******************************************************************************
* INPUT PROCESSING - PARSING
*/
static void update_global_window(void *args, uint32_t id, void *stream) {
update_global_window_args *a = args;
grpc_chttp2_transport *t = a->t;
grpc_chttp2_stream *s = stream;
int was_zero;
int is_zero;
int64_t initial_window_update = t->initial_window_update;
if (initial_window_update > 0) {
was_zero = s->outgoing_window <= 0;
GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", t, s, outgoing_window,
initial_window_update);
is_zero = s->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_become_writable(a->exec_ctx, t, s, true,
"update_global_window");
}
static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
double bdp_dbl) {
uint32_t bdp;
if (bdp_dbl <= 0) {
bdp = 0;
} else if (bdp_dbl > UINT32_MAX) {
bdp = UINT32_MAX;
} else {
GRPC_CHTTP2_FLOW_DEBIT_STREAM("settings", t, s, outgoing_window,
-initial_window_update);
bdp = (uint32_t)(bdp_dbl);
}
int64_t delta =
(int64_t)bdp -
(int64_t)t->settings[GRPC_LOCAL_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) {
return;
}
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp);
}
/*******************************************************************************
@ -1802,6 +1838,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
GPR_TIMER_BEGIN("reading_action_locked", 0);
grpc_chttp2_transport *t = tp;
bool need_bdp_ping = false;
GRPC_ERROR_REF(error);
@ -1819,9 +1856,14 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
GRPC_ERROR_NONE};
for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
if (grpc_bdp_estimator_add_incoming_bytes(
&t->bdp_estimator,
(int64_t)GRPC_SLICE_LENGTH(t->read_buffer.slices[i]))) {
need_bdp_ping = true;
}
errors[1] =
grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]);
};
}
if (errors[1] != GRPC_ERROR_NONE) {
errors[2] = try_http_parsing(exec_ctx, t);
GRPC_ERROR_UNREF(error);
@ -1835,21 +1877,16 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
GPR_TIMER_BEGIN("post_parse_locked", 0);
if (t->initial_window_update != 0) {
update_global_window_args args = {t, exec_ctx};
grpc_chttp2_stream_map_for_each(&t->stream_map, update_global_window,
&args);
if (t->initial_window_update > 0) {
grpc_chttp2_stream *s;
while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
grpc_chttp2_become_writable(
exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
"unstalled");
}
}
t->initial_window_update = 0;
}
/* handle higher level things */
if (t->incoming_window < t->connection_window_target * 3 / 4) {
int64_t announce_bytes = t->connection_window_target - t->incoming_window;
GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, announce_incoming_window,
announce_bytes);
GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, incoming_window,
announce_bytes);
grpc_chttp2_initiate_write(exec_ctx, t, false, "global incoming window");
}
GPR_TIMER_END("post_parse_locked", 0);
}
@ -1870,6 +1907,35 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
if (keep_reading) {
grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
&t->read_action_locked);
if (need_bdp_ping) {
GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
grpc_bdp_estimator_schedule_ping(&t->bdp_estimator);
send_ping_locked(exec_ctx, t,
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
&t->start_bdp_ping_locked, &t->finish_bdp_ping_locked);
}
int64_t estimate = -1;
if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
double target = 1 + log2((double)estimate);
double memory_pressure = grpc_resource_quota_get_memory_pressure(
grpc_resource_user_quota(grpc_endpoint_get_resource_user(t->ep)));
if (memory_pressure > 0.8) {
target *= 1 - GPR_MIN(1, (memory_pressure - 0.8) / 0.1);
}
double bdp_error = target - grpc_pid_controller_last(&t->pid_controller);
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec dt_timespec = gpr_time_sub(now, t->last_pid_update);
double dt = (double)dt_timespec.tv_sec + dt_timespec.tv_nsec * 1e-9;
if (dt > 0.1) {
dt = 0.1;
}
double log2_bdp_guess =
grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
t->last_pid_update = now;
}
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
} else {
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action");
@ -1882,6 +1948,26 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
GPR_TIMER_END("reading_action_locked", 0);
}
static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error) {
grpc_chttp2_transport *t = tp;
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string);
}
grpc_bdp_estimator_start_ping(&t->bdp_estimator);
}
static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error) {
grpc_chttp2_transport *t = tp;
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string);
}
grpc_bdp_estimator_complete_ping(&t->bdp_estimator);
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
}
/*******************************************************************************
* CALLBACK LOOP
*/
@ -1932,10 +2018,12 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
size_t max_size_hint,
size_t have_already) {
uint32_t max_recv_bytes;
uint32_t initial_window_size =
t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
/* clamp max recv hint to an allowable size */
if (max_size_hint >= UINT32_MAX - t->stream_lookahead) {
max_recv_bytes = UINT32_MAX - t->stream_lookahead;
if (max_size_hint >= UINT32_MAX - initial_window_size) {
max_recv_bytes = UINT32_MAX - initial_window_size;
} else {
max_recv_bytes = (uint32_t)max_size_hint;
}
@ -1948,20 +2036,26 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
}
/* add some small lookahead to keep pipelines flowing */
GPR_ASSERT(max_recv_bytes <= UINT32_MAX - t->stream_lookahead);
max_recv_bytes += t->stream_lookahead;
if (s->max_recv_bytes < max_recv_bytes) {
uint32_t add_max_recv_bytes = max_recv_bytes - s->max_recv_bytes;
bool new_window_write_is_covered_by_poller =
s->max_recv_bytes < have_already;
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, max_recv_bytes,
add_max_recv_bytes);
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window,
GPR_ASSERT(max_recv_bytes <= UINT32_MAX - initial_window_size);
if (s->incoming_window_delta < max_recv_bytes && !s->read_closed) {
uint32_t add_max_recv_bytes =
(uint32_t)(max_recv_bytes - s->incoming_window_delta);
grpc_chttp2_stream_write_type write_type =
GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED;
if (s->incoming_window_delta + initial_window_size <
(int64_t)have_already) {
write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
}
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window_delta,
add_max_recv_bytes);
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
add_max_recv_bytes);
grpc_chttp2_become_writable(exec_ctx, t, s,
new_window_write_is_covered_by_poller,
if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size -
(int64_t)s->announce_window >
(int64_t)initial_window_size / 2) {
write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK;
}
grpc_chttp2_become_writable(exec_ctx, t, s, write_type,
"read_incoming_stream");
}
}

@ -40,7 +40,7 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) {
grpc_slice slice = grpc_slice_malloc(9 + 8);
uint8_t *p = GRPC_SLICE_START_PTR(slice);
@ -53,7 +53,14 @@ grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes) {
*p++ = 0;
*p++ = 0;
*p++ = 0;
memcpy(p, opaque_8bytes, 8);
*p++ = (uint8_t)(opaque_8bytes >> 56);
*p++ = (uint8_t)(opaque_8bytes >> 48);
*p++ = (uint8_t)(opaque_8bytes >> 40);
*p++ = (uint8_t)(opaque_8bytes >> 32);
*p++ = (uint8_t)(opaque_8bytes >> 24);
*p++ = (uint8_t)(opaque_8bytes >> 16);
*p++ = (uint8_t)(opaque_8bytes >> 8);
*p++ = (uint8_t)(opaque_8bytes);
return slice;
}
@ -70,6 +77,7 @@ grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
}
parser->byte = 0;
parser->is_ack = flags;
parser->opaque_8bytes = 0;
return GRPC_ERROR_NONE;
}
@ -83,7 +91,7 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_ping_parser *p = parser;
while (p->byte != 8 && cur != end) {
p->opaque_8bytes[p->byte] = *cur;
p->opaque_8bytes |= (((uint64_t)*cur) << (8 * p->byte));
cur++;
p->byte++;
}
@ -93,8 +101,12 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
if (p->is_ack) {
grpc_chttp2_ack_ping(exec_ctx, t, p->opaque_8bytes);
} else {
grpc_slice_buffer_add(&t->qbuf,
grpc_chttp2_ping_create(1, p->opaque_8bytes));
if (t->ping_ack_count == t->ping_ack_capacity) {
t->ping_ack_capacity = GPR_MAX(t->ping_ack_capacity * 3 / 2, 3);
t->ping_acks = gpr_realloc(
t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks));
}
t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
grpc_chttp2_initiate_write(exec_ctx, t, false, "ping response");
}
}

@ -41,10 +41,10 @@
typedef struct {
uint8_t byte;
uint8_t is_ack;
uint8_t opaque_8bytes[8];
uint64_t opaque_8bytes;
} grpc_chttp2_ping_parser;
grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint8_t *opaque_8bytes);
grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes);
grpc_error *grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser *parser,
uint32_t length, uint8_t flags);

@ -236,7 +236,7 @@ grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p,
}
if (parser->id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
parser->incoming_settings[parser->id] != parser->value) {
t->initial_window_update =
t->initial_window_update +=
(int64_t)parser->value - parser->incoming_settings[parser->id];
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "adding %d for initial_window change",
@ -245,8 +245,9 @@ grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p,
}
parser->incoming_settings[parser->id] = parser->value;
if (grpc_http_trace) {
gpr_log(GPR_DEBUG, "CHTTP2:%s: got setting %d = %d",
t->is_client ? "CLI" : "SVR", parser->id, parser->value);
gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %d = %d",
t->is_client ? "CLI" : "SVR", t->peer_string, parser->id,
parser->value);
}
} else if (grpc_http_trace) {
gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)",

@ -110,13 +110,12 @@ grpc_error *grpc_chttp2_window_update_parser_parse(
if (t->incoming_stream_id != 0) {
if (s != NULL) {
bool was_zero = s->outgoing_window <= 0;
GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", t, s, outgoing_window,
GRPC_CHTTP2_FLOW_CREDIT_STREAM("parse", t, s, outgoing_window_delta,
received_update);
bool is_zero = s->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_become_writable(exec_ctx, t, s, false,
"stream.read_flow_control");
if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
grpc_chttp2_become_writable(
exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
"stream.read_flow_control");
}
}
} else {

@ -50,7 +50,9 @@
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/transport/bdp_estimator.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/pid_controller.h"
#include "src/core/lib/transport/transport_impl.h"
/* streams are kept in various linked lists depending on what things need to
@ -59,6 +61,7 @@ typedef enum {
GRPC_CHTTP2_LIST_WRITABLE,
GRPC_CHTTP2_LIST_WRITING,
GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT,
GRPC_CHTTP2_LIST_STALLED_BY_STREAM,
/** streams that are waiting to start because there are too many concurrent
streams on the connection */
GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY,
@ -72,6 +75,34 @@ typedef enum {
GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE_AND_COVERED_BY_POLLER,
} grpc_chttp2_write_state;
typedef enum {
GRPC_CHTTP2_PING_ON_NEXT_WRITE = 0,
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
GRPC_CHTTP2_PING_TYPE_COUNT /* must be last */
} grpc_chttp2_ping_type;
typedef enum {
GRPC_CHTTP2_PCL_INITIATE = 0,
GRPC_CHTTP2_PCL_NEXT,
GRPC_CHTTP2_PCL_INFLIGHT,
GRPC_CHTTP2_PCL_COUNT /* must be last */
} grpc_chttp2_ping_closure_list;
typedef struct {
grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT];
uint64_t inflight_id;
} grpc_chttp2_ping_queue;
typedef struct {
gpr_timespec min_time_between_pings;
int max_pings_without_data;
} grpc_chttp2_repeated_ping_policy;
typedef struct {
gpr_timespec last_ping_sent_time;
int pings_before_data_required;
} grpc_chttp2_repeated_ping_state;
/* deframer state for the overall http2 stream of bytes */
typedef enum {
/* prefix: one entry per http2 connection prefix byte */
@ -144,14 +175,6 @@ typedef enum {
GRPC_CHTTP2_GOAWAY_SENT,
} grpc_chttp2_sent_goaway_state;
/* Outstanding ping request data */
typedef struct grpc_chttp2_outstanding_ping {
uint8_t id[8];
grpc_closure *on_recv;
struct grpc_chttp2_outstanding_ping *next;
struct grpc_chttp2_outstanding_ping *prev;
} grpc_chttp2_outstanding_ping;
typedef struct grpc_chttp2_write_cb {
int64_t call_at_byte;
grpc_closure *closure;
@ -271,16 +294,19 @@ struct grpc_chttp2_transport {
copied to next_stream_id in parsing when parsing commences */
uint32_t next_stream_id;
/** how far to lookahead in a stream? */
uint32_t stream_lookahead;
/** last new stream id */
uint32_t last_new_stream_id;
/** pings awaiting responses */
grpc_chttp2_outstanding_ping pings;
/** next payload for an outgoing ping */
uint64_t ping_counter;
/** ping queues for various ping insertion points */
grpc_chttp2_ping_queue ping_queues[GRPC_CHTTP2_PING_TYPE_COUNT];
grpc_chttp2_repeated_ping_policy ping_policy;
grpc_chttp2_repeated_ping_state ping_state;
uint64_t ping_ctr; /* unique id for pings */
/** ping acks */
size_t ping_ack_count;
size_t ping_ack_capacity;
uint64_t *ping_acks;
/** parser for headers */
grpc_chttp2_hpack_parser hpack_parser;
@ -324,6 +350,13 @@ struct grpc_chttp2_transport {
grpc_chttp2_write_cb *write_cb_pool;
/* bdp estimator */
grpc_bdp_estimator bdp_estimator;
grpc_pid_controller pid_controller;
grpc_closure start_bdp_ping_locked;
grpc_closure finish_bdp_ping_locked;
gpr_timespec last_pid_update;
/* if non-NULL, close the transport with this error when writes are finished
*/
grpc_error *close_transport_on_writes_finished;
@ -362,12 +395,10 @@ struct grpc_chttp2_stream {
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
uint32_t id;
/** window available for us to send to peer */
int64_t outgoing_window;
/** The number of bytes the upper layers have offered to receive.
As the upper layer offers more bytes, this value increases.
As bytes are read, this value decreases. */
uint32_t max_recv_bytes;
/** window available for us to send to peer, over or under the initial window
* size of the transport... ie:
* outgoing_window = outgoing_window_delta + transport.initial_window_size */
int64_t outgoing_window_delta;
/** things the upper layers would like to send */
grpc_metadata_batch *send_initial_metadata;
grpc_closure *send_initial_metadata_finished;
@ -428,8 +459,10 @@ struct grpc_chttp2_stream {
grpc_error *forced_close_error;
/** how many header frames have we received? */
uint8_t header_frames_received;
/** window available for peer to send to us */
int64_t incoming_window;
/** window available for peer to send to us (as a delta on
* transport.initial_window_size)
* incoming_window = incoming_window_delta + transport.initial_window_size */
int64_t incoming_window_delta;
/** parsing state for data frames */
grpc_chttp2_data_parser data_parser;
/** number of bytes received - reset at end of parse thread execution */
@ -478,36 +511,43 @@ bool grpc_chttp2_list_add_writable_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
/** Get a writable stream
returns non-zero if there was a stream available */
int grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport *t, grpc_chttp2_stream *s) GRPC_MUST_USE_RESULT;
bool grpc_chttp2_list_add_writing_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
int grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t);
int grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t);
bool grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
void grpc_chttp2_list_add_written_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
int grpc_chttp2_list_pop_written_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_pop_written_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
void grpc_chttp2_list_add_waiting_for_concurrency(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
int grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
int grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s);
bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);
grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t,
uint32_t id);
grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx,
@ -672,13 +712,23 @@ void grpc_chttp2_incoming_byte_stream_finished(
grpc_error *error);
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
const uint8_t *opaque_8bytes);
uint64_t id);
typedef enum {
/* don't initiate a transport write, but piggyback on the next one */
GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK,
/* initiate a covered write */
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
/* initiate an uncovered write */
GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED
} grpc_chttp2_stream_write_type;
/** add a ref to the stream and add it to the writable list;
ref will be dropped in writing.c */
void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s, bool covered_by_poller,
grpc_chttp2_stream *s,
grpc_chttp2_stream_write_type type,
const char *reason);
void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,

@ -376,25 +376,45 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
return err;
}
uint32_t target_incoming_window = GPR_MAX(
t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
1024);
GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
incoming_frame_size);
if (t->incoming_window <= target_incoming_window / 2) {
grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control");
}
if (s != NULL) {
if (incoming_frame_size > s->incoming_window) {
if (incoming_frame_size >
s->incoming_window_delta +
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) {
char *msg;
gpr_asprintf(&msg,
"frame of size %d overflows incoming window of %" PRId64,
t->incoming_frame_size, s->incoming_window);
t->incoming_frame_size,
s->incoming_window_delta +
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
grpc_error *err = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return err;
}
GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window,
GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window_delta,
incoming_frame_size);
if ((int64_t)t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] +
(int64_t)s->incoming_window_delta - (int64_t)s->announce_window <=
(int64_t)t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] /
2) {
grpc_chttp2_become_writable(exec_ctx, t, s,
GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
"window-update-required");
}
s->received_bytes += incoming_frame_size;
s->max_recv_bytes -=
(uint32_t)GPR_MIN(s->max_recv_bytes, incoming_frame_size);
}
return GRPC_ERROR_NONE;

@ -37,14 +37,14 @@
/* core list management */
static int stream_list_empty(grpc_chttp2_transport *t,
grpc_chttp2_stream_list_id id) {
static bool stream_list_empty(grpc_chttp2_transport *t,
grpc_chttp2_stream_list_id id) {
return t->lists[id].head == NULL;
}
static int stream_list_pop(grpc_chttp2_transport *t,
grpc_chttp2_stream **stream,
grpc_chttp2_stream_list_id id) {
static bool stream_list_pop(grpc_chttp2_transport *t,
grpc_chttp2_stream **stream,
grpc_chttp2_stream_list_id id) {
grpc_chttp2_stream *s = t->lists[id].head;
if (s) {
grpc_chttp2_stream *new_head = s->links[id].next;
@ -124,8 +124,8 @@ bool grpc_chttp2_list_add_writable_stream(grpc_chttp2_transport *t,
return stream_list_add(t, s, GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
bool grpc_chttp2_list_pop_writable_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WRITABLE);
}
@ -139,12 +139,12 @@ bool grpc_chttp2_list_add_writing_stream(grpc_chttp2_transport *t,
return stream_list_add(t, s, GRPC_CHTTP2_LIST_WRITING);
}
int grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t) {
bool grpc_chttp2_list_have_writing_streams(grpc_chttp2_transport *t) {
return !stream_list_empty(t, GRPC_CHTTP2_LIST_WRITING);
}
int grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
bool grpc_chttp2_list_pop_writing_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WRITING);
}
@ -153,8 +153,8 @@ void grpc_chttp2_list_add_waiting_for_concurrency(grpc_chttp2_transport *t,
stream_list_add(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
}
int grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
bool grpc_chttp2_list_pop_waiting_for_concurrency(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
return stream_list_pop(t, s, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY);
}
@ -168,8 +168,8 @@ void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t,
stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
}
int grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
}
@ -177,3 +177,18 @@ void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
}
void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
}
bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) {
return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
}
bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) {
return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
}

@ -56,6 +56,75 @@ static void finish_write_cb(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->write_cb_pool = cb;
}
static void collapse_pings_from_into(grpc_chttp2_transport *t,
grpc_chttp2_ping_type ping_type,
grpc_chttp2_ping_queue *pq) {
for (size_t i = 0; i < GRPC_CHTTP2_PCL_COUNT; i++) {
grpc_closure_list_move(&t->ping_queues[ping_type].lists[i], &pq->lists[i]);
}
}
static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_ping_type ping_type) {
grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
if (grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
/* no ping needed: wait */
return;
}
if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) {
/* ping already in-flight: wait */
if (grpc_http_trace || grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "Ping delayed [%p]: already pinging", t->peer_string);
}
return;
}
if (t->ping_state.pings_before_data_required == 0 &&
t->ping_policy.max_pings_without_data != 0) {
/* need to send something of substance before sending a ping again */
if (grpc_http_trace || grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d",
t->peer_string, t->ping_state.pings_before_data_required,
t->ping_policy.max_pings_without_data);
}
return;
}
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec elapsed = gpr_time_sub(now, t->ping_state.last_ping_sent_time);
/*gpr_log(GPR_DEBUG, "elapsed:%d.%09d min:%d.%09d", (int)elapsed.tv_sec,
elapsed.tv_nsec, (int)t->ping_policy.min_time_between_pings.tv_sec,
(int)t->ping_policy.min_time_between_pings.tv_nsec);*/
if (gpr_time_cmp(elapsed, t->ping_policy.min_time_between_pings) < 0) {
/* not enough elapsed time between successive pings */
if (grpc_http_trace || grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG,
"Ping delayed [%p]: not enough time elapsed since last ping",
t->peer_string);
}
return;
}
/* coalesce equivalent pings into this one */
switch (ping_type) {
case GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE:
collapse_pings_from_into(t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, pq);
break;
case GRPC_CHTTP2_PING_ON_NEXT_WRITE:
break;
case GRPC_CHTTP2_PING_TYPE_COUNT:
GPR_UNREACHABLE_CODE(break);
}
pq->inflight_id = t->ping_ctr * GRPC_CHTTP2_PING_TYPE_COUNT + ping_type;
t->ping_ctr++;
grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INITIATE]);
grpc_closure_list_move(&pq->lists[GRPC_CHTTP2_PCL_NEXT],
&pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
grpc_slice_buffer_add(&t->outbuf,
grpc_chttp2_ping_create(false, pq->inflight_id));
t->ping_state.last_ping_sent_time = now;
t->ping_state.pings_before_data_required -=
(t->ping_state.pings_before_data_required != 0);
}
static void update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, int64_t send_bytes,
grpc_chttp2_write_cb **list, grpc_error *error) {
@ -139,6 +208,8 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
s->sent_initial_metadata = true;
sent_initial_metadata = true;
now_writing = true;
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
}
/* send any window updates */
if (s->announce_window > 0) {
@ -146,15 +217,22 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer_add(&t->outbuf,
grpc_chttp2_window_update_create(
s->id, s->announce_window, &s->stats.outgoing));
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, announce_window, announce);
}
if (sent_initial_metadata) {
/* send any body bytes, if allowed by flow control */
if (s->flow_controlled_buffer.length > 0) {
uint32_t max_outgoing =
(uint32_t)GPR_MIN(t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
GPR_MIN(s->outgoing_window, t->outgoing_window));
uint32_t stream_outgoing_window = (uint32_t)GPR_MAX(
0,
s->outgoing_window_delta +
(int64_t)t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
uint32_t max_outgoing = (uint32_t)GPR_MIN(
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
GPR_MIN(stream_outgoing_window, t->outgoing_window));
if (max_outgoing > 0) {
uint32_t send_bytes =
(uint32_t)GPR_MIN(max_outgoing, s->flow_controlled_buffer.length);
@ -167,10 +245,12 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, send_bytes,
is_last_frame, &s->stats.outgoing,
&t->outbuf);
GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, outgoing_window,
GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", t, s, outgoing_window_delta,
send_bytes);
GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", t, outgoing_window,
send_bytes);
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (is_last_frame) {
s->send_trailing_metadata = NULL;
s->sent_trailing_metadata = true;
@ -189,6 +269,9 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
} else if (t->outgoing_window == 0) {
grpc_chttp2_list_add_stalled_by_transport(t, s);
now_writing = true;
} else if (stream_outgoing_window == 0) {
grpc_chttp2_list_add_stalled_by_stream(t, s);
now_writing = true;
}
}
if (s->send_trailing_metadata != NULL &&
@ -227,15 +310,32 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
/* if the grpc_chttp2_transport is ready to send a window update, do so here
also; 3/4 is a magic number that will likely get tuned soon */
if (t->announce_incoming_window > 0) {
uint32_t announced =
(uint32_t)GPR_MIN(t->announce_incoming_window, UINT32_MAX);
GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", t, announce_incoming_window,
announced);
uint32_t target_incoming_window = GPR_MAX(
t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
1024);
uint32_t threshold_to_send_transport_window_update =
t->outbuf.count > 0 ? 3 * target_incoming_window / 4
: target_incoming_window / 2;
if (t->incoming_window <= threshold_to_send_transport_window_update) {
maybe_initiate_ping(exec_ctx, t,
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE);
uint32_t announced = (uint32_t)GPR_CLAMP(
target_incoming_window - t->incoming_window, 0, UINT32_MAX);
GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("write", t, incoming_window, announced);
grpc_transport_one_way_stats throwaway_stats;
grpc_slice_buffer_add(&t->outbuf, grpc_chttp2_window_update_create(
0, announced, &throwaway_stats));
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
}
for (size_t i = 0; i < t->ping_ack_count; i++) {
grpc_slice_buffer_add(&t->outbuf,
grpc_chttp2_ping_create(1, t->ping_acks[i]));
}
t->ping_ack_count = 0;
maybe_initiate_ping(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE);
GPR_TIMER_END("grpc_chttp2_begin_write", 0);

@ -140,7 +140,7 @@ static void con_get_channel_info(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
const grpc_channel_info *channel_info) {}
static const grpc_channel_filter connected_channel_filter = {
const grpc_channel_filter grpc_connected_filter = {
con_start_transport_stream_op,
con_start_transport_op,
sizeof(call_data),
@ -158,7 +158,7 @@ static const grpc_channel_filter connected_channel_filter = {
static void bind_transport(grpc_channel_stack *channel_stack,
grpc_channel_element *elem, void *t) {
channel_data *cd = (channel_data *)elem->channel_data;
GPR_ASSERT(elem->filter == &connected_channel_filter);
GPR_ASSERT(elem->filter == &grpc_connected_filter);
GPR_ASSERT(cd->transport == NULL);
cd->transport = t;
@ -178,7 +178,7 @@ bool grpc_add_connected_filter(grpc_exec_ctx *exec_ctx,
grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
GPR_ASSERT(t != NULL);
return grpc_channel_stack_builder_append_filter(
builder, &connected_channel_filter, bind_transport, t);
builder, &grpc_connected_filter, bind_transport, t);
}
grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) {

@ -36,8 +36,13 @@
#include "src/core/lib/channel/channel_stack_builder.h"
extern const grpc_channel_filter grpc_connected_filter;
bool grpc_add_connected_filter(grpc_exec_ctx *exec_ctx,
grpc_channel_stack_builder *builder,
void *arg_must_be_null);
/* Debug helper to dig the transport stream out of a call element */
grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem);
#endif /* GRPC_CORE_LIB_CHANNEL_CONNECTED_CHANNEL_H */

@ -51,20 +51,22 @@ void grpc_closure_list_init(grpc_closure_list *closure_list) {
closure_list->head = closure_list->tail = NULL;
}
void grpc_closure_list_append(grpc_closure_list *closure_list,
bool grpc_closure_list_append(grpc_closure_list *closure_list,
grpc_closure *closure, grpc_error *error) {
if (closure == NULL) {
GRPC_ERROR_UNREF(error);
return;
return false;
}
closure->error_data.error = error;
closure->next_data.next = NULL;
if (closure_list->head == NULL) {
bool was_empty = (closure_list->head == NULL);
if (was_empty) {
closure_list->head = closure;
} else {
closure_list->tail->next_data.next = closure;
}
closure_list->tail = closure;
return was_empty;
}
void grpc_closure_list_fail_all(grpc_closure_list *list,

@ -116,8 +116,9 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg,
void grpc_closure_list_init(grpc_closure_list *list);
/** add \a closure to the end of \a list
and set \a closure's result to \a error */
void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
and set \a closure's result to \a error
Returns true if \a list becomes non-empty */
bool grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
grpc_error *error);
/** force all success bits in \a list to false */

@ -33,6 +33,8 @@
#include "src/core/lib/iomgr/resource_quota.h"
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <grpc/support/alloc.h>
@ -44,6 +46,8 @@
int grpc_resource_quota_trace = 0;
#define MEMORY_USAGE_ESTIMATION_MAX 65536
/* Internal linked list pointers for a resource user */
typedef struct {
grpc_resource_user *next;
@ -126,9 +130,12 @@ struct grpc_resource_quota {
/* refcount */
gpr_refcount refs;
/* estimate of current memory usage
scaled to the range [0..RESOURCE_USAGE_ESTIMATION_MAX] */
gpr_atm memory_usage_estimation;
/* Master combiner lock: all activity on a quota executes under this combiner
* (so no mutex is needed for this data structure)
*/
* (so no mutex is needed for this data structure) */
grpc_combiner *combiner;
/* Size of the resource quota */
int64_t size;
@ -269,6 +276,16 @@ static void rq_step_sched(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_NONE);
}
/* update the atomically available resource estimate - use no barriers since
timeliness of delivery really doesn't matter much */
static void rq_update_estimate(grpc_resource_quota *resource_quota) {
gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation,
(gpr_atm)((1.0 -
((double)resource_quota->free_pool) /
((double)resource_quota->size)) *
MEMORY_USAGE_ESTIMATION_MAX));
}
/* returns true if all allocations are completed */
static bool rq_alloc(grpc_exec_ctx *exec_ctx,
grpc_resource_quota *resource_quota) {
@ -281,6 +298,7 @@ static bool rq_alloc(grpc_exec_ctx *exec_ctx,
int64_t amt = -resource_user->free_pool;
resource_user->free_pool = 0;
resource_quota->free_pool -= amt;
rq_update_estimate(resource_quota);
if (grpc_resource_quota_trace) {
gpr_log(GPR_DEBUG, "RQ %s %s: grant alloc %" PRId64
" bytes; rq_free_pool -> %" PRId64,
@ -315,6 +333,7 @@ static bool rq_reclaim_from_per_user_free_pool(
int64_t amt = resource_user->free_pool;
resource_user->free_pool = 0;
resource_quota->free_pool += amt;
rq_update_estimate(resource_quota);
if (grpc_resource_quota_trace) {
gpr_log(GPR_DEBUG, "RQ %s %s: reclaim_from_per_user_free_pool %" PRId64
" bytes; rq_free_pool -> %" PRId64,
@ -531,6 +550,7 @@ static void rq_resize(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
int64_t delta = a->size - a->resource_quota->size;
a->resource_quota->size += delta;
a->resource_quota->free_pool += delta;
rq_update_estimate(a->resource_quota);
rq_step_sched(exec_ctx, a->resource_quota);
grpc_resource_quota_unref_internal(exec_ctx, a->resource_quota);
gpr_free(a);
@ -557,6 +577,7 @@ grpc_resource_quota *grpc_resource_quota_create(const char *name) {
resource_quota->size = INT64_MAX;
resource_quota->step_scheduled = false;
resource_quota->reclaiming = false;
gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0);
if (name != NULL) {
resource_quota->name = gpr_strdup(name);
} else {
@ -602,6 +623,13 @@ void grpc_resource_quota_ref(grpc_resource_quota *resource_quota) {
grpc_resource_quota_ref_internal(resource_quota);
}
double grpc_resource_quota_get_memory_pressure(
grpc_resource_quota *resource_quota) {
return ((double)(gpr_atm_no_barrier_load(
&resource_quota->memory_usage_estimation))) /
((double)MEMORY_USAGE_ESTIMATION_MAX);
}
/* Public API */
void grpc_resource_quota_resize(grpc_resource_quota *resource_quota,
size_t size) {

@ -84,6 +84,12 @@ void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx,
grpc_resource_quota *grpc_resource_quota_from_channel_args(
const grpc_channel_args *channel_args);
/* Return a number indicating current memory pressure:
0.0 ==> no memory usage
1.0 ==> maximum memory usage */
double grpc_resource_quota_get_memory_pressure(
grpc_resource_quota *resource_quota);
typedef struct grpc_resource_user grpc_resource_user;
grpc_resource_user *grpc_resource_user_create(

@ -135,12 +135,10 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
/* Tries to issue one async connection, then schedules both an IOCP
notification request for the connection, and one timeout alert. */
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
grpc_endpoint **endpoint,
grpc_pollset_set *interested_parties,
const grpc_channel_args *channel_args,
const grpc_resolved_address *addr,
gpr_timespec deadline) {
static void tcp_client_connect_impl(
grpc_exec_ctx *exec_ctx, grpc_closure *on_done, grpc_endpoint **endpoint,
grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
const grpc_resolved_address *addr, gpr_timespec deadline) {
SOCKET sock = INVALID_SOCKET;
BOOL success;
int status;
@ -252,4 +250,21 @@ failure:
grpc_closure_sched(exec_ctx, on_done, final_error);
}
// overridden by api_fuzzer.c
void (*grpc_tcp_client_connect_impl)(
grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
const grpc_resolved_address *addr,
gpr_timespec deadline) = tcp_client_connect_impl;
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_endpoint **ep,
grpc_pollset_set *interested_parties,
const grpc_channel_args *channel_args,
const grpc_resolved_address *addr,
gpr_timespec deadline) {
grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties,
channel_args, addr, deadline);
}
#endif /* GRPC_WINSOCK_SOCKET */

@ -76,8 +76,10 @@ struct grpc_udp_listener {
grpc_udp_server *server;
grpc_resolved_address addr;
grpc_closure read_closure;
grpc_closure write_closure;
grpc_closure destroyed_closure;
grpc_udp_server_read_cb read_cb;
grpc_udp_server_write_cb write_cb;
grpc_udp_server_orphan_cb orphan_cb;
struct grpc_udp_listener *next;
@ -304,9 +306,33 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
gpr_mu_unlock(&sp->server->mu);
}
static void on_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_udp_listener *sp = arg;
gpr_mu_lock(&(sp->server->mu));
if (error != GRPC_ERROR_NONE) {
if (0 == --sp->server->active_ports) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(exec_ctx, sp->server);
} else {
gpr_mu_unlock(&sp->server->mu);
}
return;
}
/* Tell the registered callback that the socket is writeable. */
GPR_ASSERT(sp->write_cb);
sp->write_cb(exec_ctx, sp->emfd);
/* Re-arm the notification event so we get another chance to write. */
grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
gpr_mu_unlock(&sp->server->mu);
}
static int add_socket_to_server(grpc_udp_server *s, int fd,
const grpc_resolved_address *addr,
grpc_udp_server_read_cb read_cb,
grpc_udp_server_write_cb write_cb,
grpc_udp_server_orphan_cb orphan_cb) {
grpc_udp_listener *sp;
int port;
@ -333,6 +359,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
sp->emfd = grpc_fd_create(fd, name);
memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
sp->read_cb = read_cb;
sp->write_cb = write_cb;
sp->orphan_cb = orphan_cb;
GPR_ASSERT(sp->emfd);
gpr_mu_unlock(&s->mu);
@ -345,6 +372,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
int grpc_udp_server_add_port(grpc_udp_server *s,
const grpc_resolved_address *addr,
grpc_udp_server_read_cb read_cb,
grpc_udp_server_write_cb write_cb,
grpc_udp_server_orphan_cb orphan_cb) {
grpc_udp_listener *sp;
int allocated_port1 = -1;
@ -391,7 +419,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
// TODO(rjshade): Test and propagate the returned grpc_error*:
GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP,
&dsmode, &fd));
allocated_port1 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb);
allocated_port1 =
add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
goto done;
}
@ -413,7 +442,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
addr = &addr4_copy;
}
allocated_port2 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb);
allocated_port2 =
add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
done:
gpr_free(allocated_addr);
@ -451,6 +481,10 @@ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
grpc_schedule_on_exec_ctx);
grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
grpc_closure_init(&sp->write_closure, on_write, sp,
grpc_schedule_on_exec_ctx);
grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
s->active_ports++;
sp = sp->next;
}

@ -49,6 +49,10 @@ 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 socket is writeable. */
typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx,
grpc_fd *emfd);
/* Called when the grpc_fd is about to be orphaned (and the FD closed). */
typedef void (*grpc_udp_server_orphan_cb)(grpc_fd *emfd);
@ -75,6 +79,7 @@ int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index);
int grpc_udp_server_add_port(grpc_udp_server *s,
const grpc_resolved_address *addr,
grpc_udp_server_read_cb read_cb,
grpc_udp_server_write_cb write_cb,
grpc_udp_server_orphan_cb orphan_cb);
void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,

@ -37,6 +37,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <pthread.h>
#include <stdarg.h>
@ -93,10 +94,13 @@ void gpr_default_log(gpr_log_func_args *args) {
strcpy(time_buffer, "error:strftime");
}
fprintf(stderr, "%s%s.%09d %7tu %s:%d] %s\n",
gpr_log_severity_string(args->severity), time_buffer,
(int)(now.tv_nsec), gettid(), display_file, args->line,
args->message);
char *prefix;
gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
gpr_log_severity_string(args->severity), time_buffer,
(int)(now.tv_nsec), gettid(), display_file, args->line);
fprintf(stderr, "%-70s %s\n", prefix, args->message);
gpr_free(prefix);
}
#endif /* defined(GPR_POSIX_LOG) */

@ -56,7 +56,7 @@ void gpr_time_init(void) {
g_time_scale = 1.0 / (double)frequency.QuadPart;
}
gpr_timespec gpr_now(gpr_clock_type clock) {
static gpr_timespec now_impl(gpr_clock_type clock) {
gpr_timespec now_tv;
LONGLONG diff;
struct _timeb now_tb;
@ -84,6 +84,12 @@ gpr_timespec gpr_now(gpr_clock_type clock) {
return now_tv;
}
gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl;
gpr_timespec gpr_now(gpr_clock_type clock_type) {
return gpr_now_impl(clock_type);
}
void gpr_sleep_until(gpr_timespec until) {
gpr_timespec now;
gpr_timespec delta;

@ -63,6 +63,7 @@
#include "src/core/lib/surface/init.h"
#include "src/core/lib/surface/lame_client.h"
#include "src/core/lib/surface/server.h"
#include "src/core/lib/transport/bdp_estimator.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/transport_impl.h"
@ -192,6 +193,7 @@ void grpc_init(void) {
grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace);
grpc_register_tracer("combiner", &grpc_combiner_trace);
grpc_register_tracer("server_channel", &grpc_server_channel_trace);
grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace);
// Default pluck trace to 1
grpc_cq_pluck_trace = 1;
grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace);

@ -0,0 +1,104 @@
/*
*
* 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 "src/core/lib/transport/bdp_estimator.h"
#include <stdlib.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
int grpc_bdp_estimator_trace = 0;
void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name) {
estimator->estimate = 65536;
estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED;
estimator->name = name;
}
bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
int64_t *estimate) {
*estimate = estimator->estimate;
return true;
}
bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
int64_t num_bytes) {
estimator->accumulator += num_bytes;
switch (estimator->ping_state) {
case GRPC_BDP_PING_UNSCHEDULED:
return true;
case GRPC_BDP_PING_SCHEDULED:
return false;
case GRPC_BDP_PING_STARTED:
return false;
}
GPR_UNREACHABLE_CODE(return false);
}
void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator) {
if (grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64,
estimator->name, estimator->accumulator, estimator->estimate);
}
GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_UNSCHEDULED);
estimator->ping_state = GRPC_BDP_PING_SCHEDULED;
estimator->accumulator = 0;
}
void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator) {
if (grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64,
estimator->name, estimator->accumulator, estimator->estimate);
}
GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_SCHEDULED);
estimator->ping_state = GRPC_BDP_PING_STARTED;
estimator->accumulator = 0;
}
void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator) {
if (grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64,
estimator->name, estimator->accumulator, estimator->estimate);
}
GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_STARTED);
if (estimator->accumulator > 2 * estimator->estimate / 3) {
estimator->estimate *= 2;
if (grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64,
estimator->name, estimator->estimate);
}
}
estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED;
estimator->accumulator = 0;
}

@ -0,0 +1,76 @@
/*
*
* 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_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
#define GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H
#include <stdbool.h>
#include <stdint.h>
#define GRPC_BDP_SAMPLES 16
#define GRPC_BDP_MIN_SAMPLES_FOR_ESTIMATE 3
extern int grpc_bdp_estimator_trace;
typedef enum {
GRPC_BDP_PING_UNSCHEDULED,
GRPC_BDP_PING_SCHEDULED,
GRPC_BDP_PING_STARTED
} grpc_bdp_estimator_ping_state;
typedef struct grpc_bdp_estimator {
grpc_bdp_estimator_ping_state ping_state;
int64_t accumulator;
int64_t estimate;
const char *name;
} grpc_bdp_estimator;
void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name);
// Returns true if a reasonable estimate could be obtained
bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
int64_t *estimate);
// Returns true if the user should schedule a ping
bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
int64_t num_bytes);
// Schedule a ping: call in response to receiving a true from
// grpc_bdp_estimator_add_incoming_bytes once a ping has been scheduled by a
// transport (but not necessarily started)
void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator);
// Start a ping: call after calling grpc_bdp_estimator_schedule_ping and once
// the ping is on the wire
void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator);
// Completes a previously started ping
void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator);
#endif

@ -32,26 +32,46 @@
*/
#include "src/core/lib/transport/pid_controller.h"
#include <grpc/support/useful.h>
void grpc_pid_controller_init(grpc_pid_controller *pid_controller,
double gain_p, double gain_i, double gain_d) {
pid_controller->gain_p = gain_p;
pid_controller->gain_i = gain_i;
pid_controller->gain_d = gain_d;
grpc_pid_controller_args args) {
pid_controller->args = args;
pid_controller->last_control_value = args.initial_control_value;
grpc_pid_controller_reset(pid_controller);
}
void grpc_pid_controller_reset(grpc_pid_controller *pid_controller) {
pid_controller->last_error = 0.0;
pid_controller->last_dc_dt = 0.0;
pid_controller->error_integral = 0.0;
}
double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
double error, double dt) {
pid_controller->error_integral += error * dt;
/* integrate error using the trapezoid rule */
pid_controller->error_integral +=
dt * (pid_controller->last_error + error) * 0.5;
pid_controller->error_integral = GPR_CLAMP(
pid_controller->error_integral, -pid_controller->args.integral_range,
pid_controller->args.integral_range);
double diff_error = (error - pid_controller->last_error) / dt;
/* calculate derivative of control value vs time */
double dc_dt = pid_controller->args.gain_p * error +
pid_controller->args.gain_i * pid_controller->error_integral +
pid_controller->args.gain_d * diff_error;
/* and perform trapezoidal integration */
double new_control_value = pid_controller->last_control_value +
dt * (pid_controller->last_dc_dt + dc_dt) * 0.5;
new_control_value =
GPR_CLAMP(new_control_value, pid_controller->args.min_control_value,
pid_controller->args.max_control_value);
pid_controller->last_error = error;
return dt * (pid_controller->gain_p * error +
pid_controller->gain_i * pid_controller->error_integral +
pid_controller->gain_d * diff_error);
pid_controller->last_dc_dt = dc_dt;
pid_controller->last_control_value = new_control_value;
return new_control_value;
}
double grpc_pid_controller_last(grpc_pid_controller *pid_controller) {
return pid_controller->last_control_value;
}

@ -45,20 +45,33 @@ typedef struct {
double gain_p;
double gain_i;
double gain_d;
double initial_control_value;
double min_control_value;
double max_control_value;
double integral_range;
} grpc_pid_controller_args;
typedef struct {
double last_error;
double error_integral;
double last_control_value;
double last_dc_dt;
grpc_pid_controller_args args;
} grpc_pid_controller;
/** Initialize the controller */
void grpc_pid_controller_init(grpc_pid_controller *pid_controller,
double gain_p, double gain_i, double gain_d);
grpc_pid_controller_args args);
/** Reset the controller: useful when things have changed significantly */
void grpc_pid_controller_reset(grpc_pid_controller *pid_controller);
/** Update the controller: given a current error estimate, and the time since
the last update, returns a delta to the control value */
the last update, returns a new control value */
double grpc_pid_controller_update(grpc_pid_controller *pid_controller,
double error, double dt);
/** Returns the last control value calculated */
double grpc_pid_controller_last(grpc_pid_controller *pid_controller);
#endif /* GRPC_CORE_LIB_TRANSPORT_PID_CONTROLLER_H */

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Grpc.Core.Testing</RootNamespace>
<AssemblyName>Grpc.Core.Testing</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<DocumentationFile>bin\$(Configuration)\Grpc.Core.Testing.Xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestCalls.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Core.Testing.project.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,8 @@
{
"frameworks": {
"net45": { }
},
"runtimes": {
"win": { }
}
}

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>2b372155-80ba-4cf9-82d6-4b938e8ec3a0</ProjectGuid>
<RootNamespace>Grpc.Core.Testing</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

@ -1,3 +1,5 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
@ -27,24 +29,16 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto2";
option java_package = "ex.grpc";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
#endregion
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
using System.Reflection;
using System.Runtime.CompilerServices;
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}
[assembly: AssemblyTitle("Grpc.Core.Testing")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

@ -0,0 +1,10 @@
<StyleCopSettings Version="105">
<SourceFileList>
<SourceFile>Health.cs</SourceFile>
<Settings>
<GlobalSettings>
<BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
</GlobalSettings>
</Settings>
</SourceFileList>
</StyleCopSettings>

@ -0,0 +1,91 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Core.Testing
{
/// <summary>
/// Test doubles for client-side call objects.
/// </summary>
public static class TestCalls
{
/// <summary>
/// Creates a test double for <c>AsyncUnaryCall</c>. Only for testing.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TResponse> (
Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc,
Func<Metadata> getTrailersFunc, Action disposeAction)
{
return new AsyncUnaryCall<TResponse>(responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
}
/// <summary>
/// Creates a test double for <c>AsyncClientStreamingCall</c>. Only for testing.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(
IClientStreamWriter<TRequest> requestStream, Task<TResponse> responseAsync,
Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc,
Func<Metadata> getTrailersFunc, Action disposeAction)
{
return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
}
/// <summary>
/// Creates a test double for <c>AsyncServerStreamingCall</c>. Only for testing.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TResponse>(
IAsyncStreamReader<TResponse> responseStream, Task<Metadata> responseHeadersAsync,
Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)
{
return new AsyncServerStreamingCall<TResponse>(responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
}
/// <summary>
/// Creates a test double for <c>AsyncDuplexStreamingCall</c>. Only for testing.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TResponse, TRequest>(
IClientStreamWriter<TRequest> requestStream, IAsyncStreamReader<TResponse> responseStream,
Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc,
Func<Metadata> getTrailersFunc, Action disposeAction)
{
return new AsyncDuplexStreamingCall<TRequest, TResponse>(requestStream, responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction);
}
}
}

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -0,0 +1,39 @@
{
"version": "1.2.0-dev",
"title": "gRPC C# Core Testing",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2017, Google Inc.",
"packOptions": {
"summary": "Testing support for gRPC C#",
"description": "Useful when testing code that uses gRPC.",
"owners": [ "grpc-packages" ],
"licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
"projectUrl": "https://github.com/grpc/grpc",
"requireLicenseAcceptance": false,
"tags": [ "gRPC test testing" ]
},
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
}
},
"dependencies": {
"Grpc.Core": "1.2.0-dev"
},
"frameworks": {
"net45": {
"frameworkAssemblies": {
"System.Runtime": "",
"System.IO": ""
}
},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}

@ -49,6 +49,11 @@ using System.Runtime.CompilerServices;
"0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
"27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
"71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
[assembly: InternalsVisibleTo("Grpc.Core.Testing,PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
"0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
"27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
"71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
[assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
"0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
@ -56,5 +61,6 @@ using System.Runtime.CompilerServices;
"71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
#else
[assembly: InternalsVisibleTo("Grpc.Core.Tests")]
[assembly: InternalsVisibleTo("Grpc.Core.Testing")]
[assembly: InternalsVisibleTo("Grpc.IntegrationTesting")]
#endif

@ -40,6 +40,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection", "Grpc.Ref
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{B88F91D6-436D-4C78-8B99-47800FA8DE03}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Core.Testing", "Grpc.Core.Testing\Grpc.Core.Testing.csproj", "{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -110,6 +112,10 @@ Global
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.Build.0 = Release|Any CPU
{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AB047CA-6CF9-435D-AA61-2D86C6FA2457}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection

@ -59,6 +59,7 @@ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* pr
%DOTNET% restore . || goto :error
%DOTNET% pack --configuration Release Grpc.Core\project.json --output ..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Core.Testing\project.json --output ..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Auth\project.json --output ..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.HealthCheck\project.json --output ..\..\artifacts || goto :error
%DOTNET% pack --configuration Release Grpc.Reflection\project.json --output ..\..\artifacts || goto :error

@ -61,6 +61,7 @@ cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=macos/artifacts/
dotnet restore .
dotnet pack --configuration Release Grpc.Core/project.json --output ../../artifacts
dotnet pack --configuration Release Grpc.Core.Testing/project.json --output ../../artifacts
dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifacts
dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts
dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts

@ -1,5 +1,11 @@
# CocoaPods podspec for the gRPC Proto Compiler Plugin
# This file has been automatically generated from a template file.
# Please make modifications to
# `templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template`
# instead. This file can be regenerated from the template by running
# `tools/buildgen/generate_projects.sh`.
# CocoaPods podspec for the gRPC Proto Compiler Plugin
#
# Copyright 2016, Google Inc.
# All rights reserved.
#
@ -36,7 +42,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler-gRPCPlugin'
v = '1.0.2'
v = '1.2.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC
@ -84,10 +90,7 @@ Pod::Spec.new do |s|
repo = 'grpc/grpc'
file = "grpc_objective_c_plugin-#{v}-macos-x86_64.zip"
s.source = {
# TODO(mxyan): Change back to "https://github.com/#{repo}/releases/download/v#{v}/#{file}" for
# next release
# :http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}",
:http => "https://github.com/#{repo}/releases/download/objective-c-v#{v}/#{file}",
:http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}",
# TODO(jcanizales): Add sha1 or sha256
# :sha1 => '??',
}

@ -31,7 +31,7 @@
Pod::Spec.new do |s|
s.name = 'BoringSSL'
version = '7.0'
version = '8.0'
s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
# Adapted from the homepage:
@ -388,42 +388,42 @@ Pod::Spec.new do |s|
0x28340c19,
0x283480ac,
0x283500ea,
0x2c322910,
0x2c32a91e,
0x2c332930,
0x2c33a942,
0x2c342956,
0x2c34a968,
0x2c352983,
0x2c35a995,
0x2c3629a8,
0x2c3228ca,
0x2c32a8d8,
0x2c3328ea,
0x2c33a8fc,
0x2c342910,
0x2c34a922,
0x2c35293d,
0x2c35a94f,
0x2c362962,
0x2c36832d,
0x2c3729b5,
0x2c37a9c7,
0x2c3829da,
0x2c38a9f1,
0x2c3929ff,
0x2c39aa0f,
0x2c3a2a21,
0x2c3aaa35,
0x2c3b2a46,
0x2c3baa65,
0x2c3c2a79,
0x2c3caa8f,
0x2c3d2aa8,
0x2c3daac5,
0x2c3e2ad6,
0x2c3eaae4,
0x2c3f2afc,
0x2c3fab14,
0x2c402b21,
0x2c37296f,
0x2c37a981,
0x2c382994,
0x2c38a9ab,
0x2c3929b9,
0x2c39a9c9,
0x2c3a29db,
0x2c3aa9ef,
0x2c3b2a00,
0x2c3baa1f,
0x2c3c2a33,
0x2c3caa49,
0x2c3d2a62,
0x2c3daa7f,
0x2c3e2a90,
0x2c3eaa9e,
0x2c3f2ab6,
0x2c3faace,
0x2c402adb,
0x2c4090e7,
0x2c412b32,
0x2c41ab45,
0x2c412aec,
0x2c41aaff,
0x2c4210c0,
0x2c42ab56,
0x2c42ab10,
0x2c430720,
0x2c43aa57,
0x2c43aa11,
0x30320000,
0x30328015,
0x3033001f,
@ -639,74 +639,74 @@ Pod::Spec.new do |s|
0x405b1e9e,
0x405b9eaf,
0x405c1ec2,
0x405c9ee3,
0x405d1ef0,
0x405d9f07,
0x405e1f27,
0x405c9ed3,
0x405d1ee0,
0x405d9ef7,
0x405e1f17,
0x405e8a95,
0x405f1f48,
0x405f9f55,
0x40601f63,
0x40609f85,
0x40611fad,
0x40619fc2,
0x40621fd9,
0x40629fea,
0x40631ffb,
0x4063a010,
0x40642027,
0x4064a053,
0x4065206e,
0x4065a085,
0x4066209d,
0x4066a0c7,
0x406720f2,
0x4067a113,
0x40682126,
0x4068a147,
0x40692179,
0x4069a1a7,
0x406a21c8,
0x406aa1e8,
0x406b2370,
0x406ba393,
0x406c23a9,
0x406ca60b,
0x406d263a,
0x406da662,
0x406e2690,
0x406ea6a8,
0x406f26c7,
0x406fa6dc,
0x407026ef,
0x4070a70c,
0x405f1f38,
0x405f9f45,
0x40601f53,
0x40609f75,
0x40611f9d,
0x40619fb2,
0x40621fc9,
0x40629fda,
0x40631feb,
0x4063a000,
0x40642017,
0x4064a043,
0x4065205e,
0x4065a075,
0x4066208d,
0x4066a0b7,
0x406720e2,
0x4067a103,
0x40682116,
0x4068a137,
0x40692169,
0x4069a197,
0x406a21b8,
0x406aa1d8,
0x406b2360,
0x406ba383,
0x406c2399,
0x406ca5c5,
0x406d25f4,
0x406da61c,
0x406e264a,
0x406ea662,
0x406f2681,
0x406fa696,
0x407026a9,
0x4070a6c6,
0x40710800,
0x4071a71e,
0x40722731,
0x4072a74a,
0x40732762,
0x4071a6d8,
0x407226eb,
0x4072a704,
0x4073271c,
0x4073936d,
0x40742776,
0x4074a790,
0x407527a1,
0x4075a7b5,
0x407627c3,
0x40742730,
0x4074a74a,
0x4075275b,
0x4075a76f,
0x4076277d,
0x407691aa,
0x407727e8,
0x4077a80a,
0x40782825,
0x4078a85e,
0x40792875,
0x4079a88b,
0x407a2897,
0x407aa8aa,
0x407b28bf,
0x407ba8d1,
0x407c28e6,
0x407ca8ef,
0x407d2162,
0x407727a2,
0x4077a7c4,
0x407827df,
0x4078a818,
0x4079282f,
0x4079a845,
0x407a2851,
0x407aa864,
0x407b2879,
0x407ba88b,
0x407c28a0,
0x407ca8a9,
0x407d2152,
0x407d9c57,
0x407e283a,
0x407e27f4,
0x407e9e16,
0x407f1a67,
0x407f9887,
@ -714,45 +714,42 @@ Pod::Spec.new do |s|
0x40809a8f,
0x40811cd9,
0x40819c08,
0x4082267b,
0x40822635,
0x4082986d,
0x40831df1,
0x4083a038,
0x4083a028,
0x40841aa3,
0x40849e4e,
0x40851ed3,
0x41f4229b,
0x41f9232d,
0x41fe2220,
0x41fea3fc,
0x41ff24ed,
0x420322b4,
0x420822d6,
0x4208a312,
0x42092204,
0x4209a34c,
0x420a225b,
0x420aa23b,
0x420b227b,
0x420ba2f4,
0x420c2509,
0x420ca3c9,
0x420d23e3,
0x420da41a,
0x42122434,
0x421724d0,
0x4217a476,
0x421c2498,
0x421f2453,
0x42212520,
0x422624b3,
0x422b25ef,
0x422ba59d,
0x422c25d7,
0x422ca55c,
0x422d253b,
0x422da5bc,
0x422e2582,
0x41f4228b,
0x41f9231d,
0x41fe2210,
0x41fea3ec,
0x41ff24dd,
0x420322a4,
0x420822c6,
0x4208a302,
0x420921f4,
0x4209a33c,
0x420a224b,
0x420aa22b,
0x420b226b,
0x420ba2e4,
0x420c24f9,
0x420ca3b9,
0x420d23d3,
0x420da40a,
0x42122424,
0x421724c0,
0x4217a466,
0x421c2488,
0x421f2443,
0x42212510,
0x422624a3,
0x422b25a9,
0x422ba572,
0x422c2591,
0x422ca54c,
0x422d252b,
0x4432072b,
0x4432873a,
0x44330746,
@ -795,69 +792,69 @@ Pod::Spec.new do |s|
0x4c3d136d,
0x4c3d937c,
0x4c3e1389,
0x50322b68,
0x5032ab77,
0x50332b82,
0x5033ab92,
0x50342bab,
0x5034abc5,
0x50352bd3,
0x5035abe9,
0x50362bfb,
0x5036ac11,
0x50372c2a,
0x5037ac3d,
0x50382c55,
0x5038ac66,
0x50392c7b,
0x5039ac8f,
0x503a2caf,
0x503aacc5,
0x503b2cdd,
0x503bacef,
0x503c2d0b,
0x503cad22,
0x503d2d3b,
0x503dad51,
0x503e2d5e,
0x503ead74,
0x503f2d86,
0x50322b22,
0x5032ab31,
0x50332b3c,
0x5033ab4c,
0x50342b65,
0x5034ab7f,
0x50352b8d,
0x5035aba3,
0x50362bb5,
0x5036abcb,
0x50372be4,
0x5037abf7,
0x50382c0f,
0x5038ac20,
0x50392c35,
0x5039ac49,
0x503a2c69,
0x503aac7f,
0x503b2c97,
0x503baca9,
0x503c2cc5,
0x503cacdc,
0x503d2cf5,
0x503dad0b,
0x503e2d18,
0x503ead2e,
0x503f2d40,
0x503f8382,
0x50402d99,
0x5040ada9,
0x50412dc3,
0x5041add2,
0x50422dec,
0x5042ae09,
0x50432e19,
0x5043ae29,
0x50442e38,
0x50402d53,
0x5040ad63,
0x50412d7d,
0x5041ad8c,
0x50422da6,
0x5042adc3,
0x50432dd3,
0x5043ade3,
0x50442df2,
0x5044843f,
0x50452e4c,
0x5045ae6a,
0x50462e7d,
0x5046ae93,
0x50472ea5,
0x5047aeba,
0x50482ee0,
0x5048aeee,
0x50492f01,
0x5049af16,
0x504a2f2c,
0x504aaf3c,
0x504b2f5c,
0x504baf6f,
0x504c2f92,
0x504cafc0,
0x504d2fd2,
0x504dafef,
0x504e300a,
0x504eb026,
0x504f3038,
0x504fb04f,
0x5050305e,
0x50452e06,
0x5045ae24,
0x50462e37,
0x5046ae4d,
0x50472e5f,
0x5047ae74,
0x50482e9a,
0x5048aea8,
0x50492ebb,
0x5049aed0,
0x504a2ee6,
0x504aaef6,
0x504b2f16,
0x504baf29,
0x504c2f4c,
0x504caf7a,
0x504d2f8c,
0x504dafa9,
0x504e2fc4,
0x504eafe0,
0x504f2ff2,
0x504fb009,
0x50503018,
0x505086ef,
0x50513071,
0x5051302b,
0x58320ec9,
0x68320e8b,
0x68328c25,
@ -1292,7 +1289,6 @@ Pod::Spec.new do |s|
"NO_RENEGOTIATION\\0"
"NO_REQUIRED_DIGEST\\0"
"NO_SHARED_CIPHER\\0"
"NO_SHARED_GROUP\\0"
"NULL_SSL_CTX\\0"
"NULL_SSL_METHOD_PASSED\\0"
"OLD_SESSION_CIPHER_NOT_RETURNED\\0"
@ -1353,9 +1349,7 @@ Pod::Spec.new do |s|
"TLSV1_ALERT_USER_CANCELLED\\0"
"TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0"
"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0"
"TLSV1_CERTIFICATE_REQUIRED\\0"
"TLSV1_CERTIFICATE_UNOBTAINABLE\\0"
"TLSV1_UNKNOWN_PSK_IDENTITY\\0"
"TLSV1_UNRECOGNIZED_NAME\\0"
"TLSV1_UNSUPPORTED_EXTENSION\\0"
"TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0"

@ -159,11 +159,13 @@ static void PassFlagsToContextInfoBlock(SCNetworkReachabilityRef target,
if (strongSelf) {
if (lossHandler && !flags.reachable) {
lossHandler();
#if TARGET_OS_IPHONE
} else if (wifiStatusChangeHandler &&
strongSelf->_previousReachabilityFlags &&
(flags.isWWAN ^
strongSelf->_previousReachabilityFlags.isWWAN)) {
wifiStatusChangeHandler();
#endif
}
strongSelf->_previousReachabilityFlags = flags;
}

@ -45,13 +45,10 @@
#import "GRPCCompletionQueue.h"
#import "GRPCConnectivityMonitor.h"
#import "NSDictionary+GRPC.h"
#import "version.h"
NS_ASSUME_NONNULL_BEGIN
// TODO(jcanizales): Generate the version in a standalone header, from templates. Like
// templates/src/core/surface/version.c.template .
#define GRPC_OBJC_VERSION_STRING @"1.0.2"
static NSMutableDictionary *kHostCache;
// This connectivity monitor flushes the host cache when connectivity status

@ -0,0 +1,41 @@
/*
*
* 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.
*
*/
// This file is autogenerated from a template file. Please make
// modifications to
// `templates/src/objective-c/GRPCClient/private/version.h.template`
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
#define GRPC_OBJC_VERSION_STRING @"1.2.0-dev"

@ -206,7 +206,7 @@ static char *roots_filename;
inDomains:NSUserDomainMask] lastObject];
NSLog(@"Documents directory: %@", url);
[Cronet start];
[Cronet startNetLogToFile:@"Documents/cronet_netlog.json" logBytes:YES];
[Cronet startNetLogToFile:@"cronet_netlog.json" logBytes:YES];
}
// The tearDown() function is run after all test cases finish running

@ -49,6 +49,16 @@
</Test>
</SkippedTests>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4"
BuildableName = "CoreCronetEnd2EndTests.xctest"
BlueprintName = "CoreCronetEnd2EndTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
@ -90,15 +100,6 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63423F431B150A5F006CF63C"
BuildableName = "AllTests.xctest"
BlueprintName = "AllTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">

@ -12,24 +12,28 @@ shared C library.
* `composer`
* `phpunit` (optional)
**Ubuntu/Debian:**
**Install PHP and PECL on Ubuntu/Debian:**
```sh
$ sudo apt-get install php5 php5-dev
$ sudo apt-get install php5 php5-dev php-pear
OR
$ sudo apt-get install php7.0 php7.0-dev php-pear
```
**PEAR/PECL:**
**Install PECL on Mac:**
```sh
$ curl -O http://pear.php.net/go-pear.phar
$ sudo php -d detect_unicode=0 go-pear.phar
```
**Composer:**
**Install Composer (Linux or Mac):**
```sh
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer
```
**PHPUnit:**
**Install PHPUnit (Linux or Mac):**
```sh
$ wget https://phar.phpunit.de/phpunit-old.phar
$ chmod +x phpunit-old.phar
@ -48,6 +52,14 @@ This will compile and install the gRPC PHP extension into the standard PHP
extension directory. You should be able to run the [unit tests](#unit-tests),
with the PHP extension installed.
**Update php.ini**
Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
```sh
extension=grpc.so
```
**Add the gRPC PHP library as a Composer dependency**
@ -55,7 +67,7 @@ You need to add this to your project's `composer.json` file.
```
"require": {
"grpc/grpc": "v1.0.0"
"grpc/grpc": "v1.1.0"
}
```
@ -96,14 +108,6 @@ $ make
$ sudo make install
```
### Update php.ini
Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
```sh
extension=grpc.so
```
## Unit Tests
You will need the source code to run tests
@ -138,7 +142,7 @@ $ composer install
### Protobuf compiler
Again if you don't have it already, you need to install the protobuf compiler
`protoc`, version 3.1.0+.
`protoc`, version 3.2.0+.
If `protoc` hasn't been installed, you can download the `protoc` binaries from
[the protocol buffers Github repository](https://github.com/google/protobuf/releases).
@ -209,6 +213,7 @@ $ sudo apt-get install apache2
```
Add this line to your `php.ini` file, e.g. `/etc/php5/apache2/php.ini`
or `/etc/php/7.0/apache2/php.ini`
```sh
extension=grpc.so
@ -235,7 +240,7 @@ $ cd grpc/src/php
$ composer install
```
Make sure you have generated the client stub `math.php`
Make sure you have generated the client stubs
```sh
$ ./bin/generate_proto_php.sh
@ -247,11 +252,10 @@ Copy the `math_client.php` file into your Apache document root, e.g.
$ cp tests/generated_code/math_client.php /var/www/html
```
You may have to fix the first two lines to point the includes to your installation:
You may have to fix the first line to point the includes to your installation:
```php
include 'vendor/autoload.php';
include 'tests/generated_code/math.php';
```
Connect to `localhost/math_client.php` in your browser, or run this from command line:
@ -266,6 +270,10 @@ Install `nginx` and `php5-fpm`, in addition to `php5` above
```sh
$ sudo apt-get install nginx php5-fpm
OR
$ sudo apt-get install nginx php7.0-fpm
```
Add this line to your `php.ini` file, e.g. `/etc/php5/fpm/php.ini`
@ -305,7 +313,7 @@ $ cd grpc/src/php
$ composer install
```
Make sure you have generated the client stub `math.php`
Make sure you have generated the client stubs
```sh
$ ./bin/generate_proto_php.sh
@ -317,11 +325,10 @@ Copy the `math_client.php` file into your Nginx document root, e.g.
$ cp tests/generated_code/math_client.php /var/www/html
```
You may have to fix the first two lines to point the includes to your installation:
You may have to fix the first line to point the includes to your installation:
```php
include 'vendor/autoload.php';
include 'tests/generated_code/math.php';
```
Connect to `localhost/math_client.php` in your browser, or run this from command line:

@ -5,7 +5,7 @@
"version": "1.2.0",
"require": {
"php": ">=5.5.0",
"google/protobuf": "v3.1.0-alpha-1"
"google/protobuf": "v3.1.0"
},
"require-dev": {
"google/auth": "v0.9"
@ -13,10 +13,8 @@
"autoload": {
"psr-4": {
"Grpc\\": "lib/Grpc/",
"Grpc\\Testing\\": "tests/interop/Grpc/Testing/",
"GPBMetadata\\Src\\Proto\\Grpc\\Testing\\": "tests/interop/GPBMetadata/Src/Proto/Grpc/Testing/",
"Math\\": "tests/generated_code/Math/",
"GPBMetadata\\": "tests/generated_code/GPBMetadata/"
"": ["tests/interop/",
"tests/generated_code/"]
}
}
}

@ -32,9 +32,10 @@
*
*/
# Fix the following two lines to point to your installation
# Fix the following line to point to your installation
# This assumes that you are using protoc 3.2.0+ and the generated stubs
# were being autoloaded via composer.
include 'vendor/autoload.php';
include 'tests/generated_code/math.php';
function p($line)
{
@ -43,7 +44,7 @@ function p($line)
$host = 'localhost:50051';
p("Connecting to host: $host");
$client = new math\MathClient($host, [
$client = new Math\MathClient($host, [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
p('Client class: '.get_class($client));
@ -52,7 +53,7 @@ p('');
p('Running unary call test:');
$dividend = 7;
$divisor = 4;
$div_arg = new math\DivArgs();
$div_arg = new Math\DivArgs();
$div_arg->setDividend($dividend);
$div_arg->setDivisor($divisor);
$call = $client->Div($div_arg);
@ -65,7 +66,7 @@ p('');
p('Running server streaming test:');
$limit = 7;
$fib_arg = new math\FibArgs();
$fib_arg = new Math\FibArgs();
$fib_arg->setLimit($limit);
$call = $client->Fib($fib_arg);
$result_array = iterator_to_array($call->responses());
@ -79,7 +80,7 @@ p('');
p('Running client streaming test:');
$call = $client->Sum();
for ($i = 0; $i <= $limit; ++$i) {
$num = new math\Num();
$num = new Math\Num();
$num->setNum($i);
$call->write($num);
}
@ -91,7 +92,7 @@ p('');
p('Running bidi-streaming test:');
$call = $client->DivMany();
for ($i = 0; $i < 7; ++$i) {
$div_arg = new math\DivArgs();
$div_arg = new Math\DivArgs();
$dividend = 2 * $i + 1;
$divisor = 3;
$div_arg->setDividend($dividend);

@ -31,18 +31,14 @@ syntax = "proto3";
package google.trace;
// A TraceId uniquely represents a single Trace. It is a 128-bit nonce.
message TraceId {
fixed64 hi = 1;
fixed64 lo = 2;
}
// Tracing information that is propagated with RPC's.
message TraceContext {
// Trace identifer. Must be present.
TraceId trace_id = 1;
// ID of parent (client) span. Must be present.
fixed64 span_id = 2;
// true if this trace is sampled.
bool is_sampled = 3;
// A TraceId uniquely represents a single Trace. It is a 128-bit nonce.
// The 128-bit ID is split into 2 64-bit chunks. (REQUIRED)
fixed64 trace_id_hi = 1;
fixed64 trace_id_lo = 2;
// ID of parent (client) span. (REQUIRED)
fixed64 span_id = 3;
// Span option flags. First bit is true if this trace is sampled. (OPTIONAL)
fixed32 span_options = 4;
}

@ -205,9 +205,7 @@ def check_and_update_cythonization(extensions):
base, file_ext = os.path.splitext(source)
if file_ext == '.pyx':
generated_pyx_source = next((base + gen_ext
for gen_ext in (
'.c',
'.cpp',)
for gen_ext in ('.c', '.cpp',)
if os.path.isfile(base + gen_ext)),
None)
if generated_pyx_source:

@ -1297,47 +1297,22 @@ def server(thread_pool, handlers=None, options=None):
################################### __all__ #################################
__all__ = (
'FutureTimeoutError',
'FutureCancelledError',
'Future',
'ChannelConnectivity',
'StatusCode',
'RpcError',
'RpcContext',
'Call',
'ChannelCredentials',
'CallCredentials',
'AuthMetadataContext',
'AuthMetadataPluginCallback',
'AuthMetadataPlugin',
'ServerCredentials',
'UnaryUnaryMultiCallable',
'UnaryStreamMultiCallable',
'StreamUnaryMultiCallable',
'StreamStreamMultiCallable',
'Channel',
'ServicerContext',
'RpcMethodHandler',
'HandlerCallDetails',
'GenericRpcHandler',
'ServiceRpcHandler',
'Server',
'unary_unary_rpc_method_handler',
'unary_stream_rpc_method_handler',
'stream_unary_rpc_method_handler',
'stream_stream_rpc_method_handler',
'method_handlers_generic_handler',
'ssl_channel_credentials',
'metadata_call_credentials',
'access_token_call_credentials',
'composite_call_credentials',
'composite_channel_credentials',
'ssl_server_credentials',
'channel_ready_future',
'insecure_channel',
'secure_channel',
'server',)
__all__ = ('FutureTimeoutError', 'FutureCancelledError', 'Future',
'ChannelConnectivity', 'StatusCode', 'RpcError', 'RpcContext',
'Call', 'ChannelCredentials', 'CallCredentials',
'AuthMetadataContext', 'AuthMetadataPluginCallback',
'AuthMetadataPlugin', 'ServerCredentials', 'UnaryUnaryMultiCallable',
'UnaryStreamMultiCallable', 'StreamUnaryMultiCallable',
'StreamStreamMultiCallable', 'Channel', 'ServicerContext',
'RpcMethodHandler', 'HandlerCallDetails', 'GenericRpcHandler',
'ServiceRpcHandler', 'Server', 'unary_unary_rpc_method_handler',
'unary_stream_rpc_method_handler', 'stream_unary_rpc_method_handler',
'stream_stream_rpc_method_handler',
'method_handlers_generic_handler', 'ssl_channel_credentials',
'metadata_call_credentials', 'access_token_call_credentials',
'composite_call_credentials', 'composite_channel_credentials',
'ssl_server_credentials', 'channel_ready_future', 'insecure_channel',
'secure_channel', 'server',)
############################### Extension Shims ################################

@ -45,28 +45,24 @@ _EMPTY_FLAGS = 0
_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
_EMPTY_METADATA = cygrpc.Metadata(())
_UNARY_UNARY_INITIAL_DUE = (
cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
cygrpc.OperationType.send_close_from_client,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_message,
cygrpc.OperationType.receive_status_on_client,)
_UNARY_STREAM_INITIAL_DUE = (
cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
cygrpc.OperationType.send_close_from_client,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_status_on_client,)
_STREAM_UNARY_INITIAL_DUE = (
cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_message,
cygrpc.OperationType.receive_status_on_client,)
_STREAM_STREAM_INITIAL_DUE = (
cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_status_on_client,)
_UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
cygrpc.OperationType.send_close_from_client,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_message,
cygrpc.OperationType.receive_status_on_client,)
_UNARY_STREAM_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
cygrpc.OperationType.send_close_from_client,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_status_on_client,)
_STREAM_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_message,
cygrpc.OperationType.receive_status_on_client,)
_STREAM_STREAM_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_status_on_client,)
_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = (
'Exception calling channel subscription callback!')
@ -568,9 +564,9 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
)), event_handler)
operations = (
cygrpc.operation_send_initial_metadata(
_common.cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_request,
_EMPTY_FLAGS),
_common.cygrpc_metadata(metadata),
_EMPTY_FLAGS), cygrpc.operation_send_message(
serialized_request, _EMPTY_FLAGS),
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch(
@ -828,10 +824,7 @@ def _deliver(state, initial_connectivity, initial_callbacks):
def _spawn_delivery(state, callbacks):
delivering_thread = threading.Thread(
target=_deliver, args=(
state,
state.connectivity,
callbacks,))
target=_deliver, args=(state, state.connectivity, callbacks,))
delivering_thread.start()
state.delivering = True

@ -40,12 +40,16 @@ from grpc._cython import cygrpc
_EMPTY_METADATA = cygrpc.Metadata(())
CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
cygrpc.ConnectivityState.idle: grpc.ChannelConnectivity.IDLE,
cygrpc.ConnectivityState.connecting: grpc.ChannelConnectivity.CONNECTING,
cygrpc.ConnectivityState.ready: grpc.ChannelConnectivity.READY,
cygrpc.ConnectivityState.idle:
grpc.ChannelConnectivity.IDLE,
cygrpc.ConnectivityState.connecting:
grpc.ChannelConnectivity.CONNECTING,
cygrpc.ConnectivityState.ready:
grpc.ChannelConnectivity.READY,
cygrpc.ConnectivityState.transient_failure:
grpc.ChannelConnectivity.TRANSIENT_FAILURE,
cygrpc.ConnectivityState.shutdown: grpc.ChannelConnectivity.SHUTDOWN,
cygrpc.ConnectivityState.shutdown:
grpc.ChannelConnectivity.SHUTDOWN,
}
CYGRPC_STATUS_CODE_TO_STATUS_CODE = {

@ -37,8 +37,7 @@ from grpc._cython import cygrpc
class AuthMetadataContext(
collections.namedtuple('AuthMetadataContext', (
'service_url',
'method_name',)), grpc.AuthMetadataContext):
'service_url', 'method_name',)), grpc.AuthMetadataContext):
pass

@ -91,8 +91,7 @@ def _details(state):
class _HandlerCallDetails(
collections.namedtuple('_HandlerCallDetails', (
'method',
'invocation_metadata',)), grpc.HandlerCallDetails):
'method', 'invocation_metadata',)), grpc.HandlerCallDetails):
pass
@ -143,12 +142,11 @@ def _abort(state, call, code, details):
effective_code = _abortion_code(state, code)
effective_details = details if state.details is None else state.details
if state.initial_metadata_allowed:
operations = (
cygrpc.operation_send_initial_metadata(_EMPTY_METADATA,
_EMPTY_FLAGS),
cygrpc.operation_send_status_from_server(
_common.cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),)
operations = (cygrpc.operation_send_initial_metadata(
_EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_status_from_server(
_common.cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),)
token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN
else:
operations = (cygrpc.operation_send_status_from_server(
@ -417,11 +415,10 @@ def _send_response(rpc_event, state, serialized_response):
return False
else:
if state.initial_metadata_allowed:
operations = (
cygrpc.operation_send_initial_metadata(_EMPTY_METADATA,
_EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_response,
_EMPTY_FLAGS),)
operations = (cygrpc.operation_send_initial_metadata(
_EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_response,
_EMPTY_FLAGS),)
state.initial_metadata_allowed = False
token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN
else:
@ -559,10 +556,8 @@ def _handle_unrecognized_method(rpc_event):
_EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
b'Method not found!', _EMPTY_FLAGS),)
rpc_state = _RPCState()
rpc_event.operation_call.start_server_batch(operations,
lambda ignored_event: (
rpc_state,
(),))
rpc_event.operation_call.start_server_batch(
operations, lambda ignored_event: (rpc_state, (),))
return rpc_state

@ -44,14 +44,9 @@ _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = (
class RpcMethodHandler(
collections.namedtuple('_RpcMethodHandler', (
'request_streaming',
'response_streaming',
'request_deserializer',
'response_serializer',
'unary_unary',
'unary_stream',
'stream_unary',
'stream_stream',)), grpc.RpcMethodHandler):
'request_streaming', 'response_streaming', 'request_deserializer',
'response_serializer', 'unary_unary', 'unary_stream',
'stream_unary', 'stream_stream',)), grpc.RpcMethodHandler):
pass

@ -454,12 +454,9 @@ class _GenericStub(face.GenericStub):
metadata=None,
with_call=None,
protocol_options=None):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _blocking_unary_unary(self._channel, group, method, timeout,
with_call, protocol_options, metadata,
self._metadata_transformer, request,
@ -472,12 +469,9 @@ class _GenericStub(face.GenericStub):
timeout,
metadata=None,
protocol_options=None):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _future_unary_unary(self._channel, group, method, timeout,
protocol_options, metadata,
self._metadata_transformer, request,
@ -490,12 +484,9 @@ class _GenericStub(face.GenericStub):
timeout,
metadata=None,
protocol_options=None):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _unary_stream(self._channel, group, method, timeout,
protocol_options, metadata,
self._metadata_transformer, request,
@ -509,12 +500,9 @@ class _GenericStub(face.GenericStub):
metadata=None,
with_call=None,
protocol_options=None):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _blocking_stream_unary(
self._channel, group, method, timeout, with_call, protocol_options,
metadata, self._metadata_transformer, request_iterator,
@ -527,12 +515,9 @@ class _GenericStub(face.GenericStub):
timeout,
metadata=None,
protocol_options=None):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _future_stream_unary(
self._channel, group, method, timeout, protocol_options, metadata,
self._metadata_transformer, request_iterator, request_serializer,
@ -545,12 +530,9 @@ class _GenericStub(face.GenericStub):
timeout,
metadata=None,
protocol_options=None):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _stream_stream(self._channel, group, method, timeout,
protocol_options, metadata,
self._metadata_transformer, request_iterator,
@ -599,45 +581,33 @@ class _GenericStub(face.GenericStub):
raise NotImplementedError()
def unary_unary(self, group, method):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _UnaryUnaryMultiCallable(
self._channel, group, method, self._metadata_transformer,
request_serializer, response_deserializer)
def unary_stream(self, group, method):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _UnaryStreamMultiCallable(
self._channel, group, method, self._metadata_transformer,
request_serializer, response_deserializer)
def stream_unary(self, group, method):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _StreamUnaryMultiCallable(
self._channel, group, method, self._metadata_transformer,
request_serializer, response_deserializer)
def stream_stream(self, group, method):
request_serializer = self._request_serializers.get((
group,
method,))
response_deserializer = self._response_deserializers.get((
group,
method,))
request_serializer = self._request_serializers.get((group, method,))
response_deserializer = self._response_deserializers.get((group,
method,))
return _StreamStreamMultiCallable(
self._channel, group, method, self._metadata_transformer,
request_serializer, response_deserializer)

@ -85,9 +85,7 @@ class ConnectivityChannel(object):
def _spawn_delivery(self, connectivity, callbacks):
delivering_thread = threading.Thread(
target=self._deliver, args=(
connectivity,
callbacks,))
target=self._deliver, args=(connectivity, callbacks,))
delivering_thread.start()
self._delivering = True

@ -256,14 +256,9 @@ def _adapt_stream_stream_event(stream_stream_event):
class _SimpleMethodHandler(
collections.namedtuple('_MethodHandler', (
'request_streaming',
'response_streaming',
'request_deserializer',
'response_serializer',
'unary_unary',
'unary_stream',
'stream_unary',
'stream_stream',)), grpc.RpcMethodHandler):
'request_streaming', 'response_streaming', 'request_deserializer',
'response_serializer', 'unary_unary', 'unary_stream',
'stream_unary', 'stream_stream',)), grpc.RpcMethodHandler):
pass

@ -34,19 +34,14 @@ from grpc.framework.interfaces.base import base
class _Completion(base.Completion,
collections.namedtuple('_Completion', (
'terminal_metadata',
'code',
'message',))):
collections.namedtuple('_Completion', ('terminal_metadata',
'code', 'message',))):
"""A trivial implementation of base.Completion."""
class _Subscription(base.Subscription,
collections.namedtuple('_Subscription', (
'kind',
'termination_callback',
'allowance',
'operator',
'kind', 'termination_callback', 'allowance', 'operator',
'protocol_receiver',))):
"""A trivial implementation of base.Subscription."""

@ -63,18 +63,13 @@ class NoSuchMethodError(Exception):
self.method = method
def __repr__(self):
return 'face.NoSuchMethodError(%s, %s)' % (
self.group,
self.method,)
return 'face.NoSuchMethodError(%s, %s)' % (self.group, self.method,)
class Abortion(
collections.namedtuple('Abortion', (
'kind',
'initial_metadata',
'terminal_metadata',
'code',
'details',))):
collections.namedtuple('Abortion',
('kind', 'initial_metadata', 'terminal_metadata',
'code', 'details',))):
"""A value describing RPC abortion.
Attributes:

@ -180,6 +180,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/surface/server.c',
'src/core/lib/surface/validate_metadata.c',
'src/core/lib/surface/version.c',
'src/core/lib/transport/bdp_estimator.c',
'src/core/lib/transport/byte_stream.c',
'src/core/lib/transport/connectivity_state.c',
'src/core/lib/transport/error_utils.c',

@ -53,7 +53,9 @@ Could not find <Python.h>. This could mean the following:
(check your environment variables or try re-installing?)
"""
C_CHECKS = {C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE,}
C_CHECKS = {
C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE,
}
def _compile(compiler, source_string):

@ -40,14 +40,15 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)))
import health_commands
import grpc_version
PACKAGE_DIRECTORIES = {'': '.',}
PACKAGE_DIRECTORIES = {
'': '.',
}
SETUP_REQUIRES = (
'grpcio-tools>={version}'.format(version=grpc_version.VERSION),)
INSTALL_REQUIRES = (
'protobuf>=3.0.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),)
INSTALL_REQUIRES = ('protobuf>=3.0.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),)
COMMAND_CLASS = {
# Run preprocess from the repository *before* doing any packaging!

@ -40,14 +40,15 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)))
import reflection_commands
import grpc_version
PACKAGE_DIRECTORIES = {'': '.',}
PACKAGE_DIRECTORIES = {
'': '.',
}
SETUP_REQUIRES = (
'grpcio-tools>={version}'.format(version=grpc_version.VERSION),)
INSTALL_REQUIRES = (
'protobuf>=3.0.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),)
INSTALL_REQUIRES = ('protobuf>=3.0.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),)
COMMAND_CLASS = {
# Run preprocess from the repository *before* doing any packaging!

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

Loading…
Cancel
Save