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

pull/12191/head
Nicolas "Pixel" Noble 8 years ago
commit 90df76b463
  1. 9
      BUILD
  2. 26
      CMakeLists.txt
  3. 6
      INSTALL.md
  4. 31
      Makefile
  5. 10
      build.yaml
  6. 4
      doc/compression.md
  7. 2
      doc/g_stands_for.md
  8. 2
      doc/workarounds.md
  9. 12
      gRPC-Core.podspec
  10. 2
      gRPC-ProtoRPC.podspec
  11. 2
      gRPC-RxLibrary.podspec
  12. 25
      gRPC.podspec
  13. 3
      grpc.def
  14. 8
      grpc.gemspec
  15. 2479
      grpc.gyp
  16. 17
      include/grpc++/impl/codegen/call.h
  17. 30
      include/grpc/compression.h
  18. 68
      include/grpc/impl/codegen/compression_types.h
  19. 4
      include/grpc/impl/codegen/grpc_types.h
  20. 4
      include/grpc/impl/codegen/sync.h
  21. 36
      include/grpc/impl/codegen/sync_custom.h
  22. 8
      include/grpc/support/sync_custom.h
  23. 2
      package.json
  24. 22
      package.xml
  25. 1
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
  26. 27
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
  27. 121
      src/core/ext/filters/http/message_compress/message_compress_filter.c
  28. 12
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  29. 4
      src/core/ext/transport/chttp2/transport/flow_control.c
  30. 24
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  31. 98
      src/core/lib/channel/channel_args.c
  32. 31
      src/core/lib/channel/channel_args.h
  33. 14
      src/core/lib/compression/algorithm_metadata.h
  34. 100
      src/core/lib/compression/compression.c
  35. 281
      src/core/lib/iomgr/ev_epoll1_linux.c
  36. 2
      src/core/lib/iomgr/ev_epollex_linux.c
  37. 26
      src/core/lib/profiling/timers.h
  38. 17
      src/core/lib/security/credentials/jwt/jwt_verifier.c
  39. 8
      src/core/lib/security/credentials/oauth2/oauth2_credentials.c
  40. 22
      src/core/lib/support/block_annotate.h
  41. 300
      src/core/lib/surface/call.c
  42. 12
      src/core/lib/surface/call_test_only.h
  43. 29
      src/core/lib/surface/channel.c
  44. 2
      src/core/lib/surface/completion_queue.c
  45. 2
      src/core/lib/surface/version.c
  46. 816
      src/core/lib/transport/static_metadata.c
  47. 296
      src/core/lib/transport/static_metadata.h
  48. 2
      src/cpp/common/channel_filter.cc
  49. 2
      src/cpp/common/channel_filter.h
  50. 2
      src/cpp/common/version_cc.cc
  51. 2
      src/csharp/Grpc.Core.Tests/NUnitMain.cs
  52. 8
      src/csharp/Grpc.Core/Grpc.Core.targets
  53. 2
      src/csharp/Grpc.Core/GrpcEnvironment.cs
  54. 2
      src/csharp/Grpc.Core/Internal/AtomicCounter.cs
  55. 37
      src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
  56. 6
      src/csharp/Grpc.Core/Logging/LogLevel.cs
  57. 43
      src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs
  58. 2
      src/csharp/Grpc.Core/Version.csproj.include
  59. 4
      src/csharp/Grpc.Core/VersionInfo.cs
  60. 2
      src/csharp/Grpc.Examples.Tests/NUnitMain.cs
  61. 2
      src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs
  62. 2
      src/csharp/Grpc.IntegrationTesting/NUnitMain.cs
  63. 2
      src/csharp/Grpc.Microbenchmarks/Program.cs
  64. 2
      src/csharp/Grpc.Reflection.Tests/NUnitMain.cs
  65. 2
      src/csharp/build_packages_dotnetcli.bat
  66. 4
      src/csharp/build_packages_dotnetcli.sh
  67. 4
      src/node/health_check/package.json
  68. 2
      src/node/tools/package.json
  69. 2
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  70. 29
      src/objective-c/GRPCClient/GRPCCall+GID.h
  71. 14
      src/objective-c/GRPCClient/GRPCCall+GID.m
  72. 15
      src/objective-c/GRPCClient/GRPCCall+OAuth2.h
  73. 11
      src/objective-c/GRPCClient/GRPCCall+OAuth2.m
  74. 73
      src/objective-c/GRPCClient/GRPCCall.m
  75. 1
      src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
  76. 2
      src/objective-c/GRPCClient/private/GRPCWrappedCall.m
  77. 2
      src/objective-c/GRPCClient/private/version.h
  78. 38
      src/objective-c/RxLibrary/GRXConcurrentWriteable.m
  79. 6
      src/objective-c/tests/build_one_example.sh
  80. 22
      src/objective-c/tests/run_tests.sh
  81. 2
      src/php/composer.json
  82. 2
      src/php/ext/grpc/call_credentials.c
  83. 40
      src/php/ext/grpc/channel.c
  84. 8
      src/php/ext/grpc/channel_credentials.c
  85. 42
      src/php/ext/grpc/php_grpc.c
  86. 6
      src/php/ext/grpc/php_grpc.h
  87. 2
      src/php/ext/grpc/version.h
  88. 28
      src/php/lib/Grpc/ServerStreamingCall.php
  89. 28
      src/php/lib/Grpc/UnaryCall.php
  90. 15
      src/php/tests/unit_tests/ChannelTest.php
  91. 2
      src/python/grpcio/grpc/_grpcio_metadata.py
  92. 2
      src/python/grpcio/grpc_version.py
  93. 2
      src/python/grpcio_health_checking/grpc_version.py
  94. 2
      src/python/grpcio_reflection/grpc_version.py
  95. 2
      src/python/grpcio_tests/grpc_version.py
  96. 3
      src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
  97. 3
      src/ruby/ext/grpc/rb_call.c
  98. 6
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  99. 9
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  100. 6
      src/ruby/lib/grpc/generic/rpc_desc.rb
  101. Some files were not shown because too many files have changed in this diff Show More

@ -34,11 +34,11 @@ load(
)
# This should be updated along with build.yaml
g_stands_for = "gregarious"
g_stands_for = "gambit"
core_version = "4.0.0-dev"
version = "1.5.0-dev"
version = "1.7.0-dev"
GPR_PUBLIC_HDRS = [
"include/grpc/support/alloc.h",
@ -57,6 +57,7 @@ GPR_PUBLIC_HDRS = [
"include/grpc/support/string_util.h",
"include/grpc/support/subprocess.h",
"include/grpc/support/sync.h",
"include/grpc/support/sync_custom.h",
"include/grpc/support/sync_generic.h",
"include/grpc/support/sync_posix.h",
"include/grpc/support/sync_windows.h",
@ -523,7 +524,6 @@ grpc_cc_library(
"src/core/lib/support/stack_lockfree.h",
"src/core/lib/support/string.h",
"src/core/lib/support/string_windows.h",
"src/core/lib/support/thd_internal.h",
"src/core/lib/support/time_precise.h",
"src/core/lib/support/tmpfile.h",
],
@ -546,6 +546,7 @@ grpc_cc_library(
"include/grpc/impl/codegen/gpr_types.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_custom.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_windows.h",
@ -593,9 +594,9 @@ grpc_cc_library(
"src/core/lib/iomgr/ev_windows.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/executor.c",
"src/core/lib/iomgr/gethostname_fallback.c",
"src/core/lib/iomgr/gethostname_host_name_max.c",
"src/core/lib/iomgr/gethostname_sysconf.c",
"src/core/lib/iomgr/gethostname_fallback.c",
"src/core/lib/iomgr/iocp_windows.c",
"src/core/lib/iomgr/iomgr.c",
"src/core/lib/iomgr/iomgr_posix.c",

@ -24,7 +24,7 @@
cmake_minimum_required(VERSION 2.8)
set(PACKAGE_NAME "grpc")
set(PACKAGE_VERSION "1.5.0-dev")
set(PACKAGE_VERSION "1.7.0-dev")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@ -91,6 +91,8 @@ if (MSVC)
add_definitions(/wd4065 /wd4506)
# TODO(jtattermusch): revisit C4267 occurrences throughout the code
add_definitions(/wd4267)
# TODO(jtattermusch): needed to build boringssl with VS2017, revisit later
add_definitions(/wd4987 /wd4774 /wd4819 /wd4996 /wd4619)
endif()
if (gRPC_USE_PROTO_LITE)
@ -867,6 +869,7 @@ foreach(_hdr
include/grpc/support/string_util.h
include/grpc/support/subprocess.h
include/grpc/support/sync.h
include/grpc/support/sync_custom.h
include/grpc/support/sync_generic.h
include/grpc/support/sync_posix.h
include/grpc/support/sync_windows.h
@ -885,6 +888,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -1260,6 +1264,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -1566,6 +1571,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -1842,6 +1848,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -2102,6 +2109,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -2397,6 +2405,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -2661,6 +2670,7 @@ foreach(_hdr
include/grpc/support/string_util.h
include/grpc/support/subprocess.h
include/grpc/support/sync.h
include/grpc/support/sync_custom.h
include/grpc/support/sync_generic.h
include/grpc/support/sync_posix.h
include/grpc/support/sync_windows.h
@ -2679,6 +2689,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -3092,6 +3103,7 @@ foreach(_hdr
include/grpc/support/string_util.h
include/grpc/support/subprocess.h
include/grpc/support/sync.h
include/grpc/support/sync_custom.h
include/grpc/support/sync_generic.h
include/grpc/support/sync_posix.h
include/grpc/support/sync_windows.h
@ -3110,6 +3122,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -3547,6 +3560,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -3686,6 +3700,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -3839,6 +3854,7 @@ foreach(_hdr
include/grpc/support/string_util.h
include/grpc/support/subprocess.h
include/grpc/support/sync.h
include/grpc/support/sync_custom.h
include/grpc/support/sync_generic.h
include/grpc/support/sync_posix.h
include/grpc/support/sync_windows.h
@ -3857,6 +3873,7 @@ foreach(_hdr
include/grpc/impl/codegen/gpr_types.h
include/grpc/impl/codegen/port_platform.h
include/grpc/impl/codegen/sync.h
include/grpc/impl/codegen/sync_custom.h
include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h
@ -4851,6 +4868,9 @@ add_library(end2end_tests
test/core/end2end/tests/simple_delayed_request.c
test/core/end2end/tests/simple_metadata.c
test/core/end2end/tests/simple_request.c
test/core/end2end/tests/stream_compression_compressed_payload.c
test/core/end2end/tests/stream_compression_payload.c
test/core/end2end/tests/stream_compression_ping_pong_streaming.c
test/core/end2end/tests/streaming_error_response.c
test/core/end2end/tests/trailing_metadata.c
test/core/end2end/tests/workaround_cronet_compression.c
@ -4951,6 +4971,9 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/simple_delayed_request.c
test/core/end2end/tests/simple_metadata.c
test/core/end2end/tests/simple_request.c
test/core/end2end/tests/stream_compression_compressed_payload.c
test/core/end2end/tests/stream_compression_payload.c
test/core/end2end/tests/stream_compression_ping_pong_streaming.c
test/core/end2end/tests/streaming_error_response.c
test/core/end2end/tests/trailing_metadata.c
test/core/end2end/tests/workaround_cronet_compression.c
@ -9903,6 +9926,7 @@ target_link_libraries(bm_fullstack_trickle
grpc_unsecure
gpr_test_util
gpr
grpc++_test_config
${_gRPC_GFLAGS_LIBRARIES}
)

@ -141,8 +141,6 @@ MINGW64$ make
NOTE: While most of the make targets are buildable under Mingw, some haven't been ported to Windows yet
and may fail to build (mostly trying to include POSIX headers not available on Mingw).
### Pre-generated Visual Studio solution (DEPRECATED)
### Pre-generated Visual Studio solution (DELETED)
*WARNING: This used to be the recommended way to build on Windows, but because of significant limitations (hard to build dependencies including boringssl, .proto codegen is hard to support, ..), it is no longer recommended. Use cmake to build on Windows instead.*
The pre-generated VS projects & solution are checked into the repository under the [vsprojects](/vsprojects) directory.
*WARNING: This used to be the recommended way to build on Windows, but because of significant limitations (hard to build dependencies including boringssl, .proto codegen is hard to support, ..) we are no longer providing them. Use cmake to build on Windows instead.*

@ -411,8 +411,8 @@ Q = @
endif
CORE_VERSION = 4.0.0-dev
CPP_VERSION = 1.5.0-dev
CSHARP_VERSION = 1.5.0-dev
CPP_VERSION = 1.7.0-dev
CSHARP_VERSION = 1.7.0-dev
CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@ -2809,6 +2809,7 @@ PUBLIC_HEADERS_C += \
include/grpc/support/string_util.h \
include/grpc/support/subprocess.h \
include/grpc/support/sync.h \
include/grpc/support/sync_custom.h \
include/grpc/support/sync_generic.h \
include/grpc/support/sync_posix.h \
include/grpc/support/sync_windows.h \
@ -2827,6 +2828,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -3170,6 +3172,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -3474,6 +3477,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -3749,6 +3753,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -3998,6 +4003,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -4268,6 +4274,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -4505,6 +4512,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/support/string_util.h \
include/grpc/support/subprocess.h \
include/grpc/support/sync.h \
include/grpc/support/sync_custom.h \
include/grpc/support/sync_generic.h \
include/grpc/support/sync_posix.h \
include/grpc/support/sync_windows.h \
@ -4523,6 +4531,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -4943,6 +4952,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/support/string_util.h \
include/grpc/support/subprocess.h \
include/grpc/support/sync.h \
include/grpc/support/sync_custom.h \
include/grpc/support/sync_generic.h \
include/grpc/support/sync_posix.h \
include/grpc/support/sync_windows.h \
@ -4961,6 +4971,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -5381,6 +5392,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -5495,6 +5507,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -5651,6 +5664,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/support/string_util.h \
include/grpc/support/subprocess.h \
include/grpc/support/sync.h \
include/grpc/support/sync_custom.h \
include/grpc/support/sync_generic.h \
include/grpc/support/sync_posix.h \
include/grpc/support/sync_windows.h \
@ -5669,6 +5683,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/gpr_types.h \
include/grpc/impl/codegen/port_platform.h \
include/grpc/impl/codegen/sync.h \
include/grpc/impl/codegen/sync_custom.h \
include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \
@ -8418,6 +8433,9 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/simple_delayed_request.c \
test/core/end2end/tests/simple_metadata.c \
test/core/end2end/tests/simple_request.c \
test/core/end2end/tests/stream_compression_compressed_payload.c \
test/core/end2end/tests/stream_compression_payload.c \
test/core/end2end/tests/stream_compression_ping_pong_streaming.c \
test/core/end2end/tests/streaming_error_response.c \
test/core/end2end/tests/trailing_metadata.c \
test/core/end2end/tests/workaround_cronet_compression.c \
@ -8513,6 +8531,9 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/simple_delayed_request.c \
test/core/end2end/tests/simple_metadata.c \
test/core/end2end/tests/simple_request.c \
test/core/end2end/tests/stream_compression_compressed_payload.c \
test/core/end2end/tests/stream_compression_payload.c \
test/core/end2end/tests/stream_compression_ping_pong_streaming.c \
test/core/end2end/tests/streaming_error_response.c \
test/core/end2end/tests/trailing_metadata.c \
test/core/end2end/tests/workaround_cronet_compression.c \
@ -13969,17 +13990,17 @@ $(BINDIR)/$(CONFIG)/bm_fullstack_trickle: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_fullstack_trickle: $(PROTOBUF_DEP) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(BINDIR)/$(CONFIG)/bm_fullstack_trickle: $(PROTOBUF_DEP) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_trickle
$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_TRICKLE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_trickle
endif
endif
$(BM_FULLSTACK_TRICKLE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_trickle.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_trickle.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_bm_fullstack_trickle: $(BM_FULLSTACK_TRICKLE_OBJS:.o=.dep)

@ -13,8 +13,8 @@ settings:
'#09': Per-language overrides are possible with (eg) ruby_version tag here
'#10': See the expand_version.py for all the quirks here
core_version: 4.0.0-dev
g_stands_for: gregarious
version: 1.5.0-dev
g_stands_for: gambit
version: 1.7.0-dev
filegroups:
- name: census
public_headers:
@ -126,6 +126,7 @@ filegroups:
- include/grpc/support/string_util.h
- include/grpc/support/subprocess.h
- include/grpc/support/sync.h
- include/grpc/support/sync_custom.h
- include/grpc/support/sync_generic.h
- include/grpc/support/sync_posix.h
- include/grpc/support/sync_windows.h
@ -152,7 +153,6 @@ filegroups:
- src/core/lib/support/stack_lockfree.h
- src/core/lib/support/string.h
- src/core/lib/support/string_windows.h
- src/core/lib/support/thd_internal.h
- src/core/lib/support/time_precise.h
- src/core/lib/support/tmpfile.h
uses:
@ -167,6 +167,7 @@ filegroups:
- include/grpc/impl/codegen/gpr_types.h
- include/grpc/impl/codegen/port_platform.h
- include/grpc/impl/codegen/sync.h
- include/grpc/impl/codegen/sync_custom.h
- include/grpc/impl/codegen/sync_generic.h
- include/grpc/impl/codegen/sync_posix.h
- include/grpc/impl/codegen/sync_windows.h
@ -911,7 +912,7 @@ filegroups:
- third_party/nanopb/pb_common.c
- third_party/nanopb/pb_decode.c
- third_party/nanopb/pb_encode.c
filegroups:
uses:
- nanopb_headers
- name: nanopb_headers
headers:
@ -3619,6 +3620,7 @@ targets:
- grpc_unsecure
- gpr_test_util
- gpr
- grpc++_test_config
args:
- --benchmark_min_time=0
defaults: benchmark

@ -52,8 +52,8 @@ by the client WILL result in an `INTERNAL` error status on the client side.
Note that a peer MAY choose to not disclose all the encodings it supports.
However, if it receives a message compressed in an undisclosed but supported
encoding, it MUST include said encoding in the response's `grpc-accept-encoding
h`eader.
encoding, it MUST include said encoding in the response's `grpc-accept-encoding`
header.
For every message a server is requested to compress using an algorithm it knows
the client doesn't support (as indicated by the last `grpc-accept-encoding`

@ -9,3 +9,5 @@ future), and the corresponding version numbers that used them:
- 1.2 'g' stands for 'green'
- 1.3 'g' stands for 'gentle'
- 1.4 'g' stands for 'gregarious'
- 1.6 'g' stands for 'garcia'
- 1.7 'g' stands for 'gambit'

@ -1,4 +1,4 @@
# gRPC Server Backward Compatibility Issues and Workarounds Manageent
# gRPC Server Backward Compatibility Issues and Workarounds Management
## Introduction
This document lists the workarounds implemented on gRPC servers for record and reference when users need to enable a certain workaround.

@ -22,7 +22,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '1.5.0-dev'
version = '1.7.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'https://grpc.io'
@ -118,6 +118,7 @@ Pod::Spec.new do |s|
'include/grpc/support/string_util.h',
'include/grpc/support/subprocess.h',
'include/grpc/support/sync.h',
'include/grpc/support/sync_custom.h',
'include/grpc/support/sync_generic.h',
'include/grpc/support/sync_posix.h',
'include/grpc/support/sync_windows.h',
@ -136,6 +137,7 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/gpr_types.h',
'include/grpc/impl/codegen/port_platform.h',
'include/grpc/impl/codegen/sync.h',
'include/grpc/impl/codegen/sync_custom.h',
'include/grpc/impl/codegen/sync_generic.h',
'include/grpc/impl/codegen/sync_posix.h',
'include/grpc/impl/codegen/sync_windows.h',
@ -155,6 +157,7 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/gpr_types.h',
'include/grpc/impl/codegen/port_platform.h',
'include/grpc/impl/codegen/sync.h',
'include/grpc/impl/codegen/sync_custom.h',
'include/grpc/impl/codegen/sync_generic.h',
'include/grpc/impl/codegen/sync_posix.h',
'include/grpc/impl/codegen/sync_windows.h',
@ -195,7 +198,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/stack_lockfree.h',
'src/core/lib/support/string.h',
'src/core/lib/support/string_windows.h',
'src/core/lib/support/thd_internal.h',
'src/core/lib/support/time_precise.h',
'src/core/lib/support/tmpfile.h',
'src/core/lib/profiling/basic_timers.c',
@ -735,7 +737,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/stack_lockfree.h',
'src/core/lib/support/string.h',
'src/core/lib/support/string_windows.h',
'src/core/lib/support/thd_internal.h',
'src/core/lib/support/time_precise.h',
'src/core/lib/support/tmpfile.h',
'src/core/ext/transport/chttp2/transport/bin_decoder.h',
@ -994,4 +995,9 @@ Pod::Spec.new do |s|
'test/core/util/port.c',
'test/core/util/port_server_client.{c,h}'
end
# TODO (mxyan): Instead of this hack, add include path "third_party" to C core's include path?
s.prepare_command = <<-END_OF_COMMAND
find src/core/ -type f -exec sed -E -i '.back' 's;#include "third_party/nanopb/(.*)";#include <nanopb/\\1>;g' {} \\\;
END_OF_COMMAND
end

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '1.5.0-dev'
version = '1.7.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '1.5.0-dev'
version = '1.7.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'https://grpc.io'

@ -20,7 +20,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '1.5.0-dev'
version = '1.7.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'https://grpc.io'
@ -40,12 +40,9 @@ Pod::Spec.new do |s|
s.header_dir = name
src_dir = 'src/objective-c/GRPCClient'
s.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}"
s.private_header_files = "#{src_dir}/private/*.h"
s.header_mappings_dir = "#{src_dir}"
s.dependency 'gRPC-Core', version
s.dependency 'gRPC-RxLibrary', version
s.default_subspec = 'Main'
# Certificates, to be able to establish TLS connections:
s.resource_bundles = { 'gRPCCertificates' => ['etc/roots.pem'] }
@ -54,4 +51,22 @@ Pod::Spec.new do |s|
# This is needed by all pods that depend on gRPC-RxLibrary:
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
}
s.subspec 'Main' do |ss|
ss.header_mappings_dir = "#{src_dir}"
ss.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}"
ss.exclude_files = "#{src_dir}/GRPCCall+GID.{h,m}"
ss.private_header_files = "#{src_dir}/private/*.h"
ss.dependency 'gRPC-Core', version
end
s.subspec 'GID' do |ss|
ss.header_mappings_dir = "#{src_dir}"
ss.source_files = "#{src_dir}/GRPCCall+GID.{h,m}"
ss.dependency 'Google/SignIn'
end
end

@ -39,11 +39,14 @@ EXPORTS
census_record_values
grpc_compression_algorithm_parse
grpc_compression_algorithm_name
grpc_stream_compression_algorithm_name
grpc_compression_algorithm_for_level
grpc_stream_compression_algorithm_for_level
grpc_compression_options_init
grpc_compression_options_enable_algorithm
grpc_compression_options_disable_algorithm
grpc_compression_options_is_algorithm_enabled
grpc_compression_options_is_stream_compression_algorithm_enabled
grpc_metadata_array_init
grpc_metadata_array_destroy
grpc_call_details_init

@ -59,6 +59,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/support/string_util.h )
s.files += %w( include/grpc/support/subprocess.h )
s.files += %w( include/grpc/support/sync.h )
s.files += %w( include/grpc/support/sync_custom.h )
s.files += %w( include/grpc/support/sync_generic.h )
s.files += %w( include/grpc/support/sync_posix.h )
s.files += %w( include/grpc/support/sync_windows.h )
@ -77,6 +78,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/gpr_types.h )
s.files += %w( include/grpc/impl/codegen/port_platform.h )
s.files += %w( include/grpc/impl/codegen/sync.h )
s.files += %w( include/grpc/impl/codegen/sync_custom.h )
s.files += %w( include/grpc/impl/codegen/sync_generic.h )
s.files += %w( include/grpc/impl/codegen/sync_posix.h )
s.files += %w( include/grpc/impl/codegen/sync_windows.h )
@ -95,7 +97,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/stack_lockfree.h )
s.files += %w( src/core/lib/support/string.h )
s.files += %w( src/core/lib/support/string_windows.h )
s.files += %w( src/core/lib/support/thd_internal.h )
s.files += %w( src/core/lib/support/time_precise.h )
s.files += %w( src/core/lib/support/tmpfile.h )
s.files += %w( src/core/lib/profiling/basic_timers.c )
@ -160,6 +161,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/gpr_types.h )
s.files += %w( include/grpc/impl/codegen/port_platform.h )
s.files += %w( include/grpc/impl/codegen/sync.h )
s.files += %w( include/grpc/impl/codegen/sync_custom.h )
s.files += %w( include/grpc/impl/codegen/sync_generic.h )
s.files += %w( include/grpc/impl/codegen/sync_posix.h )
s.files += %w( include/grpc/impl/codegen/sync_windows.h )
@ -369,6 +371,10 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
s.files += %w( third_party/nanopb/pb.h )
s.files += %w( third_party/nanopb/pb_common.h )
s.files += %w( third_party/nanopb/pb_decode.h )
s.files += %w( third_party/nanopb/pb_encode.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h )

2479
grpc.gyp

File diff suppressed because it is too large Load Diff

@ -204,12 +204,14 @@ class CallOpSendInitialMetadata {
public:
CallOpSendInitialMetadata() : send_(false) {
maybe_compression_level_.is_set = false;
maybe_stream_compression_level_.is_set = false;
}
void SendInitialMetadata(
const std::multimap<grpc::string, grpc::string>& metadata,
uint32_t flags) {
maybe_compression_level_.is_set = false;
maybe_stream_compression_level_.is_set = false;
send_ = true;
flags_ = flags;
initial_metadata_ =
@ -221,6 +223,11 @@ class CallOpSendInitialMetadata {
maybe_compression_level_.level = level;
}
void set_stream_compression_level(grpc_stream_compression_level level) {
maybe_stream_compression_level_.is_set = true;
maybe_stream_compression_level_.level = level;
}
protected:
void AddOp(grpc_op* ops, size_t* nops) {
if (!send_) return;
@ -236,6 +243,12 @@ class CallOpSendInitialMetadata {
op->data.send_initial_metadata.maybe_compression_level.level =
maybe_compression_level_.level;
}
op->data.send_initial_metadata.maybe_stream_compression_level.is_set =
maybe_stream_compression_level_.is_set;
if (maybe_stream_compression_level_.is_set) {
op->data.send_initial_metadata.maybe_stream_compression_level.level =
maybe_stream_compression_level_.level;
}
}
void FinishOp(bool* status) {
if (!send_) return;
@ -251,6 +264,10 @@ class CallOpSendInitialMetadata {
bool is_set;
grpc_compression_level level;
} maybe_compression_level_;
struct {
bool is_set;
grpc_stream_compression_level level;
} maybe_stream_compression_level_;
};
class CallOpSendMessage {

@ -30,25 +30,42 @@
extern "C" {
#endif
/** Parses the first \a name_length bytes of \a name as a
* grpc_compression_algorithm instance, updating \a algorithm. Returns 1 upon
* success, 0 otherwise. */
/** Parses the \a slice as a grpc_compression_algorithm instance and updating \a
* algorithm. Returns 1 upon success, 0 otherwise. */
GRPCAPI int grpc_compression_algorithm_parse(
grpc_slice value, grpc_compression_algorithm *algorithm);
/** Parses the \a slice as a grpc_stream_compression_algorithm instance and
* updating \a algorithm. Returns 1 upon success, 0 otherwise. */
int grpc_stream_compression_algorithm_parse(
grpc_slice name, grpc_stream_compression_algorithm *algorithm);
/** Updates \a name with the encoding name corresponding to a valid \a
* algorithm. Note that \a name is statically allocated and must *not* be freed.
* Returns 1 upon success, 0 otherwise. */
GRPCAPI int grpc_compression_algorithm_name(
grpc_compression_algorithm algorithm, char **name);
/** Updates \a name with the encoding name corresponding to a valid \a
* algorithm. Note that \a name is statically allocated and must *not* be freed.
* Returns 1 upon success, 0 otherwise. */
GRPCAPI int grpc_stream_compression_algorithm_name(
grpc_stream_compression_algorithm algorithm, char **name);
/** Returns the compression algorithm corresponding to \a level for the
* compression algorithms encoded in the \a accepted_encodings bitset.
*
* It abort()s for unknown levels . */
* It abort()s for unknown levels. */
GRPCAPI grpc_compression_algorithm grpc_compression_algorithm_for_level(
grpc_compression_level level, uint32_t accepted_encodings);
/** Returns the stream compression algorithm corresponding to \a level for the
* compression algorithms encoded in the \a accepted_stream_encodings bitset.
* It abort()s for unknown levels. */
GRPCAPI grpc_stream_compression_algorithm
grpc_stream_compression_algorithm_for_level(grpc_stream_compression_level level,
uint32_t accepted_stream_encodings);
GRPCAPI void grpc_compression_options_init(grpc_compression_options *opts);
/** Mark \a algorithm as enabled in \a opts. */
@ -63,6 +80,11 @@ GRPCAPI void grpc_compression_options_disable_algorithm(
GRPCAPI int grpc_compression_options_is_algorithm_enabled(
const grpc_compression_options *opts, grpc_compression_algorithm algorithm);
/** Returns true if \a algorithm is marked as enabled in \a opts. */
GRPCAPI int grpc_compression_options_is_stream_compression_algorithm_enabled(
const grpc_compression_options *opts,
grpc_stream_compression_algorithm algorithm);
#ifdef __cplusplus
}
#endif

@ -29,6 +29,11 @@ extern "C" {
* algorithm */
#define GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \
"grpc-internal-encoding-request"
/** To be used as initial metadata key for the request of a concrete stream
* compression
* algorithm */
#define GRPC_STREAM_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \
"grpc-internal-stream-encoding-request"
/** To be used in channel arguments.
*
@ -38,9 +43,17 @@ extern "C" {
* Its value is an int from the \a grpc_compression_algorithm enum. */
#define GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \
"grpc.default_compression_algorithm"
/** Default stream compression algorithm for the channel.
* Its value is an int from the \a grpc_stream_compression_algorithm enum. */
#define GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \
"grpc.default_stream_compression_algorithm"
/** Default compression level for the channel.
* Its value is an int from the \a grpc_compression_level enum. */
#define GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL "grpc.default_compression_level"
/** Default stream compression level for the channel.
* Its value is an int from the \a grpc_stream_compression_level enum. */
#define GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_LEVEL \
"grpc.default_stream_compression_level"
/** Compression algorithms supported by the channel.
* Its value is a bitset (an int). Bits correspond to algorithms in \a
* grpc_compression_algorithm. For example, its LSB corresponds to
@ -50,6 +63,15 @@ extern "C" {
* be ignored). */
#define GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET \
"grpc.compression_enabled_algorithms_bitset"
/** Stream compression algorithms supported by the channel.
* Its value is a bitset (an int). Bits correspond to algorithms in \a
* grpc_stream_compression_algorithm. For example, its LSB corresponds to
* GRPC_STREAM_COMPRESS_NONE, the next bit to GRPC_STREAM_COMPRESS_DEFLATE, etc.
* Unset bits disable support for the algorithm. By default all algorithms are
* supported. It's not possible to disable GRPC_STREAM_COMPRESS_NONE (the
* attempt will be ignored). */
#define GRPC_STREAM_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET \
"grpc.stream_compression_enabled_algorithms_bitset"
/** \} */
/** The various compression algorithms supported by gRPC */
@ -61,6 +83,13 @@ typedef enum {
GRPC_COMPRESS_ALGORITHMS_COUNT
} grpc_compression_algorithm;
/** Stream compresssion algorithms supported by gRPC */
typedef enum {
GRPC_STREAM_COMPRESS_NONE = 0,
GRPC_STREAM_COMPRESS_GZIP,
GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT
} grpc_stream_compression_algorithm;
/** Compression levels allow a party with knowledge of its peer's accepted
* encodings to request compression in an abstract way. The level-algorithm
* mapping is performed internally and depends on the peer's supported
@ -73,23 +102,42 @@ typedef enum {
GRPC_COMPRESS_LEVEL_COUNT
} grpc_compression_level;
/** Compression levels for stream compression algorithms */
typedef enum {
GRPC_STREAM_COMPRESS_LEVEL_NONE = 0,
GRPC_STREAM_COMPRESS_LEVEL_LOW,
GRPC_STREAM_COMPRESS_LEVEL_MED,
GRPC_STREAM_COMPRESS_LEVEL_HIGH,
GRPC_STREAM_COMPRESS_LEVEL_COUNT
} grpc_stream_compression_level;
typedef struct grpc_compression_options {
/** All algs are enabled by default. This option corresponds to the channel
* argument key behind \a GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET
*/
uint32_t enabled_algorithms_bitset;
uint32_t enabled_stream_compression_algorithms_bitset;
/** The default channel compression level. It'll be used in the absence of
* call specific settings. This option corresponds to the channel argument key
* behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL. If present, takes
* precedence over \a default_algorithm.
/** The default message-wise compression level. It'll be used in the absence
* of * call specific settings. This option corresponds to the channel
* argument key behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL. If present,
* takes precedence over \a default_algorithm and \a
* default_stream_compression_algorithm.
* TODO(dgq): currently only available for server channels. */
struct grpc_compression_options_default_level {
int is_set;
grpc_compression_level level;
} default_level;
/** The default channel compression algorithm. It'll be used in the absence of
/** The default stream compression level. It'll be used in the absence of call
* specefic settings. If present, takes precedence over \a default_level,
* \a default_algorithm and \a default_stream_compression_algorithm. */
struct grpc_stream_compression_options_default_level {
int is_set;
grpc_stream_compression_level level;
} default_stream_compression_level;
/** The default message compression algorithm. It'll be used in the absence of
* call specific settings. This option corresponds to the channel argument key
* behind \a GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM. */
struct grpc_compression_options_default_algorithm {
@ -97,6 +145,16 @@ typedef struct grpc_compression_options {
grpc_compression_algorithm algorithm;
} default_algorithm;
/** The default stream compression algorithm. It'll be used in the absence of
* call specific settings. If present, takes precedence over \a
* default_algorithm. This option corresponds to the channel
* argument key behind \a GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM.
*/
struct grpc_stream_compression_options_default_algorithm {
int is_set;
grpc_stream_compression_algorithm algorithm;
} default_stream_compression_algorithm;
} grpc_compression_options;
#ifdef __cplusplus

@ -505,6 +505,10 @@ typedef struct grpc_op {
uint8_t is_set;
grpc_compression_level level;
} maybe_compression_level;
struct grpc_op_send_initial_metadata_maybe_stream_compression_level {
uint8_t is_set;
grpc_stream_compression_level level;
} maybe_stream_compression_level;
} send_initial_metadata;
struct grpc_op_send_message {
struct grpc_byte_buffer *send_message;

@ -49,7 +49,9 @@ extern "C" {
#include <grpc/impl/codegen/sync_posix.h>
#elif defined(GPR_WINDOWS)
#include <grpc/impl/codegen/sync_windows.h>
#elif !defined(GPR_CUSTOM_SYNC)
#elif defined(GPR_CUSTOM_SYNC)
#include <grpc/impl/codegen/sync_custom.h>
#else
#error Unable to determine platform for sync
#endif

@ -0,0 +1,36 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_IMPL_CODEGEN_SYNC_CUSTOM_H
#define GRPC_IMPL_CODEGEN_SYNC_CUSTOM_H
#include <grpc/impl/codegen/sync_generic.h>
/* Users defining GPR_CUSTOM_SYNC need to define the following macros. */
#ifdef GPR_CUSTOM_SYNC
typedef GPR_CUSTOM_MU_TYPE gpr_mu;
typedef GPR_CUSTOM_CV_TYPE gpr_cv;
typedef GPR_CUSTOM_ONCE_TYPE gpr_once;
#define GPR_ONCE_INIT GPR_CUSTOM_ONCE_INIT
#endif
#endif /* GRPC_IMPL_CODEGEN_SYNC_CUSTOM_H */

@ -1,6 +1,6 @@
/*
*
* Copyright 2015 gRPC authors.
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,3 +16,9 @@
*
*/
#ifndef GRPC_SUPPORT_SYNC_CUSTOM_H
#define GRPC_SUPPORT_SYNC_CUSTOM_H
#include <grpc/impl/codegen/sync_custom.h>
#endif /* GRPC_SUPPORT_SYNC_CUSTOM_H */

@ -1,6 +1,6 @@
{
"name": "grpc",
"version": "1.5.0-dev",
"version": "1.7.0-dev",
"author": "Google Inc.",
"description": "gRPC Library for Node",
"homepage": "https://grpc.io/",

@ -13,8 +13,8 @@
<date>2017-05-22</date>
<time>16:06:07</time>
<version>
<release>1.5.0dev</release>
<api>1.5.0dev</api>
<release>1.7.0dev</release>
<api>1.7.0dev</api>
</version>
<stability>
<release>beta</release>
@ -22,13 +22,9 @@
</stability>
<license>Apache 2.0</license>
<notes>
- Fixed some memory leaks #9559, #10996
- Disabled cares dependency from gRPC C Core #10940
- De-coupled protobuf dependency #11112
- Fixed extension reported version #10842
- Added config.w32 for Windows support #8161
- Fixed PHP distrib test after cc files were added #11193
- Fixed protoc plugin comment escape bug #11025
- Channel are now by default persistent #11878
- Some bug fixes from 1.4 branch #12109, #12123
- Fixed hang bug when fork() was used #11814
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@ -73,6 +69,7 @@
<file baseinstalldir="/" name="include/grpc/support/string_util.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/subprocess.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/sync.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/sync_custom.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/sync_generic.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/sync_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/sync_windows.h" role="src" />
@ -91,6 +88,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_custom.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
@ -109,7 +107,6 @@
<file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/thd_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/time_precise.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/tmpfile.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.c" role="src" />
@ -174,6 +171,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_custom.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
@ -383,6 +381,10 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" role="src" />

@ -1544,6 +1544,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_byte_buffer_reader bbr;
grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
grpc_byte_buffer_reader_destroy(&bbr);
grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
grpc_grpclb_initial_response *response = NULL;

@ -74,9 +74,6 @@ typedef struct round_robin_lb_policy {
bool started_picking;
/** are we shutting down? */
bool shutdown;
/** has the policy gotten into the GRPC_CHANNEL_SHUTDOWN? No picks can be
* service after this point, the policy will never transition out. */
bool in_connectivity_shutdown;
/** List of picks that are waiting on connectivity */
pending_pick *pending_picks;
@ -424,7 +421,6 @@ static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_closure *on_complete) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
GPR_ASSERT(!p->shutdown);
GPR_ASSERT(!p->in_connectivity_shutdown);
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO, "[RR %p] Trying to pick", (void *)pol);
}
@ -537,7 +533,7 @@ static grpc_connectivity_state update_lb_connectivity_status_locked(
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error),
"rr_shutdown");
p->in_connectivity_shutdown = true;
p->shutdown = true;
new_state = GRPC_CHANNEL_SHUTDOWN;
} else if (subchannel_list->num_transient_failures ==
p->subchannel_list->num_subchannels) { /* 4) TRANSIENT_FAILURE */
@ -811,19 +807,30 @@ static void rr_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
sc_args.args = new_args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);
grpc_channel_args_destroy(exec_ctx, new_args);
grpc_error *error;
// Get the connectivity state of the subchannel. Already existing ones may
// be in a state other than INIT.
const grpc_connectivity_state subchannel_connectivity_state =
grpc_subchannel_check_connectivity(subchannel, &error);
if (error != GRPC_ERROR_NONE) {
// The subchannel is in error (e.g. shutting down). Ignore it.
GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannel, "new_sc_connectivity_error");
GRPC_ERROR_UNREF(error);
continue;
}
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
char *address_uri =
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
gpr_log(
GPR_DEBUG,
"[RR %p] index %lu: Created subchannel %p for address uri %s into "
"subchannel_list %p",
"subchannel_list %p. Connectivity state %s",
(void *)p, (unsigned long)subchannel_index, (void *)subchannel,
address_uri, (void *)subchannel_list);
address_uri, (void *)subchannel_list,
grpc_connectivity_state_name(subchannel_connectivity_state));
gpr_free(address_uri);
}
grpc_channel_args_destroy(exec_ctx, new_args);
subchannel_data *sd = &subchannel_list->subchannels[subchannel_index++];
sd->subchannel_list = subchannel_list;
sd->subchannel = subchannel;
@ -835,7 +842,7 @@ static void rr_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
* won't be referring to this value again and it'll be overwritten after
* the first call to rr_connectivity_changed_locked */
sd->prev_connectivity_state = GRPC_CHANNEL_INIT;
sd->curr_connectivity_state = GRPC_CHANNEL_IDLE;
sd->curr_connectivity_state = subchannel_connectivity_state;
sd->user_data_vtable = addresses->user_data_vtable;
if (sd->user_data_vtable != NULL) {
sd->user_data =

@ -44,7 +44,9 @@
typedef struct call_data {
grpc_slice_buffer slices; /**< Buffers up input slices to be compressed */
grpc_linked_mdelem compression_algorithm_storage;
grpc_linked_mdelem stream_compression_algorithm_storage;
grpc_linked_mdelem accept_encoding_storage;
grpc_linked_mdelem accept_stream_encoding_storage;
uint32_t remaining_slice_bytes;
/** Compression algorithm we'll try to use. It may be given by incoming
* metadata, or by the channel's default compression settings. */
@ -75,6 +77,13 @@ typedef struct channel_data {
uint32_t enabled_algorithms_bitset;
/** Supported compression algorithms */
uint32_t supported_compression_algorithms;
/** The default, channel-level, stream compression algorithm */
grpc_stream_compression_algorithm default_stream_compression_algorithm;
/** Bitset of enabled stream compression algorithms */
uint32_t enabled_stream_compression_algorithms_bitset;
/** Supported stream compression algorithms */
uint32_t supported_stream_compression_algorithms;
} channel_data;
static bool skip_compression(grpc_call_element *elem, uint32_t flags,
@ -106,31 +115,56 @@ static grpc_error *process_send_initial_metadata(
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
*has_compression_algorithm = false;
/* Parse incoming request for compression. If any, it'll be available
* at calld->compression_algorithm */
if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
grpc_stream_compression_algorithm stream_compression_algorithm =
GRPC_STREAM_COMPRESS_NONE;
if (initial_metadata->idx.named.grpc_internal_stream_encoding_request !=
NULL) {
grpc_mdelem md =
initial_metadata->idx.named.grpc_internal_encoding_request->md;
if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
&calld->compression_algorithm)) {
initial_metadata->idx.named.grpc_internal_stream_encoding_request->md;
if (!grpc_stream_compression_algorithm_parse(
GRPC_MDVALUE(md), &stream_compression_algorithm)) {
char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
"Invalid stream compression algorithm: '%s' (unknown). Ignoring.",
val);
gpr_free(val);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
}
if (!GPR_BITGET(channeld->enabled_stream_compression_algorithms_bitset,
stream_compression_algorithm)) {
char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(
GPR_ERROR,
"Invalid stream compression algorithm: '%s' (previously disabled). "
"Ignoring.",
val);
gpr_free(val);
stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
}
*has_compression_algorithm = true;
grpc_metadata_batch_remove(
exec_ctx, initial_metadata,
initial_metadata->idx.named.grpc_internal_stream_encoding_request);
/* Disable message-wise compression */
calld->compression_algorithm = GRPC_COMPRESS_NONE;
if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
grpc_metadata_batch_remove(
exec_ctx, initial_metadata,
initial_metadata->idx.named.grpc_internal_encoding_request);
}
if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
calld->compression_algorithm)) {
} else if (initial_metadata->idx.named.grpc_internal_encoding_request !=
NULL) {
grpc_mdelem md =
initial_metadata->idx.named.grpc_internal_encoding_request->md;
if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
&calld->compression_algorithm)) {
char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid compression algorithm: '%s' (previously disabled). "
"Ignoring.",
val);
"Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
gpr_free(val);
calld->compression_algorithm = GRPC_COMPRESS_NONE;
}
*has_compression_algorithm = true;
grpc_metadata_batch_remove(
exec_ctx, initial_metadata,
initial_metadata->idx.named.grpc_internal_encoding_request);
@ -138,13 +172,25 @@ static grpc_error *process_send_initial_metadata(
/* If no algorithm was found in the metadata and we aren't
* exceptionally skipping compression, fall back to the channel
* default */
calld->compression_algorithm = channeld->default_compression_algorithm;
if (channeld->default_stream_compression_algorithm !=
GRPC_STREAM_COMPRESS_NONE) {
stream_compression_algorithm =
channeld->default_stream_compression_algorithm;
calld->compression_algorithm = GRPC_COMPRESS_NONE;
} else {
calld->compression_algorithm = channeld->default_compression_algorithm;
}
*has_compression_algorithm = true;
}
grpc_error *error = GRPC_ERROR_NONE;
/* hint compression algorithm */
if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
if (stream_compression_algorithm != GRPC_STREAM_COMPRESS_NONE) {
error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata,
&calld->stream_compression_algorithm_storage,
grpc_stream_compression_encoding_mdelem(stream_compression_algorithm));
} else if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
grpc_compression_encoding_mdelem(calld->compression_algorithm));
@ -158,6 +204,16 @@ static grpc_error *process_send_initial_metadata(
GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
channeld->supported_compression_algorithms));
if (error != GRPC_ERROR_NONE) return error;
/* Do not overwrite accept-encoding header if it already presents. */
if (!initial_metadata->idx.named.accept_encoding) {
error = grpc_metadata_batch_add_tail(
exec_ctx, initial_metadata, &calld->accept_stream_encoding_storage,
GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(
channeld->supported_stream_compression_algorithms));
}
return error;
}
@ -435,6 +491,7 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element_args *args) {
channel_data *channeld = elem->channel_data;
/* Configuration for message compression */
channeld->enabled_algorithms_bitset =
grpc_channel_args_compression_algorithm_get_states(args->channel_args);
@ -449,16 +506,32 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
channeld->default_compression_algorithm = GRPC_COMPRESS_NONE;
}
channeld->supported_compression_algorithms = 1; /* always support identity */
for (grpc_compression_algorithm algo_idx = 1;
algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
/* skip disabled algorithms */
if (!GPR_BITGET(channeld->enabled_algorithms_bitset, algo_idx)) {
continue;
}
channeld->supported_compression_algorithms |= 1u << algo_idx;
channeld->supported_compression_algorithms =
(((1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1) &
channeld->enabled_algorithms_bitset) |
1u;
/* Configuration for stream compression */
channeld->enabled_stream_compression_algorithms_bitset =
grpc_channel_args_stream_compression_algorithm_get_states(
args->channel_args);
channeld->default_stream_compression_algorithm =
grpc_channel_args_get_stream_compression_algorithm(args->channel_args);
if (!GPR_BITGET(channeld->enabled_stream_compression_algorithms_bitset,
channeld->default_stream_compression_algorithm)) {
gpr_log(GPR_DEBUG,
"stream compression algorithm %d not enabled: switching to none",
channeld->default_stream_compression_algorithm);
channeld->default_stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
}
channeld->supported_stream_compression_algorithms =
(((1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1) &
channeld->enabled_stream_compression_algorithms_bitset) |
1u;
GPR_ASSERT(!args->is_last);
return GRPC_ERROR_NONE;
}

@ -1298,6 +1298,15 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
if (op->send_initial_metadata) {
GPR_ASSERT(s->send_initial_metadata_finished == NULL);
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
/* Identify stream compression */
if ((s->stream_compression_send_enabled =
(op_payload->send_initial_metadata.send_initial_metadata->idx.named
.content_encoding != NULL)) == true) {
s->compressed_data_buffer = gpr_malloc(sizeof(grpc_slice_buffer));
grpc_slice_buffer_init(s->compressed_data_buffer);
}
s->send_initial_metadata_finished = add_closure_barrier(on_complete);
s->send_initial_metadata =
op_payload->send_initial_metadata.send_initial_metadata;
@ -2703,6 +2712,9 @@ static grpc_error *incoming_byte_stream_pull(grpc_exec_ctx *exec_ctx,
grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
s->stream_decompression_ctx = NULL;
}
if (s->unprocessed_incoming_frames_buffer.length == 0) {
*slice = grpc_empty_slice();
}
}
error = grpc_deframe_unprocessed_incoming_frames(
exec_ctx, &s->data_parser, s, &s->unprocessed_incoming_frames_buffer,

@ -482,8 +482,8 @@ grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_bdp_action(
double bw_dbl = -1;
if (grpc_bdp_estimator_get_bw(&tfc->bdp_estimator, &bw_dbl)) {
// we target the max of BDP or bandwidth in microseconds.
int32_t frame_size =
GPR_CLAMP(GPR_MAX((int32_t)bw_dbl / 1000, bdp), 16384, 16777215);
int32_t frame_size = (int32_t)GPR_CLAMP(
GPR_MAX((int32_t)bw_dbl / 1000, bdp), 16384, 16777215);
grpc_chttp2_flowctl_urgency frame_size_urgency = delta_is_significant(
tfc, frame_size, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE);
if (frame_size_urgency != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) {

@ -1655,6 +1655,23 @@ static void force_client_rst_stream(grpc_exec_ctx *exec_ctx, void *sp,
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "final_rst");
}
static void parse_stream_compression_md(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_metadata_batch *initial_metadata) {
if (initial_metadata->idx.named.content_encoding != NULL) {
grpc_slice content_encoding =
GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md);
if (!grpc_slice_eq(content_encoding, GRPC_MDSTR_IDENTITY)) {
if (grpc_slice_eq(content_encoding, GRPC_MDSTR_GZIP)) {
s->stream_compression_recv_enabled = true;
s->decompressed_data_buffer = gpr_malloc(sizeof(grpc_slice_buffer));
grpc_slice_buffer_init(s->decompressed_data_buffer);
}
}
}
}
grpc_error *grpc_chttp2_header_parser_parse(grpc_exec_ctx *exec_ctx,
void *hpack_parser,
grpc_chttp2_transport *t,
@ -1681,9 +1698,16 @@ grpc_error *grpc_chttp2_header_parser_parse(grpc_exec_ctx *exec_ctx,
if (s != NULL) {
if (parser->is_boundary) {
if (s->header_frames_received == GPR_ARRAY_SIZE(s->metadata_buffer)) {
GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Too many trailer frames");
}
/* Process stream compression md element if it exists */
if (s->header_frames_received ==
0) { /* Only acts on initial metadata */
parse_stream_compression_md(exec_ctx, t, s,
&s->metadata_buffer[0].batch);
}
s->published_metadata[s->header_frames_received] =
GRPC_METADATA_PUBLISHED_FROM_WIRE;
maybe_complete_funcs[s->header_frames_received](exec_ctx, t, s);

@ -221,6 +221,21 @@ grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
return GRPC_COMPRESS_NONE;
}
grpc_stream_compression_algorithm
grpc_channel_args_get_stream_compression_algorithm(const grpc_channel_args *a) {
size_t i;
if (a == NULL) return 0;
for (i = 0; i < a->num_args; ++i) {
if (a->args[i].type == GRPC_ARG_INTEGER &&
!strcmp(GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM,
a->args[i].key)) {
return (grpc_stream_compression_algorithm)a->args[i].value.integer;
break;
}
}
return GRPC_STREAM_COMPRESS_NONE;
}
grpc_channel_args *grpc_channel_args_set_compression_algorithm(
grpc_channel_args *a, grpc_compression_algorithm algorithm) {
GPR_ASSERT(algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT);
@ -231,6 +246,16 @@ grpc_channel_args *grpc_channel_args_set_compression_algorithm(
return grpc_channel_args_copy_and_add(a, &tmp, 1);
}
grpc_channel_args *grpc_channel_args_set_stream_compression_algorithm(
grpc_channel_args *a, grpc_stream_compression_algorithm algorithm) {
GPR_ASSERT(algorithm < GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT);
grpc_arg tmp;
tmp.type = GRPC_ARG_INTEGER;
tmp.key = GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM;
tmp.value.integer = algorithm;
return grpc_channel_args_copy_and_add(a, &tmp, 1);
}
/** Returns 1 if the argument for compression algorithm's enabled states bitset
* was found in \a a, returning the arg's value in \a states. Otherwise, returns
* 0. */
@ -251,6 +276,26 @@ static int find_compression_algorithm_states_bitset(const grpc_channel_args *a,
return 0; /* GPR_FALSE */
}
/** Returns 1 if the argument for compression algorithm's enabled states bitset
* was found in \a a, returning the arg's value in \a states. Otherwise, returns
* 0. */
static int find_stream_compression_algorithm_states_bitset(
const grpc_channel_args *a, int **states_arg) {
if (a != NULL) {
size_t i;
for (i = 0; i < a->num_args; ++i) {
if (a->args[i].type == GRPC_ARG_INTEGER &&
!strcmp(GRPC_STREAM_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
a->args[i].key)) {
*states_arg = &a->args[i].value.integer;
**states_arg |= 0x1; /* forcefully enable support for no compression */
return 1;
}
}
}
return 0; /* GPR_FALSE */
}
grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
grpc_exec_ctx *exec_ctx, grpc_channel_args **a,
grpc_compression_algorithm algorithm, int state) {
@ -292,6 +337,48 @@ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
return result;
}
grpc_channel_args *grpc_channel_args_stream_compression_algorithm_set_state(
grpc_exec_ctx *exec_ctx, grpc_channel_args **a,
grpc_stream_compression_algorithm algorithm, int state) {
int *states_arg = NULL;
grpc_channel_args *result = *a;
const int states_arg_found =
find_stream_compression_algorithm_states_bitset(*a, &states_arg);
if (grpc_channel_args_get_stream_compression_algorithm(*a) == algorithm &&
state == 0) {
char *algo_name = NULL;
GPR_ASSERT(grpc_stream_compression_algorithm_name(algorithm, &algo_name) !=
0);
gpr_log(GPR_ERROR,
"Tried to disable default stream compression algorithm '%s'. The "
"operation has been ignored.",
algo_name);
} else if (states_arg_found) {
if (state != 0) {
GPR_BITSET((unsigned *)states_arg, algorithm);
} else if (algorithm != GRPC_STREAM_COMPRESS_NONE) {
GPR_BITCLEAR((unsigned *)states_arg, algorithm);
}
} else {
/* create a new arg */
grpc_arg tmp;
tmp.type = GRPC_ARG_INTEGER;
tmp.key = GRPC_STREAM_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET;
/* all enabled by default */
tmp.value.integer = (1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1;
if (state != 0) {
GPR_BITSET((unsigned *)&tmp.value.integer, algorithm);
} else if (algorithm != GRPC_STREAM_COMPRESS_NONE) {
GPR_BITCLEAR((unsigned *)&tmp.value.integer, algorithm);
}
result = grpc_channel_args_copy_and_add(*a, &tmp, 1);
grpc_channel_args_destroy(exec_ctx, *a);
*a = result;
}
return result;
}
uint32_t grpc_channel_args_compression_algorithm_get_states(
const grpc_channel_args *a) {
int *states_arg;
@ -302,6 +389,17 @@ uint32_t grpc_channel_args_compression_algorithm_get_states(
}
}
uint32_t grpc_channel_args_stream_compression_algorithm_get_states(
const grpc_channel_args *a) {
int *states_arg;
if (find_stream_compression_algorithm_states_bitset(a, &states_arg)) {
return (uint32_t)*states_arg;
} else {
return (1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) -
1; /* All algs. enabled */
}
}
grpc_channel_args *grpc_channel_args_set_socket_mutator(
grpc_channel_args *a, grpc_socket_mutator *mutator) {
grpc_arg tmp = grpc_socket_mutator_to_arg(mutator);

@ -59,12 +59,24 @@ void grpc_channel_args_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_args *a);
grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
const grpc_channel_args *a);
/** Returns the stream compression algorithm set in \a a. */
grpc_stream_compression_algorithm
grpc_channel_args_get_stream_compression_algorithm(const grpc_channel_args *a);
/** Returns a channel arg instance with compression enabled. If \a a is
* non-NULL, its args are copied. N.B. GRPC_COMPRESS_NONE disables compression
* for the channel. */
grpc_channel_args *grpc_channel_args_set_compression_algorithm(
grpc_channel_args *a, grpc_compression_algorithm algorithm);
/** Returns a channel arg instance with stream compression enabled. If \a a is
* non-NULL, its args are copied. N.B. GRPC_STREAM_COMPRESS_NONE disables
* stream compression for the channel. If a value other than
* GRPC_STREAM_COMPRESS_NONE is set, it takes precedence over message-wise
* compression algorithms. */
grpc_channel_args *grpc_channel_args_set_stream_compression_algorithm(
grpc_channel_args *a, grpc_stream_compression_algorithm algorithm);
/** Sets the support for the given compression algorithm. By default, all
* compression algorithms are enabled. It's an error to disable an algorithm set
* by grpc_channel_args_set_compression_algorithm.
@ -76,6 +88,17 @@ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
grpc_exec_ctx *exec_ctx, grpc_channel_args **a,
grpc_compression_algorithm algorithm, int enabled);
/** Sets the support for the given stream compression algorithm. By default, all
* stream compression algorithms are enabled. It's an error to disable an
* algorithm set by grpc_channel_args_set_stream_compression_algorithm.
*
* Returns an instance with the updated algorithm states. The \a a pointer is
* modified to point to the returned instance (which may be different from the
* input value of \a a). */
grpc_channel_args *grpc_channel_args_stream_compression_algorithm_set_state(
grpc_exec_ctx *exec_ctx, grpc_channel_args **a,
grpc_stream_compression_algorithm algorithm, int enabled);
/** Returns the bitset representing the support state (true for enabled, false
* for disabled) for compression algorithms.
*
@ -84,6 +107,14 @@ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
uint32_t grpc_channel_args_compression_algorithm_get_states(
const grpc_channel_args *a);
/** Returns the bitset representing the support state (true for enabled, false
* for disabled) for stream compression algorithms.
*
* The i-th bit of the returned bitset corresponds to the i-th entry in the
* grpc_stream_compression_algorithm enum. */
uint32_t grpc_channel_args_stream_compression_algorithm_get_states(
const grpc_channel_args *a);
int grpc_channel_args_compare(const grpc_channel_args *a,
const grpc_channel_args *b);

@ -26,13 +26,27 @@
grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm);
/** Return stream compression algorithm based metadata value */
grpc_slice grpc_stream_compression_algorithm_slice(
grpc_stream_compression_algorithm algorithm);
/** Return compression algorithm based metadata element (grpc-encoding: xxx) */
grpc_mdelem grpc_compression_encoding_mdelem(
grpc_compression_algorithm algorithm);
/** Return stream compression algorithm based metadata element
* (content-encoding: xxx) */
grpc_mdelem grpc_stream_compression_encoding_mdelem(
grpc_stream_compression_algorithm algorithm);
/** Find compression algorithm based on passed in mdstr - returns
* GRPC_COMPRESS_ALGORITHM_COUNT on failure */
grpc_compression_algorithm grpc_compression_algorithm_from_slice(
grpc_slice str);
/** Find stream compression algorithm based on passed in mdstr - returns
* GRPC_STREAM_COMPRESS_ALGORITHM_COUNT on failure */
grpc_stream_compression_algorithm grpc_stream_compression_algorithm_from_slice(
grpc_slice str);
#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */

@ -46,6 +46,19 @@ int grpc_compression_algorithm_parse(grpc_slice name,
}
}
int grpc_stream_compression_algorithm_parse(
grpc_slice name, grpc_stream_compression_algorithm *algorithm) {
if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
*algorithm = GRPC_STREAM_COMPRESS_NONE;
return 1;
} else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
*algorithm = GRPC_STREAM_COMPRESS_GZIP;
return 1;
} else {
return 0;
}
}
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
char **name) {
GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
@ -66,6 +79,24 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
return 0;
}
int grpc_stream_compression_algorithm_name(
grpc_stream_compression_algorithm algorithm, char **name) {
GRPC_API_TRACE(
"grpc_stream_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
((int)algorithm, name));
switch (algorithm) {
case GRPC_STREAM_COMPRESS_NONE:
*name = "identity";
return 1;
case GRPC_STREAM_COMPRESS_GZIP:
*name = "gzip";
return 1;
case GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT:
return 0;
}
return 0;
}
grpc_compression_algorithm grpc_compression_algorithm_from_slice(
grpc_slice str) {
if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
@ -74,6 +105,13 @@ grpc_compression_algorithm grpc_compression_algorithm_from_slice(
return GRPC_COMPRESS_ALGORITHMS_COUNT;
}
grpc_stream_compression_algorithm grpc_stream_compression_algorithm_from_slice(
grpc_slice str) {
if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_STREAM_COMPRESS_NONE;
if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_STREAM_COMPRESS_GZIP;
return GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT;
}
grpc_slice grpc_compression_algorithm_slice(
grpc_compression_algorithm algorithm) {
switch (algorithm) {
@ -89,6 +127,19 @@ grpc_slice grpc_compression_algorithm_slice(
return grpc_empty_slice();
}
grpc_slice grpc_stream_compression_algorithm_slice(
grpc_stream_compression_algorithm algorithm) {
switch (algorithm) {
case GRPC_STREAM_COMPRESS_NONE:
return GRPC_MDSTR_IDENTITY;
case GRPC_STREAM_COMPRESS_GZIP:
return GRPC_MDSTR_GZIP;
case GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT:
return grpc_empty_slice();
}
return grpc_empty_slice();
}
grpc_mdelem grpc_compression_encoding_mdelem(
grpc_compression_algorithm algorithm) {
switch (algorithm) {
@ -104,10 +155,25 @@ grpc_mdelem grpc_compression_encoding_mdelem(
return GRPC_MDNULL;
}
grpc_mdelem grpc_stream_compression_encoding_mdelem(
grpc_stream_compression_algorithm algorithm) {
switch (algorithm) {
case GRPC_STREAM_COMPRESS_NONE:
return GRPC_MDELEM_CONTENT_ENCODING_IDENTITY;
case GRPC_STREAM_COMPRESS_GZIP:
return GRPC_MDELEM_CONTENT_ENCODING_GZIP;
default:
break;
}
return GRPC_MDNULL;
}
void grpc_compression_options_init(grpc_compression_options *opts) {
memset(opts, 0, sizeof(*opts));
/* all enabled by default */
opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
opts->enabled_stream_compression_algorithms_bitset =
(1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1;
}
void grpc_compression_options_enable_algorithm(
@ -126,6 +192,13 @@ int grpc_compression_options_is_algorithm_enabled(
return GPR_BITGET(opts->enabled_algorithms_bitset, algorithm);
}
int grpc_compression_options_is_stream_compression_algorithm_enabled(
const grpc_compression_options *opts,
grpc_stream_compression_algorithm algorithm) {
return GPR_BITGET(opts->enabled_stream_compression_algorithms_bitset,
algorithm);
}
/* TODO(dgq): Add the ability to specify parameters to the individual
* compression algorithms */
grpc_compression_algorithm grpc_compression_algorithm_for_level(
@ -181,3 +254,30 @@ grpc_compression_algorithm grpc_compression_algorithm_for_level(
abort();
};
}
GRPCAPI grpc_stream_compression_algorithm
grpc_stream_compression_algorithm_for_level(
grpc_stream_compression_level level, uint32_t accepted_stream_encodings) {
GRPC_API_TRACE("grpc_stream_compression_algorithm_for_level(level=%d)", 1,
((int)level));
if (level > GRPC_STREAM_COMPRESS_LEVEL_HIGH) {
gpr_log(GPR_ERROR, "Unknown compression level %d.", (int)level);
abort();
}
switch (level) {
case GRPC_STREAM_COMPRESS_LEVEL_NONE:
return GRPC_STREAM_COMPRESS_NONE;
case GRPC_STREAM_COMPRESS_LEVEL_LOW:
case GRPC_STREAM_COMPRESS_LEVEL_MED:
case GRPC_STREAM_COMPRESS_LEVEL_HIGH:
if (GPR_BITGET(accepted_stream_encodings, GRPC_STREAM_COMPRESS_GZIP) ==
1) {
return GRPC_STREAM_COMPRESS_GZIP;
} else {
return GRPC_STREAM_COMPRESS_NONE;
}
default:
abort();
}
}

@ -48,7 +48,60 @@
#include "src/core/lib/support/string.h"
static grpc_wakeup_fd global_wakeup_fd;
static int g_epfd;
/*******************************************************************************
* Singleton epoll set related fields
*/
#define MAX_EPOLL_EVENTS 100
#define MAX_EPOLL_EVENTS_HANDLED_PER_ITERATION 1
/* NOTE ON SYNCHRONIZATION:
* - Fields in this struct are only modified by the designated poller. Hence
* there is no need for any locks to protect the struct.
* - num_events and cursor fields have to be of atomic type to provide memory
* visibility guarantees only. i.e In case of multiple pollers, the designated
* polling thread keeps changing; the thread that wrote these values may be
* different from the thread reading the values
*/
typedef struct epoll_set {
int epfd;
/* The epoll_events after the last call to epoll_wait() */
struct epoll_event events[MAX_EPOLL_EVENTS];
/* The number of epoll_events after the last call to epoll_wait() */
gpr_atm num_events;
/* Index of the first event in epoll_events that has to be processed. This
* field is only valid if num_events > 0 */
gpr_atm cursor;
} epoll_set;
/* The global singleton epoll set */
static epoll_set g_epoll_set;
/* Must be called *only* once */
static bool epoll_set_init() {
g_epoll_set.epfd = epoll_create1(EPOLL_CLOEXEC);
if (g_epoll_set.epfd < 0) {
gpr_log(GPR_ERROR, "epoll unavailable");
return false;
}
gpr_log(GPR_INFO, "grpc epoll fd: %d", g_epoll_set.epfd);
gpr_atm_no_barrier_store(&g_epoll_set.num_events, 0);
gpr_atm_no_barrier_store(&g_epoll_set.cursor, 0);
return true;
}
/* epoll_set_init() MUST be called before calling this. */
static void epoll_set_shutdown() {
if (g_epoll_set.epfd >= 0) {
close(g_epoll_set.epfd);
g_epoll_set.epfd = -1;
}
}
/*******************************************************************************
* Fd Declarations
@ -122,7 +175,7 @@ struct grpc_pollset {
bool kicked_without_poller;
/* Set to true if the pollset is observed to have no workers available to
* poll */
poll */
bool seen_inactive;
bool shutting_down; /* Is the pollset shutting down ? */
grpc_closure *shutdown_closure; /* Called after after shutdown is complete */
@ -228,7 +281,7 @@ static grpc_fd *fd_create(int fd, const char *name) {
struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET),
.data.ptr = new_fd};
if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, fd, &ev) != 0) {
if (epoll_ctl(g_epoll_set.epfd, EPOLL_CTL_ADD, fd, &ev) != 0) {
gpr_log(GPR_ERROR, "epoll_ctl failed: %s", strerror(errno));
}
@ -326,7 +379,10 @@ static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
GPR_TLS_DECL(g_current_thread_pollset);
GPR_TLS_DECL(g_current_thread_worker);
/* The designated poller */
static gpr_atm g_active_poller;
static pollset_neighbourhood *g_neighbourhoods;
static size_t g_num_neighbourhoods;
@ -380,7 +436,8 @@ static grpc_error *pollset_global_init(void) {
if (err != GRPC_ERROR_NONE) return err;
struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLET),
.data.ptr = &global_wakeup_fd};
if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, global_wakeup_fd.read_fd, &ev) != 0) {
if (epoll_ctl(g_epoll_set.epfd, EPOLL_CTL_ADD, global_wakeup_fd.read_fd,
&ev) != 0) {
return GRPC_OS_ERROR(errno, "epoll_ctl");
}
g_num_neighbourhoods = GPR_CLAMP(gpr_cpu_num_cores(), 1, MAX_NEIGHBOURHOODS);
@ -406,7 +463,14 @@ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
gpr_mu_init(&pollset->mu);
*mu = &pollset->mu;
pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
pollset->reassigning_neighbourhood = false;
pollset->root_worker = NULL;
pollset->kicked_without_poller = false;
pollset->seen_inactive = true;
pollset->shutting_down = false;
pollset->shutdown_closure = NULL;
pollset->begin_refs = 0;
pollset->next = pollset->prev = NULL;
}
static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
@ -438,6 +502,7 @@ static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
}
static grpc_error *pollset_kick_all(grpc_pollset *pollset) {
GPR_TIMER_BEGIN("pollset_kick_all", 0);
grpc_error *error = GRPC_ERROR_NONE;
if (pollset->root_worker != NULL) {
grpc_pollset_worker *worker = pollset->root_worker;
@ -463,7 +528,7 @@ static grpc_error *pollset_kick_all(grpc_pollset *pollset) {
}
// TODO: sreek. Check if we need to set 'kicked_without_poller' to true here
// in the else case
GPR_TIMER_END("pollset_kick_all", 0);
return error;
}
@ -471,6 +536,7 @@ static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset) {
if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL &&
pollset->begin_refs == 0) {
GPR_TIMER_MARK("pollset_finish_shutdown", 0);
GRPC_CLOSURE_SCHED(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE);
pollset->shutdown_closure = NULL;
}
@ -478,16 +544,16 @@ static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure) {
GPR_TIMER_BEGIN("pollset_shutdown", 0);
GPR_ASSERT(pollset->shutdown_closure == NULL);
GPR_ASSERT(!pollset->shutting_down);
pollset->shutdown_closure = closure;
pollset->shutting_down = true;
GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset));
pollset_maybe_finish_shutdown(exec_ctx, pollset);
GPR_TIMER_END("pollset_shutdown", 0);
}
#define MAX_EPOLL_EVENTS 100
static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
gpr_timespec now) {
gpr_timespec timeout;
@ -506,52 +572,93 @@ static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
return millis >= 1 ? millis : 1;
}
static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
gpr_timespec now, gpr_timespec deadline) {
struct epoll_event events[MAX_EPOLL_EVENTS];
static const char *err_desc = "pollset_poll";
int timeout = poll_deadline_to_millis_timeout(deadline, now);
if (timeout != 0) {
GRPC_SCHEDULING_START_BLOCKING_REGION;
}
int r;
do {
r = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, timeout);
} while (r < 0 && errno == EINTR);
if (timeout != 0) {
GRPC_SCHEDULING_END_BLOCKING_REGION;
}
/* Process the epoll events found by do_epoll_wait() function.
- g_epoll_set.cursor points to the index of the first event to be processed
- This function then processes up-to MAX_EPOLL_EVENTS_PER_ITERATION and
updates the g_epoll_set.cursor
NOTE ON SYNCRHONIZATION: Similar to do_epoll_wait(), this function is only
called by g_active_poller thread. So there is no need for synchronization
when accessing fields in g_epoll_set */
static grpc_error *process_epoll_events(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset) {
static const char *err_desc = "process_events";
grpc_error *error = GRPC_ERROR_NONE;
if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
GPR_TIMER_BEGIN("process_epoll_events", 0);
long num_events = gpr_atm_acq_load(&g_epoll_set.num_events);
long cursor = gpr_atm_acq_load(&g_epoll_set.cursor);
for (int idx = 0;
(idx < MAX_EPOLL_EVENTS_HANDLED_PER_ITERATION) && cursor != num_events;
idx++) {
long c = cursor++;
struct epoll_event *ev = &g_epoll_set.events[c];
void *data_ptr = ev->data.ptr;
grpc_error *error = GRPC_ERROR_NONE;
for (int i = 0; i < r; i++) {
void *data_ptr = events[i].data.ptr;
if (data_ptr == &global_wakeup_fd) {
append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
err_desc);
} else {
grpc_fd *fd = (grpc_fd *)(data_ptr);
bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0;
bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0;
bool write_ev = (events[i].events & EPOLLOUT) != 0;
bool cancel = (ev->events & (EPOLLERR | EPOLLHUP)) != 0;
bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0;
bool write_ev = (ev->events & EPOLLOUT) != 0;
if (read_ev || cancel) {
fd_become_readable(exec_ctx, fd, pollset);
}
if (write_ev || cancel) {
fd_become_writable(exec_ctx, fd);
}
}
}
gpr_atm_rel_store(&g_epoll_set.cursor, cursor);
GPR_TIMER_END("process_epoll_events", 0);
return error;
}
/* Do epoll_wait and store the events in g_epoll_set.events field. This does not
"process" any of the events yet; that is done in process_epoll_events().
*See process_epoll_events() function for more details.
NOTE ON SYNCHRONIZATION: At any point of time, only the g_active_poller
(i.e the designated poller thread) will be calling this function. So there is
no need for any synchronization when accesing fields in g_epoll_set */
static grpc_error *do_epoll_wait(grpc_exec_ctx *exec_ctx, grpc_pollset *ps,
gpr_timespec now, gpr_timespec deadline) {
GPR_TIMER_BEGIN("do_epoll_wait", 0);
int r;
int timeout = poll_deadline_to_millis_timeout(deadline, now);
if (timeout != 0) {
GRPC_SCHEDULING_START_BLOCKING_REGION;
}
do {
r = epoll_wait(g_epoll_set.epfd, g_epoll_set.events, MAX_EPOLL_EVENTS,
timeout);
} while (r < 0 && errno == EINTR);
if (timeout != 0) {
GRPC_SCHEDULING_END_BLOCKING_REGION;
}
if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_DEBUG, "ps: %p poll got %d events", ps, r);
}
gpr_atm_rel_store(&g_epoll_set.num_events, r);
gpr_atm_rel_store(&g_epoll_set.cursor, 0);
GPR_TIMER_END("do_epoll_wait", 0);
return GRPC_ERROR_NONE;
}
static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
grpc_pollset_worker **worker_hdl, gpr_timespec *now,
gpr_timespec deadline) {
GPR_TIMER_BEGIN("begin_worker", 0);
if (worker_hdl != NULL) *worker_hdl = worker;
worker->initialized_cv = false;
SET_KICK_STATE(worker, UNKICKED);
@ -656,14 +763,17 @@ static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
if (pollset->kicked_without_poller) {
pollset->kicked_without_poller = false;
GPR_TIMER_END("begin_worker", 0);
return false;
}
GPR_TIMER_END("begin_worker", 0);
return worker->kick_state == DESIGNATED_POLLER && !pollset->shutting_down;
}
static bool check_neighbourhood_for_available_poller(
pollset_neighbourhood *neighbourhood) {
GPR_TIMER_BEGIN("check_neighbourhood_for_available_poller", 0);
bool found_worker = false;
do {
grpc_pollset *inspect = neighbourhood->active_root;
@ -685,6 +795,7 @@ static bool check_neighbourhood_for_available_poller(
}
SET_KICK_STATE(inspect_worker, DESIGNATED_POLLER);
if (inspect_worker->initialized_cv) {
GPR_TIMER_MARK("signal worker", 0);
gpr_cv_signal(&inspect_worker->cv);
}
} else {
@ -720,12 +831,14 @@ static bool check_neighbourhood_for_available_poller(
}
gpr_mu_unlock(&inspect->mu);
} while (!found_worker);
GPR_TIMER_END("check_neighbourhood_for_available_poller", 0);
return found_worker;
}
static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker *worker,
grpc_pollset_worker **worker_hdl) {
GPR_TIMER_BEGIN("end_worker", 0);
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_DEBUG, "PS:%p END_WORKER:%p", pollset, worker);
}
@ -795,42 +908,71 @@ static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
pollset_maybe_finish_shutdown(exec_ctx, pollset);
}
GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
GPR_TIMER_END("end_worker", 0);
}
/* pollset->po.mu lock must be held by the caller before calling this.
The function pollset_work() may temporarily release the lock (pollset->po.mu)
during the course of its execution but it will always re-acquire the lock and
ensure that it is held by the time the function returns */
static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *ps,
grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) {
grpc_pollset_worker worker;
grpc_error *error = GRPC_ERROR_NONE;
static const char *err_desc = "pollset_work";
if (pollset->kicked_without_poller) {
pollset->kicked_without_poller = false;
GPR_TIMER_BEGIN("pollset_work", 0);
if (ps->kicked_without_poller) {
ps->kicked_without_poller = false;
GPR_TIMER_END("pollset_work", 0);
return GRPC_ERROR_NONE;
}
if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) {
gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
if (begin_worker(ps, &worker, worker_hdl, &now, deadline)) {
gpr_tls_set(&g_current_thread_pollset, (intptr_t)ps);
gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
GPR_ASSERT(!pollset->shutting_down);
GPR_ASSERT(!pollset->seen_inactive);
gpr_mu_unlock(&pollset->mu);
append_error(&error, pollset_epoll(exec_ctx, pollset, now, deadline),
err_desc);
gpr_mu_lock(&pollset->mu);
GPR_ASSERT(!ps->shutting_down);
GPR_ASSERT(!ps->seen_inactive);
gpr_mu_unlock(&ps->mu); /* unlock */
/* This is the designated polling thread at this point and should ideally do
polling. However, if there are unprocessed events left from a previous
call to do_epoll_wait(), skip calling epoll_wait() in this iteration and
process the pending epoll events.
The reason for decoupling do_epoll_wait and process_epoll_events is to
better distrubute the work (i.e handling epoll events) across multiple
threads
process_epoll_events() returns very quickly: It just queues the work on
exec_ctx but does not execute it (the actual exectution or more
accurately grpc_exec_ctx_flush() happens in end_worker() AFTER selecting
a designated poller). So we are not waiting long periods without a
designated poller */
if (gpr_atm_acq_load(&g_epoll_set.cursor) ==
gpr_atm_acq_load(&g_epoll_set.num_events)) {
append_error(&error, do_epoll_wait(exec_ctx, ps, now, deadline),
err_desc);
}
append_error(&error, process_epoll_events(exec_ctx, ps), err_desc);
gpr_mu_lock(&ps->mu); /* lock */
gpr_tls_set(&g_current_thread_worker, 0);
} else {
gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
gpr_tls_set(&g_current_thread_pollset, (intptr_t)ps);
}
end_worker(exec_ctx, pollset, &worker, worker_hdl);
end_worker(exec_ctx, ps, &worker, worker_hdl);
gpr_tls_set(&g_current_thread_pollset, 0);
GPR_TIMER_END("pollset_work", 0);
return error;
}
static grpc_error *pollset_kick(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker) {
GPR_TIMER_BEGIN("pollset_kick", 0);
grpc_error *ret_err = GRPC_ERROR_NONE;
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_strvec log;
gpr_strvec_init(&log);
@ -865,7 +1007,7 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. kicked_without_poller");
}
return GRPC_ERROR_NONE;
goto done;
}
grpc_pollset_worker *next_worker = root_worker->next;
if (root_worker->kick_state == KICKED) {
@ -873,13 +1015,13 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
gpr_log(GPR_ERROR, " .. already kicked %p", root_worker);
}
SET_KICK_STATE(root_worker, KICKED);
return GRPC_ERROR_NONE;
goto done;
} else if (next_worker->kick_state == KICKED) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. already kicked %p", next_worker);
}
SET_KICK_STATE(next_worker, KICKED);
return GRPC_ERROR_NONE;
goto done;
} else if (root_worker ==
next_worker && // only try and wake up a poller if
// there is no next worker
@ -889,7 +1031,8 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
gpr_log(GPR_ERROR, " .. kicked %p", root_worker);
}
SET_KICK_STATE(root_worker, KICKED);
return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
goto done;
} else if (next_worker->kick_state == UNKICKED) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. kicked %p", next_worker);
@ -897,7 +1040,7 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
GPR_ASSERT(next_worker->initialized_cv);
SET_KICK_STATE(next_worker, KICKED);
gpr_cv_signal(&next_worker->cv);
return GRPC_ERROR_NONE;
goto done;
} else if (next_worker->kick_state == DESIGNATED_POLLER) {
if (root_worker->kick_state != DESIGNATED_POLLER) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
@ -910,59 +1053,64 @@ static grpc_error *pollset_kick(grpc_pollset *pollset,
if (root_worker->initialized_cv) {
gpr_cv_signal(&root_worker->cv);
}
return GRPC_ERROR_NONE;
goto done;
} else {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. non-root poller %p (root=%p)", next_worker,
root_worker);
}
SET_KICK_STATE(next_worker, KICKED);
return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
goto done;
}
} else {
GPR_ASSERT(next_worker->kick_state == KICKED);
SET_KICK_STATE(next_worker, KICKED);
return GRPC_ERROR_NONE;
goto done;
}
} else {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. kicked while waking up");
}
return GRPC_ERROR_NONE;
goto done;
}
} else if (specific_worker->kick_state == KICKED) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. specific worker already kicked");
}
return GRPC_ERROR_NONE;
goto done;
} else if (gpr_tls_get(&g_current_thread_worker) ==
(intptr_t)specific_worker) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. mark %p kicked", specific_worker);
}
SET_KICK_STATE(specific_worker, KICKED);
return GRPC_ERROR_NONE;
goto done;
} else if (specific_worker ==
(grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. kick active poller");
}
SET_KICK_STATE(specific_worker, KICKED);
return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
goto done;
} else if (specific_worker->initialized_cv) {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. kick waiting worker");
}
SET_KICK_STATE(specific_worker, KICKED);
gpr_cv_signal(&specific_worker->cv);
return GRPC_ERROR_NONE;
goto done;
} else {
if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_log(GPR_ERROR, " .. kick non-waiting worker");
}
SET_KICK_STATE(specific_worker, KICKED);
return GRPC_ERROR_NONE;
goto done;
}
done:
GPR_TIMER_END("pollset_kick", 0);
return ret_err;
}
static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@ -1006,7 +1154,7 @@ static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
static void shutdown_engine(void) {
fd_global_shutdown();
pollset_global_shutdown();
close(g_epfd);
epoll_set_shutdown();
}
static const grpc_event_engine_vtable vtable = {
@ -1041,10 +1189,9 @@ static const grpc_event_engine_vtable vtable = {
};
/* It is possible that GLIBC has epoll but the underlying kernel doesn't.
* Create a dummy epoll_fd to make sure epoll support is available */
* Create epoll_fd (epoll_set_init() takes care of that) to make sure epoll
* support is available */
const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
/* TODO(sreek): Temporarily disable this poller unless explicitly requested
* via GRPC_POLL_STRATEGY */
if (!explicit_request) {
return NULL;
}
@ -1053,22 +1200,18 @@ const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
return NULL;
}
g_epfd = epoll_create1(EPOLL_CLOEXEC);
if (g_epfd < 0) {
gpr_log(GPR_ERROR, "epoll unavailable");
if (!epoll_set_init()) {
return NULL;
}
fd_global_init();
if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
close(g_epfd);
fd_global_shutdown();
epoll_set_shutdown();
return NULL;
}
gpr_log(GPR_ERROR, "grpc epoll fd: %d", g_epfd);
return &vtable;
}

@ -49,7 +49,7 @@
#include "src/core/lib/support/spinlock.h"
/*******************************************************************************
* Pollset-set sibling link
* Polling object
*/
typedef enum {

@ -37,7 +37,8 @@ void gpr_timers_set_log_filename(const char *filename);
void gpr_timer_set_enabled(int enabled);
#if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
#if !(defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER) + \
defined(GRPC_CUSTOM_PROFILER))
/* No profiling. No-op all the things. */
#define GPR_TIMER_MARK(tag, important) \
do { \
@ -56,6 +57,12 @@ void gpr_timer_set_enabled(int enabled);
#if defined(GRPC_STAP_PROFILER) && defined(GRPC_BASIC_PROFILER)
#error "GRPC_STAP_PROFILER and GRPC_BASIC_PROFILER are mutually exclusive."
#endif
#if defined(GRPC_STAP_PROFILER) && defined(GRPC_CUSTOM_PROFILER)
#error "GRPC_STAP_PROFILER and GRPC_CUSTOM_PROFILER are mutually exclusive."
#endif
#if defined(GRPC_CUSTOM_PROFILER) && defined(GRPC_BASIC_PROFILER)
#error "GRPC_CUSTOM_PROFILER and GRPC_BASIC_PROFILER are mutually exclusive."
#endif
/* Generic profiling interface. */
#define GPR_TIMER_MARK(tag, important) \
@ -80,22 +87,25 @@ void gpr_timer_set_enabled(int enabled);
#ifdef __cplusplus
}
#if (defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER))
#if (defined(GRPC_STAP_PROFILER) + defined(GRPC_BASIC_PROFILER) + \
defined(GRPC_CUSTOM_PROFILER))
namespace grpc {
class ProfileScope {
public:
ProfileScope(const char *desc, bool important) : desc_(desc) {
GPR_TIMER_BEGIN(desc_, important ? 1 : 0);
ProfileScope(const char *desc, bool important, const char *file, int line)
: desc_(desc) {
gpr_timer_begin(desc_, important ? 1 : 0, file, line);
}
~ProfileScope() { GPR_TIMER_END(desc_, 0); }
~ProfileScope() { gpr_timer_end(desc_, 0, "n/a", 0); }
private:
const char *const desc_;
};
}
} // namespace grpc
#define GPR_TIMER_SCOPE(tag, important) \
::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important))
#define GPR_TIMER_SCOPE(tag, important) \
::grpc::ProfileScope _profile_scope_##__LINE__((tag), (important), __FILE__, \
__LINE__)
#else
#define GPR_TIMER_SCOPE(tag, important) \
do { \

@ -442,7 +442,7 @@ static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
end:
BIO_free(bio);
if (x509 != NULL) X509_free(x509);
X509_free(x509);
return result;
}
@ -496,6 +496,8 @@ static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
const grpc_json *key_prop;
RSA *rsa = NULL;
EVP_PKEY *result = NULL;
BIGNUM *tmp_n = NULL;
BIGNUM *tmp_e = NULL;
GPR_ASSERT(kty != NULL && json != NULL);
if (strcmp(kty, "RSA") != 0) {
@ -507,8 +509,6 @@ static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
gpr_log(GPR_ERROR, "Could not create rsa key.");
goto end;
}
BIGNUM *tmp_n = NULL;
BIGNUM *tmp_e = NULL;
for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
if (strcmp(key_prop->key, "n") == 0) {
tmp_n =
@ -528,11 +528,16 @@ static EVP_PKEY *pkey_from_jwk(grpc_exec_ctx *exec_ctx, const grpc_json *json,
gpr_log(GPR_ERROR, "Cannot set RSA key from inputs.");
goto end;
}
/* RSA_set0_key takes ownership on success. */
tmp_n = NULL;
tmp_e = NULL;
result = EVP_PKEY_new();
EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */
end:
if (rsa != NULL) RSA_free(rsa);
RSA_free(rsa);
BN_free(tmp_n);
BN_free(tmp_e);
return result;
}
@ -618,7 +623,7 @@ static int verify_jwt_signature(EVP_PKEY *key, const char *alg,
result = 1;
end:
if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
EVP_MD_CTX_destroy(md_ctx);
return result;
}
@ -658,7 +663,7 @@ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
end:
if (json != NULL) grpc_json_destroy(json);
if (verification_key != NULL) EVP_PKEY_free(verification_key);
EVP_PKEY_free(verification_key);
ctx->user_cb(exec_ctx, ctx->user_data, status, claims);
verifier_cb_ctx_destroy(exec_ctx, ctx);
}

@ -296,10 +296,10 @@ static bool oauth2_token_fetcher_get_request_metadata(
gpr_mu_unlock(&c->mu);
if (start_fetch) {
grpc_call_credentials_ref(creds);
c->fetch_func(exec_ctx, grpc_credentials_metadata_request_create(creds),
&c->httpcli_context, &c->pollent,
on_oauth2_token_fetcher_http_response,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
c->fetch_func(
exec_ctx, grpc_credentials_metadata_request_create(creds),
&c->httpcli_context, &c->pollent, on_oauth2_token_fetcher_http_response,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), refresh_threshold));
}
return false;
}

@ -19,15 +19,37 @@
#ifndef GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H
#define GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H
#ifdef __cplusplus
extern "C" {
#endif
void gpr_thd_start_blocking_region();
void gpr_thd_end_blocking_region();
#ifdef __cplusplus
}
#endif
/* These annotations identify the beginning and end of regions where
the code may block for reasons other than synchronization functions.
These include poll, epoll, and getaddrinfo. */
#ifdef GRPC_SCHEDULING_MARK_BLOCKING_REGION
#define GRPC_SCHEDULING_START_BLOCKING_REGION \
do { \
gpr_thd_start_blocking_region(); \
} while (0)
#define GRPC_SCHEDULING_END_BLOCKING_REGION \
do { \
gpr_thd_end_blocking_region(); \
} while (0)
#else
#define GRPC_SCHEDULING_START_BLOCKING_REGION \
do { \
} while (0)
#define GRPC_SCHEDULING_END_BLOCKING_REGION \
do { \
} while (0)
#endif
#endif /* GRPC_CORE_LIB_SUPPORT_BLOCK_ANNOTATE_H */

@ -144,6 +144,9 @@ typedef struct {
grpc_call *sibling_prev;
} child_call;
#define RECV_NONE ((gpr_atm)0)
#define RECV_INITIAL_METADATA_FIRST ((gpr_atm)1)
struct grpc_call {
gpr_refcount ext_ref;
gpr_arena *arena;
@ -170,9 +173,6 @@ struct grpc_call {
gpr_atm any_ops_sent_atm;
gpr_atm received_final_op_atm;
/* have we received initial metadata */
bool has_initial_md_been_received;
batch_control *active_batches[MAX_CONCURRENT_BATCHES];
grpc_transport_stream_op_batch_payload stream_op_payload;
@ -192,8 +192,12 @@ struct grpc_call {
/* Compression algorithm for *incoming* data */
grpc_compression_algorithm incoming_compression_algorithm;
/* Stream compression algorithm for *incoming* data */
grpc_stream_compression_algorithm incoming_stream_compression_algorithm;
/* Supported encodings (compression algorithms), a bitset */
uint32_t encodings_accepted_by_peer;
/* Supported stream encodings (stream compression algorithms), a bitset */
uint32_t stream_encodings_accepted_by_peer;
/* Contexts for various subsystems (security, tracing, ...). */
grpc_call_context_element context[GRPC_CONTEXT_COUNT];
@ -226,7 +230,23 @@ struct grpc_call {
} server;
} final_op;
void *saved_receiving_stream_ready_bctlp;
/* recv_state can contain one of the following values:
RECV_NONE : : no initial metadata and messages received
RECV_INITIAL_METADATA_FIRST : received initial metadata first
a batch_control* : received messages first
+------1------RECV_NONE------3-----+
| |
| |
v v
RECV_INITIAL_METADATA_FIRST receiving_stream_ready_bctlp
| ^ | ^
| | | |
+-----2-----+ +-----4-----+
For 1, 4: See receiving_initial_metadata_ready() function
For 2, 3: See receiving_stream_ready() function */
gpr_atm recv_state;
};
grpc_tracer_flag grpc_call_error_trace =
@ -752,6 +772,12 @@ static void set_incoming_compression_algorithm(
call->incoming_compression_algorithm = algo;
}
static void set_incoming_stream_compression_algorithm(
grpc_call *call, grpc_stream_compression_algorithm algo) {
GPR_ASSERT(algo < GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT);
call->incoming_stream_compression_algorithm = algo;
}
grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
grpc_call *call) {
grpc_compression_algorithm algorithm;
@ -765,6 +791,13 @@ static grpc_compression_algorithm compression_algorithm_for_level_locked(
call->encodings_accepted_by_peer);
}
static grpc_stream_compression_algorithm
stream_compression_algorithm_for_level_locked(
grpc_call *call, grpc_stream_compression_level level) {
return grpc_stream_compression_algorithm_for_level(
level, call->stream_encodings_accepted_by_peer);
}
uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
uint32_t flags;
flags = call->test_only_last_message_flags;
@ -819,12 +852,70 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
(void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
}
static void set_stream_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
grpc_call *call,
grpc_mdelem mdel) {
size_t i;
grpc_stream_compression_algorithm algorithm;
grpc_slice_buffer accept_encoding_parts;
grpc_slice accept_encoding_slice;
void *accepted_user_data;
accepted_user_data =
grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
if (accepted_user_data != NULL) {
call->stream_encodings_accepted_by_peer =
(uint32_t)(((uintptr_t)accepted_user_data) - 1);
return;
}
accept_encoding_slice = GRPC_MDVALUE(mdel);
grpc_slice_buffer_init(&accept_encoding_parts);
grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
/* Always support no compression */
GPR_BITSET(&call->stream_encodings_accepted_by_peer,
GRPC_STREAM_COMPRESS_NONE);
for (i = 0; i < accept_encoding_parts.count; i++) {
grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
if (grpc_stream_compression_algorithm_parse(accept_encoding_entry_slice,
&algorithm)) {
GPR_BITSET(&call->stream_encodings_accepted_by_peer, algorithm);
} else {
char *accept_encoding_entry_str =
grpc_slice_to_c_string(accept_encoding_entry_slice);
gpr_log(GPR_ERROR,
"Invalid entry in accept encoding metadata: '%s'. Ignoring.",
accept_encoding_entry_str);
gpr_free(accept_encoding_entry_str);
}
}
grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts);
grpc_mdelem_set_user_data(
mdel, destroy_encodings_accepted_by_peer,
(void *)(((uintptr_t)call->stream_encodings_accepted_by_peer) + 1));
}
uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
uint32_t encodings_accepted_by_peer;
encodings_accepted_by_peer = call->encodings_accepted_by_peer;
return encodings_accepted_by_peer;
}
uint32_t grpc_call_test_only_get_stream_encodings_accepted_by_peer(
grpc_call *call) {
uint32_t stream_encodings_accepted_by_peer;
stream_encodings_accepted_by_peer = call->stream_encodings_accepted_by_peer;
return stream_encodings_accepted_by_peer;
}
grpc_stream_compression_algorithm
grpc_call_test_only_get_incoming_stream_encodings(grpc_call *call) {
return call->incoming_stream_compression_algorithm;
}
static grpc_linked_mdelem *linked_from_md(const grpc_metadata *md) {
return (grpc_linked_mdelem *)&md->internal_data;
}
@ -936,6 +1027,22 @@ static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
return algorithm;
}
static grpc_stream_compression_algorithm decode_stream_compression(
grpc_mdelem md) {
grpc_stream_compression_algorithm algorithm =
grpc_stream_compression_algorithm_from_slice(GRPC_MDVALUE(md));
if (algorithm == GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) {
char *md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid incoming stream compression algorithm: '%s'. Interpreting "
"incoming data as uncompressed.",
md_c_str);
gpr_free(md_c_str);
return GRPC_STREAM_COMPRESS_NONE;
}
return algorithm;
}
static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
int is_trailing) {
if (b->list.count == 0) return;
@ -960,7 +1067,19 @@ static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch *b) {
if (b->idx.named.grpc_encoding != NULL) {
if (b->idx.named.content_encoding != NULL) {
if (b->idx.named.grpc_encoding != NULL) {
gpr_log(GPR_ERROR,
"Received both content-encoding and grpc-encoding header. "
"Ignoring grpc-encoding.");
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
}
GPR_TIMER_BEGIN("incoming_stream_compression_algorithm", 0);
set_incoming_stream_compression_algorithm(
call, decode_stream_compression(b->idx.named.content_encoding->md));
GPR_TIMER_END("incoming_stream_compression_algorithm", 0);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_encoding);
} else if (b->idx.named.grpc_encoding != NULL) {
GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
set_incoming_compression_algorithm(
call, decode_compression(b->idx.named.grpc_encoding->md));
@ -974,6 +1093,13 @@ static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
GPR_TIMER_END("encodings_accepted_by_peer", 0);
}
if (b->idx.named.accept_encoding != NULL) {
GPR_TIMER_BEGIN("stream_encodings_accepted_by_peer", 0);
set_stream_encodings_accepted_by_peer(exec_ctx, call,
b->idx.named.accept_encoding->md);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.accept_encoding);
GPR_TIMER_END("stream_encodings_accepted_by_peer", 0);
}
publish_app_metadata(call, b, false);
}
@ -1290,19 +1416,61 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
GRPC_ERROR_REF(error));
}
if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
call->receiving_stream == NULL) {
/* If recv_state is RECV_NONE, we will save the batch_control
* object with rel_cas, and will not use it after the cas. Its corresponding
* acq_load is in receiving_initial_metadata_ready() */
if (error != GRPC_ERROR_NONE || call->receiving_stream == NULL ||
!gpr_atm_rel_cas(&call->recv_state, RECV_NONE, (gpr_atm)bctlp)) {
process_data_after_md(exec_ctx, bctlp);
} else {
call->saved_receiving_stream_ready_bctlp = bctlp;
}
}
static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
batch_control *bctl) {
grpc_call *call = bctl->call;
/* validate call->incoming_compression_algorithm */
if (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE) {
/* validate compression algorithms */
if (call->incoming_stream_compression_algorithm !=
GRPC_STREAM_COMPRESS_NONE) {
const grpc_stream_compression_algorithm algo =
call->incoming_stream_compression_algorithm;
char *error_msg = NULL;
const grpc_compression_options compression_options =
grpc_channel_compression_options(call->channel);
if (algo >= GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) {
gpr_asprintf(&error_msg,
"Invalid stream compression algorithm value '%d'.", algo);
gpr_log(GPR_ERROR, "%s", error_msg);
cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
GRPC_STATUS_UNIMPLEMENTED, error_msg);
} else if (grpc_compression_options_is_stream_compression_algorithm_enabled(
&compression_options, algo) == 0) {
/* check if algorithm is supported by current channel config */
char *algo_name = NULL;
grpc_stream_compression_algorithm_name(algo, &algo_name);
gpr_asprintf(&error_msg, "Stream compression algorithm '%s' is disabled.",
algo_name);
gpr_log(GPR_ERROR, "%s", error_msg);
cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
GRPC_STATUS_UNIMPLEMENTED, error_msg);
}
gpr_free(error_msg);
GPR_ASSERT(call->stream_encodings_accepted_by_peer != 0);
if (!GPR_BITGET(call->stream_encodings_accepted_by_peer,
call->incoming_stream_compression_algorithm)) {
if (GRPC_TRACER_ON(grpc_compression_trace)) {
char *algo_name = NULL;
grpc_stream_compression_algorithm_name(
call->incoming_stream_compression_algorithm, &algo_name);
gpr_log(
GPR_ERROR,
"Stream compression algorithm (content-encoding = '%s') not "
"present in the bitset of accepted encodings (accept-encodings: "
"'0x%x')",
algo_name, call->stream_encodings_accepted_by_peer);
}
}
} else if (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE) {
const grpc_compression_algorithm algo =
call->incoming_compression_algorithm;
char *error_msg = NULL;
@ -1329,22 +1497,20 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
call->incoming_compression_algorithm = algo;
}
gpr_free(error_msg);
}
/* make sure the received grpc-encoding is amongst the ones listed in
* grpc-accept-encoding */
GPR_ASSERT(call->encodings_accepted_by_peer != 0);
if (!GPR_BITGET(call->encodings_accepted_by_peer,
call->incoming_compression_algorithm)) {
if (GRPC_TRACER_ON(grpc_compression_trace)) {
char *algo_name = NULL;
grpc_compression_algorithm_name(call->incoming_compression_algorithm,
&algo_name);
gpr_log(GPR_ERROR,
"Compression algorithm (grpc-encoding = '%s') not present in "
"the bitset of accepted encodings (grpc-accept-encodings: "
"'0x%x')",
algo_name, call->encodings_accepted_by_peer);
GPR_ASSERT(call->encodings_accepted_by_peer != 0);
if (!GPR_BITGET(call->encodings_accepted_by_peer,
call->incoming_compression_algorithm)) {
if (GRPC_TRACER_ON(grpc_compression_trace)) {
char *algo_name = NULL;
grpc_compression_algorithm_name(call->incoming_compression_algorithm,
&algo_name);
gpr_log(GPR_ERROR,
"Compression algorithm (grpc-encoding = '%s') not present in "
"the bitset of accepted encodings (grpc-accept-encodings: "
"'0x%x')",
algo_name, call->encodings_accepted_by_peer);
}
}
}
}
@ -1384,12 +1550,31 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
}
}
call->has_initial_md_been_received = true;
if (call->saved_receiving_stream_ready_bctlp != NULL) {
grpc_closure *saved_rsr_closure = GRPC_CLOSURE_CREATE(
receiving_stream_ready, call->saved_receiving_stream_ready_bctlp,
grpc_schedule_on_exec_ctx);
call->saved_receiving_stream_ready_bctlp = NULL;
grpc_closure *saved_rsr_closure = NULL;
while (true) {
gpr_atm rsr_bctlp = gpr_atm_acq_load(&call->recv_state);
/* Should only receive initial metadata once */
GPR_ASSERT(rsr_bctlp != 1);
if (rsr_bctlp == 0) {
/* We haven't seen initial metadata and messages before, thus initial
* metadata is received first.
* no_barrier_cas is used, as this function won't access the batch_control
* object saved by receiving_stream_ready() if the initial metadata is
* received first. */
if (gpr_atm_no_barrier_cas(&call->recv_state, RECV_NONE,
RECV_INITIAL_METADATA_FIRST)) {
break;
}
} else {
/* Already received messages */
saved_rsr_closure = GRPC_CLOSURE_CREATE(receiving_stream_ready,
(batch_control *)rsr_bctlp,
grpc_schedule_on_exec_ctx);
/* No need to modify recv_state */
break;
}
}
if (saved_rsr_closure != NULL) {
GRPC_CLOSURE_RUN(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error));
}
@ -1471,29 +1656,56 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
/* process compression level */
memset(&compression_md, 0, sizeof(compression_md));
size_t additional_metadata_count = 0;
grpc_compression_level effective_compression_level;
grpc_compression_level effective_compression_level =
GRPC_COMPRESS_LEVEL_NONE;
grpc_stream_compression_level effective_stream_compression_level =
GRPC_STREAM_COMPRESS_LEVEL_NONE;
bool level_set = false;
if (op->data.send_initial_metadata.maybe_compression_level.is_set) {
bool stream_compression = false;
if (op->data.send_initial_metadata.maybe_stream_compression_level
.is_set) {
effective_stream_compression_level =
op->data.send_initial_metadata.maybe_stream_compression_level
.level;
level_set = true;
stream_compression = true;
} else if (op->data.send_initial_metadata.maybe_compression_level
.is_set) {
effective_compression_level =
op->data.send_initial_metadata.maybe_compression_level.level;
level_set = true;
} else {
const grpc_compression_options copts =
grpc_channel_compression_options(call->channel);
level_set = copts.default_level.is_set;
if (level_set) {
if (copts.default_stream_compression_level.is_set) {
level_set = true;
effective_stream_compression_level =
copts.default_stream_compression_level.level;
stream_compression = true;
} else if (copts.default_level.is_set) {
level_set = true;
effective_compression_level = copts.default_level.level;
}
}
if (level_set && !call->is_client) {
const grpc_compression_algorithm calgo =
compression_algorithm_for_level_locked(
call, effective_compression_level);
// the following will be picked up by the compress filter and used as
// the call's compression algorithm.
compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
compression_md.value = grpc_compression_algorithm_slice(calgo);
additional_metadata_count++;
if (stream_compression) {
const grpc_stream_compression_algorithm calgo =
stream_compression_algorithm_for_level_locked(
call, effective_stream_compression_level);
compression_md.key =
GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST;
compression_md.value =
grpc_stream_compression_algorithm_slice(calgo);
} else {
const grpc_compression_algorithm calgo =
compression_algorithm_for_level_locked(
call, effective_compression_level);
/* the following will be picked up by the compress filter and used
* as the call's compression algorithm. */
compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
compression_md.value = grpc_compression_algorithm_slice(calgo);
additional_metadata_count++;
}
}
if (op->data.send_initial_metadata.count + additional_metadata_count >

@ -42,6 +42,18 @@ uint32_t grpc_call_test_only_get_message_flags(grpc_call *call);
* To be indexed by grpc_compression_algorithm enum values. */
uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call);
/** Returns a bitset for the stream encodings (stream compression algorithms)
* supported by \a call's peer.
*
* To be indexed by grpc_stream_compression_algorithm enum values. */
uint32_t grpc_call_test_only_get_stream_encodings_accepted_by_peer(
grpc_call *call);
/** Returns the incoming stream compression algorithm (content-encoding header)
* received by a call. */
grpc_stream_compression_algorithm
grpc_call_test_only_get_incoming_stream_encodings(grpc_call *call);
#ifdef __cplusplus
}
#endif

@ -141,6 +141,16 @@ grpc_channel *grpc_channel_create_with_builder(
(grpc_integer_options){GRPC_COMPRESS_LEVEL_NONE,
GRPC_COMPRESS_LEVEL_NONE,
GRPC_COMPRESS_LEVEL_COUNT - 1});
} else if (0 == strcmp(args->args[i].key,
GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
channel->compression_options.default_stream_compression_level.is_set =
true;
channel->compression_options.default_stream_compression_level.level =
(grpc_stream_compression_level)grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){GRPC_STREAM_COMPRESS_LEVEL_NONE,
GRPC_STREAM_COMPRESS_LEVEL_NONE,
GRPC_STREAM_COMPRESS_LEVEL_COUNT - 1});
} else if (0 == strcmp(args->args[i].key,
GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM)) {
channel->compression_options.default_algorithm.is_set = true;
@ -149,12 +159,31 @@ grpc_channel *grpc_channel_create_with_builder(
&args->args[i],
(grpc_integer_options){GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE,
GRPC_COMPRESS_ALGORITHMS_COUNT - 1});
} else if (0 == strcmp(args->args[i].key,
GRPC_STREAM_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM)) {
channel->compression_options.default_stream_compression_algorithm.is_set =
true;
channel->compression_options.default_stream_compression_algorithm
.algorithm =
(grpc_stream_compression_algorithm)grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){
GRPC_STREAM_COMPRESS_NONE, GRPC_STREAM_COMPRESS_NONE,
GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT - 1});
} else if (0 ==
strcmp(args->args[i].key,
GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET)) {
channel->compression_options.enabled_algorithms_bitset =
(uint32_t)args->args[i].value.integer |
0x1; /* always support no compression */
} else if (0 ==
strcmp(
args->args[i].key,
GRPC_STREAM_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET)) {
channel->compression_options
.enabled_stream_compression_algorithms_bitset =
(uint32_t)args->args[i].value.integer |
0x1; /* always support no compression */
}
}

@ -976,7 +976,6 @@ static void cq_shutdown_next(grpc_exec_ctx *exec_ctx,
if (cqd->shutdown_called) {
gpr_mu_unlock(cq->mu);
GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "shutting_down");
GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
return;
}
cqd->shutdown_called = true;
@ -1208,7 +1207,6 @@ static void cq_shutdown_pluck(grpc_exec_ctx *exec_ctx,
if (cqd->shutdown_called) {
gpr_mu_unlock(cq->mu);
GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "shutting_down (pluck cq)");
GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
return;
}
cqd->shutdown_called = true;

@ -23,4 +23,4 @@
const char *grpc_version_string(void) { return "4.0.0-dev"; }
const char *grpc_g_stands_for(void) { return "gregarious"; }
const char *grpc_g_stands_for(void) { return "gambit"; }

File diff suppressed because it is too large Load Diff

@ -29,7 +29,7 @@
#include "src/core/lib/transport/metadata.h"
#define GRPC_STATIC_MDSTR_COUNT 99
#define GRPC_STATIC_MDSTR_COUNT 100
extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
/* ":path" */
#define GRPC_MDSTR_PATH (grpc_static_slice_table[0])
@ -61,178 +61,181 @@ extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
#define GRPC_MDSTR_GRPC_TRACE_BIN (grpc_static_slice_table[13])
/* "content-type" */
#define GRPC_MDSTR_CONTENT_TYPE (grpc_static_slice_table[14])
/* "content-encoding" */
#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[15])
/* "accept-encoding" */
#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[16])
/* "grpc-internal-encoding-request" */
#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[15])
#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (grpc_static_slice_table[17])
/* "grpc-internal-stream-encoding-request" */
#define GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST \
(grpc_static_slice_table[18])
/* "user-agent" */
#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[16])
#define GRPC_MDSTR_USER_AGENT (grpc_static_slice_table[19])
/* "host" */
#define GRPC_MDSTR_HOST (grpc_static_slice_table[17])
#define GRPC_MDSTR_HOST (grpc_static_slice_table[20])
/* "lb-token" */
#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[18])
#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[21])
/* "grpc-timeout" */
#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[19])
#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[22])
/* "" */
#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[20])
#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[23])
/* "grpc.wait_for_ready" */
#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[21])
#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[24])
/* "grpc.timeout" */
#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[22])
#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[25])
/* "grpc.max_request_message_bytes" */
#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \
(grpc_static_slice_table[23])
(grpc_static_slice_table[26])
/* "grpc.max_response_message_bytes" */
#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \
(grpc_static_slice_table[24])
(grpc_static_slice_table[27])
/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */
#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \
(grpc_static_slice_table[25])
(grpc_static_slice_table[28])
/* "0" */
#define GRPC_MDSTR_0 (grpc_static_slice_table[26])
#define GRPC_MDSTR_0 (grpc_static_slice_table[29])
/* "1" */
#define GRPC_MDSTR_1 (grpc_static_slice_table[27])
#define GRPC_MDSTR_1 (grpc_static_slice_table[30])
/* "2" */
#define GRPC_MDSTR_2 (grpc_static_slice_table[28])
#define GRPC_MDSTR_2 (grpc_static_slice_table[31])
/* "identity" */
#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[29])
#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[32])
/* "gzip" */
#define GRPC_MDSTR_GZIP (grpc_static_slice_table[30])
#define GRPC_MDSTR_GZIP (grpc_static_slice_table[33])
/* "deflate" */
#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[31])
#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[34])
/* "trailers" */
#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[32])
#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[35])
/* "application/grpc" */
#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[33])
#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[36])
/* "POST" */
#define GRPC_MDSTR_POST (grpc_static_slice_table[34])
#define GRPC_MDSTR_POST (grpc_static_slice_table[37])
/* "200" */
#define GRPC_MDSTR_200 (grpc_static_slice_table[35])
#define GRPC_MDSTR_200 (grpc_static_slice_table[38])
/* "404" */
#define GRPC_MDSTR_404 (grpc_static_slice_table[36])
#define GRPC_MDSTR_404 (grpc_static_slice_table[39])
/* "http" */
#define GRPC_MDSTR_HTTP (grpc_static_slice_table[37])
#define GRPC_MDSTR_HTTP (grpc_static_slice_table[40])
/* "https" */
#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[38])
#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[41])
/* "grpc" */
#define GRPC_MDSTR_GRPC (grpc_static_slice_table[39])
#define GRPC_MDSTR_GRPC (grpc_static_slice_table[42])
/* "GET" */
#define GRPC_MDSTR_GET (grpc_static_slice_table[40])
#define GRPC_MDSTR_GET (grpc_static_slice_table[43])
/* "PUT" */
#define GRPC_MDSTR_PUT (grpc_static_slice_table[41])
#define GRPC_MDSTR_PUT (grpc_static_slice_table[44])
/* "/" */
#define GRPC_MDSTR_SLASH (grpc_static_slice_table[42])
#define GRPC_MDSTR_SLASH (grpc_static_slice_table[45])
/* "/index.html" */
#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[43])
#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[46])
/* "204" */
#define GRPC_MDSTR_204 (grpc_static_slice_table[44])
#define GRPC_MDSTR_204 (grpc_static_slice_table[47])
/* "206" */
#define GRPC_MDSTR_206 (grpc_static_slice_table[45])
#define GRPC_MDSTR_206 (grpc_static_slice_table[48])
/* "304" */
#define GRPC_MDSTR_304 (grpc_static_slice_table[46])
#define GRPC_MDSTR_304 (grpc_static_slice_table[49])
/* "400" */
#define GRPC_MDSTR_400 (grpc_static_slice_table[47])
#define GRPC_MDSTR_400 (grpc_static_slice_table[50])
/* "500" */
#define GRPC_MDSTR_500 (grpc_static_slice_table[48])
#define GRPC_MDSTR_500 (grpc_static_slice_table[51])
/* "accept-charset" */
#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[49])
/* "accept-encoding" */
#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[50])
#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[52])
/* "gzip, deflate" */
#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[51])
#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[53])
/* "accept-language" */
#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[52])
#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[54])
/* "accept-ranges" */
#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[53])
#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[55])
/* "accept" */
#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[54])
#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[56])
/* "access-control-allow-origin" */
#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[55])
#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[57])
/* "age" */
#define GRPC_MDSTR_AGE (grpc_static_slice_table[56])
#define GRPC_MDSTR_AGE (grpc_static_slice_table[58])
/* "allow" */
#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[57])
#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[59])
/* "authorization" */
#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[58])
#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[60])
/* "cache-control" */
#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[59])
#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[61])
/* "content-disposition" */
#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[60])
/* "content-encoding" */
#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[61])
#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[62])
/* "content-language" */
#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[62])
#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[63])
/* "content-length" */
#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[63])
#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[64])
/* "content-location" */
#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[64])
#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[65])
/* "content-range" */
#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[65])
#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[66])
/* "cookie" */
#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[66])
#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[67])
/* "date" */
#define GRPC_MDSTR_DATE (grpc_static_slice_table[67])
#define GRPC_MDSTR_DATE (grpc_static_slice_table[68])
/* "etag" */
#define GRPC_MDSTR_ETAG (grpc_static_slice_table[68])
#define GRPC_MDSTR_ETAG (grpc_static_slice_table[69])
/* "expect" */
#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[69])
#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[70])
/* "expires" */
#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[70])
#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[71])
/* "from" */
#define GRPC_MDSTR_FROM (grpc_static_slice_table[71])
#define GRPC_MDSTR_FROM (grpc_static_slice_table[72])
/* "if-match" */
#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[72])
#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[73])
/* "if-modified-since" */
#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[73])
#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[74])
/* "if-none-match" */
#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[74])
#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[75])
/* "if-range" */
#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[75])
#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[76])
/* "if-unmodified-since" */
#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[76])
#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[77])
/* "last-modified" */
#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[77])
#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[78])
/* "lb-cost-bin" */
#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[78])
#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[79])
/* "link" */
#define GRPC_MDSTR_LINK (grpc_static_slice_table[79])
#define GRPC_MDSTR_LINK (grpc_static_slice_table[80])
/* "location" */
#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[80])
#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[81])
/* "max-forwards" */
#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[81])
#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[82])
/* "proxy-authenticate" */
#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[82])
#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[83])
/* "proxy-authorization" */
#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[83])
#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[84])
/* "range" */
#define GRPC_MDSTR_RANGE (grpc_static_slice_table[84])
#define GRPC_MDSTR_RANGE (grpc_static_slice_table[85])
/* "referer" */
#define GRPC_MDSTR_REFERER (grpc_static_slice_table[85])
#define GRPC_MDSTR_REFERER (grpc_static_slice_table[86])
/* "refresh" */
#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[86])
#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[87])
/* "retry-after" */
#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[87])
#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[88])
/* "server" */
#define GRPC_MDSTR_SERVER (grpc_static_slice_table[88])
#define GRPC_MDSTR_SERVER (grpc_static_slice_table[89])
/* "set-cookie" */
#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[89])
#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[90])
/* "strict-transport-security" */
#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[90])
#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[91])
/* "transfer-encoding" */
#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[91])
#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[92])
/* "vary" */
#define GRPC_MDSTR_VARY (grpc_static_slice_table[92])
#define GRPC_MDSTR_VARY (grpc_static_slice_table[93])
/* "via" */
#define GRPC_MDSTR_VIA (grpc_static_slice_table[93])
#define GRPC_MDSTR_VIA (grpc_static_slice_table[94])
/* "www-authenticate" */
#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[94])
#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[95])
/* "identity,deflate" */
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[95])
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[96])
/* "identity,gzip" */
#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[96])
#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[97])
/* "deflate,gzip" */
#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[97])
#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[98])
/* "identity,deflate,gzip" */
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
(grpc_static_slice_table[98])
(grpc_static_slice_table[99])
extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable;
extern grpc_slice_refcount
@ -244,7 +247,7 @@ extern grpc_slice_refcount
#define GRPC_STATIC_METADATA_INDEX(static_slice) \
((int)((static_slice).refcount - grpc_static_metadata_refcounts))
#define GRPC_STATIC_MDELEM_COUNT 81
#define GRPC_STATIC_MDELEM_COUNT 86
extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "grpc-status": "0" */
@ -355,141 +358,156 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "content-disposition": "" */
#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[35], GRPC_MDELEM_STORAGE_STATIC))
/* "content-encoding": "identity" */
#define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC))
/* "content-encoding": "gzip" */
#define GRPC_MDELEM_CONTENT_ENCODING_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC))
/* "content-encoding": "" */
#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[36], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC))
/* "content-language": "" */
#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[37], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC))
/* "content-length": "" */
#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[38], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC))
/* "content-location": "" */
#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[39], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC))
/* "content-range": "" */
#define GRPC_MDELEM_CONTENT_RANGE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[40], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC))
/* "content-type": "" */
#define GRPC_MDELEM_CONTENT_TYPE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[41], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC))
/* "cookie": "" */
#define GRPC_MDELEM_COOKIE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[42], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC))
/* "date": "" */
#define GRPC_MDELEM_DATE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[43], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC))
/* "etag": "" */
#define GRPC_MDELEM_ETAG_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[44], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC))
/* "expect": "" */
#define GRPC_MDELEM_EXPECT_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[45], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC))
/* "expires": "" */
#define GRPC_MDELEM_EXPIRES_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[46], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC))
/* "from": "" */
#define GRPC_MDELEM_FROM_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[47], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC))
/* "host": "" */
#define GRPC_MDELEM_HOST_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[48], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC))
/* "if-match": "" */
#define GRPC_MDELEM_IF_MATCH_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[49], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC))
/* "if-modified-since": "" */
#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[50], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC))
/* "if-none-match": "" */
#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[51], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC))
/* "if-range": "" */
#define GRPC_MDELEM_IF_RANGE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[52], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC))
/* "if-unmodified-since": "" */
#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[53], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC))
/* "last-modified": "" */
#define GRPC_MDELEM_LAST_MODIFIED_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[54], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC))
/* "lb-token": "" */
#define GRPC_MDELEM_LB_TOKEN_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC))
/* "lb-cost-bin": "" */
#define GRPC_MDELEM_LB_COST_BIN_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC))
/* "link": "" */
#define GRPC_MDELEM_LINK_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC))
/* "location": "" */
#define GRPC_MDELEM_LOCATION_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC))
/* "max-forwards": "" */
#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC))
/* "proxy-authenticate": "" */
#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC))
/* "proxy-authorization": "" */
#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC))
/* "range": "" */
#define GRPC_MDELEM_RANGE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC))
/* "referer": "" */
#define GRPC_MDELEM_REFERER_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC))
/* "refresh": "" */
#define GRPC_MDELEM_REFRESH_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC))
/* "retry-after": "" */
#define GRPC_MDELEM_RETRY_AFTER_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC))
/* "server": "" */
#define GRPC_MDELEM_SERVER_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC))
/* "set-cookie": "" */
#define GRPC_MDELEM_SET_COOKIE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC))
/* "strict-transport-security": "" */
#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC))
/* "transfer-encoding": "" */
#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC))
/* "user-agent": "" */
#define GRPC_MDELEM_USER_AGENT_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC))
/* "vary": "" */
#define GRPC_MDELEM_VARY_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC))
/* "via": "" */
#define GRPC_MDELEM_VIA_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC))
/* "www-authenticate": "" */
#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[80], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[81], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[80], GRPC_MDELEM_STORAGE_STATIC))
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[82], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-encoding": "identity" */
#define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[83], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-encoding": "gzip" */
#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[84], GRPC_MDELEM_STORAGE_STATIC))
/* "accept-encoding": "identity,gzip" */
#define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[85], GRPC_MDELEM_STORAGE_STATIC))
grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);
typedef enum {
@ -508,7 +526,10 @@ typedef enum {
GRPC_BATCH_GRPC_TAGS_BIN,
GRPC_BATCH_GRPC_TRACE_BIN,
GRPC_BATCH_CONTENT_TYPE,
GRPC_BATCH_CONTENT_ENCODING,
GRPC_BATCH_ACCEPT_ENCODING,
GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST,
GRPC_BATCH_GRPC_INTERNAL_STREAM_ENCODING_REQUEST,
GRPC_BATCH_USER_AGENT,
GRPC_BATCH_HOST,
GRPC_BATCH_LB_TOKEN,
@ -533,7 +554,10 @@ typedef union {
struct grpc_linked_mdelem *grpc_tags_bin;
struct grpc_linked_mdelem *grpc_trace_bin;
struct grpc_linked_mdelem *content_type;
struct grpc_linked_mdelem *content_encoding;
struct grpc_linked_mdelem *accept_encoding;
struct grpc_linked_mdelem *grpc_internal_encoding_request;
struct grpc_linked_mdelem *grpc_internal_stream_encoding_request;
struct grpc_linked_mdelem *user_agent;
struct grpc_linked_mdelem *host;
struct grpc_linked_mdelem *lb_token;
@ -552,4 +576,10 @@ extern const uint8_t grpc_static_accept_encoding_metadata[8];
(GRPC_MAKE_MDELEM( \
&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], \
GRPC_MDELEM_STORAGE_STATIC))
extern const uint8_t grpc_static_accept_stream_encoding_metadata[4];
#define GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(algs) \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table \
[grpc_static_accept_stream_encoding_metadata[(algs)]], \
GRPC_MDELEM_STORAGE_STATIC))
#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */

@ -18,7 +18,9 @@
#include <string.h>
extern "C" {
#include "src/core/lib/channel/channel_stack.h"
}
#include "src/cpp/common/channel_filter.h"
#include <grpc++/impl/codegen/slice.h>

@ -26,9 +26,11 @@
#include <functional>
#include <vector>
extern "C" {
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/metadata_batch.h"
}
/// An interface to define filters.
///

@ -22,5 +22,5 @@
#include <grpc++/grpc++.h>
namespace grpc {
grpc::string Version() { return "1.5.0-dev"; }
grpc::string Version() { return "1.7.0-dev"; }
}

@ -33,7 +33,7 @@ namespace Grpc.Core.Tests
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
GrpcEnvironment.SetLogger(new ConsoleLogger());
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else

@ -4,26 +4,32 @@
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x86.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>grpc_csharp_ext.x86.dll</Link>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>grpc_csharp_ext.x64.dll</Link>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x86.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>libgrpc_csharp_ext.x86.so</Link>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x64.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>libgrpc_csharp_ext.x64.so</Link>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x86.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>libgrpc_csharp_ext.x86.dylib</Link>
<Visible>false</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x64.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>libgrpc_csharp_ext.x64.dylib</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
</Project>
</Project>

@ -43,7 +43,7 @@ namespace Grpc.Core
static readonly HashSet<Channel> registeredChannels = new HashSet<Channel>();
static readonly HashSet<Server> registeredServers = new HashSet<Server>();
static ILogger logger = new NullLogger();
static ILogger logger = new LogLevelFilterLogger(new ConsoleLogger(), LogLevel.Off, true);
readonly GrpcThreadPool threadPool;
readonly DebugStats debugStats = new DebugStats();

@ -64,7 +64,7 @@ namespace Grpc.Core.Internal
{
get
{
return counter;
return Interlocked.Read(ref counter);
}
}
}

@ -33,8 +33,8 @@ namespace Grpc.Core.Internal
internal class GrpcThreadPool
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<GrpcThreadPool>();
static readonly WaitCallback RunCompletionQueueEventCallbackSuccess = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, true));
static readonly WaitCallback RunCompletionQueueEventCallbackFailure = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, false));
const int FinishContinuationsSleepMillis = 10;
const int MaxFinishContinuationsSleepTotalMillis = 10000;
readonly GrpcEnvironment environment;
readonly object myLock = new object();
@ -42,6 +42,9 @@ namespace Grpc.Core.Internal
readonly int poolSize;
readonly int completionQueueCount;
readonly bool inlineHandlers;
readonly WaitCallback runCompletionQueueEventCallbackSuccess;
readonly WaitCallback runCompletionQueueEventCallbackFailure;
readonly AtomicCounter queuedContinuationCounter = new AtomicCounter();
readonly List<BasicProfiler> threadProfilers = new List<BasicProfiler>(); // profilers assigned to threadpool threads
@ -64,6 +67,9 @@ namespace Grpc.Core.Internal
this.inlineHandlers = inlineHandlers;
GrpcPreconditions.CheckArgument(poolSize >= completionQueueCount,
"Thread pool size cannot be smaller than the number of completion queues used.");
this.runCompletionQueueEventCallbackSuccess = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, true));
this.runCompletionQueueEventCallbackFailure = new WaitCallback((callback) => RunCompletionQueueEventCallback((OpCompletionDelegate) callback, false));
}
public void Start()
@ -173,7 +179,8 @@ namespace Grpc.Core.Internal
// Use cached delegates to avoid unnecessary allocations
if (!inlineHandlers)
{
ThreadPool.QueueUserWorkItem(success ? RunCompletionQueueEventCallbackSuccess : RunCompletionQueueEventCallbackFailure, callback);
queuedContinuationCounter.Increment();
ThreadPool.QueueUserWorkItem(success ? runCompletionQueueEventCallbackSuccess : runCompletionQueueEventCallbackFailure, callback);
}
else
{
@ -187,6 +194,24 @@ namespace Grpc.Core.Internal
}
}
while (ev.type != CompletionQueueEvent.CompletionType.Shutdown);
// Continuations are running on default threadpool that consists of background threads.
// GrpcThreadPool thread (a foreground thread) will not exit unless all queued work had
// been finished to prevent terminating the continuations queued prematurely.
int sleepIterations = 0;
while (queuedContinuationCounter.Count != 0)
{
// Only happens on shutdown and having pending continuations shouldn't very common,
// so sleeping here for a little bit is fine.
if (sleepIterations >= MaxFinishContinuationsSleepTotalMillis / FinishContinuationsSleepMillis)
{
Logger.Warning("Shutting down gRPC thread [{0}] with unfinished callbacks (Timed out waiting for callbacks to finish).",
Thread.CurrentThread.Name);
break;
}
Thread.Sleep(FinishContinuationsSleepMillis);
sleepIterations ++;
}
}
private static IReadOnlyCollection<CompletionQueueSafeHandle> CreateCompletionQueueList(GrpcEnvironment environment, int completionQueueCount)
@ -200,7 +225,7 @@ namespace Grpc.Core.Internal
return list.AsReadOnly();
}
private static void RunCompletionQueueEventCallback(OpCompletionDelegate callback, bool success)
private void RunCompletionQueueEventCallback(OpCompletionDelegate callback, bool success)
{
try
{
@ -210,6 +235,10 @@ namespace Grpc.Core.Internal
{
Logger.Error(e, "Exception occured while invoking completion delegate");
}
finally
{
queuedContinuationCounter.Decrement();
}
}
}
}

@ -39,6 +39,10 @@ namespace Grpc.Core.Logging
/// <summary>
/// Error severity.
/// </summary>
Error
Error,
/// <summary>
/// Logging is off.
/// </summary>
Off = int.MaxValue
}
}

@ -27,6 +27,8 @@ namespace Grpc.Core.Logging
/// <summary>Logger that filters out messages below certain log level.</summary>
public class LogLevelFilterLogger : ILogger
{
// Verbosity environment variable used by C core.
private const string CoreVerbosityEnvVarName = "GRPC_VERBOSITY";
readonly ILogger innerLogger;
readonly LogLevel logLevel;
@ -39,6 +41,19 @@ namespace Grpc.Core.Logging
this.logLevel = logLevel;
}
/// <summary>
/// Creates and instance of <c>LogLevelFilter.</c>
/// The <c>fromEnvironmentVariable</c> parameter allows looking up "GRPC_VERBOSITY" setting provided by C-core
/// and uses the same log level for C# logs. Using this setting is recommended as it can prevent unintentionally hiding
/// C core logs requested by "GRPC_VERBOSITY" environment variable (which could happen if C# logger's log level was set to a more restrictive value).
/// </summary>
/// <param name="logger">the logger to forward filtered logs to.</param>
/// <param name="defaultLogLevel">the default log level, unless overriden by env variable.</param>
/// <param name="fromEnvironmentVariable">if <c>true</c>, override log level with setting from environment variable.</param>
public LogLevelFilterLogger(ILogger logger, LogLevel defaultLogLevel, bool fromEnvironmentVariable) : this(logger, GetLogLevelFromEnvironment(defaultLogLevel, fromEnvironmentVariable))
{
}
/// <summary>
/// Returns a logger associated with the specified type.
/// </summary>
@ -141,5 +156,33 @@ namespace Grpc.Core.Logging
innerLogger.Error(exception, message);
}
}
/// <summary>Get log level based on a default and lookup of <c>GRPC_VERBOSITY</c> environment variable.</summary>
private static LogLevel GetLogLevelFromEnvironment(LogLevel defaultLogLevel, bool fromEnvironmentVariable)
{
if (!fromEnvironmentVariable)
{
return defaultLogLevel;
}
var verbosityString = System.Environment.GetEnvironmentVariable(CoreVerbosityEnvVarName);
if (verbosityString == null)
{
return defaultLogLevel;
}
// NOTE: C core doesn't have "WARNING" log level
switch (verbosityString.ToUpperInvariant())
{
case "DEBUG":
return LogLevel.Debug;
case "INFO":
return LogLevel.Info;
case "ERROR":
return LogLevel.Error;
default:
return defaultLogLevel;
}
}
}
}

@ -1,7 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
<GrpcCsharpVersion>1.5.0-dev</GrpcCsharpVersion>
<GrpcCsharpVersion>1.7.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.3.0</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -33,11 +33,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
public const string CurrentAssemblyFileVersion = "1.5.0.0";
public const string CurrentAssemblyFileVersion = "1.7.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
public const string CurrentVersion = "1.5.0-dev";
public const string CurrentVersion = "1.7.0-dev";
}
}

@ -33,7 +33,7 @@ namespace Grpc.Examples.Tests
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
GrpcEnvironment.SetLogger(new ConsoleLogger());
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else

@ -33,7 +33,7 @@ namespace Grpc.HealthCheck.Tests
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
GrpcEnvironment.SetLogger(new ConsoleLogger());
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else

@ -33,7 +33,7 @@ namespace Grpc.IntegrationTesting
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
GrpcEnvironment.SetLogger(new ConsoleLogger());
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else

@ -27,7 +27,7 @@ namespace Grpc.Microbenchmarks
{
public static void Main(string[] args)
{
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
GrpcEnvironment.SetLogger(new ConsoleLogger());
var benchmark = new SendMessageBenchmark();
benchmark.Init();
foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12})

@ -33,7 +33,7 @@ namespace Grpc.Reflection.Tests
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
GrpcEnvironment.SetLogger(new ConsoleLogger());
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else

@ -13,7 +13,7 @@
@rem limitations under the License.
@rem Current package versions
set VERSION=1.5.0-dev
set VERSION=1.7.0-dev
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe

@ -39,7 +39,7 @@ dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts
dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
nuget pack Grpc.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.nuspec -Version "1.7.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "1.7.0-dev" -OutputDirectory ../../artifacts
(cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)

@ -1,6 +1,6 @@
{
"name": "grpc-health-check",
"version": "1.5.0-dev",
"version": "1.7.0-dev",
"author": "Google Inc.",
"description": "Health check service for use with gRPC",
"repository": {
@ -15,7 +15,7 @@
}
],
"dependencies": {
"grpc": "^1.5.0-dev",
"grpc": "^1.7.0-dev",
"lodash": "^3.9.3",
"google-protobuf": "^3.0.0"
},

@ -1,6 +1,6 @@
{
"name": "grpc-tools",
"version": "1.5.0-dev",
"version": "1.7.0-dev",
"author": "Google Inc.",
"description": "Tools for developing with gRPC on Node.js",
"homepage": "https://grpc.io/",

@ -42,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.5.0-dev'
v = '1.7.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC

@ -0,0 +1,29 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import "GRPCCall.h"
#import "GRPCCall+OAuth2.h"
#import <Google/SignIn.h>
/**
* Extend GIDSignIn class to comply GRPCAuthorizationProtocol
*/
@interface GIDSignIn (GRPC) <GRPCAuthorizationProtocol>
- (void)getTokenWithHandler:(void (^)(NSString *token))hander;
@end

@ -1,6 +1,6 @@
/*
*
* Copyright 2015 gRPC authors.
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,9 +16,13 @@
*
*/
#ifndef GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H
#define GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H
#import "GRPCCall+GID.h"
/* Internal interfaces between modules within the gpr support library. */
@implementation GIDSignIn (GRPC)
#endif /* GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H */
- (void)getTokenWithHandler:(void (^)(NSString *token))handler {
NSString *token = self.currentUser.authentication.accessToken;
handler(token);
}
@end

@ -18,6 +18,13 @@
#import "GRPCCall.h"
/**
* The protocol of an OAuth2 token object from which GRPCCall can acquire a token.
*/
@protocol GRPCAuthorizationProtocol
- (void)getTokenWithHandler:(void (^)(NSString *token))hander;
@end
/** Helpers for setting and reading headers compatible with OAuth2. */
@interface GRPCCall (OAuth2)
@ -33,4 +40,12 @@
/** Returns the value (if any) of the "www-authenticate" response header (the challenge header). */
@property(atomic, readonly) NSString *oauth2ChallengeHeader;
/**
* The authorization token object to be used when starting the call. If the value is set to nil, no
* oauth authentication will be used.
*
* If tokenProvider exists, it takes precedence over the token set by oauth2AccessToken.
*/
@property(atomic, strong) id<GRPCAuthorizationProtocol> tokenProvider;
@end

@ -16,6 +16,8 @@
*
*/
#import <objc/runtime.h>
#import "GRPCCall+OAuth2.h"
static NSString * const kAuthorizationHeader = @"authorization";
@ -23,6 +25,7 @@ static NSString * const kBearerPrefix = @"Bearer ";
static NSString * const kChallengeHeader = @"www-authenticate";
@implementation GRPCCall (OAuth2)
@dynamic tokenProvider;
- (NSString *)oauth2AccessToken {
NSString *headerValue = self.requestHeaders[kAuthorizationHeader];
@ -45,4 +48,12 @@ static NSString * const kChallengeHeader = @"www-authenticate";
return self.responseHeaders[kChallengeHeader];
}
- (void)setTokenProvider:(id<GRPCAuthorizationProtocol>)tokenProvider {
objc_setAssociatedObject(self, @selector(tokenProvider), tokenProvider, OBJC_ASSOCIATION_RETAIN);
}
- (id<GRPCAuthorizationProtocol>)tokenProvider {
return objc_getAssociatedObject(self, @selector(tokenProvider));
}
@end

@ -18,6 +18,8 @@
#import "GRPCCall.h"
#import "GRPCCall+OAuth2.h"
#include <grpc/grpc.h>
#include <grpc/support/time.h>
#import <RxLibrary/GRXConcurrentWriteable.h>
@ -40,10 +42,14 @@ NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey";
NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
static NSMutableDictionary *callFlags;
static NSString * const kAuthorizationHeader = @"authorization";
static NSString * const kBearerPrefix = @"Bearer ";
@interface GRPCCall () <GRXWriteable>
// Make them read-write.
@property(atomic, strong) NSDictionary *responseHeaders;
@property(atomic, strong) NSDictionary *responseTrailers;
@property(atomic) BOOL isWaitingForToken;
@end
// The following methods of a C gRPC call object aren't reentrant, and thus
@ -181,9 +187,6 @@ static NSMutableDictionary *callFlags;
- (void)finishWithError:(NSError *)errorOrNil {
@synchronized(self) {
if (_state == GRXWriterStateFinished) {
return;
}
_state = GRXWriterStateFinished;
}
@ -211,7 +214,11 @@ static NSMutableDictionary *callFlags;
[self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeCancelled
userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]];
[self cancelCall];
if (!self.isWaitingForToken) {
[self cancelCall];
} else {
self.isWaitingForToken = NO;
}
}
- (void)dealloc {
@ -410,22 +417,13 @@ static NSMutableDictionary *callFlags;
#pragma mark GRXWriter implementation
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
@synchronized(self) {
_state = GRXWriterStateStarted;
}
// Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled).
// This makes RPCs in which the call isn't externally retained possible (as long as it is started
// before being autoreleased).
// Care is taken not to retain self strongly in any of the blocks used in this implementation, so
// that the life of the instance is determined by this retain cycle.
_retainSelf = self;
- (void)startCallWithWriteable:(id<GRXWriteable>)writeable {
_responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable
dispatchQueue:_responseQueue];
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host serverName:_serverName path:_path];
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host
serverName:_serverName
path:_path];
NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
[self sendHeaders:_requestHeaders];
@ -437,20 +435,49 @@ static NSMutableDictionary *callFlags;
// TODO(jcanizales): Check this on init.
[NSException raise:NSInvalidArgumentException format:@"host of %@ is nil", _host];
}
__weak typeof(self) weakSelf = self;
_connectivityMonitor = [GRPCConnectivityMonitor monitorWithHost:host];
__weak typeof(self) weakSelf = self;
void (^handler)() = ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeUnavailable
userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]];
}
[strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeUnavailable
userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]];
};
[_connectivityMonitor handleLossWithHandler:handler
wifiStatusChangeHandler:nil];
}
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
@synchronized(self) {
_state = GRXWriterStateStarted;
}
// Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled).
// This makes RPCs in which the call isn't externally retained possible (as long as it is started
// before being autoreleased).
// Care is taken not to retain self strongly in any of the blocks used in this implementation, so
// that the life of the instance is determined by this retain cycle.
_retainSelf = self;
if (self.tokenProvider != nil) {
self.isWaitingForToken = YES;
__weak typeof(self) weakSelf = self;
[self.tokenProvider getTokenWithHandler:^(NSString *token){
typeof(self) strongSelf = weakSelf;
if (strongSelf && strongSelf.isWaitingForToken) {
if (token) {
NSString *t = [kBearerPrefix stringByAppendingString:token];
strongSelf.requestHeaders[kAuthorizationHeader] = t;
}
[strongSelf startCallWithWriteable:writeable];
strongSelf.isWaitingForToken = NO;
}
}];
} else {
[self startCallWithWriteable:writeable];
}
}
- (void)setState:(GRXWriterState)newState {
@synchronized(self) {
// Manual transitions are only allowed from the started or paused states.

@ -103,7 +103,6 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
}
- (void)setObject:(id)obj forKey:(NSString *)key {
[self checkCallIsNotStarted];
CheckIsNonNilASCII(@"Header name", key);
key = key.lowercaseString;
CheckKeyValuePairIsValid(key, obj);

@ -68,6 +68,8 @@
_op.data.send_initial_metadata.metadata = metadata.grpc_metadataArray;
_op.data.send_initial_metadata.maybe_compression_level.is_set = false;
_op.data.send_initial_metadata.maybe_compression_level.level = 0;
_op.data.send_initial_metadata.maybe_stream_compression_level.is_set = false;
_op.data.send_initial_metadata.maybe_stream_compression_level.level = 0;
_op.flags = flags;
_handler = handler;
}

@ -23,4 +23,4 @@
// `tools/buildgen/generate_projects.sh`.
#define GRPC_OBJC_VERSION_STRING @"1.5.0-dev"
#define GRPC_OBJC_VERSION_STRING @"1.7.0-dev"

@ -28,7 +28,7 @@
@implementation GRXConcurrentWriteable {
dispatch_queue_t _writeableQueue;
// This ensures that writesFinishedWithError: is only sent once to the writeable.
dispatch_once_t _alreadyFinished;
BOOL _alreadyFinished;
}
- (instancetype)init {
@ -65,19 +65,35 @@
- (void)enqueueSuccessfulCompletion {
dispatch_async(_writeableQueue, ^{
dispatch_once(&_alreadyFinished, ^{
BOOL finished = NO;
@synchronized (self) {
if (!_alreadyFinished) {
_alreadyFinished = YES;
} else {
finished = YES;
}
}
if (!finished) {
// Cancellation is now impossible. None of the other three blocks can run concurrently with
// this one.
[self.writeable writesFinishedWithError:nil];
// Skip any possible message to the wrapped writeable enqueued after this one.
self.writeable = nil;
});
}
});
}
- (void)cancelWithError:(NSError *)error {
NSAssert(error, @"For a successful completion, use enqueueSuccessfulCompletion.");
dispatch_once(&_alreadyFinished, ^{
BOOL finished = NO;
@synchronized (self) {
if (!_alreadyFinished) {
_alreadyFinished = YES;
} else {
finished = YES;
}
}
if (!finished) {
// Skip any of the still-enqueued messages to the wrapped writeable. We use the atomic setter to
// nillify writeable because we might be running concurrently with the blocks in
// _writeableQueue, and assignment with ARC isn't atomic.
@ -87,15 +103,23 @@
dispatch_async(_writeableQueue, ^{
[writeable writesFinishedWithError:error];
});
});
}
}
- (void)cancelSilently {
dispatch_once(&_alreadyFinished, ^{
BOOL finished = NO;
@synchronized (self) {
if (!_alreadyFinished) {
_alreadyFinished = YES;
} else {
finished = YES;
}
}
if (!finished) {
// Skip any of the still-enqueued messages to the wrapped writeable. We use the atomic setter to
// nillify writeable because we might be running concurrently with the blocks in
// _writeableQueue, and assignment with ARC isn't atomic.
self.writeable = nil;
});
}
}
@end

@ -37,11 +37,11 @@ rm -f Podfile.lock
pod install
set -o pipefail
XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail|\bpassed\b)'
XCODEBUILD_FILTER='(^CompileC |^Ld |^.*clang |^ *cd |^ *export |^Libtool |^.*libtool |^CpHeader |^ *builtin-copy )'
xcodebuild \
build \
-workspace *.xcworkspace \
-scheme $SCHEME \
-destination name="iPhone 6" \
| egrep "$XCODEBUILD_FILTER" \
| egrep -v "(GPBDictionary|GPBArray)" -
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v "^$" -

@ -38,7 +38,7 @@ trap 'kill -9 `jobs -p` ; echo "EXIT TIME: $(date)"' EXIT
# element of the pipe fails.
# TODO(jcanizales): Use xctool instead? Issue #2540.
set -o pipefail
XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail|\bpassed\b)'
XCODEBUILD_FILTER='(^CompileC |^Ld |^.*clang |^ *cd |^ *export |^Libtool |^.*libtool |^CpHeader |^ *builtin-copy )'
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
@ -48,8 +48,8 @@ xcodebuild \
HOST_PORT_LOCAL=localhost:5050 \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
test \
| egrep "$XCODEBUILD_FILTER" \
| egrep -v "(GPBDictionary|GPBArray)" -
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' -
echo "TIME: $(date)"
xcodebuild \
@ -60,16 +60,12 @@ xcodebuild \
| egrep "$XCODEBUILD_FILTER" \
| egrep -v "(GPBDictionary|GPBArray)" -
# Temporarily disabled for (possible) flakiness on Jenkins.
# Fix or reenable after confirmation/disconfirmation that it is the source of
# Jenkins problem.
# echo "TIME: $(date)"
# xcodebuild \
# -workspace Tests.xcworkspace \
# -scheme CronetUnitTests \
# -destination name="iPhone 6" \
# test | xcpretty
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme CronetUnitTests \
-destination name="iPhone 6" \
test | xcpretty
echo "TIME: $(date)"
xcodebuild \

@ -2,7 +2,7 @@
"name": "grpc/grpc-dev",
"description": "gRPC library for PHP - for Developement use only",
"license": "Apache-2.0",
"version": "1.5.0",
"version": "1.7.0",
"require": {
"php": ">=5.5.0",
"google/protobuf": "^v3.3.0"

@ -179,7 +179,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
grpc_metadata_array metadata;
bool cleanup = true;
if (Z_TYPE_P(retval) != IS_ARRAY) {
if (retval == NULL || Z_TYPE_P(retval) != IS_ARRAY) {
cleanup = false;
code = GRPC_STATUS_INVALID_ARGUMENT;
} else if (!create_metadata_array(retval, &metadata)) {

@ -66,6 +66,8 @@ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), p->wrapper->key,
key_len, rsrc))) {
grpc_channel_destroy(p->wrapper->wrapped);
free(p->wrapper->target);
free(p->wrapper->args_hashstr);
}
gpr_mu_unlock(&global_persistent_list_mu);
}
@ -158,7 +160,7 @@ void create_and_add_channel_to_persistent_list(
grpc_channel_args args,
wrapped_grpc_channel_credentials *creds,
char *key,
php_grpc_int key_len) {
php_grpc_int key_len TSRMLS_DC) {
php_grpc_zend_resource new_rsrc;
channel_persistent_le_t *le;
// this links each persistent list entry to a destructor
@ -187,10 +189,8 @@ void create_and_add_channel_to_persistent_list(
* credentials.
*
* If the $args array contains a "force_new" key mapping to a boolean value
* of "true", a new underlying grpc_channel will be created regardless. If
* there are any opened channels on the same hostname, user must manually
* call close() on those dangling channels before the end of the PHP
* script.
* of "true", a new and separate underlying grpc_channel will be created
* and returned. This will not affect existing channels.
*
* @param string $target The hostname to associate with this channel
* @param array $args_array The arguments to pass to the Channel
@ -273,19 +273,15 @@ PHP_METHOD(Channel, __construct) {
}
channel->wrapper = malloc(sizeof(grpc_channel_wrapper));
channel->wrapper->key = key;
channel->wrapper->target = target;
channel->wrapper->args_hashstr = sha1str;
channel->wrapper->target = strdup(target);
channel->wrapper->args_hashstr = strdup(sha1str);
if (creds != NULL && creds->hashstr != NULL) {
channel->wrapper->creds_hashstr = creds->hashstr;
}
gpr_mu_init(&channel->wrapper->mu);
smart_str_free(&buf);
if (force_new) {
php_grpc_delete_persistent_list_entry(key, key_len TSRMLS_CC);
}
if (creds != NULL && creds->has_call_creds) {
if (force_new || (creds != NULL && creds->has_call_creds)) {
// If the ChannelCredentials object was composed with a CallCredentials
// object, there is no way we can tell them apart. Do NOT persist
// them. They should be individually destroyed.
@ -293,7 +289,7 @@ PHP_METHOD(Channel, __construct) {
} else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), key,
key_len, rsrc))) {
create_and_add_channel_to_persistent_list(
channel, target, args, creds, key, key_len);
channel, target, args, creds, key, key_len TSRMLS_CC);
} else {
// Found a previously stored channel in the persistent list
channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
@ -303,7 +299,7 @@ PHP_METHOD(Channel, __construct) {
strcmp(creds->hashstr, le->channel->creds_hashstr) != 0)) {
// somehow hash collision
create_and_add_channel_to_persistent_list(
channel, target, args, creds, key, key_len);
channel, target, args, creds, key, key_len TSRMLS_CC);
} else {
channel->wrapper = le->channel;
}
@ -416,12 +412,14 @@ PHP_METHOD(Channel, close) {
gpr_mu_lock(&channel->wrapper->mu);
if (channel->wrapper->wrapped != NULL) {
grpc_channel_destroy(channel->wrapper->wrapped);
free(channel->wrapper->target);
free(channel->wrapper->args_hashstr);
channel->wrapper->wrapped = NULL;
}
php_grpc_delete_persistent_list_entry(channel->wrapper->key,
strlen(channel->wrapper->key)
TSRMLS_CC);
php_grpc_delete_persistent_list_entry(channel->wrapper->key,
strlen(channel->wrapper->key)
TSRMLS_CC);
}
gpr_mu_unlock(&channel->wrapper->mu);
}
@ -449,12 +447,11 @@ static void php_grpc_channel_plink_dtor(php_grpc_zend_resource *rsrc
gpr_mu_lock(&le->channel->mu);
if (le->channel->wrapped != NULL) {
grpc_channel_destroy(le->channel->wrapped);
free(le->channel->key);
free(le->channel);
free(le->channel->target);
free(le->channel->args_hashstr);
}
gpr_mu_unlock(&le->channel->mu);
}
free(le);
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
@ -496,6 +493,7 @@ GRPC_STARTUP_FUNCTION(channel) {
INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods);
ce.create_object = create_wrapped_grpc_channel;
grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC);
gpr_mu_init(&global_persistent_list_mu);
le_plink = zend_register_list_destructors_ex(
NULL, php_grpc_channel_plink_dtor, "Persistent Channel", module_number);
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);

@ -135,6 +135,8 @@ PHP_METHOD(ChannelCredentials, createSsl) {
pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL;
grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
/* "|s!s!s!" == 3 optional nullable strings */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!",
&pem_root_certs, &root_certs_length,
@ -148,7 +150,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
}
php_grpc_int hashkey_len = root_certs_length + cert_chain_length;
char hashkey[hashkey_len];
char *hashkey = emalloc(hashkey_len);
if (root_certs_length > 0) {
strcpy(hashkey, pem_root_certs);
}
@ -164,6 +166,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, hashstr, false
TSRMLS_CC);
efree(hashkey);
RETURN_DESTROY_ZVAL(creds_object);
}
@ -177,6 +180,8 @@ PHP_METHOD(ChannelCredentials, createComposite) {
zval *cred1_obj;
zval *cred2_obj;
grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
/* "OO" == 2 Objects */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj,
grpc_ce_channel_credentials, &cred2_obj,
@ -245,7 +250,6 @@ void grpc_init_channel_credentials(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\ChannelCredentials",
channel_credentials_methods);
grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
ce.create_object = create_wrapped_grpc_channel_credentials;
grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC);
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel_credentials,

@ -34,7 +34,8 @@
#include <ext/standard/info.h>
#include "php_grpc.h"
// ZEND_DECLARE_MODULE_GLOBALS(grpc)
ZEND_DECLARE_MODULE_GLOBALS(grpc)
static PHP_GINIT_FUNCTION(grpc);
/* {{{ grpc_functions[]
*
@ -55,13 +56,17 @@ zend_module_entry grpc_module_entry = {
grpc_functions,
PHP_MINIT(grpc),
PHP_MSHUTDOWN(grpc),
NULL,
PHP_RINIT(grpc),
NULL,
PHP_MINFO(grpc),
#if ZEND_MODULE_API_NO >= 20010901
PHP_GRPC_VERSION,
#endif
STANDARD_MODULE_PROPERTIES};
PHP_MODULE_GLOBALS(grpc),
PHP_GINIT(grpc),
NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX};
/* }}} */
#ifdef COMPILE_DL_GRPC
@ -99,7 +104,6 @@ PHP_MINIT_FUNCTION(grpc) {
REGISTER_INI_ENTRIES();
*/
/* Register call error constants */
grpc_init();
REGISTER_LONG_CONSTANT("Grpc\\CALL_OK", GRPC_CALL_OK,
CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR", GRPC_CALL_ERROR,
@ -227,7 +231,6 @@ PHP_MINIT_FUNCTION(grpc) {
grpc_init_channel_credentials(TSRMLS_C);
grpc_init_call_credentials(TSRMLS_C);
grpc_init_server_credentials(TSRMLS_C);
grpc_php_init_completion_queue(TSRMLS_C);
return SUCCESS;
}
/* }}} */
@ -240,9 +243,12 @@ PHP_MSHUTDOWN_FUNCTION(grpc) {
*/
// WARNING: This function IS being called by PHP when the extension
// is unloaded but the logs were somehow suppressed.
grpc_shutdown_timeval(TSRMLS_C);
grpc_php_shutdown_completion_queue(TSRMLS_C);
grpc_shutdown();
if (GRPC_G(initialized)) {
grpc_shutdown_timeval(TSRMLS_C);
grpc_php_shutdown_completion_queue(TSRMLS_C);
grpc_shutdown();
GRPC_G(initialized) = 0;
}
return SUCCESS;
}
/* }}} */
@ -259,6 +265,26 @@ PHP_MINFO_FUNCTION(grpc) {
*/
}
/* }}} */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(grpc) {
if (!GRPC_G(initialized)) {
grpc_init();
grpc_php_init_completion_queue(TSRMLS_C);
GRPC_G(initialized) = 1;
}
return SUCCESS;
}
/* }}} */
/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(grpc) {
grpc_globals->initialized = 0;
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and
unfold functions in source code. See the corresponding marks just before
function definition, where the functions purpose is also documented. Please

@ -49,14 +49,16 @@ PHP_MINIT_FUNCTION(grpc);
PHP_MSHUTDOWN_FUNCTION(grpc);
/* Displays information about the module */
PHP_MINFO_FUNCTION(grpc);
/* Code that runs at request start */
PHP_RINIT_FUNCTION(grpc);
/*
Declare any global variables you may need between the BEGIN
and END macros here:
*/
ZEND_BEGIN_MODULE_GLOBALS(grpc)
zend_bool initialized;
ZEND_END_MODULE_GLOBALS(grpc)
*/
/* In every utility function you add that needs to use variables
in php_grpc_globals, call TSRMLS_FETCH(); after declaring other

@ -20,6 +20,6 @@
#ifndef VERSION_H
#define VERSION_H
#define PHP_GRPC_VERSION "1.5.0dev"
#define PHP_GRPC_VERSION "1.7.0dev"
#endif /* VERSION_H */

@ -40,13 +40,11 @@ class ServerStreamingCall extends AbstractCall
if (array_key_exists('flags', $options)) {
$message_array['flags'] = $options['flags'];
}
$event = $this->call->startBatch([
$this->call->startBatch([
OP_SEND_INITIAL_METADATA => $metadata,
OP_RECV_INITIAL_METADATA => true,
OP_SEND_MESSAGE => $message_array,
OP_SEND_CLOSE_FROM_CLIENT => true,
]);
$this->metadata = $event->metadata;
}
/**
@ -54,9 +52,15 @@ class ServerStreamingCall extends AbstractCall
*/
public function responses()
{
$response = $this->call->startBatch([
OP_RECV_MESSAGE => true,
])->message;
$batch = [OP_RECV_MESSAGE => true];
if ($this->metadata === null) {
$batch[OP_RECV_INITIAL_METADATA] = true;
}
$read_event = $this->call->startBatch($batch);
if ($this->metadata === null) {
$this->metadata = $read_event->metadata;
}
$response = $read_event->message;
while ($response !== null) {
yield $this->_deserializeResponse($response);
$response = $this->call->startBatch([
@ -81,4 +85,16 @@ class ServerStreamingCall extends AbstractCall
return $status_event->status;
}
/**
* @return mixed The metadata sent by the server
*/
public function getMetadata()
{
if ($this->metadata === null) {
$event = $this->call->startBatch([OP_RECV_INITIAL_METADATA => true]);
$this->metadata = $event->metadata;
}
return $this->metadata;
}
}

@ -40,13 +40,11 @@ class UnaryCall extends AbstractCall
if (isset($options['flags'])) {
$message_array['flags'] = $options['flags'];
}
$event = $this->call->startBatch([
$this->call->startBatch([
OP_SEND_INITIAL_METADATA => $metadata,
OP_RECV_INITIAL_METADATA => true,
OP_SEND_MESSAGE => $message_array,
OP_SEND_CLOSE_FROM_CLIENT => true,
]);
$this->metadata = $event->metadata;
}
/**
@ -56,14 +54,32 @@ class UnaryCall extends AbstractCall
*/
public function wait()
{
$event = $this->call->startBatch([
$batch = [
OP_RECV_MESSAGE => true,
OP_RECV_STATUS_ON_CLIENT => true,
]);
];
if ($this->metadata === null) {
$batch[OP_RECV_INITIAL_METADATA] = true;
}
$event = $this->call->startBatch($batch);
if ($this->metadata === null) {
$this->metadata = $event->metadata;
}
$status = $event->status;
$this->trailing_metadata = $status->metadata;
return [$this->_deserializeResponse($event->message), $status];
}
/**
* @return mixed The metadata sent by the server
*/
public function getMetadata()
{
if ($this->metadata === null) {
$event = $this->call->startBatch([OP_RECV_INITIAL_METADATA => true]);
$this->metadata = $event->metadata;
}
return $this->metadata;
}
}

@ -517,8 +517,6 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
// any dangling old connection to the same host must be
// manually closed
$this->channel1->close();
$this->channel2->close();
}
@ -529,6 +527,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$this->channel1 = new Grpc\Channel('localhost:1', []);
$this->channel2 = new Grpc\Channel('localhost:1',
["force_new" => true]);
// channel3 shares with channel1
$this->channel3 = new Grpc\Channel('localhost:1', []);
// try to connect on channel2
@ -540,29 +539,31 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$state = $this->channel2->getConnectivityState();
$this->assertConnecting($state);
$state = $this->channel3->getConnectivityState();
$this->assertConnecting($state);
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
$this->channel1->close();
$this->channel2->close();
}
/**
* @expectedException RuntimeException
*/
public function testPersistentChannelForceNewOldChannelClose()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$this->channel2 = new Grpc\Channel('localhost:1',
["force_new" => true]);
// channel3 shares with channel1
$this->channel3 = new Grpc\Channel('localhost:1', []);
$this->channel1->close();
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
$state = $this->channel3->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
$this->channel2->close();
$this->channel3->close();
// channel3 already closed
$state = $this->channel3->getConnectivityState();
}
public function testPersistentChannelForceNewNewChannelClose()

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
__version__ = """1.5.0.dev0"""
__version__ = """1.7.0.dev0"""

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
VERSION='1.5.0.dev0'
VERSION='1.7.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
VERSION='1.5.0.dev0'
VERSION='1.7.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
VERSION='1.5.0.dev0'
VERSION='1.7.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
VERSION='1.5.0.dev0'
VERSION='1.7.0.dev0'

@ -95,9 +95,6 @@ class ReflectionServicerTest(unittest.TestCase):
)),)
self.assertSequenceEqual(expected_responses, responses)
@unittest.skip(
'TODO(mmx): enable when (pure) python protobuf issue is fixed'
'(see https://github.com/google/protobuf/issues/2882)')
def testFileContainingExtension(self):
requests = (reflection_pb2.ServerReflectionRequest(
file_containing_extension=reflection_pb2.ExtensionRequest(

@ -905,6 +905,9 @@ static void Init_grpc_error_codes() {
rb_define_const(grpc_rb_mRpcErrors, "INVALID_FLAGS",
UINT2NUM(GRPC_CALL_ERROR_INVALID_FLAGS));
/* Hint the GC that this is a global and shouldn't be sweeped. */
rb_global_variable(&rb_error_code_details);
/* Add the detail strings to a Hash */
rb_error_code_details = rb_hash_new();
rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_OK),

@ -62,11 +62,14 @@ census_resource_id_type census_resource_id_import;
census_record_values_type census_record_values_import;
grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import;
grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import;
grpc_stream_compression_algorithm_name_type grpc_stream_compression_algorithm_name_import;
grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import;
grpc_stream_compression_algorithm_for_level_type grpc_stream_compression_algorithm_for_level_import;
grpc_compression_options_init_type grpc_compression_options_init_import;
grpc_compression_options_enable_algorithm_type grpc_compression_options_enable_algorithm_import;
grpc_compression_options_disable_algorithm_type grpc_compression_options_disable_algorithm_import;
grpc_compression_options_is_algorithm_enabled_type grpc_compression_options_is_algorithm_enabled_import;
grpc_compression_options_is_stream_compression_algorithm_enabled_type grpc_compression_options_is_stream_compression_algorithm_enabled_import;
grpc_metadata_array_init_type grpc_metadata_array_init_import;
grpc_metadata_array_destroy_type grpc_metadata_array_destroy_import;
grpc_call_details_init_type grpc_call_details_init_import;
@ -365,11 +368,14 @@ void grpc_rb_load_imports(HMODULE library) {
census_record_values_import = (census_record_values_type) GetProcAddress(library, "census_record_values");
grpc_compression_algorithm_parse_import = (grpc_compression_algorithm_parse_type) GetProcAddress(library, "grpc_compression_algorithm_parse");
grpc_compression_algorithm_name_import = (grpc_compression_algorithm_name_type) GetProcAddress(library, "grpc_compression_algorithm_name");
grpc_stream_compression_algorithm_name_import = (grpc_stream_compression_algorithm_name_type) GetProcAddress(library, "grpc_stream_compression_algorithm_name");
grpc_compression_algorithm_for_level_import = (grpc_compression_algorithm_for_level_type) GetProcAddress(library, "grpc_compression_algorithm_for_level");
grpc_stream_compression_algorithm_for_level_import = (grpc_stream_compression_algorithm_for_level_type) GetProcAddress(library, "grpc_stream_compression_algorithm_for_level");
grpc_compression_options_init_import = (grpc_compression_options_init_type) GetProcAddress(library, "grpc_compression_options_init");
grpc_compression_options_enable_algorithm_import = (grpc_compression_options_enable_algorithm_type) GetProcAddress(library, "grpc_compression_options_enable_algorithm");
grpc_compression_options_disable_algorithm_import = (grpc_compression_options_disable_algorithm_type) GetProcAddress(library, "grpc_compression_options_disable_algorithm");
grpc_compression_options_is_algorithm_enabled_import = (grpc_compression_options_is_algorithm_enabled_type) GetProcAddress(library, "grpc_compression_options_is_algorithm_enabled");
grpc_compression_options_is_stream_compression_algorithm_enabled_import = (grpc_compression_options_is_stream_compression_algorithm_enabled_type) GetProcAddress(library, "grpc_compression_options_is_stream_compression_algorithm_enabled");
grpc_metadata_array_init_import = (grpc_metadata_array_init_type) GetProcAddress(library, "grpc_metadata_array_init");
grpc_metadata_array_destroy_import = (grpc_metadata_array_destroy_type) GetProcAddress(library, "grpc_metadata_array_destroy");
grpc_call_details_init_import = (grpc_call_details_init_type) GetProcAddress(library, "grpc_call_details_init");

@ -167,9 +167,15 @@ extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_im
typedef int(*grpc_compression_algorithm_name_type)(grpc_compression_algorithm algorithm, char **name);
extern grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import;
#define grpc_compression_algorithm_name grpc_compression_algorithm_name_import
typedef int(*grpc_stream_compression_algorithm_name_type)(grpc_stream_compression_algorithm algorithm, char **name);
extern grpc_stream_compression_algorithm_name_type grpc_stream_compression_algorithm_name_import;
#define grpc_stream_compression_algorithm_name grpc_stream_compression_algorithm_name_import
typedef grpc_compression_algorithm(*grpc_compression_algorithm_for_level_type)(grpc_compression_level level, uint32_t accepted_encodings);
extern grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import;
#define grpc_compression_algorithm_for_level grpc_compression_algorithm_for_level_import
typedef grpc_stream_compression_algorithm(*grpc_stream_compression_algorithm_for_level_type)(grpc_stream_compression_level level, uint32_t accepted_stream_encodings);
extern grpc_stream_compression_algorithm_for_level_type grpc_stream_compression_algorithm_for_level_import;
#define grpc_stream_compression_algorithm_for_level grpc_stream_compression_algorithm_for_level_import
typedef void(*grpc_compression_options_init_type)(grpc_compression_options *opts);
extern grpc_compression_options_init_type grpc_compression_options_init_import;
#define grpc_compression_options_init grpc_compression_options_init_import
@ -182,6 +188,9 @@ extern grpc_compression_options_disable_algorithm_type grpc_compression_options_
typedef int(*grpc_compression_options_is_algorithm_enabled_type)(const grpc_compression_options *opts, grpc_compression_algorithm algorithm);
extern grpc_compression_options_is_algorithm_enabled_type grpc_compression_options_is_algorithm_enabled_import;
#define grpc_compression_options_is_algorithm_enabled grpc_compression_options_is_algorithm_enabled_import
typedef int(*grpc_compression_options_is_stream_compression_algorithm_enabled_type)(const grpc_compression_options *opts, grpc_stream_compression_algorithm algorithm);
extern grpc_compression_options_is_stream_compression_algorithm_enabled_type grpc_compression_options_is_stream_compression_algorithm_enabled_import;
#define grpc_compression_options_is_stream_compression_algorithm_enabled grpc_compression_options_is_stream_compression_algorithm_enabled_import
typedef void(*grpc_metadata_array_init_type)(grpc_metadata_array *array);
extern grpc_metadata_array_init_type grpc_metadata_array_init_import;
#define grpc_metadata_array_init grpc_metadata_array_init_import

@ -99,9 +99,13 @@ module GRPC
# event. Send a status of deadline exceeded
GRPC.logger.warn("late call: #{active_call}")
send_status(active_call, DEADLINE_EXCEEDED, 'late')
rescue StandardError => e
rescue StandardError, NotImplementedError => e
# This will usuaally be an unhandled error in the handling code.
# Send back a UNKNOWN status to the client
#
# Note: this intentionally does not map NotImplementedError to
# UNIMPLEMENTED because NotImplementedError is intended for low-level
# OS interaction (e.g. syscalls) not supported by the current OS.
GRPC.logger.warn("failed handler: #{active_call}; sending status:UNKNOWN")
GRPC.logger.warn(e)
send_status(active_call, UNKNOWN, "#{e.class}: #{e.message}")

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

Loading…
Cancel
Save