Merge remote-tracking branch 'upstream/master' into fix-stream-compression-config-interface

reviewable/pr12708/r1
Muxi Yan 8 years ago
commit 1c285b9812
  1. 1
      .github/CODEOWNERS
  2. 2
      .gitignore
  3. 14
      BUILD
  4. 302
      CMakeLists.txt
  5. 215
      Makefile
  6. 2
      bazel/generate_cc.bzl
  7. 16
      bazel/grpc_build_system.bzl
  8. 2
      binding.gyp
  9. 6
      build.yaml
  10. 4
      config.m4
  11. 2
      config.w32
  12. 14
      doc/c-style-guide.md
  13. 1
      doc/environment_variables.md
  14. 5
      doc/service_config.md
  15. 6
      examples/cpp/helloworld/CMakeLists.txt
  16. 12
      examples/cpp/helloworld/greeter_async_client.cc
  17. 14
      examples/cpp/helloworld/greeter_async_client2.cc
  18. 7
      gRPC-Core.podspec
  19. 22
      grpc.def
  20. 6
      grpc.gemspec
  21. 8
      grpc.gyp
  22. 17
      include/grpc++/generic/generic_stub.h
  23. 136
      include/grpc++/impl/codegen/async_stream.h
  24. 41
      include/grpc++/impl/codegen/async_unary_call.h
  25. 156
      include/grpc++/impl/codegen/byte_buffer.h
  26. 56
      include/grpc++/impl/codegen/call.h
  27. 9
      include/grpc++/impl/codegen/method_handler_impl.h
  28. 14
      include/grpc++/impl/codegen/rpc_service_method.h
  29. 29
      include/grpc++/impl/codegen/serialization_traits.h
  30. 78
      include/grpc++/impl/codegen/slice.h
  31. 6
      include/grpc++/server_builder.h
  32. 68
      include/grpc++/support/byte_buffer.h
  33. 80
      include/grpc++/support/slice.h
  34. 64
      include/grpc/byte_buffer.h
  35. 2
      include/grpc/compression.h
  36. 86
      include/grpc/impl/codegen/byte_buffer.h
  37. 13
      include/grpc/impl/codegen/grpc_types.h
  38. 6
      include/grpc/slice.h
  39. 10
      package.xml
  40. 2
      setup.py
  41. 1
      src/compiler/OWNERS
  42. 578
      src/compiler/cpp_generator.cc
  43. 32
      src/compiler/php_generator.cc
  44. 4
      src/compiler/python_generator.cc
  45. 28
      src/core/ext/census/base_resources.c
  46. 10
      src/core/ext/filters/client_channel/channel_connectivity.c
  47. 332
      src/core/ext/filters/client_channel/client_channel.c
  48. 9
      src/core/ext/filters/client_channel/client_channel_factory.c
  49. 4
      src/core/ext/filters/client_channel/client_channel_plugin.c
  50. 10
      src/core/ext/filters/client_channel/http_proxy.c
  51. 3
      src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c
  52. 187
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
  53. 6
      src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
  54. 8
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c
  55. 5
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
  56. 11
      src/core/ext/filters/client_channel/lb_policy_factory.c
  57. 6
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
  58. 82
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
  59. 36
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
  60. 2
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c
  61. 9
      src/core/ext/filters/client_channel/retry_throttle.c
  62. 4
      src/core/ext/filters/client_channel/subchannel.c
  63. 34
      src/core/ext/filters/client_channel/subchannel_index.c
  64. 7
      src/core/ext/filters/client_channel/subchannel_index.h
  65. 4
      src/core/ext/filters/http/message_compress/message_compress_filter.c
  66. 6
      src/core/ext/filters/http/server/http_server_filter.c
  67. 3
      src/core/ext/filters/load_reporting/server_load_reporting_plugin.c
  68. 2
      src/core/ext/filters/max_age/max_age_filter.c
  69. 2
      src/core/ext/transport/chttp2/client/chttp2_connector.c
  70. 2
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  71. 2
      src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
  72. 21
      src/core/ext/transport/chttp2/server/chttp2_server.c
  73. 1
      src/core/ext/transport/chttp2/transport/chttp2_plugin.c
  74. 427
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  75. 1
      src/core/ext/transport/chttp2/transport/chttp2_transport.h
  76. 20
      src/core/ext/transport/chttp2/transport/flow_control.c
  77. 4
      src/core/ext/transport/chttp2/transport/frame_data.c
  78. 5
      src/core/ext/transport/chttp2/transport/frame_ping.c
  79. 17
      src/core/ext/transport/chttp2/transport/frame_settings.c
  80. 10
      src/core/ext/transport/chttp2/transport/frame_window_update.c
  81. 98
      src/core/ext/transport/chttp2/transport/hpack_encoder.c
  82. 51
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  83. 5
      src/core/ext/transport/chttp2/transport/incoming_metadata.c
  84. 61
      src/core/ext/transport/chttp2/transport/internal.h
  85. 7
      src/core/ext/transport/chttp2/transport/parsing.c
  86. 52
      src/core/ext/transport/chttp2/transport/stream_lists.c
  87. 6
      src/core/ext/transport/chttp2/transport/stream_map.c
  88. 157
      src/core/ext/transport/chttp2/transport/writing.c
  89. 105
      src/core/ext/transport/inproc/inproc_transport.c
  90. 8
      src/core/lib/channel/channel_args.c
  91. 2
      src/core/lib/channel/channel_stack.h
  92. 16
      src/core/lib/channel/channel_stack_builder.c
  93. 2
      src/core/lib/compression/compression.c
  94. 2
      src/core/lib/compression/compression_internal.c
  95. 2
      src/core/lib/compression/compression_internal.h
  96. 178
      src/core/lib/compression/stream_compression.c
  97. 32
      src/core/lib/compression/stream_compression.h
  98. 228
      src/core/lib/compression/stream_compression_gzip.c
  99. 26
      src/core/lib/compression/stream_compression_gzip.h
  100. 94
      src/core/lib/compression/stream_compression_identity.c
  101. Some files were not shown because too many files have changed in this diff Show More

@ -3,5 +3,4 @@
# repository as the source of truth for module ownership. # repository as the source of truth for module ownership.
/**/OWNERS @markdroth @nicolasnoble @ctiller /**/OWNERS @markdroth @nicolasnoble @ctiller
/bazel/** @nicolasnoble @dgquintas @ctiller /bazel/** @nicolasnoble @dgquintas @ctiller
/src/compiler/cpp_generator.cc @vjpai
/src/core/ext/filters/client_channel/** @markdroth @dgquintas @ctiller /src/core/ext/filters/client_channel/** @markdroth @dgquintas @ctiller

2
.gitignore vendored

@ -16,7 +16,7 @@ htmlcov/
dist/ dist/
*.egg *.egg
py27/ py27/
py34/ py3[0-9]*/
# Node installation output # Node installation output
node_modules node_modules

14
BUILD

@ -575,6 +575,10 @@ grpc_cc_library(
"src/core/lib/compression/compression_internal.c", "src/core/lib/compression/compression_internal.c",
"src/core/lib/compression/message_compress.c", "src/core/lib/compression/message_compress.c",
"src/core/lib/compression/stream_compression.c", "src/core/lib/compression/stream_compression.c",
"src/core/lib/compression/stream_compression_gzip.c",
"src/core/lib/compression/stream_compression_identity.c",
"src/core/lib/debug/stats.c",
"src/core/lib/debug/stats_data.c",
"src/core/lib/http/format_request.c", "src/core/lib/http/format_request.c",
"src/core/lib/http/httpcli.c", "src/core/lib/http/httpcli.c",
"src/core/lib/http/parser.c", "src/core/lib/http/parser.c",
@ -691,8 +695,6 @@ grpc_cc_library(
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
"src/core/lib/transport/transport_op_string.c", "src/core/lib/transport/transport_op_string.c",
"src/core/lib/debug/stats.c",
"src/core/lib/debug/stats_data.c",
], ],
hdrs = [ hdrs = [
"src/core/lib/channel/channel_args.h", "src/core/lib/channel/channel_args.h",
@ -707,6 +709,10 @@ grpc_cc_library(
"src/core/lib/compression/compression_internal.h", "src/core/lib/compression/compression_internal.h",
"src/core/lib/compression/message_compress.h", "src/core/lib/compression/message_compress.h",
"src/core/lib/compression/stream_compression.h", "src/core/lib/compression/stream_compression.h",
"src/core/lib/compression/stream_compression_gzip.h",
"src/core/lib/compression/stream_compression_identity.h",
"src/core/lib/debug/stats.h",
"src/core/lib/debug/stats_data.h",
"src/core/lib/http/format_request.h", "src/core/lib/http/format_request.h",
"src/core/lib/http/httpcli.h", "src/core/lib/http/httpcli.h",
"src/core/lib/http/parser.h", "src/core/lib/http/parser.h",
@ -809,8 +815,6 @@ grpc_cc_library(
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
"src/core/lib/transport/transport_impl.h", "src/core/lib/transport/transport_impl.h",
"src/core/lib/debug/stats.h",
"src/core/lib/debug/stats_data.h",
], ],
external_deps = [ external_deps = [
"zlib", "zlib",
@ -991,6 +995,7 @@ grpc_cc_library(
name = "grpc_codegen", name = "grpc_codegen",
language = "c", language = "c",
public_hdrs = [ public_hdrs = [
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/byte_buffer_reader.h",
"include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h", "include/grpc/impl/codegen/connectivity_state.h",
@ -1489,6 +1494,7 @@ grpc_cc_library(
public_hdrs = [ public_hdrs = [
"include/grpc++/impl/codegen/async_stream.h", "include/grpc++/impl/codegen/async_stream.h",
"include/grpc++/impl/codegen/async_unary_call.h", "include/grpc++/impl/codegen/async_unary_call.h",
"include/grpc++/impl/codegen/byte_buffer.h",
"include/grpc++/impl/codegen/call.h", "include/grpc++/impl/codegen/call.h",
"include/grpc++/impl/codegen/call_hook.h", "include/grpc++/impl/codegen/call_hook.h",
"include/grpc++/impl/codegen/channel_interface.h", "include/grpc++/impl/codegen/channel_interface.h",

@ -123,10 +123,8 @@ if("${gRPC_ZLIB_PROVIDER}" STREQUAL "module")
set(gRPC_INSTALL FALSE) set(gRPC_INSTALL FALSE)
endif() endif()
elseif("${gRPC_ZLIB_PROVIDER}" STREQUAL "package") elseif("${gRPC_ZLIB_PROVIDER}" STREQUAL "package")
find_package(ZLIB) find_package(ZLIB REQUIRED)
if(TARGET ZLIB::ZLIB) set(_gRPC_ZLIB_LIBRARIES ${ZLIB_LIBRARIES})
set(_gRPC_ZLIB_LIBRARIES ZLIB::ZLIB)
endif()
set(_gRPC_FIND_ZLIB "if(NOT ZLIB_FOUND)\n find_package(ZLIB)\nendif()") set(_gRPC_FIND_ZLIB "if(NOT ZLIB_FOUND)\n find_package(ZLIB)\nendif()")
endif() endif()
@ -134,7 +132,8 @@ if("${gRPC_CARES_PROVIDER}" STREQUAL "module")
if(NOT CARES_ROOT_DIR) if(NOT CARES_ROOT_DIR)
set(CARES_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares/cares) set(CARES_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares/cares)
endif() endif()
set(CARES_STATIC ON) set(CARES_SHARED OFF CACHE BOOL "disable shared library")
set(CARES_STATIC ON CACHE BOOL "link cares statically")
set(CARES_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares/cares") set(CARES_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cares/cares")
add_subdirectory(third_party/cares/cares) add_subdirectory(third_party/cares/cares)
if(TARGET c-ares) if(TARGET c-ares)
@ -145,7 +144,7 @@ if("${gRPC_CARES_PROVIDER}" STREQUAL "module")
set(gRPC_INSTALL FALSE) set(gRPC_INSTALL FALSE)
endif() endif()
elseif("${gRPC_CARES_PROVIDER}" STREQUAL "package") elseif("${gRPC_CARES_PROVIDER}" STREQUAL "package")
find_package(c-ares CONFIG) find_package(c-ares REQUIRED CONFIG)
if(TARGET c-ares::cares) if(TARGET c-ares::cares)
set(_gRPC_CARES_LIBRARIES c-ares::cares) set(_gRPC_CARES_LIBRARIES c-ares::cares)
endif() endif()
@ -189,7 +188,7 @@ if("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "module")
set(gRPC_INSTALL FALSE) set(gRPC_INSTALL FALSE)
endif() endif()
elseif("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "package") elseif("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "package")
find_package(Protobuf ${gRPC_PROTOBUF_PACKAGE_TYPE}) find_package(Protobuf REQUIRED ${gRPC_PROTOBUF_PACKAGE_TYPE})
if(Protobuf_FOUND OR PROTOBUF_FOUND) if(Protobuf_FOUND OR PROTOBUF_FOUND)
if(TARGET protobuf::${_gRPC_PROTOBUF_LIBRARY_NAME}) if(TARGET protobuf::${_gRPC_PROTOBUF_LIBRARY_NAME})
set(_gRPC_PROTOBUF_LIBRARIES protobuf::${_gRPC_PROTOBUF_LIBRARY_NAME}) set(_gRPC_PROTOBUF_LIBRARIES protobuf::${_gRPC_PROTOBUF_LIBRARY_NAME})
@ -234,11 +233,9 @@ if("${gRPC_SSL_PROVIDER}" STREQUAL "module")
set(gRPC_INSTALL FALSE) set(gRPC_INSTALL FALSE)
endif() endif()
elseif("${gRPC_SSL_PROVIDER}" STREQUAL "package") elseif("${gRPC_SSL_PROVIDER}" STREQUAL "package")
find_package(OpenSSL) find_package(OpenSSL REQUIRED)
if(TARGET OpenSSL::SSL) set(_gRPC_SSL_LIBRARIES ${OPENSSL_LIBRARIES})
set(_gRPC_SSL_LIBRARIES OpenSSL::SSL) set(_gRPC_FIND_SSL "if(NOT OPENSSL_FOUND)\n find_package(OpenSSL)\nendif()")
endif()
set(_gRPC_FIND_SSL "if(NOT OpenSSL_FOUND)\n find_package(OpenSSL)\nendif()")
endif() endif()
if("${gRPC_GFLAGS_PROVIDER}" STREQUAL "module") if("${gRPC_GFLAGS_PROVIDER}" STREQUAL "module")
@ -764,6 +761,18 @@ add_dependencies(buildtests_cxx thread_stress_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx writes_per_rpc_test) add_dependencies(buildtests_cxx writes_per_rpc_test)
endif() endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx resolver_component_test_unsecure)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx resolver_component_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx resolver_component_tests_runner_invoker_unsecure)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx resolver_component_tests_runner_invoker)
endif()
add_custom_target(buildtests add_custom_target(buildtests
DEPENDS buildtests_c buildtests_cxx) DEPENDS buildtests_c buildtests_cxx)
@ -832,7 +841,7 @@ endif()
target_include_directories(gpr target_include_directories(gpr
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -924,7 +933,7 @@ endif()
target_include_directories(gpr_test_util target_include_directories(gpr_test_util
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -957,6 +966,8 @@ add_library(grpc
src/core/lib/compression/compression_internal.c src/core/lib/compression/compression_internal.c
src/core/lib/compression/message_compress.c src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c src/core/lib/http/format_request.c
@ -1220,7 +1231,7 @@ endif()
target_include_directories(grpc target_include_directories(grpc
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -1242,6 +1253,7 @@ target_link_libraries(grpc
) )
foreach(_hdr foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -1306,6 +1318,8 @@ add_library(grpc_cronet
src/core/lib/compression/compression_internal.c src/core/lib/compression/compression_internal.c
src/core/lib/compression/message_compress.c src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c src/core/lib/http/format_request.c
@ -1527,7 +1541,7 @@ endif()
target_include_directories(grpc_cronet target_include_directories(grpc_cronet
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -1549,6 +1563,7 @@ target_link_libraries(grpc_cronet
) )
foreach(_hdr foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -1623,6 +1638,8 @@ add_library(grpc_test_util
src/core/lib/compression/compression_internal.c src/core/lib/compression/compression_internal.c
src/core/lib/compression/message_compress.c src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c src/core/lib/http/format_request.c
@ -1806,7 +1823,7 @@ endif()
target_include_directories(grpc_test_util target_include_directories(grpc_test_util
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -1826,6 +1843,7 @@ target_link_libraries(grpc_test_util
) )
foreach(_hdr foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -1884,6 +1902,8 @@ add_library(grpc_test_util_unsecure
src/core/lib/compression/compression_internal.c src/core/lib/compression/compression_internal.c
src/core/lib/compression/message_compress.c src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c src/core/lib/http/format_request.c
@ -2067,7 +2087,7 @@ endif()
target_include_directories(grpc_test_util_unsecure target_include_directories(grpc_test_util_unsecure
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -2087,6 +2107,7 @@ target_link_libraries(grpc_test_util_unsecure
) )
foreach(_hdr foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -2131,6 +2152,8 @@ add_library(grpc_unsecure
src/core/lib/compression/compression_internal.c src/core/lib/compression/compression_internal.c
src/core/lib/compression/message_compress.c src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c src/core/lib/http/format_request.c
@ -2362,7 +2385,7 @@ endif()
target_include_directories(grpc_unsecure target_include_directories(grpc_unsecure
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -2383,6 +2406,7 @@ target_link_libraries(grpc_unsecure
) )
foreach(_hdr foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -2451,7 +2475,7 @@ endif()
target_include_directories(reconnect_server target_include_directories(reconnect_server
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -2493,7 +2517,7 @@ endif()
target_include_directories(test_tcp_server target_include_directories(test_tcp_server
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -2574,7 +2598,7 @@ endif()
target_include_directories(grpc++ target_include_directories(grpc++
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -2692,6 +2716,7 @@ foreach(_hdr
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
include/grpc/support/workaround_list.h include/grpc/support/workaround_list.h
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -2702,6 +2727,7 @@ foreach(_hdr
include/grpc/impl/codegen/status.h include/grpc/impl/codegen/status.h
include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_stream.h
include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/async_unary_call.h
include/grpc++/impl/codegen/byte_buffer.h
include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call.h
include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/call_hook.h
include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/channel_interface.h
@ -2774,7 +2800,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc++_core_stats target_include_directories(grpc++_core_stats
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -2884,6 +2910,8 @@ add_library(grpc++_cronet
src/core/lib/compression/compression_internal.c src/core/lib/compression/compression_internal.c
src/core/lib/compression/message_compress.c src/core/lib/compression/message_compress.c
src/core/lib/compression/stream_compression.c src/core/lib/compression/stream_compression.c
src/core/lib/compression/stream_compression_gzip.c
src/core/lib/compression/stream_compression_identity.c
src/core/lib/debug/stats.c src/core/lib/debug/stats.c
src/core/lib/debug/stats_data.c src/core/lib/debug/stats_data.c
src/core/lib/http/format_request.c src/core/lib/http/format_request.c
@ -3066,7 +3094,7 @@ endif()
target_include_directories(grpc++_cronet target_include_directories(grpc++_cronet
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3185,6 +3213,7 @@ foreach(_hdr
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
include/grpc/support/workaround_list.h include/grpc/support/workaround_list.h
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -3195,6 +3224,7 @@ foreach(_hdr
include/grpc/impl/codegen/status.h include/grpc/impl/codegen/status.h
include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_stream.h
include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/async_unary_call.h
include/grpc++/impl/codegen/byte_buffer.h
include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call.h
include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/call_hook.h
include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/channel_interface.h
@ -3265,7 +3295,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc++_error_details target_include_directories(grpc++_error_details
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3330,7 +3360,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc++_proto_reflection_desc_db target_include_directories(grpc++_proto_reflection_desc_db
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3391,7 +3421,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc++_reflection target_include_directories(grpc++_reflection
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3449,7 +3479,7 @@ endif()
target_include_directories(grpc++_test_config target_include_directories(grpc++_test_config
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3527,7 +3557,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc++_test_util target_include_directories(grpc++_test_util
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3555,6 +3585,7 @@ target_link_libraries(grpc++_test_util
foreach(_hdr foreach(_hdr
include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_stream.h
include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/async_unary_call.h
include/grpc++/impl/codegen/byte_buffer.h
include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call.h
include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/call_hook.h
include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/channel_interface.h
@ -3582,6 +3613,7 @@ foreach(_hdr
include/grpc++/impl/codegen/stub_options.h include/grpc++/impl/codegen/stub_options.h
include/grpc++/impl/codegen/sync_stream.h include/grpc++/impl/codegen/sync_stream.h
include/grpc++/impl/codegen/time.h include/grpc++/impl/codegen/time.h
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -3665,7 +3697,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc++_test_util_unsecure target_include_directories(grpc++_test_util_unsecure
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3693,6 +3725,7 @@ target_link_libraries(grpc++_test_util_unsecure
foreach(_hdr foreach(_hdr
include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_stream.h
include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/async_unary_call.h
include/grpc++/impl/codegen/byte_buffer.h
include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call.h
include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/call_hook.h
include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/channel_interface.h
@ -3720,6 +3753,7 @@ foreach(_hdr
include/grpc++/impl/codegen/stub_options.h include/grpc++/impl/codegen/stub_options.h
include/grpc++/impl/codegen/sync_stream.h include/grpc++/impl/codegen/sync_stream.h
include/grpc++/impl/codegen/time.h include/grpc++/impl/codegen/time.h
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -3805,7 +3839,7 @@ endif()
target_include_directories(grpc++_unsecure target_include_directories(grpc++_unsecure
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -3922,6 +3956,7 @@ foreach(_hdr
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
include/grpc/support/workaround_list.h include/grpc/support/workaround_list.h
include/grpc/impl/codegen/byte_buffer.h
include/grpc/impl/codegen/byte_buffer_reader.h include/grpc/impl/codegen/byte_buffer_reader.h
include/grpc/impl/codegen/compression_types.h include/grpc/impl/codegen/compression_types.h
include/grpc/impl/codegen/connectivity_state.h include/grpc/impl/codegen/connectivity_state.h
@ -3932,6 +3967,7 @@ foreach(_hdr
include/grpc/impl/codegen/status.h include/grpc/impl/codegen/status.h
include/grpc++/impl/codegen/async_stream.h include/grpc++/impl/codegen/async_stream.h
include/grpc++/impl/codegen/async_unary_call.h include/grpc++/impl/codegen/async_unary_call.h
include/grpc++/impl/codegen/byte_buffer.h
include/grpc++/impl/codegen/call.h include/grpc++/impl/codegen/call.h
include/grpc++/impl/codegen/call_hook.h include/grpc++/impl/codegen/call_hook.h
include/grpc++/impl/codegen/channel_interface.h include/grpc++/impl/codegen/channel_interface.h
@ -3995,7 +4031,7 @@ endif()
target_include_directories(grpc_benchmark target_include_directories(grpc_benchmark
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4054,7 +4090,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(grpc_cli_libs target_include_directories(grpc_cli_libs
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4114,7 +4150,7 @@ endif()
target_include_directories(grpc_plugin_support target_include_directories(grpc_plugin_support
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4192,7 +4228,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(http2_client_main target_include_directories(http2_client_main
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4247,7 +4283,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(interop_client_helper target_include_directories(interop_client_helper
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4317,7 +4353,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(interop_client_main target_include_directories(interop_client_main
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4368,7 +4404,7 @@ endif()
target_include_directories(interop_server_helper target_include_directories(interop_server_helper
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4437,7 +4473,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(interop_server_lib target_include_directories(interop_server_lib
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4488,7 +4524,7 @@ endif()
target_include_directories(interop_server_main target_include_directories(interop_server_main
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4576,7 +4612,7 @@ protobuf_generate_grpc_cpp(
) )
target_include_directories(qps target_include_directories(qps
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4623,7 +4659,7 @@ endif()
target_include_directories(grpc_csharp_ext target_include_directories(grpc_csharp_ext
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4718,7 +4754,7 @@ endif()
target_include_directories(ares target_include_directories(ares
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4756,7 +4792,7 @@ endif()
target_include_directories(bad_client_test target_include_directories(bad_client_test
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4797,7 +4833,7 @@ endif()
target_include_directories(bad_ssl_test_server target_include_directories(bad_ssl_test_server
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4898,7 +4934,7 @@ endif()
target_include_directories(end2end_tests target_include_directories(end2end_tests
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -4999,7 +5035,7 @@ endif()
target_include_directories(end2end_nosec_tests target_include_directories(end2end_nosec_tests
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${BORINGSSL_ROOT_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src PRIVATE ${PROTOBUF_ROOT_DIR}/src
@ -14123,6 +14159,178 @@ target_link_libraries(inproc_nosec_test
gpr gpr
) )
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(resolver_component_test_unsecure
test/cpp/naming/resolver_component_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(resolver_component_test_unsecure
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(resolver_component_test_unsecure
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++_test_util_unsecure
grpc_test_util_unsecure
gpr_test_util
grpc++_unsecure
grpc_unsecure
gpr
grpc++_test_config
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(resolver_component_test
test/cpp/naming/resolver_component_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(resolver_component_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(resolver_component_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++_test_util
grpc_test_util
gpr_test_util
grpc++
grpc
gpr
grpc++_test_config
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(resolver_component_tests_runner_invoker_unsecure
test/cpp/naming/resolver_component_tests_runner_invoker.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(resolver_component_tests_runner_invoker_unsecure
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(resolver_component_tests_runner_invoker_unsecure
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++_test_util
grpc_test_util
gpr_test_util
grpc++
grpc
gpr
grpc++_test_config
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(resolver_component_tests_runner_invoker
test/cpp/naming/resolver_component_tests_runner_invoker.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(resolver_component_tests_runner_invoker
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(resolver_component_tests_runner_invoker
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++_test_util
grpc_test_util
gpr_test_util
grpc++
grpc
gpr
grpc++_test_config
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)

@ -1266,6 +1266,10 @@ h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test
h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test
h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test
inproc_nosec_test: $(BINDIR)/$(CONFIG)/inproc_nosec_test inproc_nosec_test: $(BINDIR)/$(CONFIG)/inproc_nosec_test
resolver_component_test_unsecure: $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure
resolver_component_test: $(BINDIR)/$(CONFIG)/resolver_component_test
resolver_component_tests_runner_invoker_unsecure: $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure
resolver_component_tests_runner_invoker: $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker
api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
@ -1652,6 +1656,10 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/boringssl_x509_test \ $(BINDIR)/$(CONFIG)/boringssl_x509_test \
$(BINDIR)/$(CONFIG)/boringssl_tab_test \ $(BINDIR)/$(CONFIG)/boringssl_tab_test \
$(BINDIR)/$(CONFIG)/boringssl_v3name_test \ $(BINDIR)/$(CONFIG)/boringssl_v3name_test \
$(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \
$(BINDIR)/$(CONFIG)/resolver_component_test \
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure \
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker \
else else
buildtests_cxx: privatelibs_cxx \ buildtests_cxx: privatelibs_cxx \
@ -1730,6 +1738,10 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \
$(BINDIR)/$(CONFIG)/thread_stress_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \
$(BINDIR)/$(CONFIG)/resolver_component_test_unsecure \
$(BINDIR)/$(CONFIG)/resolver_component_test \
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure \
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker \
endif endif
@ -2141,6 +2153,10 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 )
$(E) "[RUN] Testing writes_per_rpc_test" $(E) "[RUN] Testing writes_per_rpc_test"
$(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 )
$(E) "[RUN] Testing resolver_component_tests_runner_invoker_unsecure"
$(Q) $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure || ( echo test resolver_component_tests_runner_invoker_unsecure failed ; exit 1 )
$(E) "[RUN] Testing resolver_component_tests_runner_invoker"
$(Q) $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker || ( echo test resolver_component_tests_runner_invoker failed ; exit 1 )
flaky_test_cxx: buildtests_cxx flaky_test_cxx: buildtests_cxx
@ -2941,6 +2957,8 @@ LIBGRPC_SRC = \
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \
@ -3191,6 +3209,7 @@ LIBGRPC_SRC = \
src/core/plugin_registry/grpc_plugin_registry.c \ src/core/plugin_registry/grpc_plugin_registry.c \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -3290,6 +3309,8 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \
@ -3498,6 +3519,7 @@ LIBGRPC_CRONET_SRC = \
src/core/plugin_registry/grpc_cronet_plugin_registry.c \ src/core/plugin_registry/grpc_cronet_plugin_registry.c \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -3606,6 +3628,8 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \
@ -3776,6 +3800,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/ext/filters/http/server/http_server_filter.c \ src/core/ext/filters/http/server/http_server_filter.c \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -3858,6 +3883,8 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \
@ -4028,6 +4055,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/ext/filters/http/server/http_server_filter.c \ src/core/ext/filters/http/server/http_server_filter.c \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -4083,6 +4111,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \
@ -4301,6 +4331,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/plugin_registry/grpc_unsecure_plugin_registry.c \ src/core/plugin_registry/grpc_unsecure_plugin_registry.c \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -4589,6 +4620,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
include/grpc/support/workaround_list.h \ include/grpc/support/workaround_list.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -4599,6 +4631,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/status.h \
include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/byte_buffer.h \
include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/channel_interface.h \
@ -4819,6 +4852,8 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \
@ -5083,6 +5118,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
include/grpc/support/workaround_list.h \ include/grpc/support/workaround_list.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -5093,6 +5129,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/status.h \
include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/byte_buffer.h \
include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/channel_interface.h \
@ -5446,6 +5483,7 @@ LIBGRPC++_TEST_UTIL_SRC = \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/byte_buffer.h \
include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/channel_interface.h \
@ -5473,6 +5511,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/stub_options.h \ include/grpc++/impl/codegen/stub_options.h \
include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/sync_stream.h \
include/grpc++/impl/codegen/time.h \ include/grpc++/impl/codegen/time.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -5561,6 +5600,7 @@ LIBGRPC++_TEST_UTIL_UNSECURE_SRC = \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/byte_buffer.h \
include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/channel_interface.h \
@ -5588,6 +5628,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/codegen/stub_options.h \ include/grpc++/impl/codegen/stub_options.h \
include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/sync_stream.h \
include/grpc++/impl/codegen/time.h \ include/grpc++/impl/codegen/time.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -5795,6 +5836,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
include/grpc/support/workaround_list.h \ include/grpc/support/workaround_list.h \
include/grpc/impl/codegen/byte_buffer.h \
include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/byte_buffer_reader.h \
include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/compression_types.h \
include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/connectivity_state.h \
@ -5805,6 +5847,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/status.h \ include/grpc/impl/codegen/status.h \
include/grpc++/impl/codegen/async_stream.h \ include/grpc++/impl/codegen/async_stream.h \
include/grpc++/impl/codegen/async_unary_call.h \ include/grpc++/impl/codegen/async_unary_call.h \
include/grpc++/impl/codegen/byte_buffer.h \
include/grpc++/impl/codegen/call.h \ include/grpc++/impl/codegen/call.h \
include/grpc++/impl/codegen/call_hook.h \ include/grpc++/impl/codegen/call_hook.h \
include/grpc++/impl/codegen/channel_interface.h \ include/grpc++/impl/codegen/channel_interface.h \
@ -19486,6 +19529,178 @@ ifneq ($(NO_DEPS),true)
endif endif
RESOLVER_COMPONENT_TEST_UNSECURE_SRC = \
test/cpp/naming/resolver_component_test.cc \
RESOLVER_COMPONENT_TEST_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVER_COMPONENT_TEST_UNSECURE_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/resolver_component_test_unsecure: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/resolver_component_test_unsecure: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/resolver_component_test_unsecure: $(PROTOBUF_DEP) $(RESOLVER_COMPONENT_TEST_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(RESOLVER_COMPONENT_TEST_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/naming/resolver_component_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_resolver_component_test_unsecure: $(RESOLVER_COMPONENT_TEST_UNSECURE_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(RESOLVER_COMPONENT_TEST_UNSECURE_OBJS:.o=.dep)
endif
endif
RESOLVER_COMPONENT_TEST_SRC = \
test/cpp/naming/resolver_component_test.cc \
RESOLVER_COMPONENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVER_COMPONENT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/resolver_component_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/resolver_component_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/resolver_component_test: $(PROTOBUF_DEP) $(RESOLVER_COMPONENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(RESOLVER_COMPONENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/resolver_component_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/naming/resolver_component_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_resolver_component_test: $(RESOLVER_COMPONENT_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(RESOLVER_COMPONENT_TEST_OBJS:.o=.dep)
endif
endif
RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_SRC = \
test/cpp/naming/resolver_component_tests_runner_invoker.cc \
RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure: $(PROTOBUF_DEP) $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/naming/resolver_component_tests_runner_invoker.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_resolver_component_tests_runner_invoker_unsecure: $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_UNSECURE_OBJS:.o=.dep)
endif
endif
RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_SRC = \
test/cpp/naming/resolver_component_tests_runner_invoker.cc \
RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker: $(PROTOBUF_DEP) $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/naming/resolver_component_tests_runner_invoker.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_resolver_component_tests_runner_invoker: $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(RESOLVER_COMPONENT_TESTS_RUNNER_INVOKER_OBJS:.o=.dep)
endif
endif
API_FUZZER_ONE_ENTRY_SRC = \ API_FUZZER_ONE_ENTRY_SRC = \
test/core/end2end/fuzzers/api_fuzzer.c \ test/core/end2end/fuzzers/api_fuzzer.c \
test/core/util/one_corpus_entry_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \

@ -55,7 +55,7 @@ def generate_cc_impl(ctx):
arguments = arguments, arguments = arguments,
) )
return struct(files=set(out_files)) return struct(files=depset(out_files))
_generate_cc = rule( _generate_cc = rule(
attrs = { attrs = {

@ -106,6 +106,22 @@ def grpc_sh_test(name, srcs, args = [], data = []):
args = args, args = args,
data = data) data = data)
def grpc_sh_binary(name, srcs, data = []):
native.sh_test(
name = name,
srcs = srcs,
data = data)
def grpc_py_binary(name, srcs, data = [], deps = []):
if name == "test_dns_server":
# TODO: allow running test_dns_server in oss bazel test suite
deps = []
native.py_binary(
name = name,
srcs = srcs,
data = data,
deps = deps)
def grpc_package(name, visibility = "private", features = []): def grpc_package(name, visibility = "private", features = []):
if visibility == "tests": if visibility == "tests":
visibility = ["//test:__subpackages__"] visibility = ["//test:__subpackages__"]

@ -668,6 +668,8 @@
'src/core/lib/compression/compression_internal.c', 'src/core/lib/compression/compression_internal.c',
'src/core/lib/compression/message_compress.c', 'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c', 'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c', 'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c', 'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c', 'src/core/lib/http/format_request.c',

@ -196,6 +196,8 @@ filegroups:
- src/core/lib/compression/compression_internal.c - src/core/lib/compression/compression_internal.c
- src/core/lib/compression/message_compress.c - src/core/lib/compression/message_compress.c
- src/core/lib/compression/stream_compression.c - src/core/lib/compression/stream_compression.c
- src/core/lib/compression/stream_compression_gzip.c
- src/core/lib/compression/stream_compression_identity.c
- src/core/lib/debug/stats.c - src/core/lib/debug/stats.c
- src/core/lib/debug/stats_data.c - src/core/lib/debug/stats_data.c
- src/core/lib/http/format_request.c - src/core/lib/http/format_request.c
@ -348,6 +350,8 @@ filegroups:
- src/core/lib/compression/compression_internal.h - src/core/lib/compression/compression_internal.h
- src/core/lib/compression/message_compress.h - src/core/lib/compression/message_compress.h
- src/core/lib/compression/stream_compression.h - src/core/lib/compression/stream_compression.h
- src/core/lib/compression/stream_compression_gzip.h
- src/core/lib/compression/stream_compression_identity.h
- src/core/lib/debug/stats.h - src/core/lib/debug/stats.h
- src/core/lib/debug/stats_data.h - src/core/lib/debug/stats_data.h
- src/core/lib/http/format_request.h - src/core/lib/http/format_request.h
@ -504,6 +508,7 @@ filegroups:
- grpc_deadline_filter - grpc_deadline_filter
- name: grpc_codegen - name: grpc_codegen
public_headers: public_headers:
- include/grpc/impl/codegen/byte_buffer.h
- include/grpc/impl/codegen/byte_buffer_reader.h - include/grpc/impl/codegen/byte_buffer_reader.h
- include/grpc/impl/codegen/compression_types.h - include/grpc/impl/codegen/compression_types.h
- include/grpc/impl/codegen/connectivity_state.h - include/grpc/impl/codegen/connectivity_state.h
@ -971,6 +976,7 @@ filegroups:
public_headers: public_headers:
- include/grpc++/impl/codegen/async_stream.h - include/grpc++/impl/codegen/async_stream.h
- include/grpc++/impl/codegen/async_unary_call.h - include/grpc++/impl/codegen/async_unary_call.h
- include/grpc++/impl/codegen/byte_buffer.h
- include/grpc++/impl/codegen/call.h - include/grpc++/impl/codegen/call.h
- include/grpc++/impl/codegen/call_hook.h - include/grpc++/impl/codegen/call_hook.h
- include/grpc++/impl/codegen/channel_interface.h - include/grpc++/impl/codegen/channel_interface.h

@ -12,7 +12,7 @@ if test "$PHP_GRPC" != "no"; then
LIBS="-lpthread $LIBS" LIBS="-lpthread $LIBS"
CFLAGS="-Wall -Werror -Wno-parentheses-equality -Wno-unused-value -std=c11" CFLAGS="-Wall -Werror -Wno-parentheses-equality -Wno-unused-value -std=c11"
CXXFLAGS="-std=c++11" CXXFLAGS="-std=c++11 -fno-exceptions -fno-rtti"
GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD" GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD"
PHP_REQUIRE_CXX() PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(pthread) PHP_ADD_LIBRARY(pthread)
@ -97,6 +97,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/compression/compression_internal.c \ src/core/lib/compression/compression_internal.c \
src/core/lib/compression/message_compress.c \ src/core/lib/compression/message_compress.c \
src/core/lib/compression/stream_compression.c \ src/core/lib/compression/stream_compression.c \
src/core/lib/compression/stream_compression_gzip.c \
src/core/lib/compression/stream_compression_identity.c \
src/core/lib/debug/stats.c \ src/core/lib/debug/stats.c \
src/core/lib/debug/stats_data.c \ src/core/lib/debug/stats_data.c \
src/core/lib/http/format_request.c \ src/core/lib/http/format_request.c \

@ -74,6 +74,8 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\compression\\compression_internal.c " + "src\\core\\lib\\compression\\compression_internal.c " +
"src\\core\\lib\\compression\\message_compress.c " + "src\\core\\lib\\compression\\message_compress.c " +
"src\\core\\lib\\compression\\stream_compression.c " + "src\\core\\lib\\compression\\stream_compression.c " +
"src\\core\\lib\\compression\\stream_compression_gzip.c " +
"src\\core\\lib\\compression\\stream_compression_identity.c " +
"src\\core\\lib\\debug\\stats.c " + "src\\core\\lib\\debug\\stats.c " +
"src\\core\\lib\\debug\\stats_data.c " + "src\\core\\lib\\debug\\stats_data.c " +
"src\\core\\lib\\http\\format_request.c " + "src\\core\\lib\\http\\format_request.c " +

@ -32,14 +32,14 @@ Header Files
# endif # endif
``` ```
- Header files should be self-contained and end in .h. - Header files should be self-contained and end in .h.
- All header files should have a #define guard to prevent multiple inclusion. - All header files should have a `#define` guard to prevent multiple inclusion.
To guarantee uniqueness they should be based on the file's path. To guarantee uniqueness they should be based on the file's path.
For public headers: `include/grpc/grpc.h``GRPC_GRPC_H` For public headers: `include/grpc/grpc.h``GRPC_GRPC_H`
For private headers: For private headers:
`src/core/channel/channel_stack.h` `src/core/lib/channel/channel_stack.h`
`GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_STACK_H` `GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H`
Variable Initialization Variable Initialization
----------------------- -----------------------
@ -72,8 +72,16 @@ Symbol Names
- Non-static functions must be prefixed by `grpc_` - Non-static functions must be prefixed by `grpc_`
- Static functions must *not* be prefixed by `grpc_` - Static functions must *not* be prefixed by `grpc_`
- Typenames of `struct`s , `union`s, and `enum`s must be prefixed by `grpc_` if
they are declared in a header file. They must not be prefixed by `grpc_` if
they are declared in a source file.
- Enumeration values and `#define` names must be uppercase. All other values - Enumeration values and `#define` names must be uppercase. All other values
must be lowercase. must be lowercase.
- Enumeration values or `#define` names defined in a header file must be
prefixed with `GRPC_` (except for `#define` macros that are being used to
substitute functions; those should follow the general rules for
functions). Enumeration values or `#define`s defined in source files must not
be prefixed with `GRPC_`.
- Multiple word identifiers use underscore as a delimiter, *never* camel - Multiple word identifiers use underscore as a delimiter, *never* camel
case. E.g. `variable_name`. case. E.g. `variable_name`.

@ -50,6 +50,7 @@ some configuration as environment variables that can be set.
- channel_stack_builder - traces information about channel stacks being built - channel_stack_builder - traces information about channel stacks being built
- executor - traces grpc's internal thread pool ('the executor') - executor - traces grpc's internal thread pool ('the executor')
- http - traces state in the http2 transport engine - http - traces state in the http2 transport engine
- http2_stream_state - traces all http2 stream state mutations.
- http1 - traces HTTP/1.x operations performed by gRPC - http1 - traces HTTP/1.x operations performed by gRPC
- inproc - traces the in-process transport - inproc - traces the in-process transport
- flowctl - traces http2 flow control - flowctl - traces http2 flow control

@ -24,10 +24,7 @@ The service config is a JSON string of the following form:
// opposed to backend addresses), gRPC will use grpclb (see // opposed to backend addresses), gRPC will use grpclb (see
// https://github.com/grpc/grpc/blob/master/doc/load-balancing.md), // https://github.com/grpc/grpc/blob/master/doc/load-balancing.md),
// regardless of what LB policy is requested either here or via the // regardless of what LB policy is requested either here or via the
// client API. However, if the resolver returns at least one backend // client API.
// address in addition to the balancer address(es), the client may fall
// back to the requested policy if it is unable to reach any of the
// grpclb load balancers.
'loadBalancingPolicy': string, 'loadBalancingPolicy': string,
// Per-method configuration. Optional. // Per-method configuration. Optional.

@ -2,7 +2,11 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
# Project # Project
project(HelloWorld CXX) project(HelloWorld C CXX)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
# Protobuf # Protobuf
set(protobuf_MODULE_COMPATIBLE TRUE) set(protobuf_MODULE_COMPATIBLE TRUE)

@ -60,11 +60,15 @@ class GreeterClient {
// Storage for the status of the RPC upon completion. // Storage for the status of the RPC upon completion.
Status status; Status status;
// stub_->AsyncSayHello() performs the RPC call, returning an instance we // stub_->PrepareAsyncSayHello() creates an RPC object, returning
// store in "rpc". Because we are using the asynchronous API, we need to // an instance to store in "call" but does not actually start the RPC
// hold on to the "rpc" instance in order to get updates on the ongoing RPC. // Because we are using the asynchronous API, we need to hold on to
// the "call" instance in order to get updates on the ongoing RPC.
std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc( std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(
stub_->AsyncSayHello(&context, request, &cq)); stub_->PrepareAsyncSayHello(&context, request, &cq));
// StartCall initiates the RPC call
rpc->StartCall();
// Request that, upon completion of the RPC, "reply" be updated with the // Request that, upon completion of the RPC, "reply" be updated with the
// server's response; "status" with the indication of whether the operation // server's response; "status" with the indication of whether the operation

@ -49,11 +49,15 @@ class GreeterClient {
// Call object to store rpc data // Call object to store rpc data
AsyncClientCall* call = new AsyncClientCall; AsyncClientCall* call = new AsyncClientCall;
// stub_->AsyncSayHello() performs the RPC call, returning an instance to // stub_->PrepareAsyncSayHello() creates an RPC object, returning
// store in "call". Because we are using the asynchronous API, we need to // an instance to store in "call" but does not actually start the RPC
// hold on to the "call" instance in order to get updates on the ongoing RPC. // Because we are using the asynchronous API, we need to hold on to
call->response_reader = stub_->AsyncSayHello(&call->context, request, &cq_); // the "call" instance in order to get updates on the ongoing RPC.
call->response_reader =
stub_->PrepareAsyncSayHello(&call->context, request, &cq_);
// StartCall initiates the RPC call
call->response_reader->StartCall();
// Request that, upon completion of the RPC, "reply" be updated with the // Request that, upon completion of the RPC, "reply" be updated with the
// server's response; "status" with the indication of whether the operation // server's response; "status" with the indication of whether the operation

@ -141,6 +141,7 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/sync_generic.h', 'include/grpc/impl/codegen/sync_generic.h',
'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_posix.h',
'include/grpc/impl/codegen/sync_windows.h', 'include/grpc/impl/codegen/sync_windows.h',
'include/grpc/impl/codegen/byte_buffer.h',
'include/grpc/impl/codegen/byte_buffer_reader.h', 'include/grpc/impl/codegen/byte_buffer_reader.h',
'include/grpc/impl/codegen/compression_types.h', 'include/grpc/impl/codegen/compression_types.h',
'include/grpc/impl/codegen/connectivity_state.h', 'include/grpc/impl/codegen/connectivity_state.h',
@ -330,6 +331,8 @@ Pod::Spec.new do |s|
'src/core/lib/compression/compression_internal.h', 'src/core/lib/compression/compression_internal.h',
'src/core/lib/compression/message_compress.h', 'src/core/lib/compression/message_compress.h',
'src/core/lib/compression/stream_compression.h', 'src/core/lib/compression/stream_compression.h',
'src/core/lib/compression/stream_compression_gzip.h',
'src/core/lib/compression/stream_compression_identity.h',
'src/core/lib/debug/stats.h', 'src/core/lib/debug/stats.h',
'src/core/lib/debug/stats_data.h', 'src/core/lib/debug/stats_data.h',
'src/core/lib/http/format_request.h', 'src/core/lib/http/format_request.h',
@ -480,6 +483,8 @@ Pod::Spec.new do |s|
'src/core/lib/compression/compression_internal.c', 'src/core/lib/compression/compression_internal.c',
'src/core/lib/compression/message_compress.c', 'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c', 'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c', 'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c', 'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c', 'src/core/lib/http/format_request.c',
@ -827,6 +832,8 @@ Pod::Spec.new do |s|
'src/core/lib/compression/compression_internal.h', 'src/core/lib/compression/compression_internal.h',
'src/core/lib/compression/message_compress.h', 'src/core/lib/compression/message_compress.h',
'src/core/lib/compression/stream_compression.h', 'src/core/lib/compression/stream_compression.h',
'src/core/lib/compression/stream_compression_gzip.h',
'src/core/lib/compression/stream_compression_identity.h',
'src/core/lib/debug/stats.h', 'src/core/lib/debug/stats.h',
'src/core/lib/debug/stats_data.h', 'src/core/lib/debug/stats_data.h',
'src/core/lib/http/format_request.h', 'src/core/lib/http/format_request.h',

@ -1,14 +1,4 @@
EXPORTS EXPORTS
grpc_raw_byte_buffer_create
grpc_raw_compressed_byte_buffer_create
grpc_byte_buffer_copy
grpc_byte_buffer_length
grpc_byte_buffer_destroy
grpc_byte_buffer_reader_init
grpc_byte_buffer_reader_destroy
grpc_byte_buffer_reader_next
grpc_byte_buffer_reader_readall
grpc_raw_byte_buffer_from_reader
census_initialize census_initialize
census_shutdown census_shutdown
census_supported census_supported
@ -37,6 +27,8 @@ EXPORTS
census_delete_resource census_delete_resource
census_resource_id census_resource_id
census_record_values census_record_values
grpc_compression_algorithm_is_message
grpc_compression_algorithm_is_stream
grpc_compression_algorithm_parse grpc_compression_algorithm_parse
grpc_compression_algorithm_name grpc_compression_algorithm_name
grpc_compression_algorithm_for_level grpc_compression_algorithm_for_level
@ -142,6 +134,16 @@ EXPORTS
grpc_server_add_secure_http2_port grpc_server_add_secure_http2_port
grpc_call_set_credentials grpc_call_set_credentials
grpc_server_credentials_set_auth_metadata_processor grpc_server_credentials_set_auth_metadata_processor
grpc_raw_byte_buffer_create
grpc_raw_compressed_byte_buffer_create
grpc_byte_buffer_copy
grpc_byte_buffer_length
grpc_byte_buffer_destroy
grpc_byte_buffer_reader_init
grpc_byte_buffer_reader_destroy
grpc_byte_buffer_reader_next
grpc_byte_buffer_reader_readall
grpc_raw_byte_buffer_from_reader
grpc_slice_ref grpc_slice_ref
grpc_slice_unref grpc_slice_unref
grpc_slice_copy grpc_slice_copy

@ -29,6 +29,7 @@ Gem::Specification.new do |s|
s.add_dependency 'google-protobuf', '~> 3.1' s.add_dependency 'google-protobuf', '~> 3.1'
s.add_dependency 'googleauth', '~> 0.5.1' s.add_dependency 'googleauth', '~> 0.5.1'
s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0'
s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'facter', '~> 2.4' s.add_development_dependency 'facter', '~> 2.4'
@ -145,6 +146,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/tmpfile_posix.c ) s.files += %w( src/core/lib/support/tmpfile_posix.c )
s.files += %w( src/core/lib/support/tmpfile_windows.c ) s.files += %w( src/core/lib/support/tmpfile_windows.c )
s.files += %w( src/core/lib/support/wrap_memcpy.c ) s.files += %w( src/core/lib/support/wrap_memcpy.c )
s.files += %w( include/grpc/impl/codegen/byte_buffer.h )
s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h ) s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h )
s.files += %w( include/grpc/impl/codegen/compression_types.h ) s.files += %w( include/grpc/impl/codegen/compression_types.h )
s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) s.files += %w( include/grpc/impl/codegen/connectivity_state.h )
@ -262,6 +264,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/compression/compression_internal.h ) s.files += %w( src/core/lib/compression/compression_internal.h )
s.files += %w( src/core/lib/compression/message_compress.h ) s.files += %w( src/core/lib/compression/message_compress.h )
s.files += %w( src/core/lib/compression/stream_compression.h ) s.files += %w( src/core/lib/compression/stream_compression.h )
s.files += %w( src/core/lib/compression/stream_compression_gzip.h )
s.files += %w( src/core/lib/compression/stream_compression_identity.h )
s.files += %w( src/core/lib/debug/stats.h ) s.files += %w( src/core/lib/debug/stats.h )
s.files += %w( src/core/lib/debug/stats_data.h ) s.files += %w( src/core/lib/debug/stats_data.h )
s.files += %w( src/core/lib/http/format_request.h ) s.files += %w( src/core/lib/http/format_request.h )
@ -416,6 +420,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/compression/compression_internal.c ) s.files += %w( src/core/lib/compression/compression_internal.c )
s.files += %w( src/core/lib/compression/message_compress.c ) s.files += %w( src/core/lib/compression/message_compress.c )
s.files += %w( src/core/lib/compression/stream_compression.c ) s.files += %w( src/core/lib/compression/stream_compression.c )
s.files += %w( src/core/lib/compression/stream_compression_gzip.c )
s.files += %w( src/core/lib/compression/stream_compression_identity.c )
s.files += %w( src/core/lib/debug/stats.c ) s.files += %w( src/core/lib/debug/stats.c )
s.files += %w( src/core/lib/debug/stats_data.c ) s.files += %w( src/core/lib/debug/stats_data.c )
s.files += %w( src/core/lib/http/format_request.c ) s.files += %w( src/core/lib/http/format_request.c )

@ -234,6 +234,8 @@
'src/core/lib/compression/compression_internal.c', 'src/core/lib/compression/compression_internal.c',
'src/core/lib/compression/message_compress.c', 'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c', 'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c', 'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c', 'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c', 'src/core/lib/http/format_request.c',
@ -534,6 +536,8 @@
'src/core/lib/compression/compression_internal.c', 'src/core/lib/compression/compression_internal.c',
'src/core/lib/compression/message_compress.c', 'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c', 'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c', 'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c', 'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c', 'src/core/lib/http/format_request.c',
@ -739,6 +743,8 @@
'src/core/lib/compression/compression_internal.c', 'src/core/lib/compression/compression_internal.c',
'src/core/lib/compression/message_compress.c', 'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c', 'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c', 'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c', 'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c', 'src/core/lib/http/format_request.c',
@ -929,6 +935,8 @@
'src/core/lib/compression/compression_internal.c', 'src/core/lib/compression/compression_internal.c',
'src/core/lib/compression/message_compress.c', 'src/core/lib/compression/message_compress.c',
'src/core/lib/compression/stream_compression.c', 'src/core/lib/compression/stream_compression.c',
'src/core/lib/compression/stream_compression_gzip.c',
'src/core/lib/compression/stream_compression_identity.c',
'src/core/lib/debug/stats.c', 'src/core/lib/debug/stats.c',
'src/core/lib/debug/stats_data.c', 'src/core/lib/debug/stats_data.c',
'src/core/lib/http/format_request.c', 'src/core/lib/http/format_request.c',

@ -20,6 +20,7 @@
#define GRPCXX_GENERIC_GENERIC_STUB_H #define GRPCXX_GENERIC_GENERIC_STUB_H
#include <grpc++/support/async_stream.h> #include <grpc++/support/async_stream.h>
#include <grpc++/support/async_unary_call.h>
#include <grpc++/support/byte_buffer.h> #include <grpc++/support/byte_buffer.h>
namespace grpc { namespace grpc {
@ -27,6 +28,7 @@ namespace grpc {
class CompletionQueue; class CompletionQueue;
typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer> typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
GenericClientAsyncReaderWriter; GenericClientAsyncReaderWriter;
typedef ClientAsyncResponseReader<ByteBuffer> GenericClientAsyncResponseReader;
/// Generic stubs provide a type-unsafe interface to call gRPC methods /// Generic stubs provide a type-unsafe interface to call gRPC methods
/// by name. /// by name.
@ -44,6 +46,21 @@ class GenericStub final {
ClientContext* context, const grpc::string& method, CompletionQueue* cq, ClientContext* context, const grpc::string& method, CompletionQueue* cq,
void* tag); void* tag);
/// Setup a call to a named method \a method using \a context, but don't
/// start it. Let it be started explicitly with StartCall and a tag.
/// The return value only indicates whether or not registration of the call
/// succeeded (i.e. the call won't proceed if the return value is nullptr).
std::unique_ptr<GenericClientAsyncReaderWriter> PrepareCall(
ClientContext* context, const grpc::string& method, CompletionQueue* cq);
/// Setup a unary call to a named method \a method using \a context, and don't
/// start it. Let it be started explicitly with StartCall.
/// The return value only indicates whether or not registration of the call
/// succeeded (i.e. the call won't proceed if the return value is nullptr).
std::unique_ptr<GenericClientAsyncResponseReader> PrepareUnaryCall(
ClientContext* context, const grpc::string& method,
const ByteBuffer& request, CompletionQueue* cq);
private: private:
std::shared_ptr<ChannelInterface> channel_; std::shared_ptr<ChannelInterface> channel_;
}; };

@ -35,6 +35,11 @@ class ClientAsyncStreamingInterface {
public: public:
virtual ~ClientAsyncStreamingInterface() {} virtual ~ClientAsyncStreamingInterface() {}
/// Start the call that was set up by the constructor, but only if the
/// constructor was invoked through the "Prepare" API which doesn't actually
/// start the call
virtual void StartCall(void* tag) = 0;
/// Request notification of the reading of the initial metadata. Completion /// Request notification of the reading of the initial metadata. Completion
/// will be notified by \a tag on the associated completion queue. /// will be notified by \a tag on the associated completion queue.
/// This call is optional, but if it is used, it cannot be used concurrently /// This call is optional, but if it is used, it cannot be used concurrently
@ -156,20 +161,22 @@ class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
template <class R> template <class R>
class ClientAsyncReader final : public ClientAsyncReaderInterface<R> { class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
public: public:
/// Create a stream and write the first request out. /// Create a stream object.
/// Write the first request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started and /// \a tag will be notified on \a cq when the call has been started and
/// \a request has been written out. /// \a request has been written out. If \a start is not set, \a tag must be
/// nullptr and the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata /// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call. /// used to send to the server when starting the call.
template <class W> template <class W>
static ClientAsyncReader* Create(ChannelInterface* channel, static ClientAsyncReader* Create(ChannelInterface* channel,
CompletionQueue* cq, const RpcMethod& method, CompletionQueue* cq, const RpcMethod& method,
ClientContext* context, const W& request, ClientContext* context, const W& request,
void* tag) { bool start, void* tag) {
Call call = channel->CreateCall(method, context, cq); Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc( return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReader))) call.call(), sizeof(ClientAsyncReader)))
ClientAsyncReader(call, context, request, tag); ClientAsyncReader(call, context, request, start, tag);
} }
// always allocated against a call arena, no memory free required // always allocated against a call arena, no memory free required
@ -177,6 +184,12 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
assert(size == sizeof(ClientAsyncReader)); assert(size == sizeof(ClientAsyncReader));
} }
void StartCall(void* tag) override {
assert(!started_);
started_ = true;
StartCallInternal(tag);
}
/// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata
/// method for semantics. /// method for semantics.
/// ///
@ -186,6 +199,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
/// calling code can access the received metadata through the /// calling code can access the received metadata through the
/// \a ClientContext. /// \a ClientContext.
void ReadInitialMetadata(void* tag) override { void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
@ -194,6 +208,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
} }
void Read(R* msg, void* tag) override { void Read(R* msg, void* tag) override {
assert(started_);
read_ops_.set_output_tag(tag); read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_); read_ops_.RecvInitialMetadata(context_);
@ -208,6 +223,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
/// - the \a ClientContext associated with this call is updated with /// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata received from the server. /// possible initial and trailing metadata received from the server.
void Finish(Status* status, void* tag) override { void Finish(Status* status, void* tag) override {
assert(started_);
finish_ops_.set_output_tag(tag); finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_); finish_ops_.RecvInitialMetadata(context_);
@ -219,19 +235,28 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
private: private:
template <class W> template <class W>
ClientAsyncReader(Call call, ClientContext* context, const W& request, ClientAsyncReader(Call call, ClientContext* context, const W& request,
void* tag) bool start, void* tag)
: context_(context), call_(call) { : context_(context), call_(call), started_(start) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok()); GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose(); init_ops_.ClientSendClose();
if (start) {
StartCallInternal(tag);
} else {
assert(tag == nullptr);
}
}
void StartCallInternal(void* tag) {
init_ops_.SendInitialMetadata(context_->send_initial_metadata_,
context_->initial_metadata_flags());
init_ops_.set_output_tag(tag);
call_.PerformOps(&init_ops_); call_.PerformOps(&init_ops_);
} }
ClientContext* context_; ClientContext* context_;
Call call_; Call call_;
bool started_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
init_ops_; init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_; CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
@ -257,9 +282,12 @@ class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
template <class W> template <class W>
class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> { class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
public: public:
/// Create a stream and write the first request out. /// Create a stream object.
/// Start the RPC if \a start is set
/// \a tag will be notified on \a cq when the call has been started (i.e. /// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out. /// intitial metadata sent) and \a request has been written out.
/// If \a start is not set, \a tag must be nullptr and the actual call
/// must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata /// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call. /// used to send to the server when starting the call.
/// \a response will be filled in with the single expected response /// \a response will be filled in with the single expected response
@ -269,11 +297,11 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
static ClientAsyncWriter* Create(ChannelInterface* channel, static ClientAsyncWriter* Create(ChannelInterface* channel,
CompletionQueue* cq, const RpcMethod& method, CompletionQueue* cq, const RpcMethod& method,
ClientContext* context, R* response, ClientContext* context, R* response,
void* tag) { bool start, void* tag) {
Call call = channel->CreateCall(method, context, cq); Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc( return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncWriter))) call.call(), sizeof(ClientAsyncWriter)))
ClientAsyncWriter(call, context, response, tag); ClientAsyncWriter(call, context, response, start, tag);
} }
// always allocated against a call arena, no memory free required // always allocated against a call arena, no memory free required
@ -281,6 +309,12 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
assert(size == sizeof(ClientAsyncWriter)); assert(size == sizeof(ClientAsyncWriter));
} }
void StartCall(void* tag) override {
assert(!started_);
started_ = true;
StartCallInternal(tag);
}
/// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for
/// semantics. /// semantics.
/// ///
@ -289,6 +323,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
/// associated with this call is updated, and the calling code can access /// associated with this call is updated, and the calling code can access
/// the received metadata through the \a ClientContext. /// the received metadata through the \a ClientContext.
void ReadInitialMetadata(void* tag) override { void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
@ -297,6 +332,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
} }
void Write(const W& msg, void* tag) override { void Write(const W& msg, void* tag) override {
assert(started_);
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
@ -304,6 +340,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
} }
void Write(const W& msg, WriteOptions options, void* tag) override { void Write(const W& msg, WriteOptions options, void* tag) override {
assert(started_);
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
if (options.is_last_message()) { if (options.is_last_message()) {
options.set_buffer_hint(); options.set_buffer_hint();
@ -315,6 +352,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
} }
void WritesDone(void* tag) override { void WritesDone(void* tag) override {
assert(started_);
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
write_ops_.ClientSendClose(); write_ops_.ClientSendClose();
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
@ -328,6 +366,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
/// - attempts to fill in the \a response parameter passed to this class's /// - attempts to fill in the \a response parameter passed to this class's
/// constructor with the server's response message. /// constructor with the server's response message.
void Finish(Status* status, void* tag) override { void Finish(Status* status, void* tag) override {
assert(started_);
finish_ops_.set_output_tag(tag); finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_); finish_ops_.RecvInitialMetadata(context_);
@ -338,25 +377,32 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
private: private:
template <class R> template <class R>
ClientAsyncWriter(Call call, ClientContext* context, R* response, void* tag) ClientAsyncWriter(Call call, ClientContext* context, R* response, bool start,
: context_(context), call_(call) { void* tag)
: context_(context), call_(call), started_(start) {
finish_ops_.RecvMessage(response); finish_ops_.RecvMessage(response);
finish_ops_.AllowNoMessage(); finish_ops_.AllowNoMessage();
// if corked bit is set in context, we buffer up the initial metadata to if (start) {
// coalesce with later message to be sent. No op is performed. StartCallInternal(tag);
if (context_->initial_metadata_corked_) {
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
} else { } else {
assert(tag == nullptr);
}
}
void StartCallInternal(void* tag) {
write_ops_.SendInitialMetadata(context_->send_initial_metadata_,
context_->initial_metadata_flags());
// if corked bit is set in context, we just keep the initial metadata
// buffered up to coalesce with later message send. No op is performed.
if (!context_->initial_metadata_corked_) {
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
} }
} }
ClientContext* context_; ClientContext* context_;
Call call_; Call call_;
bool started_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_; CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
write_ops_; write_ops_;
@ -388,20 +434,23 @@ template <class W, class R>
class ClientAsyncReaderWriter final class ClientAsyncReaderWriter final
: public ClientAsyncReaderWriterInterface<W, R> { : public ClientAsyncReaderWriterInterface<W, R> {
public: public:
/// Create a stream and write the first request out. /// Create a stream object.
/// Start the RPC request if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e. /// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent). /// intitial metadata sent). If \a start is not set, \a tag must be
/// nullptr and the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata /// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call. /// used to send to the server when starting the call.
static ClientAsyncReaderWriter* Create(ChannelInterface* channel, static ClientAsyncReaderWriter* Create(ChannelInterface* channel,
CompletionQueue* cq, CompletionQueue* cq,
const RpcMethod& method, const RpcMethod& method,
ClientContext* context, void* tag) { ClientContext* context, bool start,
void* tag) {
Call call = channel->CreateCall(method, context, cq); Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc( return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReaderWriter))) call.call(), sizeof(ClientAsyncReaderWriter)))
ClientAsyncReaderWriter(call, context, tag); ClientAsyncReaderWriter(call, context, start, tag);
} }
// always allocated against a call arena, no memory free required // always allocated against a call arena, no memory free required
@ -409,6 +458,12 @@ class ClientAsyncReaderWriter final
assert(size == sizeof(ClientAsyncReaderWriter)); assert(size == sizeof(ClientAsyncReaderWriter));
} }
void StartCall(void* tag) override {
assert(!started_);
started_ = true;
StartCallInternal(tag);
}
/// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method
/// for semantics of this method. /// for semantics of this method.
/// ///
@ -417,6 +472,7 @@ class ClientAsyncReaderWriter final
/// is updated with it, and then the receiving initial metadata can /// is updated with it, and then the receiving initial metadata can
/// be accessed through this \a ClientContext. /// be accessed through this \a ClientContext.
void ReadInitialMetadata(void* tag) override { void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag); meta_ops_.set_output_tag(tag);
@ -425,6 +481,7 @@ class ClientAsyncReaderWriter final
} }
void Read(R* msg, void* tag) override { void Read(R* msg, void* tag) override {
assert(started_);
read_ops_.set_output_tag(tag); read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_); read_ops_.RecvInitialMetadata(context_);
@ -434,6 +491,7 @@ class ClientAsyncReaderWriter final
} }
void Write(const W& msg, void* tag) override { void Write(const W& msg, void* tag) override {
assert(started_);
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
@ -441,6 +499,7 @@ class ClientAsyncReaderWriter final
} }
void Write(const W& msg, WriteOptions options, void* tag) override { void Write(const W& msg, WriteOptions options, void* tag) override {
assert(started_);
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
if (options.is_last_message()) { if (options.is_last_message()) {
options.set_buffer_hint(); options.set_buffer_hint();
@ -452,6 +511,7 @@ class ClientAsyncReaderWriter final
} }
void WritesDone(void* tag) override { void WritesDone(void* tag) override {
assert(started_);
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
write_ops_.ClientSendClose(); write_ops_.ClientSendClose();
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
@ -462,6 +522,7 @@ class ClientAsyncReaderWriter final
/// - the \a ClientContext associated with this call is updated with /// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server. /// possible initial and trailing metadata sent from the server.
void Finish(Status* status, void* tag) override { void Finish(Status* status, void* tag) override {
assert(started_);
finish_ops_.set_output_tag(tag); finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_); finish_ops_.RecvInitialMetadata(context_);
@ -471,23 +532,30 @@ class ClientAsyncReaderWriter final
} }
private: private:
ClientAsyncReaderWriter(Call call, ClientContext* context, void* tag) ClientAsyncReaderWriter(Call call, ClientContext* context, bool start,
: context_(context), call_(call) { void* tag)
if (context_->initial_metadata_corked_) { : context_(context), call_(call), started_(start) {
// if corked bit is set in context, we buffer up the initial metadata to if (start) {
// coalesce with later message to be sent. No op is performed. StartCallInternal(tag);
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
} else { } else {
assert(tag == nullptr);
}
}
void StartCallInternal(void* tag) {
write_ops_.SendInitialMetadata(context_->send_initial_metadata_,
context_->initial_metadata_flags());
// if corked bit is set in context, we just keep the initial metadata
// buffered up to coalesce with later message send. No op is performed.
if (!context_->initial_metadata_corked_) {
write_ops_.set_output_tag(tag); write_ops_.set_output_tag(tag);
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&write_ops_); call_.PerformOps(&write_ops_);
} }
} }
ClientContext* context_; ClientContext* context_;
Call call_; Call call_;
bool started_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_; CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_; CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose> CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>

@ -32,13 +32,18 @@ namespace grpc {
class CompletionQueue; class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface; extern CoreCodegenInterface* g_core_codegen_interface;
/// An interface relevant for async client side unary RPCS (which send /// An interface relevant for async client side unary RPCs (which send
/// one request message to a server and receive one response message). /// one request message to a server and receive one response message).
template <class R> template <class R>
class ClientAsyncResponseReaderInterface { class ClientAsyncResponseReaderInterface {
public: public:
virtual ~ClientAsyncResponseReaderInterface() {} virtual ~ClientAsyncResponseReaderInterface() {}
/// Start the call that was set up by the constructor, but only if the
/// constructor was invoked through the "Prepare" API which doesn't actually
/// start the call
virtual void StartCall() = 0;
/// Request notification of the reading of initial metadata. Completion /// Request notification of the reading of initial metadata. Completion
/// will be notified by \a tag on the associated completion queue. /// will be notified by \a tag on the associated completion queue.
/// This call is optional, but if it is used, it cannot be used concurrently /// This call is optional, but if it is used, it cannot be used concurrently
@ -70,9 +75,10 @@ template <class R>
class ClientAsyncResponseReader final class ClientAsyncResponseReader final
: public ClientAsyncResponseReaderInterface<R> { : public ClientAsyncResponseReaderInterface<R> {
public: public:
/// Start a call and write the request out. /// Start a call and write the request out if \a start is set.
/// \a tag will be notified on \a cq when the call has been started (i.e. /// \a tag will be notified on \a cq when the call has been started (i.e.
/// intitial metadata sent) and \a request has been written out. /// intitial metadata sent) and \a request has been written out.
/// If \a start is not set, the actual call must be initiated by StartCall
/// Note that \a context will be used to fill in custom initial metadata /// Note that \a context will be used to fill in custom initial metadata
/// used to send to the server when starting the call. /// used to send to the server when starting the call.
template <class W> template <class W>
@ -80,11 +86,11 @@ class ClientAsyncResponseReader final
CompletionQueue* cq, CompletionQueue* cq,
const RpcMethod& method, const RpcMethod& method,
ClientContext* context, ClientContext* context,
const W& request) { const W& request, bool start) {
Call call = channel->CreateCall(method, context, cq); Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc( return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncResponseReader))) call.call(), sizeof(ClientAsyncResponseReader)))
ClientAsyncResponseReader(call, context, request); ClientAsyncResponseReader(call, context, request, start);
} }
// always allocated against a call arena, no memory free required // always allocated against a call arena, no memory free required
@ -92,13 +98,20 @@ class ClientAsyncResponseReader final
assert(size == sizeof(ClientAsyncResponseReader)); assert(size == sizeof(ClientAsyncResponseReader));
} }
void StartCall() override {
assert(!started_);
started_ = true;
StartCallInternal();
}
/// See \a ClientAsyncResponseReaderInterface::ReadInitialMetadata for /// See \a ClientAsyncResponseReaderInterface::ReadInitialMetadata for
/// semantics. /// semantics.
/// ///
/// Side effect: /// Side effect:
/// - the \a ClientContext associated with this call is updated with /// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server. /// possible initial and trailing metadata sent from the server.
void ReadInitialMetadata(void* tag) { void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_buf.set_output_tag(tag); meta_buf.set_output_tag(tag);
@ -111,7 +124,8 @@ class ClientAsyncResponseReader final
/// Side effect: /// Side effect:
/// - the \a ClientContext associated with this call is updated with /// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server. /// possible initial and trailing metadata sent from the server.
void Finish(R* msg, Status* status, void* tag) { void Finish(R* msg, Status* status, void* tag) override {
assert(started_);
finish_buf.set_output_tag(tag); finish_buf.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
finish_buf.RecvInitialMetadata(context_); finish_buf.RecvInitialMetadata(context_);
@ -125,15 +139,22 @@ class ClientAsyncResponseReader final
private: private:
ClientContext* const context_; ClientContext* const context_;
Call call_; Call call_;
bool started_;
template <class W> template <class W>
ClientAsyncResponseReader(Call call, ClientContext* context, const W& request) ClientAsyncResponseReader(Call call, ClientContext* context, const W& request,
: context_(context), call_(call) { bool start)
init_buf.SendInitialMetadata(context->send_initial_metadata_, : context_(context), call_(call), started_(start) {
context->initial_metadata_flags()); // Bind the metadata at time of StartCallInternal but set up the rest here
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_buf.SendMessage(request).ok()); GPR_CODEGEN_ASSERT(init_buf.SendMessage(request).ok());
init_buf.ClientSendClose(); init_buf.ClientSendClose();
if (start) StartCallInternal();
}
void StartCallInternal() {
init_buf.SendInitialMetadata(context_->send_initial_metadata_,
context_->initial_metadata_flags());
call_.PerformOps(&init_buf); call_.PerformOps(&init_buf);
} }

@ -0,0 +1,156 @@
/*
*
* 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 GRPCXX_IMPL_CODEGEN_BYTE_BUFFER_H
#define GRPCXX_IMPL_CODEGEN_BYTE_BUFFER_H
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/slice.h>
#include <grpc++/impl/codegen/status.h>
#include <vector>
namespace grpc {
template <class R>
class CallOpRecvMessage;
class MethodHandler;
template <class ServiceType, class RequestType, class ResponseType>
class RpcMethodHandler;
template <class ServiceType, class RequestType, class ResponseType>
class ServerStreamingHandler;
namespace CallOpGenericRecvMessageHelper {
template <class R>
class DeserializeFuncType;
} // namespace CallOpGenericRecvMessageHelper
/// A sequence of bytes.
class ByteBuffer final {
public:
/// Constuct an empty buffer.
ByteBuffer() : buffer_(nullptr) {}
/// Construct buffer from \a slices, of which there are \a nslices.
ByteBuffer(const Slice* slices, size_t nslices);
/// Constuct a byte buffer by referencing elements of existing buffer
/// \a buf. Wrapper of core function grpc_byte_buffer_copy
ByteBuffer(const ByteBuffer& buf);
~ByteBuffer() {
if (buffer_) {
g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
}
}
ByteBuffer& operator=(const ByteBuffer&);
/// Dump (read) the buffer contents into \a slices.
Status Dump(std::vector<Slice>* slices) const;
/// Remove all data.
void Clear() {
if (buffer_) {
g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
buffer_ = nullptr;
}
}
/// Make a duplicate copy of the internals of this byte
/// buffer so that we have our own owned version of it.
/// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable
void Duplicate() {
buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(buffer_);
}
/// Forget underlying byte buffer without destroying
/// Use this only for un-owned byte buffers
void Release() { buffer_ = nullptr; }
/// Buffer size in bytes.
size_t Length() const;
/// Swap the state of *this and *other.
void Swap(ByteBuffer* other);
/// Is this ByteBuffer valid?
bool Valid() const { return (buffer_ != nullptr); }
private:
friend class SerializationTraits<ByteBuffer, void>;
friend class CallOpSendMessage;
template <class R>
friend class CallOpRecvMessage;
friend class CallOpGenericRecvMessage;
friend class MethodHandler;
template <class ServiceType, class RequestType, class ResponseType>
friend class RpcMethodHandler;
template <class ServiceType, class RequestType, class ResponseType>
friend class ServerStreamingHandler;
template <class R>
friend class CallOpGenericRecvMessageHelper::DeserializeFuncType;
grpc_byte_buffer* buffer_;
// takes ownership
void set_buffer(grpc_byte_buffer* buf) {
if (buffer_) {
Clear();
}
buffer_ = buf;
}
grpc_byte_buffer* c_buffer() { return buffer_; }
grpc_byte_buffer** c_buffer_ptr() { return &buffer_; }
class ByteBufferPointer {
public:
ByteBufferPointer(const ByteBuffer* b)
: bbuf_(const_cast<ByteBuffer*>(b)) {}
operator ByteBuffer*() { return bbuf_; }
operator grpc_byte_buffer*() { return bbuf_->buffer_; }
operator grpc_byte_buffer**() { return &bbuf_->buffer_; }
private:
ByteBuffer* bbuf_;
};
ByteBufferPointer bbuf_ptr() const { return ByteBufferPointer(this); }
};
template <>
class SerializationTraits<ByteBuffer, void> {
public:
static Status Deserialize(ByteBuffer* byte_buffer, ByteBuffer* dest) {
dest->set_buffer(byte_buffer->buffer_);
return Status::OK;
}
static Status Serialize(const ByteBuffer& source, ByteBuffer* buffer,
bool* own_buffer) {
*buffer = source;
*own_buffer = true;
return Status::OK;
}
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_BYTE_BUFFER_H

@ -25,6 +25,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <grpc++/impl/codegen/byte_buffer.h>
#include <grpc++/impl/codegen/call_hook.h> #include <grpc++/impl/codegen/call_hook.h>
#include <grpc++/impl/codegen/client_context.h> #include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/completion_queue_tag.h> #include <grpc++/impl/codegen/completion_queue_tag.h>
@ -39,8 +40,6 @@
#include <grpc/impl/codegen/compression_types.h> #include <grpc/impl/codegen/compression_types.h>
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/grpc_types.h>
struct grpc_byte_buffer;
namespace grpc { namespace grpc {
class ByteBuffer; class ByteBuffer;
@ -281,7 +280,7 @@ class CallOpSendInitialMetadata {
class CallOpSendMessage { class CallOpSendMessage {
public: public:
CallOpSendMessage() : send_buf_(nullptr) {} CallOpSendMessage() : send_buf_() {}
/// Send \a message using \a options for the write. The \a options are cleared /// Send \a message using \a options for the write. The \a options are cleared
/// after use. /// after use.
@ -294,33 +293,35 @@ class CallOpSendMessage {
protected: protected:
void AddOp(grpc_op* ops, size_t* nops) { void AddOp(grpc_op* ops, size_t* nops) {
if (send_buf_ == nullptr) return; if (!send_buf_.Valid()) return;
grpc_op* op = &ops[(*nops)++]; grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_SEND_MESSAGE; op->op = GRPC_OP_SEND_MESSAGE;
op->flags = write_options_.flags(); op->flags = write_options_.flags();
op->reserved = NULL; op->reserved = NULL;
op->data.send_message.send_message = send_buf_; op->data.send_message.send_message = send_buf_.c_buffer();
// Flags are per-message: clear them after use. // Flags are per-message: clear them after use.
write_options_.Clear(); write_options_.Clear();
} }
void FinishOp(bool* status) { void FinishOp(bool* status) { send_buf_.Clear(); }
g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
send_buf_ = nullptr;
}
private: private:
grpc_byte_buffer* send_buf_; ByteBuffer send_buf_;
WriteOptions write_options_; WriteOptions write_options_;
}; };
namespace internal {
template <class T>
T Example();
} // namespace internal
template <class M> template <class M>
Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
write_options_ = options; write_options_ = options;
bool own_buf; bool own_buf;
Status result = Status result = SerializationTraits<M>::Serialize(
SerializationTraits<M>::Serialize(message, &send_buf_, &own_buf); message, send_buf_.bbuf_ptr(), &own_buf);
if (!own_buf) { if (!own_buf) {
send_buf_ = g_core_codegen_interface->grpc_byte_buffer_copy(send_buf_); send_buf_.Duplicate();
} }
return result; return result;
} }
@ -352,18 +353,20 @@ class CallOpRecvMessage {
op->op = GRPC_OP_RECV_MESSAGE; op->op = GRPC_OP_RECV_MESSAGE;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op->data.recv_message.recv_message = &recv_buf_; op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
} }
void FinishOp(bool* status) { void FinishOp(bool* status) {
if (message_ == nullptr) return; if (message_ == nullptr) return;
if (recv_buf_) { if (recv_buf_.Valid()) {
if (*status) { if (*status) {
got_message = *status = got_message = *status =
SerializationTraits<R>::Deserialize(recv_buf_, message_).ok(); SerializationTraits<R>::Deserialize(recv_buf_.bbuf_ptr(), message_)
.ok();
recv_buf_.Release();
} else { } else {
got_message = false; got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); recv_buf_.Clear();
} }
} else { } else {
got_message = false; got_message = false;
@ -376,14 +379,14 @@ class CallOpRecvMessage {
private: private:
R* message_; R* message_;
grpc_byte_buffer* recv_buf_; ByteBuffer recv_buf_;
bool allow_not_getting_message_; bool allow_not_getting_message_;
}; };
namespace CallOpGenericRecvMessageHelper { namespace CallOpGenericRecvMessageHelper {
class DeserializeFunc { class DeserializeFunc {
public: public:
virtual Status Deserialize(grpc_byte_buffer* buf) = 0; virtual Status Deserialize(ByteBuffer* buf) = 0;
virtual ~DeserializeFunc() {} virtual ~DeserializeFunc() {}
}; };
@ -391,8 +394,8 @@ template <class R>
class DeserializeFuncType final : public DeserializeFunc { class DeserializeFuncType final : public DeserializeFunc {
public: public:
DeserializeFuncType(R* message) : message_(message) {} DeserializeFuncType(R* message) : message_(message) {}
Status Deserialize(grpc_byte_buffer* buf) override { Status Deserialize(ByteBuffer* buf) override {
return SerializationTraits<R>::Deserialize(buf, message_); return SerializationTraits<R>::Deserialize(buf->bbuf_ptr(), message_);
} }
~DeserializeFuncType() override {} ~DeserializeFuncType() override {}
@ -428,18 +431,19 @@ class CallOpGenericRecvMessage {
op->op = GRPC_OP_RECV_MESSAGE; op->op = GRPC_OP_RECV_MESSAGE;
op->flags = 0; op->flags = 0;
op->reserved = NULL; op->reserved = NULL;
op->data.recv_message.recv_message = &recv_buf_; op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
} }
void FinishOp(bool* status) { void FinishOp(bool* status) {
if (!deserialize_) return; if (!deserialize_) return;
if (recv_buf_) { if (recv_buf_.Valid()) {
if (*status) { if (*status) {
got_message = true; got_message = true;
*status = deserialize_->Deserialize(recv_buf_).ok(); *status = deserialize_->Deserialize(&recv_buf_).ok();
recv_buf_.Release();
} else { } else {
got_message = false; got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); recv_buf_.Clear();
} }
} else { } else {
got_message = false; got_message = false;
@ -452,7 +456,7 @@ class CallOpGenericRecvMessage {
private: private:
std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_; std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_;
grpc_byte_buffer* recv_buf_; ByteBuffer recv_buf_;
bool allow_not_getting_message_; bool allow_not_getting_message_;
}; };

@ -19,6 +19,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H #ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
#define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H #define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
#include <grpc++/impl/codegen/byte_buffer.h>
#include <grpc++/impl/codegen/core_codegen_interface.h> #include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h> #include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc++/impl/codegen/sync_stream.h> #include <grpc++/impl/codegen/sync_stream.h>
@ -37,8 +38,8 @@ class RpcMethodHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) final { void RunHandler(const HandlerParameter& param) final {
RequestType req; RequestType req;
Status status = Status status = SerializationTraits<RequestType>::Deserialize(
SerializationTraits<RequestType>::Deserialize(param.request, &req); param.request.bbuf_ptr(), &req);
ResponseType rsp; ResponseType rsp;
if (status.ok()) { if (status.ok()) {
status = func_(service_, param.server_context, &req, &rsp); status = func_(service_, param.server_context, &req, &rsp);
@ -123,8 +124,8 @@ class ServerStreamingHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) final { void RunHandler(const HandlerParameter& param) final {
RequestType req; RequestType req;
Status status = Status status = SerializationTraits<RequestType>::Deserialize(
SerializationTraits<RequestType>::Deserialize(param.request, &req); param.request.bbuf_ptr(), &req);
if (status.ok()) { if (status.ok()) {
ServerWriter<ResponseType> writer(param.call, param.server_context); ServerWriter<ResponseType> writer(param.call, param.server_context);

@ -25,14 +25,11 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <grpc++/impl/codegen/byte_buffer.h>
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/rpc_method.h> #include <grpc++/impl/codegen/rpc_method.h>
#include <grpc++/impl/codegen/status.h> #include <grpc++/impl/codegen/status.h>
extern "C" {
struct grpc_byte_buffer;
}
namespace grpc { namespace grpc {
class ServerContext; class ServerContext;
class StreamContextInterface; class StreamContextInterface;
@ -43,11 +40,14 @@ class MethodHandler {
virtual ~MethodHandler() {} virtual ~MethodHandler() {}
struct HandlerParameter { struct HandlerParameter {
HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req) HandlerParameter(Call* c, ServerContext* context, grpc_byte_buffer* req)
: call(c), server_context(context), request(req) {} : call(c), server_context(context) {
request.set_buffer(req);
}
~HandlerParameter() { request.Release(); }
Call* call; Call* call;
ServerContext* server_context; ServerContext* server_context;
// Handler required to grpc_byte_buffer_destroy this // Handler required to destroy these contents
grpc_byte_buffer* request; ByteBuffer request;
}; };
virtual void RunHandler(const HandlerParameter& param) = 0; virtual void RunHandler(const HandlerParameter& param) = 0;
}; };

@ -24,17 +24,26 @@ namespace grpc {
/// Defines how to serialize and deserialize some type. /// Defines how to serialize and deserialize some type.
/// ///
/// Used for hooking different message serialization API's into GRPC. /// Used for hooking different message serialization API's into GRPC.
/// Each SerializationTraits implementation must provide the following /// Each SerializationTraits<Message> implementation must provide the
/// functions: /// following functions:
/// static Status Serialize(const Message& msg, /// 1. static Status Serialize(const Message& msg,
/// grpc_byte_buffer** buffer, /// ByteBuffer* buffer,
/// bool* own_buffer); /// bool* own_buffer);
/// static Status Deserialize(grpc_byte_buffer* buffer, /// OR
/// Message* msg, /// static Status Serialize(const Message& msg,
/// int max_receive_message_size); /// grpc_byte_buffer** buffer,
/// bool* own_buffer);
/// The former is preferred; the latter is deprecated
/// ///
/// Serialize is required to convert message to a grpc_byte_buffer, and /// 2. static Status Deserialize(ByteBuffer* buffer,
/// to store a pointer to that byte buffer at *buffer. *own_buffer should /// Message* msg);
/// OR
/// static Status Deserialize(grpc_byte_buffer* buffer,
/// Message* msg);
/// The former is preferred; the latter is deprecated
///
/// Serialize is required to convert message to a ByteBuffer, and
/// return that byte buffer through *buffer. *own_buffer should
/// be set to true if the caller owns said byte buffer, or false if /// be set to true if the caller owns said byte buffer, or false if
/// ownership is retained elsewhere. /// ownership is retained elsewhere.
/// ///

@ -19,11 +19,89 @@
#ifndef GRPCXX_IMPL_CODEGEN_SLICE_H #ifndef GRPCXX_IMPL_CODEGEN_SLICE_H
#define GRPCXX_IMPL_CODEGEN_SLICE_H #define GRPCXX_IMPL_CODEGEN_SLICE_H
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h> #include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/string_ref.h> #include <grpc++/impl/codegen/string_ref.h>
#include <grpc/impl/codegen/slice.h>
namespace grpc { namespace grpc {
/// A wrapper around \a grpc_slice.
///
/// A slice represents a contiguous reference counted array of bytes.
/// It is cheap to take references to a slice, and it is cheap to create a
/// slice pointing to a subset of another slice.
class Slice final {
public:
/// Construct an empty slice.
Slice();
/// Destructor - drops one reference.
~Slice();
enum AddRef { ADD_REF };
/// Construct a slice from \a slice, adding a reference.
Slice(grpc_slice slice, AddRef);
enum StealRef { STEAL_REF };
/// Construct a slice from \a slice, stealing a reference.
Slice(grpc_slice slice, StealRef);
/// Allocate a slice of specified size
Slice(size_t len);
/// Construct a slice from a copied buffer
Slice(const void* buf, size_t len);
/// Construct a slice from a copied string
Slice(const grpc::string& str);
enum StaticSlice { STATIC_SLICE };
/// Construct a slice from a static buffer
Slice(const void* buf, size_t len, StaticSlice);
/// Copy constructor, adds a reference.
Slice(const Slice& other);
/// Assignment, reference count is unchanged.
Slice& operator=(Slice other) {
std::swap(slice_, other.slice_);
return *this;
}
/// Create a slice pointing at some data. Calls malloc to allocate a refcount
/// for the object, and arranges that destroy will be called with the
/// user data pointer passed in at destruction. Can be the same as buf or
/// different (e.g., if data is part of a larger structure that must be
/// destroyed when the data is no longer needed)
Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data);
/// Specialization of above for common case where buf == user_data
Slice(void* buf, size_t len, void (*destroy)(void*))
: Slice(buf, len, destroy, buf) {}
/// Similar to the above but has a destroy that also takes slice length
Slice(void* buf, size_t len, void (*destroy)(void*, size_t));
/// Byte size.
size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
/// Raw pointer to the beginning (first element) of the slice.
const uint8_t* begin() const { return GRPC_SLICE_START_PTR(slice_); }
/// Raw pointer to the end (one byte \em past the last element) of the slice.
const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); }
/// Raw C slice. Caller needs to call grpc_slice_unref when done.
grpc_slice c_slice() const;
private:
friend class ByteBuffer;
grpc_slice slice_;
};
inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) { inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) {
return grpc::string_ref( return grpc::string_ref(
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)), reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)),

@ -136,8 +136,10 @@ class ServerBuilder {
/// It can be invoked multiple times. /// It can be invoked multiple times.
/// ///
/// \param addr_uri The address to try to bind to the server in URI form. If /// \param addr_uri The address to try to bind to the server in URI form. If
/// the scheme name is omitted, "dns:///" is assumed. Valid values include /// the scheme name is omitted, "dns:///" is assumed. To bind to any address,
/// dns:///localhost:1234, / 192.168.1.1:31416, dns:///[::1]:27182, etc.). /// please use IPv6 any, i.e., [::]:<port>, which also accepts IPv4
/// connections. Valid values include dns:///localhost:1234, /
/// 192.168.1.1:31416, dns:///[::1]:27182, etc.).
/// \params creds The credentials associated with the server. /// \params creds The credentials associated with the server.
/// \param selected_port[out] If not `nullptr`, gets populated with the port /// \param selected_port[out] If not `nullptr`, gets populated with the port
/// number bound to the \a grpc::Server for the corresponding endpoint after /// number bound to the \a grpc::Server for the corresponding endpoint after

@ -19,6 +19,7 @@
#ifndef GRPCXX_SUPPORT_BYTE_BUFFER_H #ifndef GRPCXX_SUPPORT_BYTE_BUFFER_H
#define GRPCXX_SUPPORT_BYTE_BUFFER_H #define GRPCXX_SUPPORT_BYTE_BUFFER_H
#include <grpc++/impl/codegen/byte_buffer.h>
#include <grpc++/impl/serialization_traits.h> #include <grpc++/impl/serialization_traits.h>
#include <grpc++/support/config.h> #include <grpc++/support/config.h>
#include <grpc++/support/slice.h> #include <grpc++/support/slice.h>
@ -27,71 +28,4 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <vector>
namespace grpc {
/// A sequence of bytes.
class ByteBuffer final {
public:
/// Constuct an empty buffer.
ByteBuffer() : buffer_(nullptr) {}
/// Construct buffer from \a slices, of which there are \a nslices.
ByteBuffer(const Slice* slices, size_t nslices);
/// Constuct a byte buffer by referencing elements of existing buffer
/// \a buf. Wrapper of core function grpc_byte_buffer_copy
ByteBuffer(const ByteBuffer& buf);
~ByteBuffer();
ByteBuffer& operator=(const ByteBuffer&);
/// Dump (read) the buffer contents into \a slices.
Status Dump(std::vector<Slice>* slices) const;
/// Remove all data.
void Clear();
/// Buffer size in bytes.
size_t Length() const;
/// Swap the state of *this and *other.
void Swap(ByteBuffer* other);
private:
friend class SerializationTraits<ByteBuffer, void>;
// takes ownership
void set_buffer(grpc_byte_buffer* buf) {
if (buffer_) {
Clear();
}
buffer_ = buf;
}
// For \a SerializationTraits's usage.
grpc_byte_buffer* buffer() const { return buffer_; }
grpc_byte_buffer* buffer_;
};
template <>
class SerializationTraits<ByteBuffer, void> {
public:
static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest) {
dest->set_buffer(byte_buffer);
return Status::OK;
}
static Status Serialize(const ByteBuffer& source, grpc_byte_buffer** buffer,
bool* own_buffer) {
*buffer = grpc_byte_buffer_copy(source.buffer());
*own_buffer = true;
return Status::OK;
}
};
} // namespace grpc
#endif // GRPCXX_SUPPORT_BYTE_BUFFER_H #endif // GRPCXX_SUPPORT_BYTE_BUFFER_H

@ -19,86 +19,8 @@
#ifndef GRPCXX_SUPPORT_SLICE_H #ifndef GRPCXX_SUPPORT_SLICE_H
#define GRPCXX_SUPPORT_SLICE_H #define GRPCXX_SUPPORT_SLICE_H
#include <grpc++/impl/codegen/slice.h>
#include <grpc++/support/config.h> #include <grpc++/support/config.h>
#include <grpc/slice.h> #include <grpc/slice.h>
namespace grpc {
/// A wrapper around \a grpc_slice.
///
/// A slice represents a contiguous reference counted array of bytes.
/// It is cheap to take references to a slice, and it is cheap to create a
/// slice pointing to a subset of another slice.
class Slice final {
public:
/// Construct an empty slice.
Slice();
/// Destructor - drops one reference.
~Slice();
enum AddRef { ADD_REF };
/// Construct a slice from \a slice, adding a reference.
Slice(grpc_slice slice, AddRef);
enum StealRef { STEAL_REF };
/// Construct a slice from \a slice, stealing a reference.
Slice(grpc_slice slice, StealRef);
/// Allocate a slice of specified size
Slice(size_t len);
/// Construct a slice from a copied buffer
Slice(const void* buf, size_t len);
/// Construct a slice from a copied string
Slice(const grpc::string& str);
enum StaticSlice { STATIC_SLICE };
/// Construct a slice from a static buffer
Slice(const void* buf, size_t len, StaticSlice);
/// Copy constructor, adds a reference.
Slice(const Slice& other);
/// Assignment, reference count is unchanged.
Slice& operator=(Slice other) {
std::swap(slice_, other.slice_);
return *this;
}
/// Create a slice pointing at some data. Calls malloc to allocate a refcount
/// for the object, and arranges that destroy will be called with the
/// user data pointer passed in at destruction. Can be the same as buf or
/// different (e.g., if data is part of a larger structure that must be
/// destroyed when the data is no longer needed)
Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data);
/// Specialization of above for common case where buf == user_data
Slice(void* buf, size_t len, void (*destroy)(void*))
: Slice(buf, len, destroy, buf) {}
/// Similar to the above but has a destroy that also takes slice length
Slice(void* buf, size_t len, void (*destroy)(void*, size_t));
/// Byte size.
size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
/// Raw pointer to the beginning (first element) of the slice.
const uint8_t* begin() const { return GRPC_SLICE_START_PTR(slice_); }
/// Raw pointer to the end (one byte \em past the last element) of the slice.
const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); }
/// Raw C slice. Caller needs to call grpc_slice_unref when done.
grpc_slice c_slice() const { return grpc_slice_ref(slice_); }
private:
friend class ByteBuffer;
grpc_slice slice_;
};
} // namespace grpc
#endif // GRPCXX_SUPPORT_SLICE_H #endif // GRPCXX_SUPPORT_SLICE_H

@ -19,69 +19,7 @@
#ifndef GRPC_BYTE_BUFFER_H #ifndef GRPC_BYTE_BUFFER_H
#define GRPC_BYTE_BUFFER_H #define GRPC_BYTE_BUFFER_H
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/slice_buffer.h> #include <grpc/slice_buffer.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Returns a RAW byte buffer instance over the given slices (up to \a nslices).
*
* Increases the reference count for all \a slices processed. The user is
* responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/
GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_create(grpc_slice *slices,
size_t nslices);
/** Returns a *compressed* RAW byte buffer instance over the given slices (up to
* \a nslices). The \a compression argument defines the compression algorithm
* used to generate the data in \a slices.
*
* Increases the reference count for all \a slices processed. The user is
* responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/
GRPCAPI grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
grpc_slice *slices, size_t nslices, grpc_compression_algorithm compression);
/** Copies input byte buffer \a bb.
*
* Increases the reference count of all the source slices. The user is
* responsible for calling grpc_byte_buffer_destroy over the returned copy. */
GRPCAPI grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb);
/** Returns the size of the given byte buffer, in bytes. */
GRPCAPI size_t grpc_byte_buffer_length(grpc_byte_buffer *bb);
/** Destroys \a byte_buffer deallocating all its memory. */
GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer);
/** Reader for byte buffers. Iterates over slices in the byte buffer */
struct grpc_byte_buffer_reader;
typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader;
/** Initialize \a reader to read over \a buffer.
* Returns 1 upon success, 0 otherwise. */
GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
grpc_byte_buffer *buffer);
/** Cleanup and destroy \a reader */
GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader);
/** Updates \a slice with the next piece of data from from \a reader and returns
* 1. Returns 0 at the end of the stream. Caller is responsible for calling
* grpc_slice_unref on the result. */
GRPCAPI int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
grpc_slice *slice);
/** Merge all data from \a reader into single slice */
GRPCAPI grpc_slice
grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader);
/** Returns a RAW byte buffer instance from the output of \a reader. */
GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
grpc_byte_buffer_reader *reader);
#ifdef __cplusplus
}
#endif
#endif /* GRPC_BYTE_BUFFER_H */ #endif /* GRPC_BYTE_BUFFER_H */

@ -47,7 +47,7 @@ GRPCAPI int grpc_compression_algorithm_parse(
* algorithm. Note that \a name is statically allocated and must *not* be freed. * algorithm. Note that \a name is statically allocated and must *not* be freed.
* Returns 1 upon success, 0 otherwise. */ * Returns 1 upon success, 0 otherwise. */
GRPCAPI int grpc_compression_algorithm_name( GRPCAPI int grpc_compression_algorithm_name(
grpc_compression_algorithm algorithm, char **name); grpc_compression_algorithm algorithm, const char **name);
/** Returns the compression algorithm corresponding to \a level for the /** Returns the compression algorithm corresponding to \a level for the
* compression algorithms encoded in the \a accepted_encodings bitset. * compression algorithms encoded in the \a accepted_encodings bitset.

@ -0,0 +1,86 @@
/*
*
* Copyright 2015 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_BYTE_BUFFER_H
#define GRPC_IMPL_CODEGEN_BYTE_BUFFER_H
#include <grpc/impl/codegen/grpc_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Returns a RAW byte buffer instance over the given slices (up to \a nslices).
*
* Increases the reference count for all \a slices processed. The user is
* responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/
GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_create(grpc_slice *slices,
size_t nslices);
/** Returns a *compressed* RAW byte buffer instance over the given slices (up to
* \a nslices). The \a compression argument defines the compression algorithm
* used to generate the data in \a slices.
*
* Increases the reference count for all \a slices processed. The user is
* responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/
GRPCAPI grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
grpc_slice *slices, size_t nslices, grpc_compression_algorithm compression);
/** Copies input byte buffer \a bb.
*
* Increases the reference count of all the source slices. The user is
* responsible for calling grpc_byte_buffer_destroy over the returned copy. */
GRPCAPI grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb);
/** Returns the size of the given byte buffer, in bytes. */
GRPCAPI size_t grpc_byte_buffer_length(grpc_byte_buffer *bb);
/** Destroys \a byte_buffer deallocating all its memory. */
GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer);
/** Reader for byte buffers. Iterates over slices in the byte buffer */
struct grpc_byte_buffer_reader;
typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader;
/** Initialize \a reader to read over \a buffer.
* Returns 1 upon success, 0 otherwise. */
GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
grpc_byte_buffer *buffer);
/** Cleanup and destroy \a reader */
GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader);
/** Updates \a slice with the next piece of data from from \a reader and returns
* 1. Returns 0 at the end of the stream. Caller is responsible for calling
* grpc_slice_unref on the result. */
GRPCAPI int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader,
grpc_slice *slice);
/** Merge all data from \a reader into single slice */
GRPCAPI grpc_slice
grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader);
/** Returns a RAW byte buffer instance from the output of \a reader. */
GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
grpc_byte_buffer_reader *reader);
#ifdef __cplusplus
}
#endif
#endif /* GRPC_IMPL_CODEGEN_BYTE_BUFFER_H */

@ -188,9 +188,14 @@ typedef struct {
#define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size" #define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size"
/** Should BDP probing be performed? */ /** Should BDP probing be performed? */
#define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe" #define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe"
/** Minimum time (in milliseconds) between successive ping frames being sent */ /** Minimum time between sending successive ping frames without receiving any
#define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \ data frame, Int valued, milliseconds. */
#define GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS \
"grpc.http2.min_time_between_pings_ms" "grpc.http2.min_time_between_pings_ms"
/** Minimum allowed time between receiving successive ping frames without
sending any data frame. Int valued, milliseconds */
#define GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS \
"grpc.http2.min_ping_interval_without_data_ms"
/** Channel arg to override the http2 :scheme header */ /** Channel arg to override the http2 :scheme header */
#define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme" #define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
/** How many pings can we send before needing to send a data frame or header /** How many pings can we send before needing to send a data frame or header
@ -202,10 +207,6 @@ typedef struct {
closing the transport? (0 indicates that the server can bear an infinite closing the transport? (0 indicates that the server can bear an infinite
number of misbehaving pings) */ number of misbehaving pings) */
#define GRPC_ARG_HTTP2_MAX_PING_STRIKES "grpc.http2.max_ping_strikes" #define GRPC_ARG_HTTP2_MAX_PING_STRIKES "grpc.http2.max_ping_strikes"
/** Minimum allowed time between two pings without sending any data frame. Int
valued, seconds */
#define GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS \
"grpc.http2.min_ping_interval_without_data_ms"
/** How much data are we willing to queue up per stream if /** How much data are we willing to queue up per stream if
GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */ GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */
#define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size" #define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size"

@ -65,11 +65,7 @@ GPRAPI grpc_slice grpc_slice_new_with_len(void *p, size_t len,
GPRAPI grpc_slice grpc_slice_malloc(size_t length); GPRAPI grpc_slice grpc_slice_malloc(size_t length);
GPRAPI grpc_slice grpc_slice_malloc_large(size_t length); GPRAPI grpc_slice grpc_slice_malloc_large(size_t length);
#define GRPC_SLICE_MALLOC(len) \ #define GRPC_SLICE_MALLOC(len) grpc_slice_malloc(len)
((len) <= GRPC_SLICE_INLINED_SIZE \
? (grpc_slice){.refcount = NULL, \
.data.inlined = {.length = (uint8_t)(len)}} \
: grpc_slice_malloc_large((len)))
/** Intern a slice: /** Intern a slice:

@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email> <email>grpc-packages@google.com</email>
<active>yes</active> <active>yes</active>
</lead> </lead>
<date>2017-05-22</date> <date>2017-08-24</date>
<time>16:06:07</time> <time>16:06:07</time>
<version> <version>
<release>1.7.0dev</release> <release>1.7.0dev</release>
@ -25,6 +25,9 @@
- Channel are now by default persistent #11878 - Channel are now by default persistent #11878
- Some bug fixes from 1.4 branch #12109, #12123 - Some bug fixes from 1.4 branch #12109, #12123
- Fixed hang bug when fork() was used #11814 - Fixed hang bug when fork() was used #11814
- License changed to Apache 2.0
- Added support for php_namespace option in codegen plugin #11886
- Updated gRPC C Core library version 1.6
</notes> </notes>
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
@ -155,6 +158,7 @@
<file baseinstalldir="/" name="src/core/lib/support/tmpfile_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/tmpfile_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/tmpfile_windows.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/tmpfile_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/wrap_memcpy.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/wrap_memcpy.c" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer_reader.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer_reader.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" /> <file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" />
@ -272,6 +276,8 @@
<file baseinstalldir="/" name="src/core/lib/compression/compression_internal.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/compression_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/stream_compression.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_gzip.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_identity.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/debug/stats.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats_data.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/debug/stats_data.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/format_request.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/format_request.h" role="src" />
@ -426,6 +432,8 @@
<file baseinstalldir="/" name="src/core/lib/compression/compression_internal.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/compression_internal.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/stream_compression.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_gzip.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/stream_compression_identity.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/debug/stats.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/stats_data.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/debug/stats_data.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/format_request.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/format_request.c" role="src" />

@ -70,7 +70,7 @@ CLASSIFIERS = [
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
], ]
# Environment variable to determine whether or not the Cython extension should # Environment variable to determine whether or not the Cython extension should
# *use* Cython or use the generated C files. Note that this requires the C files # *use* Cython or use the generated C files. Note that this requires the C files

@ -1 +0,0 @@
@vjpai cpp_generator.cc

@ -165,25 +165,37 @@ void PrintHeaderClientMethodInterfaces(
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name(); (*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string method_params; // extra arguments to method
grpc::string raw_args; // extra arguments to raw version of method
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
{"PrepareAsync", "", ""}};
if (is_public) { if (is_public) {
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print( printer->Print(
*vars, *vars,
"virtual ::grpc::Status $Method$(::grpc::ClientContext* context, " "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) = 0;\n"); "const $Request$& request, $Response$* response) = 0;\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"std::unique_ptr< " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> " printer->Print(
"Async$Method$(::grpc::ClientContext* context, " *vars,
"const $Request$& request, " "std::unique_ptr< "
"::grpc::CompletionQueue* cq) {\n"); "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
printer->Indent(); "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
printer->Print(*vars, "const $Request$& request, "
"return std::unique_ptr< " "::grpc::CompletionQueue* cq) {\n");
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>(" printer->Indent();
"Async$Method$Raw(context, request, cq));\n"); printer->Print(
printer->Outdent(); *vars,
printer->Print("}\n"); "return std::unique_ptr< "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -197,19 +209,26 @@ void PrintHeaderClientMethodInterfaces(
"($Method$Raw(context, response));\n"); "($Method$Raw(context, response));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>" (*vars)["AsyncMethodParams"] = async_prefix.method_params;
" Async$Method$(::grpc::ClientContext* context, $Response$* " (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"response, " printer->Print(
"::grpc::CompletionQueue* cq, void* tag) {\n"); *vars,
printer->Indent(); "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
printer->Print(*vars, " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"return std::unique_ptr< " "$Response$* "
"::grpc::ClientAsyncWriterInterface< $Request$>>(" "response, "
"Async$Method$Raw(context, response, cq, tag));\n"); "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Outdent(); printer->Indent();
printer->Print("}\n"); printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncWriterInterface< $Request$>>("
"$AsyncPrefix$$Method$Raw(context, response, "
"cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ServerOnlyStreaming(method)) { } else if (ServerOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -223,19 +242,25 @@ void PrintHeaderClientMethodInterfaces(
"($Method$Raw(context, request));\n"); "($Method$Raw(context, request));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"Async$Method$(" (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"::grpc::ClientContext* context, const $Request$& request, " printer->Print(
"::grpc::CompletionQueue* cq, void* tag) {\n"); *vars,
printer->Indent(); "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
printer->Print(*vars, "$AsyncPrefix$$Method$("
"return std::unique_ptr< " "::grpc::ClientContext* context, const $Request$& request, "
"::grpc::ClientAsyncReaderInterface< $Response$>>(" "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"Async$Method$Raw(context, request, cq, tag));\n"); printer->Indent();
printer->Outdent(); printer->Print(
printer->Print("}\n"); *vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderInterface< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (method->BidiStreaming()) { } else if (method->BidiStreaming()) {
printer->Print(*vars, printer->Print(*vars,
"std::unique_ptr< ::grpc::ClientReaderWriterInterface< " "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
@ -249,61 +274,83 @@ void PrintHeaderClientMethodInterfaces(
"$Method$Raw(context));\n"); "$Method$Raw(context));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"std::unique_ptr< " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> " (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"Async$Method$(::grpc::ClientContext* context, " printer->Print(
"::grpc::CompletionQueue* cq, void* tag) {\n"); *vars,
printer->Indent(); "std::unique_ptr< "
printer->Print( "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
*vars, "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"return std::unique_ptr< " "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>(" printer->Indent();
"Async$Method$Raw(context, cq, tag));\n"); printer->Print(
printer->Outdent(); *vars,
printer->Print("}\n"); "return std::unique_ptr< "
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} }
} else { } else {
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* " printer->Print(
"Async$Method$Raw(::grpc::ClientContext* context, " *vars,
"const $Request$& request, " "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
"::grpc::CompletionQueue* cq) = 0;\n"); "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) = 0;\n");
}
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
"virtual ::grpc::ClientWriterInterface< $Request$>*" "virtual ::grpc::ClientWriterInterface< $Request$>*"
" $Method$Raw(" " $Method$Raw("
"::grpc::ClientContext* context, $Response$* response) = 0;\n"); "::grpc::ClientContext* context, $Response$* response) = 0;\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*" (*vars)["AsyncPrefix"] = async_prefix.prefix;
" Async$Method$Raw(::grpc::ClientContext* context, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"$Response$* response, " printer->Print(
"::grpc::CompletionQueue* cq, void* tag) = 0;\n"); *vars,
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
" $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"$Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
}
} else if (ServerOnlyStreaming(method)) { } else if (ServerOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
"virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw(" "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
"::grpc::ClientContext* context, const $Request$& request) = 0;\n"); "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"virtual ::grpc::ClientAsyncReaderInterface< $Response$>* " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"Async$Method$Raw(" printer->Print(
"::grpc::ClientContext* context, const $Request$& request, " *vars,
"::grpc::CompletionQueue* cq, void* tag) = 0;\n"); "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
"$AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
}
} else if (method->BidiStreaming()) { } else if (method->BidiStreaming()) {
printer->Print(*vars, printer->Print(*vars,
"virtual ::grpc::ClientReaderWriterInterface< $Request$, " "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
"$Response$>* " "$Response$>* "
"$Method$Raw(::grpc::ClientContext* context) = 0;\n"); "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"virtual ::grpc::ClientAsyncReaderWriterInterface< " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"$Request$, $Response$>* " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"Async$Method$Raw(::grpc::ClientContext* context, " printer->Print(
"::grpc::CompletionQueue* cq, void* tag) = 0;\n"); *vars,
"virtual ::grpc::ClientAsyncReaderWriterInterface< "
"$Request$, $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
}
} }
} }
} }
@ -315,25 +362,35 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name(); (*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string method_params; // extra arguments to method
grpc::string raw_args; // extra arguments to raw version of method
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
{"PrepareAsync", "", ""}};
if (is_public) { if (is_public) {
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print( printer->Print(
*vars, *vars,
"::grpc::Status $Method$(::grpc::ClientContext* context, " "::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) override;\n"); "const $Request$& request, $Response$* response) override;\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " printer->Print(
"Async$Method$(::grpc::ClientContext* context, " *vars,
"const $Request$& request, " "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
"::grpc::CompletionQueue* cq) {\n"); "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
printer->Indent(); "const $Request$& request, "
printer->Print(*vars, "::grpc::CompletionQueue* cq) {\n");
"return std::unique_ptr< " printer->Indent();
"::grpc::ClientAsyncResponseReader< $Response$>>(" printer->Print(*vars,
"Async$Method$Raw(context, request, cq));\n"); "return std::unique_ptr< "
printer->Outdent(); "::grpc::ClientAsyncResponseReader< $Response$>>("
printer->Print("}\n"); "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -346,18 +403,24 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, response));\n"); "($Method$Raw(context, response));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>" (*vars)["AsyncPrefix"] = async_prefix.prefix;
" Async$Method$(::grpc::ClientContext* context, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"$Response$* response, " (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars,
printer->Indent(); "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
printer->Print( " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
*vars, "$Response$* response, "
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>(" "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"Async$Method$Raw(context, response, cq, tag));\n"); printer->Indent();
printer->Outdent(); printer->Print(
printer->Print("}\n"); *vars,
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
"$AsyncPrefix$$Method$Raw(context, response, "
"cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ServerOnlyStreaming(method)) { } else if (ServerOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -371,19 +434,24 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, request));\n"); "($Method$Raw(context, request));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"Async$Method$(" (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"::grpc::ClientContext* context, const $Request$& request, " printer->Print(
"::grpc::CompletionQueue* cq, void* tag) {\n"); *vars,
printer->Indent(); "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
printer->Print( "$AsyncPrefix$$Method$("
*vars, "::grpc::ClientContext* context, const $Request$& request, "
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>(" "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"Async$Method$Raw(context, request, cq, tag));\n"); printer->Indent();
printer->Outdent(); printer->Print(
printer->Print("}\n"); *vars,
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (method->BidiStreaming()) { } else if (method->BidiStreaming()) {
printer->Print( printer->Print(
*vars, *vars,
@ -396,53 +464,80 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"$Method$Raw(context));\n"); "$Method$Raw(context));\n");
printer->Outdent(); printer->Outdent();
printer->Print("}\n"); printer->Print("}\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"$Request$, $Response$>> " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"Async$Method$(::grpc::ClientContext* context, " (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"::grpc::CompletionQueue* cq, void* tag) {\n"); printer->Print(*vars,
printer->Indent(); "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
printer->Print(*vars, "$Request$, $Response$>> "
"return std::unique_ptr< " "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>(" "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"Async$Method$Raw(context, cq, tag));\n"); printer->Indent();
printer->Outdent(); printer->Print(
printer->Print("}\n"); *vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} }
} else { } else {
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"::grpc::ClientAsyncResponseReader< $Response$>* " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"Async$Method$Raw(::grpc::ClientContext* context, " printer->Print(
"const $Request$& request, " *vars,
"::grpc::CompletionQueue* cq) override;\n"); "::grpc::ClientAsyncResponseReader< $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) override;\n");
}
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print(*vars, printer->Print(*vars,
"::grpc::ClientWriter< $Request$>* $Method$Raw(" "::grpc::ClientWriter< $Request$>* $Method$Raw("
"::grpc::ClientContext* context, $Response$* response) " "::grpc::ClientContext* context, $Response$* response) "
"override;\n"); "override;\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw(" (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientContext* context, $Response$* response, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::CompletionQueue* cq, void* tag) override;\n"); (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
}
} else if (ServerOnlyStreaming(method)) { } else if (ServerOnlyStreaming(method)) {
printer->Print(*vars, printer->Print(*vars,
"::grpc::ClientReader< $Response$>* $Method$Raw(" "::grpc::ClientReader< $Response$>* $Method$Raw("
"::grpc::ClientContext* context, const $Request$& request)" "::grpc::ClientContext* context, const $Request$& request)"
" override;\n"); " override;\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw(" (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::ClientContext* context, const $Request$& request, " (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
"::grpc::CompletionQueue* cq, void* tag) override;\n"); printer->Print(
*vars,
"::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
}
} else if (method->BidiStreaming()) { } else if (method->BidiStreaming()) {
printer->Print(*vars, printer->Print(*vars,
"::grpc::ClientReaderWriter< $Request$, $Response$>* " "::grpc::ClientReaderWriter< $Request$, $Response$>* "
"$Method$Raw(::grpc::ClientContext* context) override;\n"); "$Method$Raw(::grpc::ClientContext* context) override;\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"Async$Method$Raw(::grpc::ClientContext* context, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::CompletionQueue* cq, void* tag) override;\n"); (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
}
} }
} }
} }
@ -1077,6 +1172,13 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name(); (*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string start; // bool literal expressed as string
grpc::string method_params; // extra arguments to method
grpc::string create_args; // extra arguments to creator
} async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
{"PrepareAsync", "false", "", ", nullptr"}};
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print(*vars, printer->Print(*vars,
"::grpc::Status $ns$$Service$::Stub::$Method$(" "::grpc::Status $ns$$Service$::Stub::$Method$("
@ -1087,19 +1189,23 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, " "rpcmethod_$Method$_, "
"context, request, response);\n" "context, request, response);\n"
"}\n\n"); "}\n\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncResponseReader< $Response$>* " (*vars)["AsyncStart"] = async_prefix.start;
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " printer->Print(*vars,
"const $Request$& request, " "::grpc::ClientAsyncResponseReader< $Response$>* "
"::grpc::CompletionQueue* cq) {\n"); "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
printer->Print(*vars, "ClientContext* context, "
" return " "const $Request$& request, "
"::grpc::ClientAsyncResponseReader< $Response$>::Create(" "::grpc::CompletionQueue* cq) {\n");
"channel_.get(), cq, " printer->Print(*vars,
"rpcmethod_$Method$_, " " return "
"context, request);\n" "::grpc::ClientAsyncResponseReader< $Response$>::Create("
"}\n\n"); "channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, $AsyncStart$);\n"
"}\n\n");
}
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print(*vars, printer->Print(*vars,
"::grpc::ClientWriter< $Request$>* " "::grpc::ClientWriter< $Request$>* "
@ -1111,17 +1217,23 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, " "rpcmethod_$Method$_, "
"context, response);\n" "context, response);\n"
"}\n\n"); "}\n\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"::grpc::ClientAsyncWriter< $Request$>* " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"$ns$$Service$::Stub::Async$Method$Raw(" (*vars)["AsyncStart"] = async_prefix.start;
"::grpc::ClientContext* context, $Response$* response, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::CompletionQueue* cq, void* tag) {\n"); (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
printer->Print(*vars, printer->Print(*vars,
" return ::grpc::ClientAsyncWriter< $Request$>::Create(" "::grpc::ClientAsyncWriter< $Request$>* "
"channel_.get(), cq, " "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
"rpcmethod_$Method$_, " "::grpc::ClientContext* context, $Response$* response, "
"context, response, tag);\n" "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"}\n\n"); printer->Print(*vars,
" return ::grpc::ClientAsyncWriter< $Request$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, response, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
}
} else if (ServerOnlyStreaming(method)) { } else if (ServerOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
@ -1134,17 +1246,24 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, " "rpcmethod_$Method$_, "
"context, request);\n" "context, request);\n"
"}\n\n"); "}\n\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"::grpc::ClientAsyncReader< $Response$>* " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"$ns$$Service$::Stub::Async$Method$Raw(" (*vars)["AsyncStart"] = async_prefix.start;
"::grpc::ClientContext* context, const $Request$& request, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::CompletionQueue* cq, void* tag) {\n"); (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
printer->Print(*vars, printer->Print(
" return ::grpc::ClientAsyncReader< $Response$>::Create(" *vars,
"channel_.get(), cq, " "::grpc::ClientAsyncReader< $Response$>* "
"rpcmethod_$Method$_, " "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
"context, request, tag);\n" "::grpc::ClientContext* context, const $Request$& request, "
"}\n\n"); "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(*vars,
" return ::grpc::ClientAsyncReader< $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
}
} else if (method->BidiStreaming()) { } else if (method->BidiStreaming()) {
printer->Print( printer->Print(
*vars, *vars,
@ -1157,19 +1276,25 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"rpcmethod_$Method$_, " "rpcmethod_$Method$_, "
"context);\n" "context);\n"
"}\n\n"); "}\n\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " (*vars)["AsyncStart"] = async_prefix.start;
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::CompletionQueue* cq, void* tag) {\n"); (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
printer->Print( printer->Print(*vars,
*vars, "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
" return " "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>::Create(" "ClientContext* context, "
"channel_.get(), cq, " "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
"rpcmethod_$Method$_, " printer->Print(
"context, tag);\n" *vars,
"}\n\n"); " return "
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
}
} }
} }
@ -1460,50 +1585,79 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name(); (*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string method_params; // extra arguments to method
int extra_method_param_count;
} async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print( printer->Print(
*vars, *vars,
"MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, " "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response));\n"); "const $Request$& request, $Response$* response));\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"MOCK_METHOD3(Async$Method$Raw, " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*" printer->Print(
"(::grpc::ClientContext* context, const $Request$& request, " *vars,
"::grpc::CompletionQueue* cq));\n"); "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq));\n");
}
} else if (ClientOnlyStreaming(method)) { } else if (ClientOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
"MOCK_METHOD2($Method$Raw, " "MOCK_METHOD2($Method$Raw, "
"::grpc::ClientWriterInterface< $Request$>*" "::grpc::ClientWriterInterface< $Request$>*"
"(::grpc::ClientContext* context, $Response$* response));\n"); "(::grpc::ClientContext* context, $Response$* response));\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"MOCK_METHOD4(Async$Method$Raw, " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncWriterInterface< $Request$>*" (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"(::grpc::ClientContext* context, $Response$* response, " (*vars)["MockArgs"] =
"::grpc::CompletionQueue* cq, void* tag));\n"); std::to_string(3 + async_prefix.extra_method_param_count);
printer->Print(*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncWriterInterface< $Request$>*"
"(::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
}
} else if (ServerOnlyStreaming(method)) { } else if (ServerOnlyStreaming(method)) {
printer->Print( printer->Print(
*vars, *vars,
"MOCK_METHOD2($Method$Raw, " "MOCK_METHOD2($Method$Raw, "
"::grpc::ClientReaderInterface< $Response$>*" "::grpc::ClientReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request));\n"); "(::grpc::ClientContext* context, const $Request$& request));\n");
printer->Print(*vars, for (auto async_prefix : async_prefixes) {
"MOCK_METHOD4(Async$Method$Raw, " (*vars)["AsyncPrefix"] = async_prefix.prefix;
"::grpc::ClientAsyncReaderInterface< $Response$>*" (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"(::grpc::ClientContext* context, const $Request$& request, " (*vars)["MockArgs"] =
"::grpc::CompletionQueue* cq, void* tag));\n"); std::to_string(3 + async_prefix.extra_method_param_count);
printer->Print(
*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
}
} else if (method->BidiStreaming()) { } else if (method->BidiStreaming()) {
printer->Print( printer->Print(
*vars, *vars,
"MOCK_METHOD1($Method$Raw, " "MOCK_METHOD1($Method$Raw, "
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>*" "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
"(::grpc::ClientContext* context));\n"); "(::grpc::ClientContext* context));\n");
printer->Print( for (auto async_prefix : async_prefixes) {
*vars, (*vars)["AsyncPrefix"] = async_prefix.prefix;
"MOCK_METHOD3(Async$Method$Raw, " (*vars)["AsyncMethodParams"] = async_prefix.method_params;
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*" (*vars)["MockArgs"] =
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, " std::to_string(2 + async_prefix.extra_method_param_count);
"void* tag));\n"); printer->Print(
*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
"$AsyncMethodParams$));\n");
}
} }
} }

@ -33,7 +33,7 @@ using std::map;
namespace grpc_php_generator { namespace grpc_php_generator {
namespace { namespace {
grpc::string MessageIdentifierName(const grpc::string &name) { grpc::string ConvertToPhpNamespace(const grpc::string &name) {
std::vector<grpc::string> tokens = grpc_generator::tokenize(name, "."); std::vector<grpc::string> tokens = grpc_generator::tokenize(name, ".");
std::ostringstream oss; std::ostringstream oss;
for (unsigned int i = 0; i < tokens.size(); i++) { for (unsigned int i = 0; i < tokens.size(); i++) {
@ -43,14 +43,33 @@ grpc::string MessageIdentifierName(const grpc::string &name) {
return oss.str(); return oss.str();
} }
grpc::string PackageName(const FileDescriptor *file) {
if (file->options().has_php_namespace()) {
return file->options().php_namespace();
} else {
return ConvertToPhpNamespace(file->package());
}
}
grpc::string MessageIdentifierName(const grpc::string &name,
const FileDescriptor *file) {
std::vector<grpc::string> tokens = grpc_generator::tokenize(name, ".");
std::ostringstream oss;
oss << PackageName(file) << "\\"
<< grpc_generator::CapitalizeFirstLetter(tokens[tokens.size() - 1]);
return oss.str();
}
void PrintMethod(const MethodDescriptor *method, Printer *out) { void PrintMethod(const MethodDescriptor *method, Printer *out) {
const Descriptor *input_type = method->input_type(); const Descriptor *input_type = method->input_type();
const Descriptor *output_type = method->output_type(); const Descriptor *output_type = method->output_type();
map<grpc::string, grpc::string> vars; map<grpc::string, grpc::string> vars;
vars["service_name"] = method->service()->full_name(); vars["service_name"] = method->service()->full_name();
vars["name"] = method->name(); vars["name"] = method->name();
vars["input_type_id"] = MessageIdentifierName(input_type->full_name()); vars["input_type_id"] =
vars["output_type_id"] = MessageIdentifierName(output_type->full_name()); MessageIdentifierName(input_type->full_name(), input_type->file());
vars["output_type_id"] =
MessageIdentifierName(output_type->full_name(), output_type->file());
out->Print("/**\n"); out->Print("/**\n");
out->Print(GetPHPComments(method, " *").c_str()); out->Print(GetPHPComments(method, " *").c_str());
@ -149,12 +168,7 @@ grpc::string GenerateFile(const FileDescriptor *file,
} }
map<grpc::string, grpc::string> vars; map<grpc::string, grpc::string> vars;
grpc::string php_namespace; grpc::string php_namespace = PackageName(file);
if (file->options().has_php_namespace()) {
php_namespace = file->options().php_namespace();
} else {
php_namespace = MessageIdentifierName(file->package());
}
vars["package"] = php_namespace; vars["package"] = php_namespace;
out.Print(vars, "namespace $package$;\n\n"); out.Print(vars, "namespace $package$;\n\n");

@ -767,9 +767,9 @@ bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
ProtoBufFile pbfile(file); ProtoBufFile pbfile(file);
PrivateGenerator generator(config_, &pbfile); PrivateGenerator generator(config_, &pbfile);
if (parameter == "grpc_2_0") { if (parameter == "" || parameter == "grpc_2_0") {
return GenerateGrpc(context, generator, pb2_grpc_file_name, true); return GenerateGrpc(context, generator, pb2_grpc_file_name, true);
} else if (parameter == "") { } else if (parameter == "grpc_1_0") {
return GenerateGrpc(context, generator, pb2_grpc_file_name, true) && return GenerateGrpc(context, generator, pb2_grpc_file_name, true) &&
GenerateGrpc(context, generator, pb2_file_name, false); GenerateGrpc(context, generator, pb2_file_name, false);
} else { } else {

@ -37,20 +37,20 @@
void define_base_resources() { void define_base_resources() {
google_census_Resource_BasicUnit numerator = google_census_Resource_BasicUnit numerator =
google_census_Resource_BasicUnit_SECS; google_census_Resource_BasicUnit_SECS;
resource r = {"client_rpc_latency", // name resource r = {(char *)"client_rpc_latency", // name
"Client RPC latency in seconds", // description (char *)"Client RPC latency in seconds", // description
0, // prefix 0, // prefix
1, // n_numerators 1, // n_numerators
&numerator, // numerators &numerator, // numerators
0, // n_denominators 0, // n_denominators
NULL}; // denominators NULL}; // denominators
define_resource(&r); define_resource(&r);
r = (resource){"server_rpc_latency", // name r = (resource){(char *)"server_rpc_latency", // name
"Server RPC latency in seconds", // description (char *)"Server RPC latency in seconds", // description
0, // prefix 0, // prefix
1, // n_numerators 1, // n_numerators
&numerator, // numerators &numerator, // numerators
0, // n_denominators 0, // n_denominators
NULL}; // denominators NULL}; // denominators
define_resource(&r); define_resource(&r);
} }

@ -86,7 +86,7 @@ static void delete_state_watcher(grpc_exec_ctx *exec_ctx, state_watcher *w) {
static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw, static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
grpc_cq_completion *ignored) { grpc_cq_completion *ignored) {
int delete = 0; bool should_delete = false;
state_watcher *w = (state_watcher *)pw; state_watcher *w = (state_watcher *)pw;
gpr_mu_lock(&w->mu); gpr_mu_lock(&w->mu);
switch (w->phase) { switch (w->phase) {
@ -94,12 +94,12 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw,
case READY_TO_CALL_BACK: case READY_TO_CALL_BACK:
GPR_UNREACHABLE_CODE(return ); GPR_UNREACHABLE_CODE(return );
case CALLING_BACK_AND_FINISHED: case CALLING_BACK_AND_FINISHED:
delete = 1; should_delete = true;
break; break;
} }
gpr_mu_unlock(&w->mu); gpr_mu_unlock(&w->mu);
if (delete) { if (should_delete) {
delete_state_watcher(exec_ctx, w); delete_state_watcher(exec_ctx, w);
} }
} }
@ -161,12 +161,12 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw, static void watch_complete(grpc_exec_ctx *exec_ctx, void *pw,
grpc_error *error) { grpc_error *error) {
partly_done(exec_ctx, pw, true, GRPC_ERROR_REF(error)); partly_done(exec_ctx, (state_watcher *)pw, true, GRPC_ERROR_REF(error));
} }
static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw,
grpc_error *error) { grpc_error *error) {
partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error)); partly_done(exec_ctx, (state_watcher *)pw, false, GRPC_ERROR_REF(error));
} }
int grpc_channel_num_external_connectivity_watchers(grpc_channel *channel) { int grpc_channel_num_external_connectivity_watchers(grpc_channel *channel) {

@ -85,7 +85,7 @@ static void method_parameters_unref(method_parameters *method_params) {
} }
static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) { static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
method_parameters_unref(value); method_parameters_unref((method_parameters *)value);
} }
static bool parse_wait_for_ready(grpc_json *field, static bool parse_wait_for_ready(grpc_json *field,
@ -375,7 +375,7 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
} }
// Extract the following fields from the resolver result, if non-NULL. // Extract the following fields from the resolver result, if non-NULL.
bool lb_policy_updated = false; bool lb_policy_updated = false;
char *lb_policy_name = NULL; char *lb_policy_name_dup = NULL;
bool lb_policy_name_changed = false; bool lb_policy_name_changed = false;
grpc_lb_policy *new_lb_policy = NULL; grpc_lb_policy *new_lb_policy = NULL;
char *service_config_json = NULL; char *service_config_json = NULL;
@ -383,6 +383,7 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table *method_params_table = NULL; grpc_slice_hash_table *method_params_table = NULL;
if (chand->resolver_result != NULL) { if (chand->resolver_result != NULL) {
// Find LB policy name. // Find LB policy name.
const char *lb_policy_name = NULL;
const grpc_arg *channel_arg = const grpc_arg *channel_arg =
grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
if (channel_arg != NULL) { if (channel_arg != NULL) {
@ -473,7 +474,7 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
// Before we clean up, save a copy of lb_policy_name, since it might // Before we clean up, save a copy of lb_policy_name, since it might
// be pointing to data inside chand->resolver_result. // be pointing to data inside chand->resolver_result.
// The copy will be saved in chand->lb_policy_name below. // The copy will be saved in chand->lb_policy_name below.
lb_policy_name = gpr_strdup(lb_policy_name); lb_policy_name_dup = gpr_strdup(lb_policy_name);
grpc_channel_args_destroy(exec_ctx, chand->resolver_result); grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
chand->resolver_result = NULL; chand->resolver_result = NULL;
} }
@ -481,8 +482,8 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"chand=%p: resolver result: lb_policy_name=\"%s\"%s, " "chand=%p: resolver result: lb_policy_name=\"%s\"%s, "
"service_config=\"%s\"", "service_config=\"%s\"",
chand, lb_policy_name, lb_policy_name_changed ? " (changed)" : "", chand, lb_policy_name_dup,
service_config_json); lb_policy_name_changed ? " (changed)" : "", service_config_json);
} }
// Now swap out fields in chand. Note that the new values may still // Now swap out fields in chand. Note that the new values may still
// be NULL if (e.g.) the resolver failed to return results or the // be NULL if (e.g.) the resolver failed to return results or the
@ -490,9 +491,9 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
// //
// First, swap out the data used by cc_get_channel_info(). // First, swap out the data used by cc_get_channel_info().
gpr_mu_lock(&chand->info_mu); gpr_mu_lock(&chand->info_mu);
if (lb_policy_name != NULL) { if (lb_policy_name_dup != NULL) {
gpr_free(chand->info_lb_policy_name); gpr_free(chand->info_lb_policy_name);
chand->info_lb_policy_name = lb_policy_name; chand->info_lb_policy_name = lb_policy_name_dup;
} }
if (service_config_json != NULL) { if (service_config_json != NULL) {
gpr_free(chand->info_service_config_json); gpr_free(chand->info_service_config_json);
@ -717,7 +718,8 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"client channel factory arg must be a pointer"); "client channel factory arg must be a pointer");
} }
grpc_client_channel_factory_ref(arg->value.pointer.p); grpc_client_channel_factory_ref(
(grpc_client_channel_factory *)arg->value.pointer.p);
chand->client_channel_factory = chand->client_channel_factory =
(grpc_client_channel_factory *)arg->value.pointer.p; (grpc_client_channel_factory *)arg->value.pointer.p;
// Get server name to resolve, using proxy mapper if needed. // Get server name to resolve, using proxy mapper if needed.
@ -1016,13 +1018,11 @@ static void create_subchannel_call_locked(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, // Invoked when a pick is completed, on both success or failure.
grpc_call_element *elem, static void pick_done_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_error *error) { grpc_error *error) {
call_data *calld = (call_data *)elem->call_data; call_data *calld = (call_data *)elem->call_data;
channel_data *chand = (channel_data *)elem->channel_data; channel_data *chand = (channel_data *)elem->channel_data;
grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties);
if (calld->connected_subchannel == NULL) { if (calld->connected_subchannel == NULL) {
// Failed to create subchannel. // Failed to create subchannel.
GRPC_ERROR_UNREF(calld->error); GRPC_ERROR_UNREF(calld->error);
@ -1044,12 +1044,116 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
/** Return true if subchannel is available immediately (in which case // A wrapper around pick_done_locked() that is used in cases where
subchannel_ready_locked() should not be called), or false otherwise (in // either (a) the pick was deferred pending a resolver result or (b) the
which case subchannel_ready_locked() should be called when the subchannel // pick was done asynchronously. Removes the call's polling entity from
is available). */ // chand->interested_parties before invoking pick_done_locked().
static bool pick_subchannel_locked(grpc_exec_ctx *exec_ctx, static void async_pick_done_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem); grpc_call_element *elem, grpc_error *error) {
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties);
pick_done_locked(exec_ctx, elem, error);
}
// Note: This runs under the client_channel combiner, but will NOT be
// holding the call combiner.
static void pick_callback_cancel_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_call_element *elem = (grpc_call_element *)arg;
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
if (calld->lb_policy != NULL) {
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: cancelling pick from LB policy %p",
chand, calld, calld->lb_policy);
}
grpc_lb_policy_cancel_pick_locked(exec_ctx, calld->lb_policy,
&calld->connected_subchannel,
GRPC_ERROR_REF(error));
}
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_callback_cancel");
}
// Callback invoked by grpc_lb_policy_pick_locked() for async picks.
// Unrefs the LB policy and invokes async_pick_done_locked().
static void pick_callback_done_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_call_element *elem = (grpc_call_element *)arg;
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed asynchronously",
chand, calld);
}
GPR_ASSERT(calld->lb_policy != NULL);
GRPC_LB_POLICY_UNREF(exec_ctx, calld->lb_policy, "pick_subchannel");
calld->lb_policy = NULL;
async_pick_done_locked(exec_ctx, elem, GRPC_ERROR_REF(error));
}
// Takes a ref to chand->lb_policy and calls grpc_lb_policy_pick_locked().
// If the pick was completed synchronously, unrefs the LB policy and
// returns true.
static bool pick_callback_start_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: starting pick on lb_policy=%p",
chand, calld, chand->lb_policy);
}
apply_service_config_to_call_locked(exec_ctx, elem);
// If the application explicitly set wait_for_ready, use that.
// Otherwise, if the service config specified a value for this
// method, use that.
uint32_t initial_metadata_flags =
calld->initial_metadata_batch->payload->send_initial_metadata
.send_initial_metadata_flags;
const bool wait_for_ready_set_from_api =
initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
const bool wait_for_ready_set_from_service_config =
calld->method_params != NULL &&
calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
if (!wait_for_ready_set_from_api && wait_for_ready_set_from_service_config) {
if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
}
}
const grpc_lb_policy_pick_args inputs = {
calld->initial_metadata_batch->payload->send_initial_metadata
.send_initial_metadata,
initial_metadata_flags, &calld->lb_token_mdelem};
// Keep a ref to the LB policy in calld while the pick is pending.
GRPC_LB_POLICY_REF(chand->lb_policy, "pick_subchannel");
calld->lb_policy = chand->lb_policy;
GRPC_CLOSURE_INIT(&calld->lb_pick_closure, pick_callback_done_locked, elem,
grpc_combiner_scheduler(chand->combiner));
const bool pick_done = grpc_lb_policy_pick_locked(
exec_ctx, chand->lb_policy, &inputs, &calld->connected_subchannel,
calld->subchannel_call_context, NULL, &calld->lb_pick_closure);
if (pick_done) {
/* synchronous grpc_lb_policy_pick call. Unref the LB policy. */
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed synchronously",
chand, calld);
}
GRPC_LB_POLICY_UNREF(exec_ctx, calld->lb_policy, "pick_subchannel");
calld->lb_policy = NULL;
} else {
GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback_cancel");
grpc_call_combiner_set_notify_on_cancel(
exec_ctx, calld->call_combiner,
GRPC_CLOSURE_INIT(&calld->lb_pick_cancel_closure,
pick_callback_cancel_locked, elem,
grpc_combiner_scheduler(chand->combiner)));
}
return pick_done;
}
typedef struct { typedef struct {
grpc_call_element *elem; grpc_call_element *elem;
@ -1069,17 +1173,17 @@ static void pick_after_resolver_result_cancel_locked(grpc_exec_ctx *exec_ctx,
gpr_free(args); gpr_free(args);
return; return;
} }
args->finished = true;
grpc_call_element *elem = args->elem;
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
// If we don't yet have a resolver result, then a closure for // If we don't yet have a resolver result, then a closure for
// pick_after_resolver_result_done_locked() will have been added to // pick_after_resolver_result_done_locked() will have been added to
// chand->waiting_for_resolver_result_closures, and it may not be invoked // chand->waiting_for_resolver_result_closures, and it may not be invoked
// until after this call has been destroyed. We mark the operation as // until after this call has been destroyed. We mark the operation as
// finished, so that when pick_after_resolver_result_done_locked() // finished, so that when pick_after_resolver_result_done_locked()
// is called, it will be a no-op. We also immediately invoke // is called, it will be a no-op. We also immediately invoke
// subchannel_ready_locked() to propagate the error back to the caller. // async_pick_done_locked() to propagate the error back to the caller.
args->finished = true;
grpc_call_element *elem = args->elem;
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
if (GRPC_TRACER_ON(grpc_client_channel_trace)) { if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"chand=%p calld=%p: cancelling pick waiting for resolver result", "chand=%p calld=%p: cancelling pick waiting for resolver result",
@ -1087,12 +1191,12 @@ static void pick_after_resolver_result_cancel_locked(grpc_exec_ctx *exec_ctx,
} }
// Note: Although we are not in the call combiner here, we are // Note: Although we are not in the call combiner here, we are
// basically stealing the call combiner from the pending pick, so // basically stealing the call combiner from the pending pick, so
// it's safe to call subchannel_ready_locked() here -- we are // it's safe to call async_pick_done_locked() here -- we are
// essentially calling it here instead of calling it in // essentially calling it here instead of calling it in
// pick_after_resolver_result_done_locked(). // pick_after_resolver_result_done_locked().
subchannel_ready_locked(exec_ctx, elem, async_pick_done_locked(exec_ctx, elem,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1)); "Pick cancelled", &error, 1));
} }
static void pick_after_resolver_result_done_locked(grpc_exec_ctx *exec_ctx, static void pick_after_resolver_result_done_locked(grpc_exec_ctx *exec_ctx,
@ -1117,14 +1221,19 @@ static void pick_after_resolver_result_done_locked(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver failed to return data", gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver failed to return data",
chand, calld); chand, calld);
} }
subchannel_ready_locked(exec_ctx, elem, GRPC_ERROR_REF(error)); async_pick_done_locked(exec_ctx, elem, GRPC_ERROR_REF(error));
} else { } else {
if (GRPC_TRACER_ON(grpc_client_channel_trace)) { if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver returned, doing pick", gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver returned, doing pick",
chand, calld); chand, calld);
} }
if (pick_subchannel_locked(exec_ctx, elem)) { if (pick_callback_start_locked(exec_ctx, elem)) {
subchannel_ready_locked(exec_ctx, elem, GRPC_ERROR_NONE); // Even if the LB policy returns a result synchronously, we have
// already added our polling entity to chand->interested_parties
// in order to wait for the resolver result, so we need to
// remove it here. Therefore, we call async_pick_done_locked()
// instead of pick_done_locked().
async_pick_done_locked(exec_ctx, elem, GRPC_ERROR_NONE);
} }
} }
} }
@ -1152,154 +1261,38 @@ static void pick_after_resolver_result_start_locked(grpc_exec_ctx *exec_ctx,
grpc_combiner_scheduler(chand->combiner))); grpc_combiner_scheduler(chand->combiner)));
} }
// Note: This runs under the client_channel combiner, but will NOT be static void start_pick_locked(grpc_exec_ctx *exec_ctx, void *arg,
// holding the call combiner. grpc_error *ignored) {
static void pick_callback_cancel_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_call_element *elem = (grpc_call_element *)arg;
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
if (error != GRPC_ERROR_NONE && calld->lb_policy != NULL) {
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: cancelling pick from LB policy %p",
chand, calld, calld->lb_policy);
}
grpc_lb_policy_cancel_pick_locked(exec_ctx, calld->lb_policy,
&calld->connected_subchannel,
GRPC_ERROR_REF(error));
}
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_callback_cancel");
}
// Callback invoked by grpc_lb_policy_pick_locked() for async picks.
// Unrefs the LB policy and invokes subchannel_ready_locked().
static void pick_callback_done_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_call_element *elem = (grpc_call_element *)arg; grpc_call_element *elem = (grpc_call_element *)arg;
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data; call_data *calld = (call_data *)elem->call_data;
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed asynchronously",
chand, calld);
}
GPR_ASSERT(calld->lb_policy != NULL);
GRPC_LB_POLICY_UNREF(exec_ctx, calld->lb_policy, "pick_subchannel");
calld->lb_policy = NULL;
subchannel_ready_locked(exec_ctx, elem, GRPC_ERROR_REF(error));
}
// Takes a ref to chand->lb_policy and calls grpc_lb_policy_pick_locked().
// If the pick was completed synchronously, unrefs the LB policy and
// returns true.
static bool pick_callback_start_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_lb_policy_pick_args *inputs) {
channel_data *chand = (channel_data *)elem->channel_data; channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data; GPR_ASSERT(calld->connected_subchannel == NULL);
if (GRPC_TRACER_ON(grpc_client_channel_trace)) { if (chand->lb_policy != NULL) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: starting pick on lb_policy=%p", // We already have an LB policy, so ask it for a pick.
chand, calld, chand->lb_policy); if (pick_callback_start_locked(exec_ctx, elem)) {
} // Pick completed synchronously.
// Keep a ref to the LB policy in calld while the pick is pending. pick_done_locked(exec_ctx, elem, GRPC_ERROR_NONE);
GRPC_LB_POLICY_REF(chand->lb_policy, "pick_subchannel"); return;
calld->lb_policy = chand->lb_policy;
GRPC_CLOSURE_INIT(&calld->lb_pick_closure, pick_callback_done_locked, elem,
grpc_combiner_scheduler(chand->combiner));
const bool pick_done = grpc_lb_policy_pick_locked(
exec_ctx, chand->lb_policy, inputs, &calld->connected_subchannel,
calld->subchannel_call_context, NULL, &calld->lb_pick_closure);
if (pick_done) {
/* synchronous grpc_lb_policy_pick call. Unref the LB policy. */
if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed synchronously",
chand, calld);
} }
GRPC_LB_POLICY_UNREF(exec_ctx, calld->lb_policy, "pick_subchannel");
calld->lb_policy = NULL;
} else { } else {
GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback_cancel"); // We do not yet have an LB policy, so wait for a resolver result.
grpc_call_combiner_set_notify_on_cancel( if (chand->resolver == NULL) {
exec_ctx, calld->call_combiner, pick_done_locked(exec_ctx, elem,
GRPC_CLOSURE_INIT(&calld->lb_pick_cancel_closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
pick_callback_cancel_locked, elem, return;
grpc_combiner_scheduler(chand->combiner)));
}
return pick_done;
}
static bool pick_subchannel_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
GPR_TIMER_BEGIN("pick_subchannel", 0);
channel_data *chand = (channel_data *)elem->channel_data;
call_data *calld = (call_data *)elem->call_data;
bool pick_done = false;
if (chand->lb_policy != NULL) {
apply_service_config_to_call_locked(exec_ctx, elem);
// If the application explicitly set wait_for_ready, use that.
// Otherwise, if the service config specified a value for this
// method, use that.
uint32_t initial_metadata_flags =
calld->initial_metadata_batch->payload->send_initial_metadata
.send_initial_metadata_flags;
const bool wait_for_ready_set_from_api =
initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
const bool wait_for_ready_set_from_service_config =
calld->method_params != NULL &&
calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
if (!wait_for_ready_set_from_api &&
wait_for_ready_set_from_service_config) {
if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
}
} }
const grpc_lb_policy_pick_args inputs = {
calld->initial_metadata_batch->payload->send_initial_metadata
.send_initial_metadata,
initial_metadata_flags, &calld->lb_token_mdelem};
pick_done = pick_callback_start_locked(exec_ctx, elem, &inputs);
} else if (chand->resolver != NULL) {
if (!chand->started_resolving) { if (!chand->started_resolving) {
start_resolving_locked(exec_ctx, chand); start_resolving_locked(exec_ctx, chand);
} }
pick_after_resolver_result_start_locked(exec_ctx, elem); pick_after_resolver_result_start_locked(exec_ctx, elem);
} else {
subchannel_ready_locked(
exec_ctx, elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
}
GPR_TIMER_END("pick_subchannel", 0);
return pick_done;
}
static void start_pick_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
GPR_TIMER_BEGIN("start_pick_locked", 0);
grpc_call_element *elem = (grpc_call_element *)arg;
call_data *calld = (call_data *)elem->call_data;
channel_data *chand = (channel_data *)elem->channel_data;
GPR_ASSERT(calld->connected_subchannel == NULL);
if (pick_subchannel_locked(exec_ctx, elem)) {
// Pick was returned synchronously.
if (calld->connected_subchannel == NULL) {
GRPC_ERROR_UNREF(calld->error);
calld->error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Call dropped by load balancing policy");
waiting_for_pick_batches_fail(exec_ctx, elem,
GRPC_ERROR_REF(calld->error));
} else {
// Create subchannel call.
create_subchannel_call_locked(exec_ctx, elem, GRPC_ERROR_NONE);
}
} else {
// Pick will be done asynchronously. Add the call's polling entity to
// the channel's interested_parties, so that I/O for the resolver
// and LB policy can be done under it.
grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties);
} }
GPR_TIMER_END("start_pick_locked", 0); // We need to wait for either a resolver result or for an async result
// from the LB policy. Add the polling entity from call_data to the
// channel_data's interested_parties, so that the I/O of the LB policy
// and resolver can be done under it. The polling entity will be
// removed in async_pick_done_locked().
grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties);
} }
static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
@ -1394,7 +1387,8 @@ static void cc_start_transport_stream_op_batch(
// combiner to start a pick. // combiner to start a pick.
if (batch->send_initial_metadata) { if (batch->send_initial_metadata) {
if (GRPC_TRACER_ON(grpc_client_channel_trace)) { if (GRPC_TRACER_ON(grpc_client_channel_trace)) {
gpr_log(GPR_DEBUG, "chand=%p calld=%p: entering combiner", chand, calld); gpr_log(GPR_DEBUG, "chand=%p calld=%p: entering client_channel combiner",
chand, calld);
} }
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(
exec_ctx, exec_ctx,

@ -43,14 +43,13 @@ grpc_channel* grpc_client_channel_factory_create_channel(
} }
static void* factory_arg_copy(void* factory) { static void* factory_arg_copy(void* factory) {
grpc_client_channel_factory_ref(factory); grpc_client_channel_factory_ref((grpc_client_channel_factory*)factory);
return factory; return factory;
} }
static void factory_arg_destroy(grpc_exec_ctx* exec_ctx, void* factory) { static void factory_arg_destroy(grpc_exec_ctx* exec_ctx, void* factory) {
// TODO(roth): Remove local exec_ctx when grpc_client_channel_factory_unref(exec_ctx,
// https://github.com/grpc/grpc/pull/8705 is merged. (grpc_client_channel_factory*)factory);
grpc_client_channel_factory_unref(exec_ctx, factory);
} }
static int factory_arg_cmp(void* factory1, void* factory2) { static int factory_arg_cmp(void* factory1, void* factory2) {
@ -64,6 +63,6 @@ static const grpc_arg_pointer_vtable factory_arg_vtable = {
grpc_arg grpc_client_channel_factory_create_channel_arg( grpc_arg grpc_client_channel_factory_create_channel_arg(
grpc_client_channel_factory* factory) { grpc_client_channel_factory* factory) {
return grpc_channel_arg_pointer_create(GRPC_ARG_CLIENT_CHANNEL_FACTORY, return grpc_channel_arg_pointer_create((char*)GRPC_ARG_CLIENT_CHANNEL_FACTORY,
factory, &factory_arg_vtable); factory, &factory_arg_vtable);
} }

@ -54,8 +54,8 @@ static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx,
char *default_authority = grpc_get_default_authority( char *default_authority = grpc_get_default_authority(
exec_ctx, grpc_channel_stack_builder_get_target(builder)); exec_ctx, grpc_channel_stack_builder_get_target(builder));
if (default_authority != NULL) { if (default_authority != NULL) {
grpc_arg arg = grpc_channel_arg_string_create(GRPC_ARG_DEFAULT_AUTHORITY, grpc_arg arg = grpc_channel_arg_string_create(
default_authority); (char *)GRPC_ARG_DEFAULT_AUTHORITY, default_authority);
grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1); grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
grpc_channel_stack_builder_set_channel_arguments(exec_ctx, builder, grpc_channel_stack_builder_set_channel_arguments(exec_ctx, builder,
new_args); new_args);

@ -44,6 +44,8 @@ static char* get_http_proxy_server(grpc_exec_ctx* exec_ctx, char** user_cred) {
GPR_ASSERT(user_cred != NULL); GPR_ASSERT(user_cred != NULL);
char* proxy_name = NULL; char* proxy_name = NULL;
char* uri_str = gpr_getenv("http_proxy"); char* uri_str = gpr_getenv("http_proxy");
char** authority_strs = NULL;
size_t authority_nstrs;
if (uri_str == NULL) return NULL; if (uri_str == NULL) return NULL;
grpc_uri* uri = grpc_uri* uri =
grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */); grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */);
@ -56,8 +58,6 @@ static char* get_http_proxy_server(grpc_exec_ctx* exec_ctx, char** user_cred) {
goto done; goto done;
} }
/* Split on '@' to separate user credentials from host */ /* Split on '@' to separate user credentials from host */
char** authority_strs = NULL;
size_t authority_nstrs;
gpr_string_split(uri->authority, "@", &authority_strs, &authority_nstrs); gpr_string_split(uri->authority, "@", &authority_strs, &authority_nstrs);
GPR_ASSERT(authority_nstrs != 0); /* should have at least 1 string */ GPR_ASSERT(authority_nstrs != 0); /* should have at least 1 string */
if (authority_nstrs == 1) { if (authority_nstrs == 1) {
@ -157,7 +157,7 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
} }
grpc_arg args_to_add[2]; grpc_arg args_to_add[2];
args_to_add[0] = grpc_channel_arg_string_create( args_to_add[0] = grpc_channel_arg_string_create(
GRPC_ARG_HTTP_CONNECT_SERVER, (char*)GRPC_ARG_HTTP_CONNECT_SERVER,
uri->path[0] == '/' ? uri->path + 1 : uri->path); uri->path[0] == '/' ? uri->path + 1 : uri->path);
if (user_cred != NULL) { if (user_cred != NULL) {
/* Use base64 encoding for user credentials as stated in RFC 7617 */ /* Use base64 encoding for user credentials as stated in RFC 7617 */
@ -166,8 +166,8 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
char* header; char* header;
gpr_asprintf(&header, "Proxy-Authorization:Basic %s", encoded_user_cred); gpr_asprintf(&header, "Proxy-Authorization:Basic %s", encoded_user_cred);
gpr_free(encoded_user_cred); gpr_free(encoded_user_cred);
args_to_add[1] = args_to_add[1] = grpc_channel_arg_string_create(
grpc_channel_arg_string_create(GRPC_ARG_HTTP_CONNECT_HEADERS, header); (char*)GRPC_ARG_HTTP_CONNECT_HEADERS, header);
*new_args = grpc_channel_args_copy_and_add(args, args_to_add, 2); *new_args = grpc_channel_args_copy_and_add(args, args_to_add, 2);
gpr_free(header); gpr_free(header);
} else { } else {

@ -75,7 +75,8 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(args->context != NULL); GPR_ASSERT(args->context != NULL);
GPR_ASSERT(args->context[GRPC_GRPCLB_CLIENT_STATS].value != NULL); GPR_ASSERT(args->context[GRPC_GRPCLB_CLIENT_STATS].value != NULL);
calld->client_stats = grpc_grpclb_client_stats_ref( calld->client_stats = grpc_grpclb_client_stats_ref(
args->context[GRPC_GRPCLB_CLIENT_STATS].value); (grpc_grpclb_client_stats *)args->context[GRPC_GRPCLB_CLIENT_STATS]
.value);
// Record call started. // Record call started.
grpc_grpclb_client_stats_add_call_started(calld->client_stats); grpc_grpclb_client_stats_add_call_started(calld->client_stats);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -101,6 +101,7 @@
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/combiner.h"
@ -137,7 +138,7 @@ static grpc_error *initial_metadata_add_lb_token(
} }
static void destroy_client_stats(void *arg) { static void destroy_client_stats(void *arg) {
grpc_grpclb_client_stats_unref(arg); grpc_grpclb_client_stats_unref((grpc_grpclb_client_stats *)arg);
} }
typedef struct wrapped_rr_closure_arg { typedef struct wrapped_rr_closure_arg {
@ -285,7 +286,7 @@ static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
* glb_lb_policy * glb_lb_policy
*/ */
typedef struct rr_connectivity_data rr_connectivity_data; typedef struct rr_connectivity_data rr_connectivity_data;
static const grpc_lb_policy_vtable glb_lb_policy_vtable;
typedef struct glb_lb_policy { typedef struct glb_lb_policy {
/** base policy: must be first */ /** base policy: must be first */
grpc_lb_policy base; grpc_lb_policy base;
@ -727,7 +728,7 @@ static void create_rr_locked(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
/* Allocate the data for the tracking of the new RR policy's connectivity. /* Allocate the data for the tracking of the new RR policy's connectivity.
* It'll be deallocated in glb_rr_connectivity_changed() */ * It'll be deallocated in glb_rr_connectivity_changed() */
rr_connectivity_data *rr_connectivity = rr_connectivity_data *rr_connectivity =
gpr_zalloc(sizeof(rr_connectivity_data)); (rr_connectivity_data *)gpr_zalloc(sizeof(rr_connectivity_data));
GRPC_CLOSURE_INIT(&rr_connectivity->on_change, GRPC_CLOSURE_INIT(&rr_connectivity->on_change,
glb_rr_connectivity_changed_locked, rr_connectivity, glb_rr_connectivity_changed_locked, rr_connectivity,
grpc_combiner_scheduler(glb_policy->base.combiner)); grpc_combiner_scheduler(glb_policy->base.combiner));
@ -869,7 +870,8 @@ static grpc_channel_args *build_lb_channel_args(
grpc_lb_addresses *lb_addresses = grpc_lb_addresses *lb_addresses =
grpc_lb_addresses_create(num_grpclb_addrs, NULL); grpc_lb_addresses_create(num_grpclb_addrs, NULL);
grpc_slice_hash_table_entry *targets_info_entries = grpc_slice_hash_table_entry *targets_info_entries =
gpr_zalloc(sizeof(*targets_info_entries) * num_grpclb_addrs); (grpc_slice_hash_table_entry *)gpr_zalloc(sizeof(*targets_info_entries) *
num_grpclb_addrs);
size_t lb_addresses_idx = 0; size_t lb_addresses_idx = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) { for (size_t i = 0; i < addresses->num_addresses; ++i) {
@ -911,92 +913,6 @@ static grpc_channel_args *build_lb_channel_args(
return result; return result;
} }
static void glb_lb_channel_on_connectivity_changed_cb(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_error *error);
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
/* Count the number of gRPC-LB addresses. There must be at least one.
* TODO(roth): For now, we ignore non-balancer addresses, but in the
* future, we may change the behavior such that we fall back to using
* the non-balancer addresses if we cannot reach any balancers. In the
* fallback case, we should use the LB policy indicated by
* GRPC_ARG_LB_POLICY_NAME (although if that specifies grpclb or is
* unset, we should default to pick_first). */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
return NULL;
}
grpc_lb_addresses *addresses = (grpc_lb_addresses *)arg->value.pointer.p;
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
}
if (num_grpclb_addrs == 0) return NULL;
glb_lb_policy *glb_policy = (glb_lb_policy *)gpr_zalloc(sizeof(*glb_policy));
/* Get server name. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING);
grpc_uri *uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
GPR_ASSERT(uri->path[0] != '\0');
glb_policy->server_name =
gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.",
glb_policy->server_name);
}
grpc_uri_destroy(uri);
glb_policy->cc_factory = args->client_channel_factory;
GPR_ASSERT(glb_policy->cc_factory != NULL);
arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS);
glb_policy->lb_call_timeout_ms =
grpc_channel_arg_get_integer(arg, (grpc_integer_options){0, 0, INT_MAX});
// Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
// since we use this to trigger the client_load_reporting filter.
grpc_arg new_arg =
grpc_channel_arg_string_create(GRPC_ARG_LB_POLICY_NAME, "grpclb");
static const char *args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
glb_policy->args = grpc_channel_args_copy_and_add_and_remove(
args->args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
/* Create a client channel over them to communicate with a LB service */
glb_policy->response_generator =
grpc_fake_resolver_response_generator_create();
grpc_channel_args *lb_channel_args = build_lb_channel_args(
exec_ctx, addresses, glb_policy->response_generator, args->args);
char *uri_str;
gpr_asprintf(&uri_str, "fake:///%s", glb_policy->server_name);
glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
exec_ctx, uri_str, args->client_channel_factory, lb_channel_args);
/* Propagate initial resolution */
grpc_fake_resolver_response_generator_set_response(
exec_ctx, glb_policy->response_generator, lb_channel_args);
grpc_channel_args_destroy(exec_ctx, lb_channel_args);
gpr_free(uri_str);
if (glb_policy->lb_channel == NULL) {
gpr_free((void *)glb_policy->server_name);
grpc_channel_args_destroy(exec_ctx, glb_policy->args);
gpr_free(glb_policy);
return NULL;
}
GRPC_CLOSURE_INIT(&glb_policy->lb_channel_on_connectivity_changed,
glb_lb_channel_on_connectivity_changed_cb, glb_policy,
grpc_combiner_scheduler(args->combiner));
grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
"grpclb");
return &glb_policy->base;
}
static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol; glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
GPR_ASSERT(glb_policy->pending_picks == NULL); GPR_ASSERT(glb_policy->pending_picks == NULL);
@ -1011,6 +927,7 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_grpclb_destroy_serverlist(glb_policy->serverlist); grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
} }
grpc_fake_resolver_response_generator_unref(glb_policy->response_generator); grpc_fake_resolver_response_generator_unref(glb_policy->response_generator);
grpc_subchannel_index_unref();
if (glb_policy->pending_update_args != NULL) { if (glb_policy->pending_update_args != NULL) {
grpc_channel_args_destroy(exec_ctx, glb_policy->pending_update_args->args); grpc_channel_args_destroy(exec_ctx, glb_policy->pending_update_args->args);
gpr_free(glb_policy->pending_update_args); gpr_free(glb_policy->pending_update_args);
@ -1303,7 +1220,8 @@ static void do_send_client_load_report_locked(grpc_exec_ctx *exec_ctx,
static bool load_report_counters_are_zero(grpc_grpclb_request *request) { static bool load_report_counters_are_zero(grpc_grpclb_request *request) {
grpc_grpclb_dropped_call_counts *drop_entries = grpc_grpclb_dropped_call_counts *drop_entries =
request->client_stats.calls_finished_with_drop.arg; (grpc_grpclb_dropped_call_counts *)
request->client_stats.calls_finished_with_drop.arg;
return request->client_stats.num_calls_started == 0 && return request->client_stats.num_calls_started == 0 &&
request->client_stats.num_calls_finished == 0 && request->client_stats.num_calls_finished == 0 &&
request->client_stats.num_calls_finished_with_client_failed_to_send == request->client_stats.num_calls_finished_with_client_failed_to_send ==
@ -1642,6 +1560,9 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops), exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
&glb_policy->lb_on_response_received); /* loop */ &glb_policy->lb_on_response_received); /* loop */
GPR_ASSERT(GRPC_CALL_OK == call_error); GPR_ASSERT(GRPC_CALL_OK == call_error);
} else {
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
"lb_on_response_received_locked_shutdown");
} }
} else { /* empty payload: call cancelled. */ } else { /* empty payload: call cancelled. */
/* dispose of the "lb_on_response_received_locked" weak ref taken in /* dispose of the "lb_on_response_received_locked" weak ref taken in
@ -1865,6 +1786,90 @@ static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
glb_notify_on_state_change_locked, glb_notify_on_state_change_locked,
glb_update_locked}; glb_update_locked};
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
/* Count the number of gRPC-LB addresses. There must be at least one.
* TODO(roth): For now, we ignore non-balancer addresses, but in the
* future, we may change the behavior such that we fall back to using
* the non-balancer addresses if we cannot reach any balancers. In the
* fallback case, we should use the LB policy indicated by
* GRPC_ARG_LB_POLICY_NAME (although if that specifies grpclb or is
* unset, we should default to pick_first). */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
return NULL;
}
grpc_lb_addresses *addresses = (grpc_lb_addresses *)arg->value.pointer.p;
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
}
if (num_grpclb_addrs == 0) return NULL;
glb_lb_policy *glb_policy = (glb_lb_policy *)gpr_zalloc(sizeof(*glb_policy));
/* Get server name. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING);
grpc_uri *uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
GPR_ASSERT(uri->path[0] != '\0');
glb_policy->server_name =
gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.",
glb_policy->server_name);
}
grpc_uri_destroy(uri);
glb_policy->cc_factory = args->client_channel_factory;
GPR_ASSERT(glb_policy->cc_factory != NULL);
arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS);
glb_policy->lb_call_timeout_ms =
grpc_channel_arg_get_integer(arg, (grpc_integer_options){0, 0, INT_MAX});
// Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
// since we use this to trigger the client_load_reporting filter.
grpc_arg new_arg = grpc_channel_arg_string_create(
(char *)GRPC_ARG_LB_POLICY_NAME, (char *)"grpclb");
static const char *args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
glb_policy->args = grpc_channel_args_copy_and_add_and_remove(
args->args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
/* Create a client channel over them to communicate with a LB service */
glb_policy->response_generator =
grpc_fake_resolver_response_generator_create();
grpc_channel_args *lb_channel_args = build_lb_channel_args(
exec_ctx, addresses, glb_policy->response_generator, args->args);
char *uri_str;
gpr_asprintf(&uri_str, "fake:///%s", glb_policy->server_name);
glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
exec_ctx, uri_str, args->client_channel_factory, lb_channel_args);
/* Propagate initial resolution */
grpc_fake_resolver_response_generator_set_response(
exec_ctx, glb_policy->response_generator, lb_channel_args);
grpc_channel_args_destroy(exec_ctx, lb_channel_args);
gpr_free(uri_str);
if (glb_policy->lb_channel == NULL) {
gpr_free((void *)glb_policy->server_name);
grpc_channel_args_destroy(exec_ctx, glb_policy->args);
gpr_free(glb_policy);
return NULL;
}
grpc_subchannel_index_ref();
GRPC_CLOSURE_INIT(&glb_policy->lb_channel_on_connectivity_changed,
glb_lb_channel_on_connectivity_changed_cb, glb_policy,
grpc_combiner_scheduler(args->combiner));
grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
"grpclb");
return &glb_policy->base;
}
static void glb_factory_ref(grpc_lb_policy_factory *factory) {} static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
static void glb_factory_unref(grpc_lb_policy_factory *factory) {} static void glb_factory_unref(grpc_lb_policy_factory *factory) {}

@ -148,7 +148,8 @@ grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) {
void grpc_grpclb_request_destroy(grpc_grpclb_request *request) { void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
if (request->has_client_stats) { if (request->has_client_stats) {
grpc_grpclb_dropped_call_counts *drop_entries = grpc_grpclb_dropped_call_counts *drop_entries =
request->client_stats.calls_finished_with_drop.arg; (grpc_grpclb_dropped_call_counts *)
request->client_stats.calls_finished_with_drop.arg;
grpc_grpclb_dropped_call_counts_destroy(drop_entries); grpc_grpclb_dropped_call_counts_destroy(drop_entries);
} }
gpr_free(request); gpr_free(request);
@ -170,7 +171,8 @@ grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
if (!res.has_initial_response) return NULL; if (!res.has_initial_response) return NULL;
grpc_grpclb_initial_response *initial_res = grpc_grpclb_initial_response *initial_res =
gpr_malloc(sizeof(grpc_grpclb_initial_response)); (grpc_grpclb_initial_response *)gpr_malloc(
sizeof(grpc_grpclb_initial_response));
memcpy(initial_res, &res.initial_response, memcpy(initial_res, &res.initial_response,
sizeof(grpc_grpclb_initial_response)); sizeof(grpc_grpclb_initial_response));

@ -89,6 +89,7 @@ static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
"picked_first_destroy"); "picked_first_destroy");
} }
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker); grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
grpc_subchannel_index_unref();
if (p->pending_update_args != NULL) { if (p->pending_update_args != NULL) {
grpc_channel_args_destroy(exec_ctx, p->pending_update_args->args); grpc_channel_args_destroy(exec_ctx, p->pending_update_args->args);
gpr_free(p->pending_update_args); gpr_free(p->pending_update_args);
@ -330,8 +331,8 @@ static void pf_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
gpr_log(GPR_INFO, "Pick First %p received update with %lu addresses", gpr_log(GPR_INFO, "Pick First %p received update with %lu addresses",
(void *)p, (unsigned long)addresses->num_addresses); (void *)p, (unsigned long)addresses->num_addresses);
} }
grpc_subchannel_args *sc_args = grpc_subchannel_args *sc_args = (grpc_subchannel_args *)gpr_zalloc(
gpr_zalloc(sizeof(*sc_args) * addresses->num_addresses); sizeof(*sc_args) * addresses->num_addresses);
/* We remove the following keys in order for subchannel keys belonging to /* We remove the following keys in order for subchannel keys belonging to
* subchannels point to the same address to match. */ * subchannels point to the same address to match. */
static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS, static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
@ -403,7 +404,7 @@ static void pf_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
} }
/* Create the subchannels for the new subchannel args/addresses. */ /* Create the subchannels for the new subchannel args/addresses. */
grpc_subchannel **new_subchannels = grpc_subchannel **new_subchannels =
gpr_zalloc(sizeof(*new_subchannels) * sc_args_count); (grpc_subchannel **)gpr_zalloc(sizeof(*new_subchannels) * sc_args_count);
size_t num_new_subchannels = 0; size_t num_new_subchannels = 0;
for (size_t i = 0; i < sc_args_count; i++) { for (size_t i = 0; i < sc_args_count; i++) {
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
@ -686,6 +687,7 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
} }
pf_update_locked(exec_ctx, &p->base, args); pf_update_locked(exec_ctx, &p->base, args);
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner); grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
grpc_subchannel_index_ref();
GRPC_CLOSURE_INIT(&p->connectivity_changed, pf_connectivity_changed_locked, p, GRPC_CLOSURE_INIT(&p->connectivity_changed, pf_connectivity_changed_locked, p,
grpc_combiner_scheduler(args->combiner)); grpc_combiner_scheduler(args->combiner));
return &p->base; return &p->base;

@ -30,6 +30,7 @@
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/combiner.h"
@ -310,6 +311,7 @@ static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
(void *)pol, (void *)pol); (void *)pol, (void *)pol);
} }
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker); grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
grpc_subchannel_index_unref();
gpr_free(p); gpr_free(p);
} }
@ -587,7 +589,7 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
// Dispose of outdated subchannel lists. // Dispose of outdated subchannel lists.
if (sd->subchannel_list != p->subchannel_list && if (sd->subchannel_list != p->subchannel_list &&
sd->subchannel_list != p->latest_pending_subchannel_list) { sd->subchannel_list != p->latest_pending_subchannel_list) {
char *reason = NULL; const char *reason = NULL;
if (sd->subchannel_list->shutting_down) { if (sd->subchannel_list->shutting_down) {
reason = "sl_outdated_straggler"; reason = "sl_outdated_straggler";
rr_subchannel_list_unref(exec_ctx, sd->subchannel_list, reason); rr_subchannel_list_unref(exec_ctx, sd->subchannel_list, reason);
@ -890,6 +892,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(args->client_channel_factory != NULL); GPR_ASSERT(args->client_channel_factory != NULL);
round_robin_lb_policy *p = (round_robin_lb_policy *)gpr_zalloc(sizeof(*p)); round_robin_lb_policy *p = (round_robin_lb_policy *)gpr_zalloc(sizeof(*p));
grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner); grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner);
grpc_subchannel_index_ref();
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
"round_robin"); "round_robin");
rr_update_locked(exec_ctx, &p->base, args); rr_update_locked(exec_ctx, &p->base, args);

@ -126,13 +126,14 @@ void grpc_lb_addresses_destroy(grpc_exec_ctx* exec_ctx,
} }
static void* lb_addresses_copy(void* addresses) { static void* lb_addresses_copy(void* addresses) {
return grpc_lb_addresses_copy(addresses); return grpc_lb_addresses_copy((grpc_lb_addresses*)addresses);
} }
static void lb_addresses_destroy(grpc_exec_ctx* exec_ctx, void* addresses) { static void lb_addresses_destroy(grpc_exec_ctx* exec_ctx, void* addresses) {
grpc_lb_addresses_destroy(exec_ctx, addresses); grpc_lb_addresses_destroy(exec_ctx, (grpc_lb_addresses*)addresses);
} }
static int lb_addresses_cmp(void* addresses1, void* addresses2) { static int lb_addresses_cmp(void* addresses1, void* addresses2) {
return grpc_lb_addresses_cmp(addresses1, addresses2); return grpc_lb_addresses_cmp((grpc_lb_addresses*)addresses1,
(grpc_lb_addresses*)addresses2);
} }
static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = { static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = {
lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp}; lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp};
@ -140,7 +141,7 @@ static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = {
grpc_arg grpc_lb_addresses_create_channel_arg( grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses* addresses) { const grpc_lb_addresses* addresses) {
return grpc_channel_arg_pointer_create( return grpc_channel_arg_pointer_create(
GRPC_ARG_LB_ADDRESSES, (void*)addresses, &lb_addresses_arg_vtable); (char*)GRPC_ARG_LB_ADDRESSES, (void*)addresses, &lb_addresses_arg_vtable);
} }
grpc_lb_addresses* grpc_lb_addresses_find_channel_arg( grpc_lb_addresses* grpc_lb_addresses_find_channel_arg(
@ -149,7 +150,7 @@ grpc_lb_addresses* grpc_lb_addresses_find_channel_arg(
grpc_channel_args_find(channel_args, GRPC_ARG_LB_ADDRESSES); grpc_channel_args_find(channel_args, GRPC_ARG_LB_ADDRESSES);
if (lb_addresses_arg == NULL || lb_addresses_arg->type != GRPC_ARG_POINTER) if (lb_addresses_arg == NULL || lb_addresses_arg->type != GRPC_ARG_POINTER)
return NULL; return NULL;
return lb_addresses_arg->value.pointer.p; return (grpc_lb_addresses*)lb_addresses_arg->value.pointer.p;
} }
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) { void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {

@ -204,7 +204,7 @@ static char *choose_service_config(char *service_config_choice_json) {
int random_pct = rand() % 100; int random_pct = rand() % 100;
int percentage; int percentage;
if (sscanf(field->value, "%d", &percentage) != 1 || if (sscanf(field->value, "%d", &percentage) != 1 ||
random_pct > percentage) { random_pct > percentage || percentage == 0) {
service_config_json = NULL; service_config_json = NULL;
break; break;
} }
@ -249,7 +249,7 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
service_config_string); service_config_string);
args_to_remove[num_args_to_remove++] = GRPC_ARG_SERVICE_CONFIG; args_to_remove[num_args_to_remove++] = GRPC_ARG_SERVICE_CONFIG;
new_args[num_args_to_add++] = grpc_channel_arg_string_create( new_args[num_args_to_add++] = grpc_channel_arg_string_create(
GRPC_ARG_SERVICE_CONFIG, service_config_string); (char *)GRPC_ARG_SERVICE_CONFIG, service_config_string);
service_config = grpc_service_config_create(service_config_string); service_config = grpc_service_config_create(service_config_string);
if (service_config != NULL) { if (service_config != NULL) {
const char *lb_policy_name = const char *lb_policy_name =
@ -257,7 +257,7 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
if (lb_policy_name != NULL) { if (lb_policy_name != NULL) {
args_to_remove[num_args_to_remove++] = GRPC_ARG_LB_POLICY_NAME; args_to_remove[num_args_to_remove++] = GRPC_ARG_LB_POLICY_NAME;
new_args[num_args_to_add++] = grpc_channel_arg_string_create( new_args[num_args_to_add++] = grpc_channel_arg_string_create(
GRPC_ARG_LB_POLICY_NAME, (char *)lb_policy_name); (char *)GRPC_ARG_LB_POLICY_NAME, (char *)lb_policy_name);
} }
} }
} }

@ -20,6 +20,7 @@
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) #if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET)
#include <ares.h> #include <ares.h>
#include <sys/ioctl.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
@ -37,8 +38,6 @@
typedef struct fd_node { typedef struct fd_node {
/** the owner of this fd node */ /** the owner of this fd node */
grpc_ares_ev_driver *ev_driver; grpc_ares_ev_driver *ev_driver;
/** the grpc_fd owned by this fd node */
grpc_fd *grpc_fd;
/** a closure wrapping on_readable_cb, which should be invoked when the /** a closure wrapping on_readable_cb, which should be invoked when the
grpc_fd in this node becomes readable. */ grpc_fd in this node becomes readable. */
grpc_closure read_closure; grpc_closure read_closure;
@ -50,10 +49,14 @@ typedef struct fd_node {
/** mutex guarding the rest of the state */ /** mutex guarding the rest of the state */
gpr_mu mu; gpr_mu mu;
/** the grpc_fd owned by this fd node */
grpc_fd *fd;
/** if the readable closure has been registered */ /** if the readable closure has been registered */
bool readable_registered; bool readable_registered;
/** if the writable closure has been registered */ /** if the writable closure has been registered */
bool writable_registered; bool writable_registered;
/** if the fd is being shut down */
bool shutting_down;
} fd_node; } fd_node;
struct grpc_ares_ev_driver { struct grpc_ares_ev_driver {
@ -96,19 +99,31 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver *ev_driver) {
} }
static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) { static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) {
gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->fd));
GPR_ASSERT(!fdn->readable_registered); GPR_ASSERT(!fdn->readable_registered);
GPR_ASSERT(!fdn->writable_registered); GPR_ASSERT(!fdn->writable_registered);
gpr_mu_destroy(&fdn->mu); gpr_mu_destroy(&fdn->mu);
grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, fdn->grpc_fd);
/* c-ares library has closed the fd inside grpc_fd. This fd may be picked up /* c-ares library has closed the fd inside grpc_fd. This fd may be picked up
immediately by another thread, and should not be closed by the following immediately by another thread, and should not be closed by the following
grpc_fd_orphan. */ grpc_fd_orphan. */
grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, true /* already_closed */, grpc_fd_orphan(exec_ctx, fdn->fd, NULL, NULL, true /* already_closed */,
"c-ares query finished"); "c-ares query finished");
gpr_free(fdn); gpr_free(fdn);
} }
static void fd_node_shutdown(grpc_exec_ctx *exec_ctx, fd_node *fdn) {
gpr_mu_lock(&fdn->mu);
fdn->shutting_down = true;
if (!fdn->readable_registered && !fdn->writable_registered) {
gpr_mu_unlock(&fdn->mu);
fd_node_destroy(exec_ctx, fdn);
} else {
grpc_fd_shutdown(exec_ctx, fdn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"c-ares fd shutdown"));
gpr_mu_unlock(&fdn->mu);
}
}
grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver,
grpc_pollset_set *pollset_set) { grpc_pollset_set *pollset_set) {
*ev_driver = (grpc_ares_ev_driver *)gpr_malloc(sizeof(grpc_ares_ev_driver)); *ev_driver = (grpc_ares_ev_driver *)gpr_malloc(sizeof(grpc_ares_ev_driver));
@ -150,9 +165,8 @@ void grpc_ares_ev_driver_shutdown(grpc_exec_ctx *exec_ctx,
ev_driver->shutting_down = true; ev_driver->shutting_down = true;
fd_node *fn = ev_driver->fds; fd_node *fn = ev_driver->fds;
while (fn != NULL) { while (fn != NULL) {
grpc_fd_shutdown( grpc_fd_shutdown(exec_ctx, fn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
exec_ctx, fn->grpc_fd, "grpc_ares_ev_driver_shutdown"));
GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_ares_ev_driver_shutdown"));
fn = fn->next; fn = fn->next;
} }
gpr_mu_unlock(&ev_driver->mu); gpr_mu_unlock(&ev_driver->mu);
@ -165,7 +179,7 @@ static fd_node *pop_fd_node(fd_node **head, int fd) {
dummy_head.next = *head; dummy_head.next = *head;
fd_node *node = &dummy_head; fd_node *node = &dummy_head;
while (node->next != NULL) { while (node->next != NULL) {
if (grpc_fd_wrapped_fd(node->next->grpc_fd) == fd) { if (grpc_fd_wrapped_fd(node->next->fd) == fd) {
fd_node *ret = node->next; fd_node *ret = node->next;
node->next = node->next->next; node->next = node->next->next;
*head = dummy_head.next; *head = dummy_head.next;
@ -176,18 +190,33 @@ static fd_node *pop_fd_node(fd_node **head, int fd) {
return NULL; return NULL;
} }
/* Check if \a fd is still readable */
static bool grpc_ares_is_fd_still_readable(grpc_ares_ev_driver *ev_driver,
int fd) {
size_t bytes_available = 0;
return ioctl(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0;
}
static void on_readable_cb(grpc_exec_ctx *exec_ctx, void *arg, static void on_readable_cb(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
fd_node *fdn = (fd_node *)arg; fd_node *fdn = (fd_node *)arg;
grpc_ares_ev_driver *ev_driver = fdn->ev_driver; grpc_ares_ev_driver *ev_driver = fdn->ev_driver;
gpr_mu_lock(&fdn->mu); gpr_mu_lock(&fdn->mu);
const int fd = grpc_fd_wrapped_fd(fdn->fd);
fdn->readable_registered = false; fdn->readable_registered = false;
if (fdn->shutting_down && !fdn->writable_registered) {
gpr_mu_unlock(&fdn->mu);
fd_node_destroy(exec_ctx, fdn);
grpc_ares_ev_driver_unref(ev_driver);
return;
}
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
gpr_log(GPR_DEBUG, "readable on %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); gpr_log(GPR_DEBUG, "readable on %d", fd);
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
ares_process_fd(ev_driver->channel, grpc_fd_wrapped_fd(fdn->grpc_fd), do {
ARES_SOCKET_BAD); ares_process_fd(ev_driver->channel, fd, ARES_SOCKET_BAD);
} while (grpc_ares_is_fd_still_readable(ev_driver, fd));
} else { } else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled // timed out. The pending lookups made on this ev_driver will be cancelled
@ -208,13 +237,19 @@ static void on_writable_cb(grpc_exec_ctx *exec_ctx, void *arg,
fd_node *fdn = (fd_node *)arg; fd_node *fdn = (fd_node *)arg;
grpc_ares_ev_driver *ev_driver = fdn->ev_driver; grpc_ares_ev_driver *ev_driver = fdn->ev_driver;
gpr_mu_lock(&fdn->mu); gpr_mu_lock(&fdn->mu);
const int fd = grpc_fd_wrapped_fd(fdn->fd);
fdn->writable_registered = false; fdn->writable_registered = false;
if (fdn->shutting_down && !fdn->readable_registered) {
gpr_mu_unlock(&fdn->mu);
fd_node_destroy(exec_ctx, fdn);
grpc_ares_ev_driver_unref(ev_driver);
return;
}
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
gpr_log(GPR_DEBUG, "writable on %d", grpc_fd_wrapped_fd(fdn->grpc_fd)); gpr_log(GPR_DEBUG, "writable on %d", fd);
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, fd);
grpc_fd_wrapped_fd(fdn->grpc_fd));
} else { } else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled // timed out. The pending lookups made on this ev_driver will be cancelled
@ -253,17 +288,17 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx,
gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i); gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i);
fdn = (fd_node *)gpr_malloc(sizeof(fd_node)); fdn = (fd_node *)gpr_malloc(sizeof(fd_node));
gpr_log(GPR_DEBUG, "new fd: %d", socks[i]); gpr_log(GPR_DEBUG, "new fd: %d", socks[i]);
fdn->grpc_fd = grpc_fd_create(socks[i], fd_name); fdn->fd = grpc_fd_create(socks[i], fd_name);
fdn->ev_driver = ev_driver; fdn->ev_driver = ev_driver;
fdn->readable_registered = false; fdn->readable_registered = false;
fdn->writable_registered = false; fdn->writable_registered = false;
fdn->shutting_down = false;
gpr_mu_init(&fdn->mu); gpr_mu_init(&fdn->mu);
GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_cb, fdn, GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_cb, fdn,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_cb, fdn, GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_cb, fdn,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, fdn->fd);
fdn->grpc_fd);
gpr_free(fd_name); gpr_free(fd_name);
} }
fdn->next = new_list; fdn->next = new_list;
@ -274,9 +309,8 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx,
if (ARES_GETSOCK_READABLE(socks_bitmask, i) && if (ARES_GETSOCK_READABLE(socks_bitmask, i) &&
!fdn->readable_registered) { !fdn->readable_registered) {
grpc_ares_ev_driver_ref(ev_driver); grpc_ares_ev_driver_ref(ev_driver);
gpr_log(GPR_DEBUG, "notify read on: %d", gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->fd));
grpc_fd_wrapped_fd(fdn->grpc_fd)); grpc_fd_notify_on_read(exec_ctx, fdn->fd, &fdn->read_closure);
grpc_fd_notify_on_read(exec_ctx, fdn->grpc_fd, &fdn->read_closure);
fdn->readable_registered = true; fdn->readable_registered = true;
} }
// Register write_closure if the socket is writable and write_closure // Register write_closure if the socket is writable and write_closure
@ -284,9 +318,9 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx,
if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) && if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) &&
!fdn->writable_registered) { !fdn->writable_registered) {
gpr_log(GPR_DEBUG, "notify write on: %d", gpr_log(GPR_DEBUG, "notify write on: %d",
grpc_fd_wrapped_fd(fdn->grpc_fd)); grpc_fd_wrapped_fd(fdn->fd));
grpc_ares_ev_driver_ref(ev_driver); grpc_ares_ev_driver_ref(ev_driver);
grpc_fd_notify_on_write(exec_ctx, fdn->grpc_fd, &fdn->write_closure); grpc_fd_notify_on_write(exec_ctx, fdn->fd, &fdn->write_closure);
fdn->writable_registered = true; fdn->writable_registered = true;
} }
gpr_mu_unlock(&fdn->mu); gpr_mu_unlock(&fdn->mu);
@ -299,7 +333,7 @@ static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx,
while (ev_driver->fds != NULL) { while (ev_driver->fds != NULL) {
fd_node *cur = ev_driver->fds; fd_node *cur = ev_driver->fds;
ev_driver->fds = ev_driver->fds->next; ev_driver->fds = ev_driver->fds->next;
fd_node_destroy(exec_ctx, cur); fd_node_shutdown(exec_ctx, cur);
} }
ev_driver->fds = new_list; ev_driver->fds = new_list;
// If the ev driver has no working fd, all the tasks are done. // If the ev driver has no working fd, all the tasks are done.

@ -123,8 +123,8 @@ static void grpc_ares_request_unref(grpc_exec_ctx *exec_ctx,
static grpc_ares_hostbyname_request *create_hostbyname_request( static grpc_ares_hostbyname_request *create_hostbyname_request(
grpc_ares_request *parent_request, char *host, uint16_t port, grpc_ares_request *parent_request, char *host, uint16_t port,
bool is_balancer) { bool is_balancer) {
grpc_ares_hostbyname_request *hr = grpc_ares_hostbyname_request *hr = (grpc_ares_hostbyname_request *)gpr_zalloc(
gpr_zalloc(sizeof(grpc_ares_hostbyname_request)); sizeof(grpc_ares_hostbyname_request));
hr->parent_request = parent_request; hr->parent_request = parent_request;
hr->host = gpr_strdup(host); hr->host = gpr_strdup(host);
hr->port = port; hr->port = port;
@ -174,7 +174,7 @@ static void on_hostbyname_done_cb(void *arg, int status, int timeouts,
grpc_lb_addresses_set_address( grpc_lb_addresses_set_address(
*lb_addresses, i, &addr, addr_len, *lb_addresses, i, &addr, addr_len,
hr->is_balancer /* is_balancer */, hr->is_balancer /* is_balancer */,
hr->is_balancer ? strdup(hr->host) : NULL /* balancer_name */, hr->is_balancer ? hr->host : NULL /* balancer_name */,
NULL /* user_data */); NULL /* user_data */);
char output[INET6_ADDRSTRLEN]; char output[INET6_ADDRSTRLEN];
ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN); ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN);
@ -195,7 +195,7 @@ static void on_hostbyname_done_cb(void *arg, int status, int timeouts,
grpc_lb_addresses_set_address( grpc_lb_addresses_set_address(
*lb_addresses, i, &addr, addr_len, *lb_addresses, i, &addr, addr_len,
hr->is_balancer /* is_balancer */, hr->is_balancer /* is_balancer */,
hr->is_balancer ? strdup(hr->host) : NULL /* balancer_name */, hr->is_balancer ? hr->host : NULL /* balancer_name */,
NULL /* user_data */); NULL /* user_data */);
char output[INET_ADDRSTRLEN]; char output[INET_ADDRSTRLEN];
ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN); ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN);
@ -275,14 +275,15 @@ static void on_txt_done_cb(void *arg, int status, int timeouts,
gpr_log(GPR_DEBUG, "on_txt_done_cb"); gpr_log(GPR_DEBUG, "on_txt_done_cb");
char *error_msg; char *error_msg;
grpc_ares_request *r = (grpc_ares_request *)arg; grpc_ares_request *r = (grpc_ares_request *)arg;
const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
struct ares_txt_ext *result = NULL;
struct ares_txt_ext *reply = NULL;
grpc_error *error = GRPC_ERROR_NONE;
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
if (status != ARES_SUCCESS) goto fail; if (status != ARES_SUCCESS) goto fail;
struct ares_txt_ext *reply = NULL;
status = ares_parse_txt_reply_ext(buf, len, &reply); status = ares_parse_txt_reply_ext(buf, len, &reply);
if (status != ARES_SUCCESS) goto fail; if (status != ARES_SUCCESS) goto fail;
// Find service config in TXT record. // Find service config in TXT record.
const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
struct ares_txt_ext *result;
for (result = reply; result != NULL; result = result->next) { for (result = reply; result != NULL; result = result->next) {
if (result->record_start && if (result->record_start &&
memcmp(result->txt, g_service_config_attribute_prefix, prefix_len) == memcmp(result->txt, g_service_config_attribute_prefix, prefix_len) ==
@ -313,7 +314,7 @@ static void on_txt_done_cb(void *arg, int status, int timeouts,
fail: fail:
gpr_asprintf(&error_msg, "C-ares TXT lookup status is not ARES_SUCCESS: %s", gpr_asprintf(&error_msg, "C-ares TXT lookup status is not ARES_SUCCESS: %s",
ares_strerror(status)); ares_strerror(status));
grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg); gpr_free(error_msg);
if (r->error == GRPC_ERROR_NONE) { if (r->error == GRPC_ERROR_NONE) {
r->error = error; r->error = error;
@ -331,6 +332,9 @@ static grpc_ares_request *grpc_dns_lookup_ares_impl(
grpc_closure *on_done, grpc_lb_addresses **addrs, bool check_grpclb, grpc_closure *on_done, grpc_lb_addresses **addrs, bool check_grpclb,
char **service_config_json) { char **service_config_json) {
grpc_error *error = GRPC_ERROR_NONE; grpc_error *error = GRPC_ERROR_NONE;
grpc_ares_hostbyname_request *hr = NULL;
grpc_ares_request *r = NULL;
ares_channel *channel = NULL;
/* TODO(zyc): Enable tracing after #9603 is checked in */ /* TODO(zyc): Enable tracing after #9603 is checked in */
/* if (grpc_dns_trace) { /* if (grpc_dns_trace) {
gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s", gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
@ -360,8 +364,7 @@ static grpc_ares_request *grpc_dns_lookup_ares_impl(
error = grpc_ares_ev_driver_create(&ev_driver, interested_parties); error = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
if (error != GRPC_ERROR_NONE) goto error_cleanup; if (error != GRPC_ERROR_NONE) goto error_cleanup;
grpc_ares_request *r = r = (grpc_ares_request *)gpr_zalloc(sizeof(grpc_ares_request));
(grpc_ares_request *)gpr_zalloc(sizeof(grpc_ares_request));
gpr_mu_init(&r->mu); gpr_mu_init(&r->mu);
r->ev_driver = ev_driver; r->ev_driver = ev_driver;
r->on_done = on_done; r->on_done = on_done;
@ -369,7 +372,7 @@ static grpc_ares_request *grpc_dns_lookup_ares_impl(
r->service_config_json_out = service_config_json; r->service_config_json_out = service_config_json;
r->success = false; r->success = false;
r->error = GRPC_ERROR_NONE; r->error = GRPC_ERROR_NONE;
ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver); channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
// If dns_server is specified, use it. // If dns_server is specified, use it.
if (dns_server != NULL) { if (dns_server != NULL) {
@ -410,12 +413,12 @@ static grpc_ares_request *grpc_dns_lookup_ares_impl(
} }
gpr_ref_init(&r->pending_queries, 1); gpr_ref_init(&r->pending_queries, 1);
if (grpc_ipv6_loopback_available()) { if (grpc_ipv6_loopback_available()) {
grpc_ares_hostbyname_request *hr = create_hostbyname_request( hr = create_hostbyname_request(r, host, strhtons(port),
r, host, strhtons(port), false /* is_balancer */); false /* is_balancer */);
ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_cb, hr); ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_cb, hr);
} }
grpc_ares_hostbyname_request *hr = create_hostbyname_request( hr = create_hostbyname_request(r, host, strhtons(port),
r, host, strhtons(port), false /* is_balancer */); false /* is_balancer */);
ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, hr); ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, hr);
if (check_grpclb) { if (check_grpclb) {
/* Query the SRV record */ /* Query the SRV record */
@ -527,7 +530,8 @@ static void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx,
grpc_closure *on_done, grpc_closure *on_done,
grpc_resolved_addresses **addrs) { grpc_resolved_addresses **addrs) {
grpc_resolve_address_ares_request *r = grpc_resolve_address_ares_request *r =
gpr_zalloc(sizeof(grpc_resolve_address_ares_request)); (grpc_resolve_address_ares_request *)gpr_zalloc(
sizeof(grpc_resolve_address_ares_request));
r->addrs_out = addrs; r->addrs_out = addrs;
r->on_resolve_address_done = on_done; r->on_resolve_address_done = on_done;
GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r, GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r,

@ -210,7 +210,7 @@ grpc_arg grpc_fake_resolver_response_generator_arg(
grpc_fake_resolver_response_generator* generator) { grpc_fake_resolver_response_generator* generator) {
grpc_arg arg; grpc_arg arg;
arg.type = GRPC_ARG_POINTER; arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR; arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
arg.value.pointer.p = generator; arg.value.pointer.p = generator;
arg.value.pointer.vtable = &response_generator_arg_vtable; arg.value.pointer.vtable = &response_generator_arg_vtable;
return arg; return arg;

@ -99,7 +99,7 @@ static grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_create(
int max_milli_tokens, int milli_token_ratio, int max_milli_tokens, int milli_token_ratio,
grpc_server_retry_throttle_data* old_throttle_data) { grpc_server_retry_throttle_data* old_throttle_data) {
grpc_server_retry_throttle_data* throttle_data = grpc_server_retry_throttle_data* throttle_data =
gpr_malloc(sizeof(*throttle_data)); (grpc_server_retry_throttle_data*)gpr_malloc(sizeof(*throttle_data));
memset(throttle_data, 0, sizeof(*throttle_data)); memset(throttle_data, 0, sizeof(*throttle_data));
gpr_ref_init(&throttle_data->refs, 1); gpr_ref_init(&throttle_data->refs, 1);
throttle_data->max_milli_tokens = max_milli_tokens; throttle_data->max_milli_tokens = max_milli_tokens;
@ -131,11 +131,11 @@ static grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_create(
// //
static void* copy_server_name(void* key, void* unused) { static void* copy_server_name(void* key, void* unused) {
return gpr_strdup(key); return gpr_strdup((const char*)key);
} }
static long compare_server_name(void* key1, void* key2, void* unused) { static long compare_server_name(void* key1, void* key2, void* unused) {
return strcmp(key1, key2); return strcmp((const char*)key1, (const char*)key2);
} }
static void destroy_server_retry_throttle_data(void* value, void* unused) { static void destroy_server_retry_throttle_data(void* value, void* unused) {
@ -177,7 +177,8 @@ grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
const char* server_name, int max_milli_tokens, int milli_token_ratio) { const char* server_name, int max_milli_tokens, int milli_token_ratio) {
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
grpc_server_retry_throttle_data* throttle_data = grpc_server_retry_throttle_data* throttle_data =
gpr_avl_get(g_avl, (char*)server_name, NULL); (grpc_server_retry_throttle_data*)gpr_avl_get(g_avl, (char*)server_name,
NULL);
if (throttle_data == NULL) { if (throttle_data == NULL) {
// Entry not found. Create a new one. // Entry not found. Create a new one.
throttle_data = grpc_server_retry_throttle_data_create( throttle_data = grpc_server_retry_throttle_data_create(

@ -32,6 +32,7 @@
#include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/ext/filters/client_channel/uri_parser.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
@ -290,6 +291,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
return c; return c;
} }
GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(exec_ctx);
c = (grpc_subchannel *)gpr_zalloc(sizeof(*c)); c = (grpc_subchannel *)gpr_zalloc(sizeof(*c));
c->key = key; c->key = key;
gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
@ -809,6 +811,6 @@ const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args) {
grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) { grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) {
return grpc_channel_arg_string_create( return grpc_channel_arg_string_create(
GRPC_ARG_SUBCHANNEL_ADDRESS, (char *)GRPC_ARG_SUBCHANNEL_ADDRESS,
addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""));
} }

@ -34,6 +34,8 @@ static gpr_avl g_subchannel_index;
static gpr_mu g_mu; static gpr_mu g_mu;
static gpr_refcount g_refcount;
struct grpc_subchannel_key { struct grpc_subchannel_key {
grpc_subchannel_args args; grpc_subchannel_args args;
}; };
@ -88,24 +90,26 @@ void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
static void sck_avl_destroy(void *p, void *user_data) { static void sck_avl_destroy(void *p, void *user_data) {
grpc_exec_ctx *exec_ctx = (grpc_exec_ctx *)user_data; grpc_exec_ctx *exec_ctx = (grpc_exec_ctx *)user_data;
grpc_subchannel_key_destroy(exec_ctx, p); grpc_subchannel_key_destroy(exec_ctx, (grpc_subchannel_key *)p);
} }
static void *sck_avl_copy(void *p, void *unused) { static void *sck_avl_copy(void *p, void *unused) {
return subchannel_key_copy(p); return subchannel_key_copy((grpc_subchannel_key *)p);
} }
static long sck_avl_compare(void *a, void *b, void *unused) { static long sck_avl_compare(void *a, void *b, void *unused) {
return grpc_subchannel_key_compare(a, b); return grpc_subchannel_key_compare((grpc_subchannel_key *)a,
(grpc_subchannel_key *)b);
} }
static void scv_avl_destroy(void *p, void *user_data) { static void scv_avl_destroy(void *p, void *user_data) {
grpc_exec_ctx *exec_ctx = (grpc_exec_ctx *)user_data; grpc_exec_ctx *exec_ctx = (grpc_exec_ctx *)user_data;
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, p, "subchannel_index"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, (grpc_subchannel *)p,
"subchannel_index");
} }
static void *scv_avl_copy(void *p, void *unused) { static void *scv_avl_copy(void *p, void *unused) {
GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index"); GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel *)p, "subchannel_index");
return p; return p;
} }
@ -119,15 +123,27 @@ static const gpr_avl_vtable subchannel_avl_vtable = {
void grpc_subchannel_index_init(void) { void grpc_subchannel_index_init(void) {
g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable); g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable);
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
gpr_ref_init(&g_refcount, 1);
} }
void grpc_subchannel_index_shutdown(void) { void grpc_subchannel_index_shutdown(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; // TODO(juanlishen): This refcounting mechanism may lead to memory leackage.
gpr_mu_destroy(&g_mu); // To solve that, we should force polling to flush any pending callbacks, then
gpr_avl_unref(g_subchannel_index, &exec_ctx); // shutdown safely.
grpc_exec_ctx_finish(&exec_ctx); grpc_subchannel_index_unref();
}
void grpc_subchannel_index_unref(void) {
if (gpr_unref(&g_refcount)) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_mu_destroy(&g_mu);
gpr_avl_unref(g_subchannel_index, &exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
}
} }
void grpc_subchannel_index_ref(void) { gpr_ref_non_zero(&g_refcount); }
grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx, grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
grpc_subchannel_key *key) { grpc_subchannel_key *key) {
// Lock, and take a reference to the subchannel index. // Lock, and take a reference to the subchannel index.

@ -59,6 +59,13 @@ void grpc_subchannel_index_init(void);
/** Shutdown the subchannel index (global) */ /** Shutdown the subchannel index (global) */
void grpc_subchannel_index_shutdown(void); void grpc_subchannel_index_shutdown(void);
/** Increment the refcount (non-zero) of subchannel index (global). */
void grpc_subchannel_index_ref(void);
/** Decrement the refcount of subchannel index (global). If the refcount drops
to zero, unref the subchannel index and destroy its mutex. */
void grpc_subchannel_index_unref(void);
/** \em TEST ONLY. /** \em TEST ONLY.
* If \a force_creation is true, all key comparisons will be false, resulting in * If \a force_creation is true, all key comparisons will be false, resulting in
* new subchannels always being created. Otherwise, the keys will be compared as * new subchannels always being created. Otherwise, the keys will be compared as

@ -225,7 +225,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
exec_ctx, calld->message_compression_algorithm, &calld->slices, &tmp); exec_ctx, calld->message_compression_algorithm, &calld->slices, &tmp);
if (did_compress) { if (did_compress) {
if (GRPC_TRACER_ON(grpc_compression_trace)) { if (GRPC_TRACER_ON(grpc_compression_trace)) {
char *algo_name; const char *algo_name;
const size_t before_size = calld->slices.length; const size_t before_size = calld->slices.length;
const size_t after_size = tmp.length; const size_t after_size = tmp.length;
const float savings_ratio = 1.0f - (float)after_size / (float)before_size; const float savings_ratio = 1.0f - (float)after_size / (float)before_size;
@ -239,7 +239,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
send_flags |= GRPC_WRITE_INTERNAL_COMPRESS; send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
} else { } else {
if (GRPC_TRACER_ON(grpc_compression_trace)) { if (GRPC_TRACER_ON(grpc_compression_trace)) {
char *algo_name; const char *algo_name;
GPR_ASSERT(grpc_message_compression_algorithm_name( GPR_ASSERT(grpc_message_compression_algorithm_name(
calld->message_compression_algorithm, &algo_name)); calld->message_compression_algorithm, &algo_name));
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,

@ -83,12 +83,12 @@ static grpc_error *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx,
} }
static void add_error(const char *error_name, grpc_error **cumulative, static void add_error(const char *error_name, grpc_error **cumulative,
grpc_error *new) { grpc_error *new_err) {
if (new == GRPC_ERROR_NONE) return; if (new_err == GRPC_ERROR_NONE) return;
if (*cumulative == GRPC_ERROR_NONE) { if (*cumulative == GRPC_ERROR_NONE) {
*cumulative = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_name); *cumulative = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_name);
} }
*cumulative = grpc_error_add_child(*cumulative, new); *cumulative = grpc_error_add_child(*cumulative, new_err);
} }
static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx, static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,

@ -55,7 +55,8 @@ static bool maybe_add_server_load_reporting_filter(
} }
grpc_arg grpc_load_reporting_enable_arg() { grpc_arg grpc_load_reporting_enable_arg() {
return grpc_channel_arg_integer_create(GRPC_ARG_ENABLE_LOAD_REPORTING, 1); return grpc_channel_arg_integer_create((char *)GRPC_ARG_ENABLE_LOAD_REPORTING,
1);
} }
/* Plugin registration */ /* Plugin registration */

@ -402,7 +402,7 @@ static bool maybe_add_max_age_filter(grpc_exec_ctx* exec_ctx,
bool enable = bool enable =
grpc_channel_arg_get_integer( grpc_channel_arg_get_integer(
grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS), grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS),
MAX_CONNECTION_AGE_INTEGER_OPTIONS) != INT_MAX && MAX_CONNECTION_AGE_INTEGER_OPTIONS) != INT_MAX ||
grpc_channel_arg_get_integer( grpc_channel_arg_get_integer(
grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS), grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS),
MAX_CONNECTION_IDLE_INTEGER_OPTIONS) != INT_MAX; MAX_CONNECTION_IDLE_INTEGER_OPTIONS) != INT_MAX;

@ -161,7 +161,7 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(error)); grpc_endpoint_shutdown(exec_ctx, c->endpoint, GRPC_ERROR_REF(error));
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
chttp2_connector_unref(exec_ctx, arg); chttp2_connector_unref(exec_ctx, (grpc_connector *)arg);
} else { } else {
GPR_ASSERT(c->endpoint != NULL); GPR_ASSERT(c->endpoint != NULL);
start_handshake_locked(exec_ctx, c); start_handshake_locked(exec_ctx, c);

@ -55,7 +55,7 @@ static grpc_channel *client_channel_factory_create_channel(
} }
// Add channel arg containing the server URI. // Add channel arg containing the server URI.
grpc_arg arg = grpc_channel_arg_string_create( grpc_arg arg = grpc_channel_arg_string_create(
GRPC_ARG_SERVER_URI, (char *)GRPC_ARG_SERVER_URI,
grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target)); grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target));
const char *to_remove[] = {GRPC_ARG_SERVER_URI}; const char *to_remove[] = {GRPC_ARG_SERVER_URI};
grpc_channel_args *new_args = grpc_channel_args *new_args =

@ -42,7 +42,7 @@ grpc_channel *grpc_insecure_channel_create_from_fd(
(target, fd, args)); (target, fd, args));
grpc_arg default_authority_arg = grpc_channel_arg_string_create( grpc_arg default_authority_arg = grpc_channel_arg_string_create(
GRPC_ARG_DEFAULT_AUTHORITY, "test.authority"); (char *)GRPC_ARG_DEFAULT_AUTHORITY, (char *)"test.authority");
grpc_channel_args *final_args = grpc_channel_args *final_args =
grpc_channel_args_copy_and_add(args, &default_authority_arg, 1); grpc_channel_args_copy_and_add(args, &default_authority_arg, 1);

@ -52,7 +52,7 @@ typedef struct {
} server_state; } server_state;
typedef struct { typedef struct {
server_state *server_state; server_state *svr_state;
grpc_pollset *accepting_pollset; grpc_pollset *accepting_pollset;
grpc_tcp_server_acceptor *acceptor; grpc_tcp_server_acceptor *acceptor;
grpc_handshake_manager *handshake_mgr; grpc_handshake_manager *handshake_mgr;
@ -63,8 +63,8 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_handshaker_args *args = (grpc_handshaker_args *)arg; grpc_handshaker_args *args = (grpc_handshaker_args *)arg;
server_connection_state *connection_state = server_connection_state *connection_state =
(server_connection_state *)args->user_data; (server_connection_state *)args->user_data;
gpr_mu_lock(&connection_state->server_state->mu); gpr_mu_lock(&connection_state->svr_state->mu);
if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) { if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) {
const char *error_str = grpc_error_string(error); const char *error_str = grpc_error_string(error);
gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str); gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
@ -89,7 +89,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_transport *transport = grpc_transport *transport =
grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0); grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0);
grpc_server_setup_transport( grpc_server_setup_transport(
exec_ctx, connection_state->server_state->server, transport, exec_ctx, connection_state->svr_state->server, transport,
connection_state->accepting_pollset, args->args); connection_state->accepting_pollset, args->args);
grpc_chttp2_transport_start_reading(exec_ctx, transport, grpc_chttp2_transport_start_reading(exec_ctx, transport,
args->read_buffer); args->read_buffer);
@ -97,11 +97,11 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
} }
} }
grpc_handshake_manager_pending_list_remove( grpc_handshake_manager_pending_list_remove(
&connection_state->server_state->pending_handshake_mgrs, &connection_state->svr_state->pending_handshake_mgrs,
connection_state->handshake_mgr); connection_state->handshake_mgr);
gpr_mu_unlock(&connection_state->server_state->mu); gpr_mu_unlock(&connection_state->svr_state->mu);
grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server); grpc_tcp_server_unref(exec_ctx, connection_state->svr_state->tcp_server);
gpr_free(connection_state->acceptor); gpr_free(connection_state->acceptor);
gpr_free(connection_state); gpr_free(connection_state);
} }
@ -124,8 +124,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
grpc_tcp_server_ref(state->tcp_server); grpc_tcp_server_ref(state->tcp_server);
server_connection_state *connection_state = server_connection_state *connection_state =
gpr_malloc(sizeof(*connection_state)); (server_connection_state *)gpr_malloc(sizeof(*connection_state));
connection_state->server_state = state; connection_state->svr_state = state;
connection_state->accepting_pollset = accepting_pollset; connection_state->accepting_pollset = accepting_pollset;
connection_state->acceptor = acceptor; connection_state->acceptor = acceptor;
connection_state->handshake_mgr = handshake_mgr; connection_state->handshake_mgr = handshake_mgr;
@ -201,6 +201,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
grpc_error *err = GRPC_ERROR_NONE; grpc_error *err = GRPC_ERROR_NONE;
server_state *state = NULL; server_state *state = NULL;
grpc_error **errors = NULL; grpc_error **errors = NULL;
size_t naddrs = 0;
*port_num = -1; *port_num = -1;
@ -225,7 +226,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
state->shutdown = true; state->shutdown = true;
gpr_mu_init(&state->mu); gpr_mu_init(&state->mu);
const size_t naddrs = resolved->naddrs; naddrs = resolved->naddrs;
errors = (grpc_error **)gpr_malloc(sizeof(*errors) * naddrs); errors = (grpc_error **)gpr_malloc(sizeof(*errors) * naddrs);
for (i = 0; i < naddrs; i++) { for (i = 0; i < naddrs; i++) {
errors[i] = errors[i] =

@ -23,6 +23,7 @@
void grpc_chttp2_plugin_init(void) { void grpc_chttp2_plugin_init(void) {
grpc_register_tracer(&grpc_http_trace); grpc_register_tracer(&grpc_http_trace);
grpc_register_tracer(&grpc_flowctl_trace); grpc_register_tracer(&grpc_flowctl_trace);
grpc_register_tracer(&grpc_trace_http2_stream_state);
#ifndef NDEBUG #ifndef NDEBUG
grpc_register_tracer(&grpc_trace_chttp2_refcount); grpc_register_tracer(&grpc_trace_chttp2_refcount);
#endif #endif

@ -64,6 +64,11 @@
#define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false #define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
#define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2 #define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2
#define DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
#define DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
#define DEFAULT_MAX_PINGS_BETWEEN_DATA 0 /* unlimited */
#define DEFAULT_MAX_PING_STRIKES 2
static int g_default_client_keepalive_time_ms = static int g_default_client_keepalive_time_ms =
DEFAULT_CLIENT_KEEPALIVE_TIME_MS; DEFAULT_CLIENT_KEEPALIVE_TIME_MS;
static int g_default_client_keepalive_timeout_ms = static int g_default_client_keepalive_timeout_ms =
@ -75,6 +80,13 @@ static int g_default_server_keepalive_timeout_ms =
static bool g_default_keepalive_permit_without_calls = static bool g_default_keepalive_permit_without_calls =
DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
static int g_default_min_sent_ping_interval_without_data_ms =
DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS;
static int g_default_min_recv_ping_interval_without_data_ms =
DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS;
static int g_default_max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA;
static int g_default_max_ping_strikes = DEFAULT_MAX_PING_STRIKES;
#define MAX_CLIENT_STREAM_ID 0x7fffffffu #define MAX_CLIENT_STREAM_ID 0x7fffffffu
grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false, "http"); grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false, "http");
grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false, "flowctl"); grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false, "flowctl");
@ -144,18 +156,14 @@ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_error *error); grpc_error *error);
static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void send_ping_locked(
grpc_chttp2_ping_type ping_type, grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure *on_initiate, grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate,
grpc_closure *on_complete); grpc_closure *on_complete,
grpc_chttp2_initiate_write_reason initiate_write_reason);
static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error); grpc_error *error);
#define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
#define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
#define DEFAULT_MAX_PING_STRIKES 2
#define DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
/** keepalive-relevant functions */ /** keepalive-relevant functions */
static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg, static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error); grpc_error *error);
@ -346,7 +354,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (is_client) { if (is_client) {
grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string( grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
GRPC_CHTTP2_CLIENT_CONNECT_STRING)); GRPC_CHTTP2_CLIENT_CONNECT_STRING));
grpc_chttp2_initiate_write(exec_ctx, t, "initial_write");
} }
/* configure http2 the way we like it */ /* configure http2 the way we like it */
@ -362,14 +369,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
queue_setting_update(exec_ctx, t, queue_setting_update(exec_ctx, t,
GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1); GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1);
t->ping_policy = (grpc_chttp2_repeated_ping_policy){ t->ping_policy.max_pings_without_data = g_default_max_pings_without_data;
.max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA, t->ping_policy.min_sent_ping_interval_without_data = gpr_time_from_millis(
.min_time_between_pings = g_default_min_sent_ping_interval_without_data_ms, GPR_TIMESPAN);
gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN), t->ping_policy.max_ping_strikes = g_default_max_ping_strikes;
.max_ping_strikes = DEFAULT_MAX_PING_STRIKES, t->ping_policy.min_recv_ping_interval_without_data = gpr_time_from_millis(
.min_ping_interval_without_data = gpr_time_from_millis( g_default_min_recv_ping_interval_without_data_ms, GPR_TIMESPAN);
DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, GPR_TIMESPAN),
};
/* Keepalive setting */ /* Keepalive setting */
if (t->is_client) { if (t->is_client) {
@ -428,29 +433,37 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) { GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer( t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer(
&channel_args->args[i], &channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX}); (grpc_integer_options){g_default_max_pings_without_data, 0,
INT_MAX});
} else if (0 == strcmp(channel_args->args[i].key, } else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_MAX_PING_STRIKES)) { GRPC_ARG_HTTP2_MAX_PING_STRIKES)) {
t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer( t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer(
&channel_args->args[i], &channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_PING_STRIKES, 0, INT_MAX}); (grpc_integer_options){g_default_max_ping_strikes, 0, INT_MAX});
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) {
t->ping_policy.min_time_between_pings = gpr_time_from_millis(
grpc_channel_arg_get_integer(
&channel_args->args[i],
(grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0,
INT_MAX}),
GPR_TIMESPAN);
} else if (0 == } else if (0 ==
strcmp(channel_args->args[i].key, strcmp(
GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS)) { channel_args->args[i].key,
t->ping_policy.min_ping_interval_without_data = gpr_time_from_millis( GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) {
grpc_channel_arg_get_integer( t->ping_policy.min_sent_ping_interval_without_data =
&channel_args->args[i], gpr_time_from_millis(
(grpc_integer_options){ grpc_channel_arg_get_integer(
DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, 0, INT_MAX}), &channel_args->args[i],
GPR_TIMESPAN); (grpc_integer_options){
g_default_min_sent_ping_interval_without_data_ms, 0,
INT_MAX}),
GPR_TIMESPAN);
} else if (0 ==
strcmp(
channel_args->args[i].key,
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) {
t->ping_policy.min_recv_ping_interval_without_data =
gpr_time_from_millis(
grpc_channel_arg_get_integer(
&channel_args->args[i],
(grpc_integer_options){
g_default_min_recv_ping_interval_without_data_ms, 0,
INT_MAX}),
GPR_TIMESPAN);
} else if (0 == strcmp(channel_args->args[i].key, } else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer( t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
@ -557,8 +570,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
} }
} }
t->ping_state.pings_before_data_required = /* No pings allowed before receiving a header or data frame. */
t->ping_policy.max_pings_without_data; t->ping_state.pings_before_data_required = 0;
t->ping_state.is_delayed_ping_timer_set = false; t->ping_state.is_delayed_ping_timer_set = false;
t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC); t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
@ -578,7 +591,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED; t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED;
} }
grpc_chttp2_initiate_write(exec_ctx, t, "init"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE);
post_benign_reclaimer(exec_ctx, t); post_benign_reclaimer(exec_ctx, t);
} }
@ -624,6 +638,9 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN, connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "close_transport"); GRPC_ERROR_REF(error), "close_transport");
grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error)); grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
if (t->ping_state.is_delayed_ping_timer_set) {
grpc_timer_cancel(exec_ctx, &t->ping_state.delayed_ping_timer);
}
switch (t->keepalive_state) { switch (t->keepalive_state) {
case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING:
grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer); grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
@ -689,7 +706,10 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_slice_buffer_init(&s->unprocessed_incoming_frames_buffer); grpc_slice_buffer_init(&s->unprocessed_incoming_frames_buffer);
grpc_slice_buffer_init(&s->frame_storage); grpc_slice_buffer_init(&s->frame_storage);
grpc_slice_buffer_init(&s->compressed_data_buffer);
grpc_slice_buffer_init(&s->decompressed_data_buffer);
s->pending_byte_stream = false; s->pending_byte_stream = false;
s->decompressed_header_bytes = 0;
GRPC_CLOSURE_INIT(&s->reset_byte_stream, reset_byte_stream, s, GRPC_CLOSURE_INIT(&s->reset_byte_stream, reset_byte_stream, s,
grpc_combiner_scheduler(t->combiner)); grpc_combiner_scheduler(t->combiner));
@ -723,14 +743,8 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
grpc_slice_buffer_destroy_internal(exec_ctx, grpc_slice_buffer_destroy_internal(exec_ctx,
&s->unprocessed_incoming_frames_buffer); &s->unprocessed_incoming_frames_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, &s->frame_storage); grpc_slice_buffer_destroy_internal(exec_ctx, &s->frame_storage);
if (s->compressed_data_buffer) { grpc_slice_buffer_destroy_internal(exec_ctx, &s->compressed_data_buffer);
grpc_slice_buffer_destroy_internal(exec_ctx, s->compressed_data_buffer); grpc_slice_buffer_destroy_internal(exec_ctx, &s->decompressed_data_buffer);
gpr_free(s->compressed_data_buffer);
}
if (s->decompressed_data_buffer) {
grpc_slice_buffer_destroy_internal(exec_ctx, s->decompressed_data_buffer);
gpr_free(s->decompressed_data_buffer);
}
grpc_chttp2_list_remove_stalled_by_transport(t, s); grpc_chttp2_list_remove_stalled_by_transport(t, s);
grpc_chttp2_list_remove_stalled_by_stream(t, s); grpc_chttp2_list_remove_stalled_by_stream(t, s);
@ -846,13 +860,91 @@ static void set_write_state(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
} }
} }
static void inc_initiate_write_reason(
grpc_exec_ctx *exec_ctx, grpc_chttp2_initiate_write_reason reason) {
switch (reason) {
case GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_INITIAL_WRITE(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_START_NEW_STREAM(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_MESSAGE(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_INITIAL_METADATA(
exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_TRAILING_METADATA(
exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RETRY_SEND_PING(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CONTINUE_PINGS(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_GOAWAY_SENT(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RST_STREAM(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CLOSE_FROM_API(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_STREAM_FLOW_CONTROL(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL(
exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_SETTINGS(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_BDP_ESTIMATOR_PING(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_SETTING(
exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_UPDATE(
exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_APPLICATION_PING(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_KEEPALIVE_PING(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL_UNSTALLED(
exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_PING_RESPONSE(exec_ctx);
break;
case GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM:
GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FORCE_RST_STREAM(exec_ctx);
break;
}
}
void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, const char *reason) { grpc_chttp2_transport *t,
grpc_chttp2_initiate_write_reason reason) {
GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0); GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0);
switch (t->write_state) { switch (t->write_state) {
case GRPC_CHTTP2_WRITE_STATE_IDLE: case GRPC_CHTTP2_WRITE_STATE_IDLE:
set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, reason); inc_initiate_write_reason(exec_ctx, reason);
set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
grpc_chttp2_initiate_write_reason_string(reason));
t->is_first_write_in_batch = true; t->is_first_write_in_batch = true;
GRPC_CHTTP2_REF_TRANSPORT(t, "writing"); GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(
@ -864,7 +956,7 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
break; break;
case GRPC_CHTTP2_WRITE_STATE_WRITING: case GRPC_CHTTP2_WRITE_STATE_WRITING:
set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE, set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE,
reason); grpc_chttp2_initiate_write_reason_string(reason));
break; break;
case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE: case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
break; break;
@ -872,16 +964,12 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
GPR_TIMER_END("grpc_chttp2_initiate_write", 0); GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
} }
void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, void grpc_chttp2_mark_stream_writable(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_chttp2_stream *s) {
bool also_initiate_write, const char *reason) {
if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) { if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become"); GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
} }
if (also_initiate_write) {
grpc_chttp2_initiate_write(exec_ctx, t, reason);
}
} }
static grpc_closure_scheduler *write_scheduler(grpc_chttp2_transport *t, static grpc_closure_scheduler *write_scheduler(grpc_chttp2_transport *t,
@ -1105,7 +1193,9 @@ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_map_add(&t->stream_map, s->id, s); grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
post_destructive_reclaimer(exec_ctx, t); post_destructive_reclaimer(exec_ctx, t);
grpc_chttp2_become_writable(exec_ctx, t, s, true, "new_stream"); grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM);
} }
/* cancel out streams that will never be started */ /* cancel out streams that will never be started */
while (t->next_stream_id >= MAX_CLIENT_STREAM_ID && while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@ -1202,7 +1292,9 @@ static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream *s) { grpc_chttp2_stream *s) {
if (s->id != 0 && (!s->write_buffering || if (s->id != 0 && (!s->write_buffering ||
s->flow_controlled_buffer.length > t->write_buffer_size)) { s->flow_controlled_buffer.length > t->write_buffer_size)) {
grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message"); grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE);
} }
} }
@ -1353,12 +1445,14 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
/* Identify stream compression */ /* Identify stream compression */
if ((s->stream_compression_send_enabled = if (op_payload->send_initial_metadata.send_initial_metadata->idx.named
(op_payload->send_initial_metadata.send_initial_metadata->idx.named .content_encoding == NULL ||
.content_encoding != NULL)) == true) { grpc_stream_compression_method_parse(
s->compressed_data_buffer = GRPC_MDVALUE(
(grpc_slice_buffer *)gpr_malloc(sizeof(grpc_slice_buffer)); op_payload->send_initial_metadata.send_initial_metadata->idx
grpc_slice_buffer_init(s->compressed_data_buffer); .named.content_encoding->md),
true, &s->stream_compression_method) == 0) {
s->stream_compression_method = GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS;
} }
s->send_initial_metadata_finished = add_closure_barrier(on_complete); s->send_initial_metadata_finished = add_closure_barrier(on_complete);
@ -1404,14 +1498,13 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
} }
} else { } else {
GPR_ASSERT(s->id != 0); GPR_ASSERT(s->id != 0);
bool initiate_write = true; grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
if (op->send_message && if (!(op->send_message &&
(op->payload->send_message.send_message->flags & (op->payload->send_message.send_message->flags &
GRPC_WRITE_BUFFER_HINT)) { GRPC_WRITE_BUFFER_HINT))) {
initiate_write = false; grpc_chttp2_initiate_write(
exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA);
} }
grpc_chttp2_become_writable(exec_ctx, t, s, initiate_write,
"op.send_initial_metadata");
} }
} else { } else {
s->send_initial_metadata = NULL; s->send_initial_metadata = NULL;
@ -1519,8 +1612,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
} else if (s->id != 0) { } else if (s->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding /* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */ bytes before going writable */
grpc_chttp2_become_writable(exec_ctx, t, s, true, grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
"op.send_trailing_metadata"); grpc_chttp2_initiate_write(
exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA);
} }
} }
} }
@ -1632,15 +1726,17 @@ static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void send_ping_locked(
grpc_chttp2_ping_type ping_type, grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure *on_initiate, grpc_closure *on_ack) { grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate,
grpc_closure *on_ack,
grpc_chttp2_initiate_write_reason initiate_write_reason) {
grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type]; grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate, grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack, if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
GRPC_ERROR_NONE)) { GRPC_ERROR_NONE)) {
grpc_chttp2_initiate_write(exec_ctx, t, "send_ping"); grpc_chttp2_initiate_write(exec_ctx, t, initiate_write_reason);
} }
} }
@ -1648,7 +1744,10 @@ static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error) { grpc_error *error) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp; grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
t->ping_state.is_delayed_ping_timer_set = false; t->ping_state.is_delayed_ping_timer_set = false;
grpc_chttp2_initiate_write(exec_ctx, t, "retry_send_ping"); if (error == GRPC_ERROR_NONE) {
grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING);
}
} }
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@ -1663,7 +1762,8 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
} }
GRPC_CLOSURE_LIST_SCHED(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]); GRPC_CLOSURE_LIST_SCHED(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) { if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
grpc_chttp2_initiate_write(exec_ctx, t, "continue_pings"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS);
} }
} }
@ -1676,7 +1776,8 @@ static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
&slice, &http_error); &slice, &http_error);
grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error, grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
grpc_slice_ref_internal(slice), &t->qbuf); grpc_slice_ref_internal(slice), &t->qbuf);
grpc_chttp2_initiate_write(exec_ctx, t, "goaway_sent"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
@ -1723,7 +1824,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
if (op->send_ping) { if (op->send_ping) {
send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL, send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL,
op->send_ping); op->send_ping,
GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING);
} }
if (op->on_connectivity_state_change != NULL) { if (op->on_connectivity_state_change != NULL) {
@ -1799,20 +1901,20 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
&s->frame_storage); &s->frame_storage);
s->unprocessed_incoming_frames_decompressed = false; s->unprocessed_incoming_frames_decompressed = false;
} }
if (s->stream_compression_recv_enabled && if (!s->unprocessed_incoming_frames_decompressed) {
!s->unprocessed_incoming_frames_decompressed) { GPR_ASSERT(s->decompressed_data_buffer.length == 0);
GPR_ASSERT(s->decompressed_data_buffer->length == 0);
bool end_of_context; bool end_of_context;
if (!s->stream_decompression_ctx) { if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx = s->stream_decompression_ctx =
grpc_stream_compression_context_create( grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS); s->stream_decompression_method);
} }
if (!grpc_stream_decompress(s->stream_decompression_ctx, if (!grpc_stream_decompress(
&s->unprocessed_incoming_frames_buffer, s->stream_decompression_ctx,
s->decompressed_data_buffer, NULL, &s->unprocessed_incoming_frames_buffer,
GRPC_HEADER_SIZE_IN_BYTES, &s->decompressed_data_buffer, NULL,
&end_of_context)) { GRPC_HEADER_SIZE_IN_BYTES - s->decompressed_header_bytes,
&end_of_context)) {
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
&s->frame_storage); &s->frame_storage);
grpc_slice_buffer_reset_and_unref_internal( grpc_slice_buffer_reset_and_unref_internal(
@ -1820,9 +1922,13 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Stream decompression error."); "Stream decompression error.");
} else { } else {
s->decompressed_header_bytes += s->decompressed_data_buffer.length;
if (s->decompressed_header_bytes == GRPC_HEADER_SIZE_IN_BYTES) {
s->decompressed_header_bytes = 0;
}
error = grpc_deframe_unprocessed_incoming_frames( error = grpc_deframe_unprocessed_incoming_frames(
exec_ctx, &s->data_parser, s, s->decompressed_data_buffer, NULL, exec_ctx, &s->data_parser, s, &s->decompressed_data_buffer,
s->recv_message); NULL, s->recv_message);
if (end_of_context) { if (end_of_context) {
grpc_stream_compression_context_destroy( grpc_stream_compression_context_destroy(
s->stream_decompression_ctx); s->stream_decompression_ctx);
@ -1871,15 +1977,14 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
} }
bool pending_data = s->pending_byte_stream || bool pending_data = s->pending_byte_stream ||
s->unprocessed_incoming_frames_buffer.length > 0; s->unprocessed_incoming_frames_buffer.length > 0;
if (s->stream_compression_recv_enabled && s->read_closed && if (s->read_closed && s->frame_storage.length > 0 && !pending_data &&
s->frame_storage.length > 0 && !pending_data && !s->seen_error && !s->seen_error && s->recv_trailing_metadata_finished != NULL) {
s->recv_trailing_metadata_finished != NULL) {
/* Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and /* Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and
* maybe decompress the next 5 bytes in the stream. */ * maybe decompress the next 5 bytes in the stream. */
bool end_of_context; bool end_of_context;
if (!s->stream_decompression_ctx) { if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx = grpc_stream_compression_context_create( s->stream_decompression_ctx = grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS); s->stream_decompression_method);
} }
if (!grpc_stream_decompress(s->stream_decompression_ctx, if (!grpc_stream_decompress(s->stream_decompression_ctx,
&s->frame_storage, &s->frame_storage,
@ -1892,6 +1997,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
} else { } else {
if (s->unprocessed_incoming_frames_buffer.length > 0) { if (s->unprocessed_incoming_frames_buffer.length > 0) {
s->unprocessed_incoming_frames_decompressed = true; s->unprocessed_incoming_frames_decompressed = true;
pending_data = true;
} }
if (end_of_context) { if (end_of_context) {
grpc_stream_compression_context_destroy(s->stream_decompression_ctx); grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
@ -1968,7 +2074,8 @@ void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error, &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
&s->stats.outgoing)); &s->stats.outgoing));
grpc_chttp2_initiate_write(exec_ctx, t, "rst_stream"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
} }
} }
if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) { if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
@ -2289,7 +2396,8 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
&s->stats.outgoing)); &s->stats.outgoing));
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
grpc_chttp2_initiate_write(exec_ctx, t, "close_from_api"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API);
} }
typedef struct { typedef struct {
@ -2324,19 +2432,20 @@ void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED: case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
break; break;
case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY: case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
grpc_chttp2_become_writable(exec_ctx, t, s, true, grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
"immediate stream flowctl"); grpc_chttp2_initiate_write(
exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL);
break; break;
case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE: case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
grpc_chttp2_become_writable(exec_ctx, t, s, false, grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
"queue stream flowctl");
break; break;
} }
switch (action.send_transport_update) { switch (action.send_transport_update) {
case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED: case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
break; break;
case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY: case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
grpc_chttp2_initiate_write(exec_ctx, t, "immediate transport flowctl"); grpc_chttp2_initiate_write(
exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL);
break; break;
// this is the same as no action b/c every time the transport enters the // this is the same as no action b/c every time the transport enters the
// writing path it will maybe do an update // writing path it will maybe do an update
@ -2354,7 +2463,8 @@ void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
(uint32_t)action.max_frame_size); (uint32_t)action.max_frame_size);
} }
if (action.send_setting_update == GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY) { if (action.send_setting_update == GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY) {
grpc_chttp2_initiate_write(exec_ctx, t, "immediate setting update"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS);
} }
} }
if (action.need_ping) { if (action.need_ping) {
@ -2362,7 +2472,8 @@ void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
grpc_bdp_estimator_schedule_ping(&t->flow_control.bdp_estimator); grpc_bdp_estimator_schedule_ping(&t->flow_control.bdp_estimator);
send_ping_locked(exec_ctx, t, send_ping_locked(exec_ctx, t,
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE, GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
&t->start_bdp_ping_locked, &t->finish_bdp_ping_locked); &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked,
GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING);
} }
} }
@ -2441,7 +2552,10 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
if (t->flow_control.initial_window_update > 0) { if (t->flow_control.initial_window_update > 0) {
grpc_chttp2_stream *s; grpc_chttp2_stream *s;
while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) { while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
grpc_chttp2_become_writable(exec_ctx, t, s, true, "unstalled"); grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
grpc_chttp2_initiate_write(
exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING);
} }
} }
t->flow_control.initial_window_update = 0; t->flow_control.initial_window_update = 0;
@ -2538,6 +2652,36 @@ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args,
&args->args[i], &args->args[i],
(grpc_integer_options){g_default_keepalive_permit_without_calls, (grpc_integer_options){g_default_keepalive_permit_without_calls,
0, 1}); 0, 1});
} else if (0 ==
strcmp(args->args[i].key, GRPC_ARG_HTTP2_MAX_PING_STRIKES)) {
g_default_max_ping_strikes = grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){g_default_max_ping_strikes, 0, INT_MAX});
} else if (0 == strcmp(args->args[i].key,
GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
g_default_max_pings_without_data = grpc_channel_arg_get_integer(
&args->args[i], (grpc_integer_options){
g_default_max_pings_without_data, 0, INT_MAX});
} else if (0 ==
strcmp(
args->args[i].key,
GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) {
g_default_min_sent_ping_interval_without_data_ms =
grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){
g_default_min_sent_ping_interval_without_data_ms, 0,
INT_MAX});
} else if (0 ==
strcmp(
args->args[i].key,
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) {
g_default_min_recv_ping_interval_without_data_ms =
grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){
g_default_min_recv_ping_interval_without_data_ms, 0,
INT_MAX});
} }
} }
} }
@ -2556,7 +2700,8 @@ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end"); GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE,
&t->start_keepalive_ping_locked, &t->start_keepalive_ping_locked,
&t->finish_keepalive_ping_locked); &t->finish_keepalive_ping_locked,
GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING);
} else { } else {
GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
grpc_timer_init( grpc_timer_init(
@ -2671,7 +2816,7 @@ static void reset_byte_stream(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_UNREF(s->byte_stream_error); GRPC_ERROR_UNREF(s->byte_stream_error);
s->byte_stream_error = GRPC_ERROR_NONE; s->byte_stream_error = GRPC_ERROR_NONE;
grpc_chttp2_cancel_stream(exec_ctx, s->t, s, GRPC_ERROR_REF(error)); grpc_chttp2_cancel_stream(exec_ctx, s->t, s, GRPC_ERROR_REF(error));
s->byte_stream_error = error; s->byte_stream_error = GRPC_ERROR_REF(error);
} }
} }
@ -2769,24 +2914,23 @@ static grpc_error *incoming_byte_stream_pull(grpc_exec_ctx *exec_ctx,
grpc_error *error; grpc_error *error;
if (s->unprocessed_incoming_frames_buffer.length > 0) { if (s->unprocessed_incoming_frames_buffer.length > 0) {
if (s->stream_compression_recv_enabled && if (!s->unprocessed_incoming_frames_decompressed) {
!s->unprocessed_incoming_frames_decompressed) {
bool end_of_context; bool end_of_context;
if (!s->stream_decompression_ctx) { if (!s->stream_decompression_ctx) {
s->stream_decompression_ctx = grpc_stream_compression_context_create( s->stream_decompression_ctx = grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_DECOMPRESS); s->stream_decompression_method);
} }
if (!grpc_stream_decompress(s->stream_decompression_ctx, if (!grpc_stream_decompress(s->stream_decompression_ctx,
&s->unprocessed_incoming_frames_buffer, &s->unprocessed_incoming_frames_buffer,
s->decompressed_data_buffer, NULL, MAX_SIZE_T, &s->decompressed_data_buffer, NULL,
&end_of_context)) { MAX_SIZE_T, &end_of_context)) {
error = error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error."); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error.");
return error; return error;
} }
GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0); GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer, grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
s->decompressed_data_buffer); &s->decompressed_data_buffer);
s->unprocessed_incoming_frames_decompressed = true; s->unprocessed_incoming_frames_decompressed = true;
if (end_of_context) { if (end_of_context) {
grpc_stream_compression_context_destroy(s->stream_decompression_ctx); grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
@ -2912,7 +3056,8 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
uint32_t frame_size, uint32_t flags) { uint32_t frame_size, uint32_t flags) {
grpc_chttp2_incoming_byte_stream *incoming_byte_stream = grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
gpr_malloc(sizeof(*incoming_byte_stream)); (grpc_chttp2_incoming_byte_stream *)gpr_malloc(
sizeof(*incoming_byte_stream));
incoming_byte_stream->base.length = frame_size; incoming_byte_stream->base.length = frame_size;
incoming_byte_stream->remaining_bytes = frame_size; incoming_byte_stream->remaining_bytes = frame_size;
incoming_byte_stream->base.flags = flags; incoming_byte_stream->base.flags = flags;
@ -3016,6 +3161,56 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
/******************************************************************************* /*******************************************************************************
* MONITORING * MONITORING
*/ */
const char *grpc_chttp2_initiate_write_reason_string(
grpc_chttp2_initiate_write_reason reason) {
switch (reason) {
case GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE:
return "INITIAL_WRITE";
case GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM:
return "START_NEW_STREAM";
case GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE:
return "SEND_MESSAGE";
case GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA:
return "SEND_INITIAL_METADATA";
case GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA:
return "SEND_TRAILING_METADATA";
case GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING:
return "RETRY_SEND_PING";
case GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS:
return "CONTINUE_PINGS";
case GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT:
return "GOAWAY_SENT";
case GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM:
return "RST_STREAM";
case GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API:
return "CLOSE_FROM_API";
case GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL:
return "STREAM_FLOW_CONTROL";
case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL:
return "TRANSPORT_FLOW_CONTROL";
case GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS:
return "SEND_SETTINGS";
case GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING:
return "BDP_ESTIMATOR_PING";
case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING:
return "FLOW_CONTROL_UNSTALLED_BY_SETTING";
case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE:
return "FLOW_CONTROL_UNSTALLED_BY_UPDATE";
case GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING:
return "APPLICATION_PING";
case GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING:
return "KEEPALIVE_PING";
case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED:
return "TRANSPORT_FLOW_CONTROL_UNSTALLED";
case GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE:
return "PING_RESPONSE";
case GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM:
return "FORCE_RST_STREAM";
}
GPR_UNREACHABLE_CODE(return "unknown");
}
static grpc_endpoint *chttp2_get_endpoint(grpc_exec_ctx *exec_ctx, static grpc_endpoint *chttp2_get_endpoint(grpc_exec_ctx *exec_ctx,
grpc_transport *t) { grpc_transport *t) {
return ((grpc_chttp2_transport *)t)->ep; return ((grpc_chttp2_transport *)t)->ep;

@ -25,6 +25,7 @@
extern grpc_tracer_flag grpc_http_trace; extern grpc_tracer_flag grpc_http_trace;
extern grpc_tracer_flag grpc_flowctl_trace; extern grpc_tracer_flag grpc_flowctl_trace;
extern grpc_tracer_flag grpc_trace_http2_stream_state;
#ifndef NDEBUG #ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_chttp2_refcount; extern grpc_tracer_flag grpc_trace_chttp2_refcount;

@ -18,6 +18,7 @@
#include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/internal.h"
#include <limits.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
@ -59,24 +60,24 @@ static void pretrace(shadow_flow_control* shadow_fc,
#define TRACE_PADDING 30 #define TRACE_PADDING 30
static char* fmt_int64_diff_str(int64_t old, int64_t new) { static char* fmt_int64_diff_str(int64_t old_val, int64_t new_val) {
char* str; char* str;
if (old != new) { if (old_val != new_val) {
gpr_asprintf(&str, "%" PRId64 " -> %" PRId64 "", old, new); gpr_asprintf(&str, "%" PRId64 " -> %" PRId64 "", old_val, new_val);
} else { } else {
gpr_asprintf(&str, "%" PRId64 "", old); gpr_asprintf(&str, "%" PRId64 "", old_val);
} }
char* str_lp = gpr_leftpad(str, ' ', TRACE_PADDING); char* str_lp = gpr_leftpad(str, ' ', TRACE_PADDING);
gpr_free(str); gpr_free(str);
return str_lp; return str_lp;
} }
static char* fmt_uint32_diff_str(uint32_t old, uint32_t new) { static char* fmt_uint32_diff_str(uint32_t old_val, uint32_t new_val) {
char* str; char* str;
if (new > 0 && old != new) { if (new_val > 0 && old_val != new_val) {
gpr_asprintf(&str, "%" PRIu32 " -> %" PRIu32 "", old, new); gpr_asprintf(&str, "%" PRIu32 " -> %" PRIu32 "", old_val, new_val);
} else { } else {
gpr_asprintf(&str, "%" PRIu32 "", old); gpr_asprintf(&str, "%" PRIu32 "", old_val);
} }
char* str_lp = gpr_leftpad(str, ' ', TRACE_PADDING); char* str_lp = gpr_leftpad(str, ' ', TRACE_PADDING);
gpr_free(str); gpr_free(str);
@ -483,7 +484,8 @@ grpc_chttp2_flowctl_action grpc_chttp2_flowctl_get_bdp_action(
if (grpc_bdp_estimator_get_bw(&tfc->bdp_estimator, &bw_dbl)) { if (grpc_bdp_estimator_get_bw(&tfc->bdp_estimator, &bw_dbl)) {
// we target the max of BDP or bandwidth in microseconds. // we target the max of BDP or bandwidth in microseconds.
int32_t frame_size = (int32_t)GPR_CLAMP( int32_t frame_size = (int32_t)GPR_CLAMP(
GPR_MAX((int32_t)bw_dbl / 1000, bdp), 16384, 16777215); GPR_MAX((int32_t)GPR_CLAMP(bw_dbl, 0, INT_MAX) / 1000, bdp), 16384,
16777215);
grpc_chttp2_flowctl_urgency frame_size_urgency = delta_is_significant( grpc_chttp2_flowctl_urgency frame_size_urgency = delta_is_significant(
tfc, frame_size, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE); tfc, frame_size, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE);
if (frame_size_urgency != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) { if (frame_size_urgency != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) {

@ -210,7 +210,7 @@ grpc_error *grpc_deframe_unprocessed_incoming_frames(
if (cur != end) { if (cur != end) {
grpc_slice_buffer_undo_take_first( grpc_slice_buffer_undo_take_first(
&s->unprocessed_incoming_frames_buffer, slices,
grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
} }
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(exec_ctx, slice);
@ -277,7 +277,7 @@ grpc_error *grpc_deframe_unprocessed_incoming_frames(
p->state = GRPC_CHTTP2_DATA_FH_0; p->state = GRPC_CHTTP2_DATA_FH_0;
cur += p->frame_size; cur += p->frame_size;
grpc_slice_buffer_undo_take_first( grpc_slice_buffer_undo_take_first(
&s->unprocessed_incoming_frames_buffer, slices,
grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
grpc_slice_unref_internal(exec_ctx, slice); grpc_slice_unref_internal(exec_ctx, slice);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -92,7 +92,7 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_allowed_ping = gpr_timespec next_allowed_ping =
gpr_time_add(t->ping_recv_state.last_ping_recv_time, gpr_time_add(t->ping_recv_state.last_ping_recv_time,
t->ping_policy.min_ping_interval_without_data); t->ping_policy.min_recv_ping_interval_without_data);
if (t->keepalive_permit_without_calls == 0 && if (t->keepalive_permit_without_calls == 0 &&
grpc_chttp2_stream_map_size(&t->stream_map) == 0) { grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
@ -117,7 +117,8 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks)); t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks));
} }
t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes; t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
grpc_chttp2_initiate_write(exec_ctx, t, "ping response"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE);
} }
} }
} }

@ -44,7 +44,8 @@ static uint8_t *fill_header(uint8_t *out, uint32_t length, uint8_t flags) {
return out; return out;
} }
grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new, grpc_slice grpc_chttp2_settings_create(uint32_t *old_settings,
const uint32_t *new_settings,
uint32_t force_mask, size_t count) { uint32_t force_mask, size_t count) {
size_t i; size_t i;
uint32_t n = 0; uint32_t n = 0;
@ -52,21 +53,21 @@ grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
uint8_t *p; uint8_t *p;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
n += (new[i] != old[i] || (force_mask & (1u << i)) != 0); n += (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0);
} }
output = GRPC_SLICE_MALLOC(9 + 6 * n); output = GRPC_SLICE_MALLOC(9 + 6 * n);
p = fill_header(GRPC_SLICE_START_PTR(output), 6 * n, 0); p = fill_header(GRPC_SLICE_START_PTR(output), 6 * n, 0);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (new[i] != old[i] || (force_mask & (1u << i)) != 0) { if (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0) {
*p++ = (uint8_t)(grpc_setting_id_to_wire_id[i] >> 8); *p++ = (uint8_t)(grpc_setting_id_to_wire_id[i] >> 8);
*p++ = (uint8_t)(grpc_setting_id_to_wire_id[i]); *p++ = (uint8_t)(grpc_setting_id_to_wire_id[i]);
*p++ = (uint8_t)(new[i] >> 24); *p++ = (uint8_t)(new_settings[i] >> 24);
*p++ = (uint8_t)(new[i] >> 16); *p++ = (uint8_t)(new_settings[i] >> 16);
*p++ = (uint8_t)(new[i] >> 8); *p++ = (uint8_t)(new_settings[i] >> 8);
*p++ = (uint8_t)(new[i]); *p++ = (uint8_t)(new_settings[i]);
old[i] = new[i]; old_settings[i] = new_settings[i];
} }
} }

@ -99,8 +99,10 @@ grpc_error *grpc_chttp2_window_update_parser_parse(
grpc_chttp2_flowctl_recv_stream_update( grpc_chttp2_flowctl_recv_stream_update(
&t->flow_control, &s->flow_control, received_update); &t->flow_control, &s->flow_control, received_update);
if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) { if (grpc_chttp2_list_remove_stalled_by_stream(t, s)) {
grpc_chttp2_become_writable(exec_ctx, t, s, true, grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
"stream.read_flow_control"); grpc_chttp2_initiate_write(
exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE);
} }
} }
} else { } else {
@ -109,7 +111,9 @@ grpc_error *grpc_chttp2_window_update_parser_parse(
received_update); received_update);
bool is_zero = t->flow_control.remote_window <= 0; bool is_zero = t->flow_control.remote_window <= 0;
if (was_zero && !is_zero) { if (was_zero && !is_zero) {
grpc_chttp2_initiate_write(exec_ctx, t, "new_global_flow_control"); grpc_chttp2_initiate_write(
exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED);
} }
} }
} }

@ -33,6 +33,7 @@
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/ext/transport/chttp2/transport/hpack_table.h" #include "src/core/ext/transport/chttp2/transport/hpack_table.h"
#include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
@ -51,8 +52,10 @@
#define MAX_DECODER_SPACE_USAGE 512 #define MAX_DECODER_SPACE_USAGE 512
static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL}; static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL};
static const grpc_slice terminal_slice = {&terminal_slice_refcount, static const grpc_slice terminal_slice = {
.data.refcounted = {0, 0}}; &terminal_slice_refcount, /* refcount */
{{0, 0}} /* data.refcounted */
};
extern grpc_tracer_flag grpc_http_trace; extern grpc_tracer_flag grpc_http_trace;
@ -269,8 +272,10 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
} }
} }
static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index, static void emit_indexed(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
framer_state *st) { framer_state *st) {
GRPC_STATS_INC_HPACK_SEND_INDEXED(exec_ctx);
uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1); uint32_t len = GRPC_CHTTP2_VARINT_LENGTH(elem_index, 1);
GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len), GRPC_CHTTP2_WRITE_VARINT(elem_index, 1, 0x80, add_tiny_header_data(st, len),
len); len);
@ -282,30 +287,31 @@ typedef struct {
bool insert_null_before_wire_value; bool insert_null_before_wire_value;
} wire_value; } wire_value;
static wire_value get_wire_value(grpc_mdelem elem, bool true_binary_enabled) { static wire_value get_wire_value(grpc_exec_ctx *exec_ctx, grpc_mdelem elem,
bool true_binary_enabled) {
wire_value wire_val;
if (grpc_is_binary_header(GRPC_MDKEY(elem))) { if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
if (true_binary_enabled) { if (true_binary_enabled) {
return (wire_value){ GRPC_STATS_INC_HPACK_SEND_BINARY(exec_ctx);
.huffman_prefix = 0x00, wire_val.huffman_prefix = 0x00;
.insert_null_before_wire_value = true, wire_val.insert_null_before_wire_value = true;
.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)), wire_val.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem));
};
} else { } else {
return (wire_value){ GRPC_STATS_INC_HPACK_SEND_BINARY_BASE64(exec_ctx);
.huffman_prefix = 0x80, wire_val.huffman_prefix = 0x80;
.insert_null_before_wire_value = false, wire_val.insert_null_before_wire_value = false;
.data = grpc_chttp2_base64_encode_and_huffman_compress( wire_val.data =
GRPC_MDVALUE(elem)), grpc_chttp2_base64_encode_and_huffman_compress(GRPC_MDVALUE(elem));
};
} }
} else { } else {
/* TODO(ctiller): opportunistically compress non-binary headers */ /* TODO(ctiller): opportunistically compress non-binary headers */
return (wire_value){ GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(exec_ctx);
.huffman_prefix = 0x00, wire_val.huffman_prefix = 0x00;
.insert_null_before_wire_value = false, wire_val.insert_null_before_wire_value = false;
.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem)), wire_val.data = grpc_slice_ref_internal(GRPC_MDVALUE(elem));
};
} }
return wire_val;
} }
static size_t wire_value_length(wire_value v) { static size_t wire_value_length(wire_value v) {
@ -317,11 +323,14 @@ static void add_wire_value(framer_state *st, wire_value v) {
add_header_data(st, v.data); add_header_data(st, v.data);
} }
static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_incidx(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
uint32_t key_index, grpc_mdelem elem, uint32_t key_index, grpc_mdelem elem,
framer_state *st) { framer_state *st) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX(exec_ctx);
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2); uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 2);
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); wire_value value =
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata);
size_t len_val = wire_value_length(value); size_t len_val = wire_value_length(value);
uint32_t len_val_len; uint32_t len_val_len;
GPR_ASSERT(len_val <= UINT32_MAX); GPR_ASSERT(len_val <= UINT32_MAX);
@ -333,11 +342,14 @@ static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value); add_wire_value(st, value);
} }
static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_noidx(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
uint32_t key_index, grpc_mdelem elem, uint32_t key_index, grpc_mdelem elem,
framer_state *st) { framer_state *st) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX(exec_ctx);
uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4); uint32_t len_pfx = GRPC_CHTTP2_VARINT_LENGTH(key_index, 4);
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); wire_value value =
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata);
size_t len_val = wire_value_length(value); size_t len_val = wire_value_length(value);
uint32_t len_val_len; uint32_t len_val_len;
GPR_ASSERT(len_val <= UINT32_MAX); GPR_ASSERT(len_val <= UINT32_MAX);
@ -349,10 +361,14 @@ static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value); add_wire_value(st, value);
} }
static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_incidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) { grpc_mdelem elem, framer_state *st) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V(exec_ctx);
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(exec_ctx);
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); wire_value value =
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata);
uint32_t len_val = (uint32_t)wire_value_length(value); uint32_t len_val = (uint32_t)wire_value_length(value);
uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
@ -367,10 +383,14 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
add_wire_value(st, value); add_wire_value(st, value);
} }
static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c, static void emit_lithdr_noidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) { grpc_mdelem elem, framer_state *st) {
GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(exec_ctx);
GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(exec_ctx);
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
wire_value value = get_wire_value(elem, st->use_true_binary_metadata); wire_value value =
get_wire_value(exec_ctx, elem, st->use_true_binary_metadata);
uint32_t len_val = (uint32_t)wire_value_length(value); uint32_t len_val = (uint32_t)wire_value_length(value);
uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1); uint32_t len_key_len = GRPC_CHTTP2_VARINT_LENGTH(len_key, 1);
uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1); uint32_t len_val_len = GRPC_CHTTP2_VARINT_LENGTH(len_val, 1);
@ -423,7 +443,7 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
gpr_free(v); gpr_free(v);
} }
if (!GRPC_MDELEM_IS_INTERNED(elem)) { if (!GRPC_MDELEM_IS_INTERNED(elem)) {
emit_lithdr_noidx_v(c, elem, st); emit_lithdr_noidx_v(exec_ctx, c, elem, st);
return; return;
} }
@ -445,16 +465,16 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) && if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) { c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
/* HIT: complete element (first cuckoo hash) */ /* HIT: complete element (first cuckoo hash) */
emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), emit_indexed(exec_ctx, c,
st); dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]), st);
return; return;
} }
if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) && if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) { c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
/* HIT: complete element (second cuckoo hash) */ /* HIT: complete element (second cuckoo hash) */
emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), emit_indexed(exec_ctx, c,
st); dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]), st);
return; return;
} }
@ -472,11 +492,11 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
indices_key > c->tail_remote_index) { indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */ /* HIT: key (first cuckoo hash) */
if (should_add_elem) { if (should_add_elem) {
emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); emit_lithdr_incidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
add_elem(exec_ctx, c, elem); add_elem(exec_ctx, c, elem);
return; return;
} else { } else {
emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); emit_lithdr_noidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
return; return;
} }
GPR_UNREACHABLE_CODE(return ); GPR_UNREACHABLE_CODE(return );
@ -488,11 +508,11 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
indices_key > c->tail_remote_index) { indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */ /* HIT: key (first cuckoo hash) */
if (should_add_elem) { if (should_add_elem) {
emit_lithdr_incidx(c, dynidx(c, indices_key), elem, st); emit_lithdr_incidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
add_elem(exec_ctx, c, elem); add_elem(exec_ctx, c, elem);
return; return;
} else { } else {
emit_lithdr_noidx(c, dynidx(c, indices_key), elem, st); emit_lithdr_noidx(exec_ctx, c, dynidx(c, indices_key), elem, st);
return; return;
} }
GPR_UNREACHABLE_CODE(return ); GPR_UNREACHABLE_CODE(return );
@ -501,11 +521,11 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* no elem, key in the table... fall back to literal emission */ /* no elem, key in the table... fall back to literal emission */
if (should_add_elem) { if (should_add_elem) {
emit_lithdr_incidx_v(c, elem, st); emit_lithdr_incidx_v(exec_ctx, c, elem, st);
add_elem(exec_ctx, c, elem); add_elem(exec_ctx, c, elem);
return; return;
} else { } else {
emit_lithdr_noidx_v(c, elem, st); emit_lithdr_noidx_v(exec_ctx, c, elem, st);
return; return;
} }
GPR_UNREACHABLE_CODE(return ); GPR_UNREACHABLE_CODE(return );

@ -30,6 +30,7 @@
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
@ -777,8 +778,7 @@ static grpc_error *parse_stream_dep0(grpc_exec_ctx *exec_ctx,
return parse_stream_dep1(exec_ctx, p, cur + 1, end); return parse_stream_dep1(exec_ctx, p, cur + 1, end);
} }
/* emit an indexed field; for now just logs it to console; jumps to /* emit an indexed field; jumps to begin the next field on completion */
begin the next field on completion */
static grpc_error *finish_indexed_field(grpc_exec_ctx *exec_ctx, static grpc_error *finish_indexed_field(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
@ -792,6 +792,7 @@ static grpc_error *finish_indexed_field(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents); GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
} }
GRPC_MDELEM_REF(md); GRPC_MDELEM_REF(md);
GRPC_STATS_INC_HPACK_RECV_INDEXED(exec_ctx);
grpc_error *err = on_hdr(exec_ctx, p, md, 0); grpc_error *err = on_hdr(exec_ctx, p, md, 0);
if (err != GRPC_ERROR_NONE) return err; if (err != GRPC_ERROR_NONE) return err;
return parse_begin(exec_ctx, p, cur, end); return parse_begin(exec_ctx, p, cur, end);
@ -820,14 +821,14 @@ static grpc_error *parse_indexed_field_x(grpc_exec_ctx *exec_ctx,
return parse_value0(exec_ctx, p, cur + 1, end); return parse_value0(exec_ctx, p, cur + 1, end);
} }
/* finish a literal header with incremental indexing: just log, and jump to ' /* finish a literal header with incremental indexing */
begin */
static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx, static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */ GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX(exec_ctx);
grpc_error *err = on_hdr( grpc_error *err = on_hdr(
exec_ctx, p, exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
@ -842,6 +843,7 @@ static grpc_error *finish_lithdr_incidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX_V(exec_ctx);
grpc_error *err = on_hdr( grpc_error *err = on_hdr(
exec_ctx, p, exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true), grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
@ -898,6 +900,7 @@ static grpc_error *finish_lithdr_notidx(grpc_exec_ctx *exec_ctx,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */ GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX(exec_ctx);
grpc_error *err = on_hdr( grpc_error *err = on_hdr(
exec_ctx, p, exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
@ -912,6 +915,7 @@ static grpc_error *finish_lithdr_notidx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX_V(exec_ctx);
grpc_error *err = on_hdr( grpc_error *err = on_hdr(
exec_ctx, p, exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true), grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
@ -968,6 +972,7 @@ static grpc_error *finish_lithdr_nvridx(grpc_exec_ctx *exec_ctx,
const uint8_t *end) { const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */ GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX(exec_ctx);
grpc_error *err = on_hdr( grpc_error *err = on_hdr(
exec_ctx, p, exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)), grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
@ -982,6 +987,7 @@ static grpc_error *finish_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p, grpc_chttp2_hpack_parser *p,
const uint8_t *cur, const uint8_t *cur,
const uint8_t *end) { const uint8_t *end) {
GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX_V(exec_ctx);
grpc_error *err = on_hdr( grpc_error *err = on_hdr(
exec_ctx, p, exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true), grpc_mdelem_from_slices(exec_ctx, take_string(exec_ctx, p, &p->key, true),
@ -1310,9 +1316,11 @@ static grpc_error *append_string(grpc_exec_ctx *exec_ctx,
/* 'true-binary' case */ /* 'true-binary' case */
++cur; ++cur;
p->binary = NOT_BINARY; p->binary = NOT_BINARY;
GRPC_STATS_INC_HPACK_RECV_BINARY(exec_ctx);
append_bytes(str, cur, (size_t)(end - cur)); append_bytes(str, cur, (size_t)(end - cur));
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
GRPC_STATS_INC_HPACK_RECV_BINARY_BASE64(exec_ctx);
/* fallthrough */ /* fallthrough */
b64_byte0: b64_byte0:
case B64_BYTE0: case B64_BYTE0:
@ -1510,6 +1518,7 @@ static grpc_error *begin_parse_string(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser_string *str) { grpc_chttp2_hpack_parser_string *str) {
if (!p->huff && binary == NOT_BINARY && (end - cur) >= (intptr_t)p->strlen && if (!p->huff && binary == NOT_BINARY && (end - cur) >= (intptr_t)p->strlen &&
p->current_slice_refcount != NULL) { p->current_slice_refcount != NULL) {
GRPC_STATS_INC_HPACK_RECV_UNCOMPRESSED(exec_ctx);
str->copied = false; str->copied = false;
str->data.referenced.refcount = p->current_slice_refcount; str->data.referenced.refcount = p->current_slice_refcount;
str->data.referenced.data.refcounted.bytes = (uint8_t *)cur; str->data.referenced.data.refcounted.bytes = (uint8_t *)cur;
@ -1523,6 +1532,20 @@ static grpc_error *begin_parse_string(grpc_exec_ctx *exec_ctx,
p->parsing.str = str; p->parsing.str = str;
p->huff_state = 0; p->huff_state = 0;
p->binary = binary; p->binary = binary;
switch (p->binary) {
case NOT_BINARY:
if (p->huff) {
GRPC_STATS_INC_HPACK_RECV_HUFFMAN(exec_ctx);
} else {
GRPC_STATS_INC_HPACK_RECV_UNCOMPRESSED(exec_ctx);
}
break;
case BINARY_BEGIN:
/* stats incremented later: don't know true binary or not */
break;
default:
abort();
}
return parse_string(exec_ctx, p, cur, end); return parse_string(exec_ctx, p, cur, end);
} }
@ -1649,7 +1672,8 @@ static void force_client_rst_stream(grpc_exec_ctx *exec_ctx, void *sp,
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR, &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
&s->stats.outgoing)); &s->stats.outgoing));
grpc_chttp2_initiate_write(exec_ctx, t, "force_rst_stream"); grpc_chttp2_initiate_write(exec_ctx, t,
GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM);
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, GRPC_ERROR_NONE);
} }
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "final_rst"); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "final_rst");
@ -1659,17 +1683,12 @@ static void parse_stream_compression_md(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_chttp2_stream *s,
grpc_metadata_batch *initial_metadata) { grpc_metadata_batch *initial_metadata) {
if (initial_metadata->idx.named.content_encoding != NULL) { if (initial_metadata->idx.named.content_encoding == NULL ||
grpc_slice content_encoding = grpc_stream_compression_method_parse(
GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md); GRPC_MDVALUE(initial_metadata->idx.named.content_encoding->md), false,
if (!grpc_slice_eq(content_encoding, GRPC_MDSTR_IDENTITY)) { &s->stream_decompression_method) == 0) {
if (grpc_slice_eq(content_encoding, GRPC_MDSTR_GZIP)) { s->stream_decompression_method =
s->stream_compression_recv_enabled = true; GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS;
s->decompressed_data_buffer =
(grpc_slice_buffer *)gpr_malloc(sizeof(grpc_slice_buffer));
grpc_slice_buffer_init(s->decompressed_data_buffer);
}
}
} }
} }

@ -42,8 +42,9 @@ grpc_error *grpc_chttp2_incoming_metadata_buffer_add(
grpc_mdelem elem) { grpc_mdelem elem) {
buffer->size += GRPC_MDELEM_LENGTH(elem); buffer->size += GRPC_MDELEM_LENGTH(elem);
return grpc_metadata_batch_add_tail( return grpc_metadata_batch_add_tail(
exec_ctx, &buffer->batch, exec_ctx, &buffer->batch, (grpc_linked_mdelem *)gpr_arena_alloc(
gpr_arena_alloc(buffer->arena, sizeof(grpc_linked_mdelem)), elem); buffer->arena, sizeof(grpc_linked_mdelem)),
elem);
} }
grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add(

@ -79,16 +79,43 @@ typedef enum {
GRPC_CHTTP2_PCL_COUNT /* must be last */ GRPC_CHTTP2_PCL_COUNT /* must be last */
} grpc_chttp2_ping_closure_list; } grpc_chttp2_ping_closure_list;
typedef enum {
GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE,
GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM,
GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE,
GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA,
GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA,
GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING,
GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS,
GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT,
GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM,
GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API,
GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL,
GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL,
GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS,
GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING,
GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING,
GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE,
GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING,
GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING,
GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED,
GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE,
GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM,
} grpc_chttp2_initiate_write_reason;
const char *grpc_chttp2_initiate_write_reason_string(
grpc_chttp2_initiate_write_reason reason);
typedef struct { typedef struct {
grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT]; grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT];
uint64_t inflight_id; uint64_t inflight_id;
} grpc_chttp2_ping_queue; } grpc_chttp2_ping_queue;
typedef struct { typedef struct {
gpr_timespec min_time_between_pings;
int max_pings_without_data; int max_pings_without_data;
int max_ping_strikes; int max_ping_strikes;
gpr_timespec min_ping_interval_without_data; gpr_timespec min_sent_ping_interval_without_data;
gpr_timespec min_recv_ping_interval_without_data;
} grpc_chttp2_repeated_ping_policy; } grpc_chttp2_repeated_ping_policy;
typedef struct { typedef struct {
@ -565,25 +592,27 @@ struct grpc_chttp2_stream {
grpc_chttp2_write_cb *finish_after_write; grpc_chttp2_write_cb *finish_after_write;
size_t sending_bytes; size_t sending_bytes;
/** Whether stream compression send is enabled */ /* Stream compression method to be used. */
bool stream_compression_recv_enabled; grpc_stream_compression_method stream_compression_method;
/** Whether stream compression recv is enabled */ /* Stream decompression method to be used. */
bool stream_compression_send_enabled; grpc_stream_compression_method stream_decompression_method;
/** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
*/
bool unprocessed_incoming_frames_decompressed;
/** Stream compression decompress context */ /** Stream compression decompress context */
grpc_stream_compression_context *stream_decompression_ctx; grpc_stream_compression_context *stream_decompression_ctx;
/** Stream compression compress context */ /** Stream compression compress context */
grpc_stream_compression_context *stream_compression_ctx; grpc_stream_compression_context *stream_compression_ctx;
/** Buffer storing data that is compressed but not sent */ /** Buffer storing data that is compressed but not sent */
grpc_slice_buffer *compressed_data_buffer; grpc_slice_buffer compressed_data_buffer;
/** Amount of uncompressed bytes sent out when compressed_data_buffer is /** Amount of uncompressed bytes sent out when compressed_data_buffer is
* emptied */ * emptied */
size_t uncompressed_data_size; size_t uncompressed_data_size;
/** Temporary buffer storing decompressed data */ /** Temporary buffer storing decompressed data */
grpc_slice_buffer *decompressed_data_buffer; grpc_slice_buffer decompressed_data_buffer;
/** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
*/
bool unprocessed_incoming_frames_decompressed;
/** gRPC header bytes that are already decompressed */
size_t decompressed_header_bytes;
}; };
/** Transport writing call flow: /** Transport writing call flow:
@ -599,7 +628,8 @@ struct grpc_chttp2_stream {
The actual call chain is documented in the implementation of this function. The actual call chain is documented in the implementation of this function.
*/ */
void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, const char *reason); grpc_chttp2_transport *t,
grpc_chttp2_initiate_write_reason reason);
typedef struct { typedef struct {
/** are we writing? */ /** are we writing? */
@ -851,10 +881,9 @@ void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx,
/** add a ref to the stream and add it to the writable list; /** add a ref to the stream and add it to the writable list;
ref will be dropped in writing.c */ ref will be dropped in writing.c */
void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, void grpc_chttp2_mark_stream_writable(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_chttp2_stream *s);
bool also_initiate_write, const char *reason);
void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx, void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_chttp2_transport *t, grpc_chttp2_stream *s,

@ -383,6 +383,9 @@ error_handler:
/* t->parser = grpc_chttp2_data_parser_parse;*/ /* t->parser = grpc_chttp2_data_parser_parse;*/
t->parser = grpc_chttp2_data_parser_parse; t->parser = grpc_chttp2_data_parser_parse;
t->parser_data = &s->data_parser; t->parser_data = &s->data_parser;
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
t->ping_state.last_ping_sent_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) { } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
/* handle stream errors by closing the stream */ /* handle stream errors by closing the stream */
@ -559,6 +562,10 @@ static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
(t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0; (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
} }
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
t->ping_state.last_ping_sent_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
/* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */ /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
if (s == NULL) { if (s == NULL) {

@ -20,6 +20,27 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
static char *stream_list_id_string(grpc_chttp2_stream_list_id id) {
switch (id) {
case GRPC_CHTTP2_LIST_WRITABLE:
return "writable";
case GRPC_CHTTP2_LIST_WRITING:
return "writing";
case GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT:
return "stalled_by_transport";
case GRPC_CHTTP2_LIST_STALLED_BY_STREAM:
return "stalled_by_stream";
case GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY:
return "waiting_for_concurrency";
case STREAM_LIST_COUNT:
GPR_UNREACHABLE_CODE(return "unknown");
}
GPR_UNREACHABLE_CODE(return "unknown");
}
grpc_tracer_flag grpc_trace_http2_stream_state =
GRPC_TRACER_INITIALIZER(false, "http2_stream_state");
/* core list management */ /* core list management */
static bool stream_list_empty(grpc_chttp2_transport *t, static bool stream_list_empty(grpc_chttp2_transport *t,
@ -44,6 +65,10 @@ static bool stream_list_pop(grpc_chttp2_transport *t,
s->included[id] = 0; s->included[id] = 0;
} }
*stream = s; *stream = s;
if (s && GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
gpr_log(GPR_DEBUG, "%p[%d][%s]: pop from %s", t, s->id,
t->is_client ? "cli" : "svr", stream_list_id_string(id));
}
return s != 0; return s != 0;
} }
@ -62,6 +87,10 @@ static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
} else { } else {
t->lists[id].tail = s->links[id].prev; t->lists[id].tail = s->links[id].prev;
} }
if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
gpr_log(GPR_DEBUG, "%p[%d][%s]: remove from %s", t, s->id,
t->is_client ? "cli" : "svr", stream_list_id_string(id));
}
} }
static bool stream_list_maybe_remove(grpc_chttp2_transport *t, static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
@ -90,6 +119,10 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
} }
t->lists[id].tail = s; t->lists[id].tail = s;
s->included[id] = 1; s->included[id] = 1;
if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
gpr_log(GPR_DEBUG, "%p[%d][%s]: add to %s", t, s->id,
t->is_client ? "cli" : "svr", stream_list_id_string(id));
}
} }
static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s, static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
@ -150,17 +183,12 @@ void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t,
void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t, void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) { grpc_chttp2_stream *s) {
GRPC_FLOW_CONTROL_IF_TRACING(
gpr_log(GPR_DEBUG, "stream %u stalled by transport", s->id));
stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
} }
bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t, bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) { grpc_chttp2_stream **s) {
bool ret = stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT); return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
GRPC_FLOW_CONTROL_IF_TRACING(if (ret) gpr_log(
GPR_DEBUG, "stream %u un-stalled by transport", (*s)->id));
return ret;
} }
void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t, void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
@ -170,23 +198,15 @@ void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t, void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) { grpc_chttp2_stream *s) {
GRPC_FLOW_CONTROL_IF_TRACING(
gpr_log(GPR_DEBUG, "stream %u stalled by stream", s->id));
stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM); stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
} }
bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t, bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream **s) { grpc_chttp2_stream **s) {
bool ret = stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM); return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
GRPC_FLOW_CONTROL_IF_TRACING(
if (ret) gpr_log(GPR_DEBUG, "stream %u un-stalled by stream", (*s)->id));
return ret;
} }
bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t, bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s) { grpc_chttp2_stream *s) {
bool ret = stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM); return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
GRPC_FLOW_CONTROL_IF_TRACING(
if (ret) gpr_log(GPR_DEBUG, "stream %u un-stalled by stream", s->id));
return ret;
} }

@ -72,8 +72,10 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key,
/* resize when less than 25% of the table is free, because compaction /* resize when less than 25% of the table is free, because compaction
won't help much */ won't help much */
map->capacity = capacity = 3 * capacity / 2; map->capacity = capacity = 3 * capacity / 2;
map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t)); map->keys = keys =
map->values = values = gpr_realloc(values, capacity * sizeof(void *)); (uint32_t *)gpr_realloc(keys, capacity * sizeof(uint32_t));
map->values = values =
(void **)gpr_realloc(values, capacity * sizeof(void *));
} }
} }

@ -68,7 +68,7 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
} }
if (t->ping_state.pings_before_data_required == 0 && if (t->ping_state.pings_before_data_required == 0 &&
t->ping_policy.max_pings_without_data != 0) { t->ping_policy.max_pings_without_data != 0) {
/* need to send something of substance before sending a ping again */ /* need to receive something of substance before sending a ping again */
if (GRPC_TRACER_ON(grpc_http_trace) || if (GRPC_TRACER_ON(grpc_http_trace) ||
GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d", gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d",
@ -78,11 +78,18 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
return; return;
} }
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec elapsed = gpr_time_sub(now, t->ping_state.last_ping_sent_time); gpr_timespec next_allowed_ping =
/*gpr_log(GPR_DEBUG, "elapsed:%d.%09d min:%d.%09d", (int)elapsed.tv_sec, gpr_time_add(t->ping_state.last_ping_sent_time,
elapsed.tv_nsec, (int)t->ping_policy.min_time_between_pings.tv_sec, t->ping_policy.min_sent_ping_interval_without_data);
(int)t->ping_policy.min_time_between_pings.tv_nsec);*/ if (t->keepalive_permit_without_calls == 0 &&
if (gpr_time_cmp(elapsed, t->ping_policy.min_time_between_pings) < 0) { grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
next_allowed_ping = gpr_time_add(t->ping_recv_state.last_ping_recv_time,
gpr_time_from_seconds(7200, GPR_TIMESPAN));
}
/* gpr_log(GPR_DEBUG, "next_allowed_ping:%d.%09d now:%d.%09d",
(int)next_allowed_ping.tv_sec, (int)next_allowed_ping.tv_nsec,
(int)now.tv_sec, (int)now.tv_nsec); */
if (gpr_time_cmp(next_allowed_ping, now) > 0) {
/* not enough elapsed time between successive pings */ /* not enough elapsed time between successive pings */
if (GRPC_TRACER_ON(grpc_http_trace) || if (GRPC_TRACER_ON(grpc_http_trace) ||
GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
@ -93,9 +100,7 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
if (!t->ping_state.is_delayed_ping_timer_set) { if (!t->ping_state.is_delayed_ping_timer_set) {
t->ping_state.is_delayed_ping_timer_set = true; t->ping_state.is_delayed_ping_timer_set = true;
grpc_timer_init(exec_ctx, &t->ping_state.delayed_ping_timer, grpc_timer_init(exec_ctx, &t->ping_state.delayed_ping_timer,
gpr_time_add(t->ping_state.last_ping_sent_time, next_allowed_ping, &t->retry_initiate_ping_locked,
t->ping_policy.min_time_between_pings),
&t->retry_initiate_ping_locked,
gpr_now(GPR_CLOCK_MONOTONIC)); gpr_now(GPR_CLOCK_MONOTONIC));
} }
return; return;
@ -119,6 +124,12 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_ping_create(false, pq->inflight_id)); grpc_chttp2_ping_create(false, pq->inflight_id));
GRPC_STATS_INC_HTTP2_PINGS_SENT(exec_ctx); GRPC_STATS_INC_HTTP2_PINGS_SENT(exec_ctx);
t->ping_state.last_ping_sent_time = now; t->ping_state.last_ping_sent_time = now;
if (GRPC_TRACER_ON(grpc_http_trace) ||
GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
gpr_log(GPR_DEBUG, "Ping sent [%p]: %d/%d", t->peer_string,
t->ping_state.pings_before_data_required,
t->ping_policy.max_pings_without_data);
}
t->ping_state.pings_before_data_required -= t->ping_state.pings_before_data_required -=
(t->ping_state.pings_before_data_required != 0); (t->ping_state.pings_before_data_required != 0);
} }
@ -201,9 +212,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (t->flow_control.remote_window > 0) { if (t->flow_control.remote_window > 0) {
while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) { while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) {
if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s) && if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
stream_ref_if_not_destroyed(&s->refcount->refs)) { stream_ref_if_not_destroyed(&s->refcount->refs);
grpc_chttp2_initiate_write(exec_ctx, t, "transport.read_flow_control");
} }
} }
} }
@ -258,8 +268,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
.stats = &s->stats.outgoing}; .stats = &s->stats.outgoing};
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, NULL, 0, grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, NULL, 0,
s->send_initial_metadata, &hopt, &t->outbuf); s->send_initial_metadata, &hopt, &t->outbuf);
t->ping_state.pings_before_data_required = now_writing = true;
t->ping_policy.max_pings_without_data;
if (!t->is_client) { if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time = t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC); gpr_inf_past(GPR_CLOCK_MONOTONIC);
@ -298,8 +307,6 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->outbuf, grpc_chttp2_window_update_create(s->id, stream_announce, &t->outbuf, grpc_chttp2_window_update_create(s->id, stream_announce,
&s->stats.outgoing)); &s->stats.outgoing));
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) { if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time = t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC); gpr_inf_past(GPR_CLOCK_MONOTONIC);
@ -310,8 +317,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (sent_initial_metadata) { if (sent_initial_metadata) {
/* send any body bytes, if allowed by flow control */ /* send any body bytes, if allowed by flow control */
if (s->flow_controlled_buffer.length > 0 || if (s->flow_controlled_buffer.length > 0 ||
(s->stream_compression_send_enabled && s->compressed_data_buffer.length > 0) {
s->compressed_data_buffer->length > 0)) {
uint32_t stream_remote_window = (uint32_t)GPR_MAX( uint32_t stream_remote_window = (uint32_t)GPR_MAX(
0, 0,
s->flow_control.remote_window_delta + s->flow_control.remote_window_delta +
@ -325,59 +331,60 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
bool is_last_data_frame = false; bool is_last_data_frame = false;
bool is_last_frame = false; bool is_last_frame = false;
size_t sending_bytes_before = s->sending_bytes; size_t sending_bytes_before = s->sending_bytes;
if (s->stream_compression_send_enabled) { while ((s->flow_controlled_buffer.length > 0 ||
while ((s->flow_controlled_buffer.length > 0 || s->compressed_data_buffer.length > 0) &&
s->compressed_data_buffer->length > 0) && max_outgoing > 0) {
max_outgoing > 0) { if (s->compressed_data_buffer.length > 0) {
if (s->compressed_data_buffer->length > 0) { uint32_t send_bytes = (uint32_t)GPR_MIN(
uint32_t send_bytes = (uint32_t)GPR_MIN( max_outgoing, s->compressed_data_buffer.length);
max_outgoing, s->compressed_data_buffer->length); is_last_data_frame =
is_last_data_frame = (send_bytes == s->compressed_data_buffer.length &&
(send_bytes == s->compressed_data_buffer->length && s->flow_controlled_buffer.length == 0 &&
s->flow_controlled_buffer.length == 0 && s->fetching_send_message == NULL);
s->fetching_send_message == NULL); if (is_last_data_frame && s->send_trailing_metadata != NULL &&
is_last_frame = s->stream_compression_ctx != NULL) {
is_last_data_frame && s->send_trailing_metadata != NULL && if (!grpc_stream_compress(
grpc_metadata_batch_is_empty(s->send_trailing_metadata); s->stream_compression_ctx, &s->flow_controlled_buffer,
grpc_chttp2_encode_data(s->id, s->compressed_data_buffer, &s->compressed_data_buffer, NULL, MAX_SIZE_T,
send_bytes, is_last_frame, GRPC_STREAM_COMPRESSION_FLUSH_FINISH)) {
&s->stats.outgoing, &t->outbuf); gpr_log(GPR_ERROR, "Stream compression failed.");
grpc_chttp2_flowctl_sent_data(&t->flow_control,
&s->flow_control, send_bytes);
max_outgoing -= send_bytes;
if (s->compressed_data_buffer->length == 0) {
s->sending_bytes += s->uncompressed_data_size;
}
} else {
if (s->stream_compression_ctx == NULL) {
s->stream_compression_ctx =
grpc_stream_compression_context_create(
GRPC_STREAM_COMPRESSION_COMPRESS);
} }
s->uncompressed_data_size = s->flow_controlled_buffer.length; grpc_stream_compression_context_destroy(
GPR_ASSERT(grpc_stream_compress( s->stream_compression_ctx);
s->stream_compression_ctx, &s->flow_controlled_buffer, s->stream_compression_ctx = NULL;
s->compressed_data_buffer, NULL, MAX_SIZE_T, /* After finish, bytes in s->compressed_data_buffer may be
GRPC_STREAM_COMPRESSION_FLUSH_SYNC)); * more than max_outgoing. Start another round of the current
* while loop so that send_bytes and is_last_data_frame are
* recalculated. */
continue;
}
is_last_frame =
is_last_data_frame && s->send_trailing_metadata != NULL &&
grpc_metadata_batch_is_empty(s->send_trailing_metadata);
grpc_chttp2_encode_data(s->id, &s->compressed_data_buffer,
send_bytes, is_last_frame,
&s->stats.outgoing, &t->outbuf);
grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
send_bytes);
max_outgoing -= send_bytes;
if (s->compressed_data_buffer.length == 0) {
s->sending_bytes += s->uncompressed_data_size;
}
} else {
if (s->stream_compression_ctx == NULL) {
s->stream_compression_ctx =
grpc_stream_compression_context_create(
s->stream_compression_method);
}
s->uncompressed_data_size = s->flow_controlled_buffer.length;
if (!grpc_stream_compress(
s->stream_compression_ctx, &s->flow_controlled_buffer,
&s->compressed_data_buffer, NULL, MAX_SIZE_T,
GRPC_STREAM_COMPRESSION_FLUSH_SYNC)) {
gpr_log(GPR_ERROR, "Stream compression failed.");
} }
} }
} else {
uint32_t send_bytes = (uint32_t)GPR_MIN(
max_outgoing, s->flow_controlled_buffer.length);
is_last_data_frame = s->fetching_send_message == NULL &&
send_bytes == s->flow_controlled_buffer.length;
is_last_frame =
is_last_data_frame && s->send_trailing_metadata != NULL &&
grpc_metadata_batch_is_empty(s->send_trailing_metadata);
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer,
send_bytes, is_last_frame,
&s->stats.outgoing, &t->outbuf);
grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
send_bytes);
s->sending_bytes += send_bytes;
} }
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) { if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time = t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC); gpr_inf_past(GPR_CLOCK_MONOTONIC);
@ -391,6 +398,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
s->id, GRPC_HTTP2_NO_ERROR, s->id, GRPC_HTTP2_NO_ERROR,
&s->stats.outgoing)); &s->stats.outgoing));
} }
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
GRPC_ERROR_NONE);
} }
result.early_results_scheduled |= result.early_results_scheduled |=
update_list(exec_ctx, t, s, update_list(exec_ctx, t, s,
@ -399,8 +408,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
&s->flow_controlled_bytes_flowed, GRPC_ERROR_NONE); &s->flow_controlled_bytes_flowed, GRPC_ERROR_NONE);
now_writing = true; now_writing = true;
if (s->flow_controlled_buffer.length > 0 || if (s->flow_controlled_buffer.length > 0 ||
(s->stream_compression_send_enabled && s->compressed_data_buffer.length > 0) {
s->compressed_data_buffer->length > 0)) {
GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork"); GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork");
grpc_chttp2_list_add_writable_stream(t, s); grpc_chttp2_list_add_writable_stream(t, s);
} }
@ -416,8 +424,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (s->send_trailing_metadata != NULL && if (s->send_trailing_metadata != NULL &&
s->fetching_send_message == NULL && s->fetching_send_message == NULL &&
s->flow_controlled_buffer.length == 0 && s->flow_controlled_buffer.length == 0 &&
(!s->stream_compression_send_enabled || s->compressed_data_buffer.length == 0) {
s->compressed_data_buffer->length == 0)) {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata")); GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) { if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true, grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
@ -449,6 +456,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
&t->outbuf, grpc_chttp2_rst_stream_create( &t->outbuf, grpc_chttp2_rst_stream_create(
s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing)); s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing));
} }
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
GRPC_ERROR_NONE);
now_writing = true; now_writing = true;
result.early_results_scheduled = true; result.early_results_scheduled = true;
grpc_chttp2_complete_closure_step( grpc_chttp2_complete_closure_step(
@ -484,8 +493,6 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
grpc_slice_buffer_add( grpc_slice_buffer_add(
&t->outbuf, grpc_chttp2_window_update_create(0, transport_announce, &t->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
&throwaway_stats)); &throwaway_stats));
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) { if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time = t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC); gpr_inf_past(GPR_CLOCK_MONOTONIC);
@ -519,10 +526,6 @@ void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
s->sending_bytes = 0; s->sending_bytes = 0;
} }
if (s->sent_trailing_metadata) {
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
GRPC_ERROR_REF(error));
}
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:end"); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:end");
} }
grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->outbuf); grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->outbuf);

@ -37,7 +37,6 @@
if (GRPC_TRACER_ON(grpc_inproc_trace)) gpr_log(__VA_ARGS__); \ if (GRPC_TRACER_ON(grpc_inproc_trace)) gpr_log(__VA_ARGS__); \
} while (0) } while (0)
static const grpc_transport_vtable inproc_vtable;
static grpc_slice g_empty_slice; static grpc_slice g_empty_slice;
static grpc_slice g_fake_path_key; static grpc_slice g_fake_path_key;
static grpc_slice g_fake_path_value; static grpc_slice g_fake_path_value;
@ -1166,6 +1165,55 @@ static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
unref_transport(exec_ctx, t); unref_transport(exec_ctx, t);
} }
/*******************************************************************************
* INTEGRATION GLUE
*/
static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_pollset *pollset) {
// Nothing to do here
}
static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_pollset_set *pollset_set) {
// Nothing to do here
}
static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
return NULL;
}
/*******************************************************************************
* GLOBAL INIT AND DESTROY
*/
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
void grpc_inproc_transport_init(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL,
grpc_schedule_on_exec_ctx);
g_empty_slice = grpc_slice_from_static_buffer(NULL, 0);
grpc_slice key_tmp = grpc_slice_from_static_string(":path");
g_fake_path_key = grpc_slice_intern(key_tmp);
grpc_slice_unref_internal(&exec_ctx, key_tmp);
g_fake_path_value = grpc_slice_from_static_string("/");
grpc_slice auth_tmp = grpc_slice_from_static_string(":authority");
g_fake_auth_key = grpc_slice_intern(auth_tmp);
grpc_slice_unref_internal(&exec_ctx, auth_tmp);
g_fake_auth_value = grpc_slice_from_static_string("inproc-fail");
grpc_exec_ctx_finish(&exec_ctx);
}
static const grpc_transport_vtable inproc_vtable = {
sizeof(inproc_stream), "inproc", init_stream,
set_pollset, set_pollset_set, perform_stream_op,
perform_transport_op, destroy_stream, destroy_transport,
get_endpoint};
/******************************************************************************* /*******************************************************************************
* Main inproc transport functions * Main inproc transport functions
*/ */
@ -1178,7 +1226,7 @@ static void inproc_transports_create(grpc_exec_ctx *exec_ctx,
inproc_transport *st = (inproc_transport *)gpr_zalloc(sizeof(*st)); inproc_transport *st = (inproc_transport *)gpr_zalloc(sizeof(*st));
inproc_transport *ct = (inproc_transport *)gpr_zalloc(sizeof(*ct)); inproc_transport *ct = (inproc_transport *)gpr_zalloc(sizeof(*ct));
// Share one lock between both sides since both sides get affected // Share one lock between both sides since both sides get affected
st->mu = ct->mu = gpr_malloc(sizeof(*st->mu)); st->mu = ct->mu = (shared_mu *)gpr_malloc(sizeof(*st->mu));
gpr_mu_init(&st->mu->mu); gpr_mu_init(&st->mu->mu);
gpr_ref_init(&st->mu->refs, 2); gpr_ref_init(&st->mu->refs, 2);
st->base.vtable = &inproc_vtable; st->base.vtable = &inproc_vtable;
@ -1215,8 +1263,8 @@ grpc_channel *grpc_inproc_channel_create(grpc_server *server,
grpc_arg default_authority_arg; grpc_arg default_authority_arg;
default_authority_arg.type = GRPC_ARG_STRING; default_authority_arg.type = GRPC_ARG_STRING;
default_authority_arg.key = GRPC_ARG_DEFAULT_AUTHORITY; default_authority_arg.key = (char *)GRPC_ARG_DEFAULT_AUTHORITY;
default_authority_arg.value.string = "inproc.authority"; default_authority_arg.value.string = (char *)"inproc.authority";
grpc_channel_args *client_args = grpc_channel_args *client_args =
grpc_channel_args_copy_and_add(args, &default_authority_arg, 1); grpc_channel_args_copy_and_add(args, &default_authority_arg, 1);
@ -1240,55 +1288,6 @@ grpc_channel *grpc_inproc_channel_create(grpc_server *server,
return channel; return channel;
} }
/*******************************************************************************
* INTEGRATION GLUE
*/
static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_pollset *pollset) {
// Nothing to do here
}
static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_pollset_set *pollset_set) {
// Nothing to do here
}
static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
return NULL;
}
static const grpc_transport_vtable inproc_vtable = {
sizeof(inproc_stream), "inproc", init_stream,
set_pollset, set_pollset_set, perform_stream_op,
perform_transport_op, destroy_stream, destroy_transport,
get_endpoint};
/*******************************************************************************
* GLOBAL INIT AND DESTROY
*/
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
void grpc_inproc_transport_init(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, NULL,
grpc_schedule_on_exec_ctx);
g_empty_slice = grpc_slice_from_static_buffer(NULL, 0);
grpc_slice key_tmp = grpc_slice_from_static_string(":path");
g_fake_path_key = grpc_slice_intern(key_tmp);
grpc_slice_unref_internal(&exec_ctx, key_tmp);
g_fake_path_value = grpc_slice_from_static_string("/");
grpc_slice auth_tmp = grpc_slice_from_static_string(":authority");
g_fake_auth_key = grpc_slice_intern(auth_tmp);
grpc_slice_unref_internal(&exec_ctx, auth_tmp);
g_fake_auth_value = grpc_slice_from_static_string("inproc-fail");
grpc_exec_ctx_finish(&exec_ctx);
}
void grpc_inproc_transport_shutdown(void) { void grpc_inproc_transport_shutdown(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_slice_unref_internal(&exec_ctx, g_empty_slice); grpc_slice_unref_internal(&exec_ctx, g_empty_slice);

@ -212,7 +212,7 @@ void grpc_channel_args_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_args *a) {
grpc_compression_algorithm grpc_channel_args_get_compression_algorithm( grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(
const grpc_channel_args *a) { const grpc_channel_args *a) {
size_t i; size_t i;
if (a == NULL) return 0; if (a == NULL) return GRPC_COMPRESS_NONE;
for (i = 0; i < a->num_args; ++i) { for (i = 0; i < a->num_args; ++i) {
if (a->args[i].type == GRPC_ARG_INTEGER && if (a->args[i].type == GRPC_ARG_INTEGER &&
!strcmp(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, a->args[i].key)) { !strcmp(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, a->args[i].key)) {
@ -228,7 +228,7 @@ grpc_channel_args *grpc_channel_args_set_compression_algorithm(
GPR_ASSERT(algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT); GPR_ASSERT(algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT);
grpc_arg tmp; grpc_arg tmp;
tmp.type = GRPC_ARG_INTEGER; tmp.type = GRPC_ARG_INTEGER;
tmp.key = GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM; tmp.key = (char *)GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM;
tmp.value.integer = algorithm; tmp.value.integer = algorithm;
return grpc_channel_args_copy_and_add(a, &tmp, 1); return grpc_channel_args_copy_and_add(a, &tmp, 1);
} }
@ -263,7 +263,7 @@ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
if (grpc_channel_args_get_compression_algorithm(*a) == algorithm && if (grpc_channel_args_get_compression_algorithm(*a) == algorithm &&
state == 0) { state == 0) {
char *algo_name = NULL; const char *algo_name = NULL;
GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algo_name) != 0); GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algo_name) != 0);
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"Tried to disable default compression algorithm '%s'. The " "Tried to disable default compression algorithm '%s'. The "
@ -279,7 +279,7 @@ grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
/* create a new arg */ /* create a new arg */
grpc_arg tmp; grpc_arg tmp;
tmp.type = GRPC_ARG_INTEGER; tmp.type = GRPC_ARG_INTEGER;
tmp.key = GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET; tmp.key = (char *)GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET;
/* all enabled by default */ /* all enabled by default */
tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
if (state != 0) { if (state != 0) {

@ -281,7 +281,7 @@ grpc_channel_stack *grpc_channel_stack_from_top_element(
/* Given the top element of a call stack, get the call stack itself */ /* Given the top element of a call stack, get the call stack itself */
grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem); grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem);
void grpc_call_log_op(char *file, int line, gpr_log_severity severity, void grpc_call_log_op(const char *file, int line, gpr_log_severity severity,
grpc_call_element *elem, grpc_call_element *elem,
grpc_transport_stream_op_batch *op); grpc_transport_stream_op_batch *op);

@ -214,13 +214,13 @@ bool grpc_channel_stack_builder_prepend_filter(
static void add_after(filter_node *before, const grpc_channel_filter *filter, static void add_after(filter_node *before, const grpc_channel_filter *filter,
grpc_post_filter_create_init_func post_init_func, grpc_post_filter_create_init_func post_init_func,
void *user_data) { void *user_data) {
filter_node *new = (filter_node *)gpr_malloc(sizeof(*new)); filter_node *new_node = (filter_node *)gpr_malloc(sizeof(*new_node));
new->next = before->next; new_node->next = before->next;
new->prev = before; new_node->prev = before;
new->next->prev = new->prev->next = new; new_node->next->prev = new_node->prev->next = new_node;
new->filter = filter; new_node->filter = filter;
new->init = post_init_func; new_node->init = post_init_func;
new->init_arg = user_data; new_node->init_arg = user_data;
} }
bool grpc_channel_stack_builder_add_filter_before( bool grpc_channel_stack_builder_add_filter_before(
@ -268,7 +268,7 @@ grpc_error *grpc_channel_stack_builder_finish(
// create an array of filters // create an array of filters
const grpc_channel_filter **filters = const grpc_channel_filter **filters =
gpr_malloc(sizeof(*filters) * num_filters); (const grpc_channel_filter **)gpr_malloc(sizeof(*filters) * num_filters);
size_t i = 0; size_t i = 0;
for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) { for (filter_node *p = builder->begin.next; p != &builder->end; p = p->next) {
filters[i++] = p->filter; filters[i++] = p->filter;

@ -59,7 +59,7 @@ int grpc_compression_algorithm_parse(grpc_slice name,
} }
int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
char **name) { const char **name) {
GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2, GRPC_API_TRACE("grpc_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
((int)algorithm, name)); ((int)algorithm, name));
switch (algorithm) { switch (algorithm) {

@ -183,7 +183,7 @@ int grpc_compression_algorithm_from_message_stream_compression_algorithm(
/* Interfaces for message compression. */ /* Interfaces for message compression. */
int grpc_message_compression_algorithm_name( int grpc_message_compression_algorithm_name(
grpc_message_compression_algorithm algorithm, char **name) { grpc_message_compression_algorithm algorithm, const char **name) {
GRPC_API_TRACE("grpc_message_compression_algorithm_parse(algorithm=%d, name=%p)", 2, GRPC_API_TRACE("grpc_message_compression_algorithm_parse(algorithm=%d, name=%p)", 2,
((int)algorithm, name)); ((int)algorithm, name));
switch (algorithm) { switch (algorithm) {

@ -91,7 +91,7 @@ int grpc_compression_algorithm_from_message_stream_compression_algorithm(
/* Interfaces for message compression. */ /* Interfaces for message compression. */
int grpc_message_compression_algorithm_name( int grpc_message_compression_algorithm_name(
grpc_message_compression_algorithm algorithm, char **name); grpc_message_compression_algorithm algorithm, const char **name);
grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level( grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level(
grpc_message_compression_level level, uint32_t accepted_encodings); grpc_message_compression_level level, uint32_t accepted_encodings);

@ -16,176 +16,62 @@
* *
*/ */
#include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/compression/stream_compression.h"
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/compression/stream_compression_gzip.h"
#include "src/core/lib/slice/slice_internal.h"
#define OUTPUT_BLOCK_SIZE (1024) extern const grpc_stream_compression_vtable
grpc_stream_compression_identity_vtable;
static bool gzip_flate(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in, grpc_slice_buffer *out,
size_t *output_size, size_t max_output_size, int flush,
bool *end_of_context) {
GPR_ASSERT(flush == 0 || flush == Z_SYNC_FLUSH || flush == Z_FINISH);
/* Full flush is not allowed when inflating. */
GPR_ASSERT(!(ctx->flate == inflate && (flush == Z_FINISH)));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
int r;
bool eoc = false;
size_t original_max_output_size = max_output_size;
while (max_output_size > 0 && (in->length > 0 || flush) && !eoc) {
size_t slice_size = max_output_size < OUTPUT_BLOCK_SIZE ? max_output_size
: OUTPUT_BLOCK_SIZE;
grpc_slice slice_out = GRPC_SLICE_MALLOC(slice_size);
ctx->zs.avail_out = (uInt)slice_size;
ctx->zs.next_out = GRPC_SLICE_START_PTR(slice_out);
while (ctx->zs.avail_out > 0 && in->length > 0 && !eoc) {
grpc_slice slice = grpc_slice_buffer_take_first(in);
ctx->zs.avail_in = (uInt)GRPC_SLICE_LENGTH(slice);
ctx->zs.next_in = GRPC_SLICE_START_PTR(slice);
r = ctx->flate(&ctx->zs, Z_NO_FLUSH);
if (r < 0 && r != Z_BUF_ERROR) {
gpr_log(GPR_ERROR, "zlib error (%d)", r);
grpc_slice_unref_internal(&exec_ctx, slice_out);
grpc_exec_ctx_finish(&exec_ctx);
return false;
} else if (r == Z_STREAM_END && ctx->flate == inflate) {
eoc = true;
}
if (ctx->zs.avail_in > 0) {
grpc_slice_buffer_undo_take_first(
in,
grpc_slice_sub(slice, GRPC_SLICE_LENGTH(slice) - ctx->zs.avail_in,
GRPC_SLICE_LENGTH(slice)));
}
grpc_slice_unref_internal(&exec_ctx, slice);
}
if (flush != 0 && ctx->zs.avail_out > 0 && !eoc) {
GPR_ASSERT(in->length == 0);
r = ctx->flate(&ctx->zs, flush);
if (flush == Z_SYNC_FLUSH) {
switch (r) {
case Z_OK:
/* Maybe flush is not complete; just made some partial progress. */
if (ctx->zs.avail_out > 0) {
flush = 0;
}
break;
case Z_BUF_ERROR:
case Z_STREAM_END:
flush = 0;
break;
default:
gpr_log(GPR_ERROR, "zlib error (%d)", r);
grpc_slice_unref_internal(&exec_ctx, slice_out);
grpc_exec_ctx_finish(&exec_ctx);
return false;
}
} else if (flush == Z_FINISH) {
switch (r) {
case Z_OK:
case Z_BUF_ERROR:
/* Wait for the next loop to assign additional output space. */
GPR_ASSERT(ctx->zs.avail_out == 0);
break;
case Z_STREAM_END:
flush = 0;
break;
default:
gpr_log(GPR_ERROR, "zlib error (%d)", r);
grpc_slice_unref_internal(&exec_ctx, slice_out);
grpc_exec_ctx_finish(&exec_ctx);
return false;
}
}
}
if (ctx->zs.avail_out == 0) {
grpc_slice_buffer_add(out, slice_out);
} else if (ctx->zs.avail_out < slice_size) {
slice_out.data.refcounted.length -= ctx->zs.avail_out;
grpc_slice_buffer_add(out, slice_out);
} else {
grpc_slice_unref_internal(&exec_ctx, slice_out);
}
max_output_size -= (slice_size - ctx->zs.avail_out);
}
grpc_exec_ctx_finish(&exec_ctx);
if (end_of_context) {
*end_of_context = eoc;
}
if (output_size) {
*output_size = original_max_output_size - max_output_size;
}
return true;
}
bool grpc_stream_compress(grpc_stream_compression_context *ctx, bool grpc_stream_compress(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in, grpc_slice_buffer *out, grpc_slice_buffer *in, grpc_slice_buffer *out,
size_t *output_size, size_t max_output_size, size_t *output_size, size_t max_output_size,
grpc_stream_compression_flush flush) { grpc_stream_compression_flush flush) {
GPR_ASSERT(ctx->flate == deflate); return ctx->vtable->compress(ctx, in, out, output_size, max_output_size,
int gzip_flush; flush);
switch (flush) {
case GRPC_STREAM_COMPRESSION_FLUSH_NONE:
gzip_flush = 0;
break;
case GRPC_STREAM_COMPRESSION_FLUSH_SYNC:
gzip_flush = Z_SYNC_FLUSH;
break;
case GRPC_STREAM_COMPRESSION_FLUSH_FINISH:
gzip_flush = Z_FINISH;
break;
default:
gzip_flush = 0;
}
return gzip_flate(ctx, in, out, output_size, max_output_size, gzip_flush,
NULL);
} }
bool grpc_stream_decompress(grpc_stream_compression_context *ctx, bool grpc_stream_decompress(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in, grpc_slice_buffer *out, grpc_slice_buffer *in, grpc_slice_buffer *out,
size_t *output_size, size_t max_output_size, size_t *output_size, size_t max_output_size,
bool *end_of_context) { bool *end_of_context) {
GPR_ASSERT(ctx->flate == inflate); return ctx->vtable->decompress(ctx, in, out, output_size, max_output_size,
return gzip_flate(ctx, in, out, output_size, max_output_size, Z_SYNC_FLUSH, end_of_context);
end_of_context);
} }
grpc_stream_compression_context *grpc_stream_compression_context_create( grpc_stream_compression_context *grpc_stream_compression_context_create(
grpc_stream_compression_method method) { grpc_stream_compression_method method) {
grpc_stream_compression_context *ctx = switch (method) {
gpr_zalloc(sizeof(grpc_stream_compression_context)); case GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS:
int r; case GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS:
if (ctx == NULL) { return grpc_stream_compression_identity_vtable.context_create(method);
return NULL; case GRPC_STREAM_COMPRESSION_GZIP_COMPRESS:
} case GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS:
if (method == GRPC_STREAM_COMPRESSION_DECOMPRESS) { return grpc_stream_compression_gzip_vtable.context_create(method);
r = inflateInit2(&ctx->zs, 0x1F); default:
ctx->flate = inflate; gpr_log(GPR_ERROR, "Unknown stream compression method: %d", method);
} else { return NULL;
r = deflateInit2(&ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8,
Z_DEFAULT_STRATEGY);
ctx->flate = deflate;
}
if (r != Z_OK) {
gpr_free(ctx);
return NULL;
} }
return ctx;
} }
void grpc_stream_compression_context_destroy( void grpc_stream_compression_context_destroy(
grpc_stream_compression_context *ctx) { grpc_stream_compression_context *ctx) {
if (ctx->flate == inflate) { ctx->vtable->context_destroy(ctx);
inflateEnd(&ctx->zs); }
int grpc_stream_compression_method_parse(
grpc_slice value, bool is_compress,
grpc_stream_compression_method *method) {
if (grpc_slice_eq(value, GRPC_MDSTR_IDENTITY)) {
*method = is_compress ? GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS
: GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS;
return 1;
} else if (grpc_slice_eq(value, GRPC_MDSTR_GZIP)) {
*method = is_compress ? GRPC_STREAM_COMPRESSION_GZIP_COMPRESS
: GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS;
return 1;
} else { } else {
deflateEnd(&ctx->zs); return 0;
} }
gpr_free(ctx);
} }

@ -24,15 +24,20 @@
#include <grpc/slice_buffer.h> #include <grpc/slice_buffer.h>
#include <zlib.h> #include <zlib.h>
#include "src/core/lib/transport/static_metadata.h"
typedef struct grpc_stream_compression_vtable grpc_stream_compression_vtable;
/* Stream compression/decompression context */ /* Stream compression/decompression context */
typedef struct grpc_stream_compression_context { typedef struct grpc_stream_compression_context {
z_stream zs; const grpc_stream_compression_vtable *vtable;
int (*flate)(z_stream *zs, int flush);
} grpc_stream_compression_context; } grpc_stream_compression_context;
typedef enum grpc_stream_compression_method { typedef enum grpc_stream_compression_method {
GRPC_STREAM_COMPRESSION_COMPRESS = 0, GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS = 0,
GRPC_STREAM_COMPRESSION_DECOMPRESS, GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS,
GRPC_STREAM_COMPRESSION_GZIP_COMPRESS,
GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS,
GRPC_STREAM_COMPRESSION_METHOD_COUNT GRPC_STREAM_COMPRESSION_METHOD_COUNT
} grpc_stream_compression_method; } grpc_stream_compression_method;
@ -43,6 +48,19 @@ typedef enum grpc_stream_compression_flush {
GRPC_STREAM_COMPRESSION_FLUSH_COUNT GRPC_STREAM_COMPRESSION_FLUSH_COUNT
} grpc_stream_compression_flush; } grpc_stream_compression_flush;
struct grpc_stream_compression_vtable {
bool (*compress)(grpc_stream_compression_context *ctx, grpc_slice_buffer *in,
grpc_slice_buffer *out, size_t *output_size,
size_t max_output_size, grpc_stream_compression_flush flush);
bool (*decompress)(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in, grpc_slice_buffer *out,
size_t *output_size, size_t max_output_size,
bool *end_of_context);
grpc_stream_compression_context *(*context_create)(
grpc_stream_compression_method method);
void (*context_destroy)(grpc_stream_compression_context *ctx);
};
/** /**
* Compress bytes provided in \a in with a given context, with an optional flush * Compress bytes provided in \a in with a given context, with an optional flush
* at the end of compression. Emits at most \a max_output_size compressed bytes * at the end of compression. Emits at most \a max_output_size compressed bytes
@ -87,4 +105,10 @@ grpc_stream_compression_context *grpc_stream_compression_context_create(
void grpc_stream_compression_context_destroy( void grpc_stream_compression_context_destroy(
grpc_stream_compression_context *ctx); grpc_stream_compression_context *ctx);
/**
* Parse stream compression method based on algorithm name
*/
int grpc_stream_compression_method_parse(
grpc_slice value, bool is_compress, grpc_stream_compression_method *method);
#endif #endif

@ -0,0 +1,228 @@
/*
*
* 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.
*
*/
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/compression/stream_compression_gzip.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#define OUTPUT_BLOCK_SIZE (1024)
typedef struct grpc_stream_compression_context_gzip {
grpc_stream_compression_context base;
z_stream zs;
int (*flate)(z_stream *zs, int flush);
} grpc_stream_compression_context_gzip;
static bool gzip_flate(grpc_stream_compression_context_gzip *ctx,
grpc_slice_buffer *in, grpc_slice_buffer *out,
size_t *output_size, size_t max_output_size, int flush,
bool *end_of_context) {
GPR_ASSERT(flush == 0 || flush == Z_SYNC_FLUSH || flush == Z_FINISH);
/* Full flush is not allowed when inflating. */
GPR_ASSERT(!(ctx->flate == inflate && (flush == Z_FINISH)));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
int r;
bool eoc = false;
size_t original_max_output_size = max_output_size;
while (max_output_size > 0 && (in->length > 0 || flush) && !eoc) {
size_t slice_size = max_output_size < OUTPUT_BLOCK_SIZE ? max_output_size
: OUTPUT_BLOCK_SIZE;
grpc_slice slice_out = GRPC_SLICE_MALLOC(slice_size);
ctx->zs.avail_out = (uInt)slice_size;
ctx->zs.next_out = GRPC_SLICE_START_PTR(slice_out);
while (ctx->zs.avail_out > 0 && in->length > 0 && !eoc) {
grpc_slice slice = grpc_slice_buffer_take_first(in);
ctx->zs.avail_in = (uInt)GRPC_SLICE_LENGTH(slice);
ctx->zs.next_in = GRPC_SLICE_START_PTR(slice);
r = ctx->flate(&ctx->zs, Z_NO_FLUSH);
if (r < 0 && r != Z_BUF_ERROR) {
gpr_log(GPR_ERROR, "zlib error (%d)", r);
grpc_slice_unref_internal(&exec_ctx, slice_out);
grpc_exec_ctx_finish(&exec_ctx);
return false;
} else if (r == Z_STREAM_END && ctx->flate == inflate) {
eoc = true;
}
if (ctx->zs.avail_in > 0) {
grpc_slice_buffer_undo_take_first(
in,
grpc_slice_sub(slice, GRPC_SLICE_LENGTH(slice) - ctx->zs.avail_in,
GRPC_SLICE_LENGTH(slice)));
}
grpc_slice_unref_internal(&exec_ctx, slice);
}
if (flush != 0 && ctx->zs.avail_out > 0 && !eoc) {
GPR_ASSERT(in->length == 0);
r = ctx->flate(&ctx->zs, flush);
if (flush == Z_SYNC_FLUSH) {
switch (r) {
case Z_OK:
/* Maybe flush is not complete; just made some partial progress. */
if (ctx->zs.avail_out > 0) {
flush = 0;
}
break;
case Z_BUF_ERROR:
case Z_STREAM_END:
flush = 0;
break;
default:
gpr_log(GPR_ERROR, "zlib error (%d)", r);
grpc_slice_unref_internal(&exec_ctx, slice_out);
grpc_exec_ctx_finish(&exec_ctx);
return false;
}
} else if (flush == Z_FINISH) {
switch (r) {
case Z_OK:
case Z_BUF_ERROR:
/* Wait for the next loop to assign additional output space. */
GPR_ASSERT(ctx->zs.avail_out == 0);
break;
case Z_STREAM_END:
flush = 0;
break;
default:
gpr_log(GPR_ERROR, "zlib error (%d)", r);
grpc_slice_unref_internal(&exec_ctx, slice_out);
grpc_exec_ctx_finish(&exec_ctx);
return false;
}
}
}
if (ctx->zs.avail_out == 0) {
grpc_slice_buffer_add(out, slice_out);
} else if (ctx->zs.avail_out < slice_size) {
slice_out.data.refcounted.length -= ctx->zs.avail_out;
grpc_slice_buffer_add(out, slice_out);
} else {
grpc_slice_unref_internal(&exec_ctx, slice_out);
}
max_output_size -= (slice_size - ctx->zs.avail_out);
}
grpc_exec_ctx_finish(&exec_ctx);
if (end_of_context) {
*end_of_context = eoc;
}
if (output_size) {
*output_size = original_max_output_size - max_output_size;
}
return true;
}
static bool grpc_stream_compress_gzip(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in,
grpc_slice_buffer *out,
size_t *output_size,
size_t max_output_size,
grpc_stream_compression_flush flush) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)ctx;
GPR_ASSERT(gzip_ctx->flate == deflate);
int gzip_flush;
switch (flush) {
case GRPC_STREAM_COMPRESSION_FLUSH_NONE:
gzip_flush = 0;
break;
case GRPC_STREAM_COMPRESSION_FLUSH_SYNC:
gzip_flush = Z_SYNC_FLUSH;
break;
case GRPC_STREAM_COMPRESSION_FLUSH_FINISH:
gzip_flush = Z_FINISH;
break;
default:
gzip_flush = 0;
}
return gzip_flate(gzip_ctx, in, out, output_size, max_output_size, gzip_flush,
NULL);
}
static bool grpc_stream_decompress_gzip(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in,
grpc_slice_buffer *out,
size_t *output_size,
size_t max_output_size,
bool *end_of_context) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)ctx;
GPR_ASSERT(gzip_ctx->flate == inflate);
return gzip_flate(gzip_ctx, in, out, output_size, max_output_size,
Z_SYNC_FLUSH, end_of_context);
}
static grpc_stream_compression_context *
grpc_stream_compression_context_create_gzip(
grpc_stream_compression_method method) {
GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_GZIP_COMPRESS ||
method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS);
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)gpr_zalloc(
sizeof(grpc_stream_compression_context_gzip));
int r;
if (gzip_ctx == NULL) {
return NULL;
}
if (method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS) {
r = inflateInit2(&gzip_ctx->zs, 0x1F);
gzip_ctx->flate = inflate;
} else {
r = deflateInit2(&gzip_ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8,
Z_DEFAULT_STRATEGY);
gzip_ctx->flate = deflate;
}
if (r != Z_OK) {
gpr_free(gzip_ctx);
return NULL;
}
gzip_ctx->base.vtable = &grpc_stream_compression_gzip_vtable;
return (grpc_stream_compression_context *)gzip_ctx;
}
static void grpc_stream_compression_context_destroy_gzip(
grpc_stream_compression_context *ctx) {
if (ctx == NULL) {
return;
}
grpc_stream_compression_context_gzip *gzip_ctx =
(grpc_stream_compression_context_gzip *)ctx;
if (gzip_ctx->flate == inflate) {
inflateEnd(&gzip_ctx->zs);
} else {
deflateEnd(&gzip_ctx->zs);
}
gpr_free(ctx);
}
const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable = {
.compress = grpc_stream_compress_gzip,
.decompress = grpc_stream_decompress_gzip,
.context_create = grpc_stream_compression_context_create_gzip,
.context_destroy = grpc_stream_compression_context_destroy_gzip};

@ -0,0 +1,26 @@
/*
*
* 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_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H
#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H
#include "src/core/lib/compression/stream_compression.h"
extern const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable;
#endif

@ -0,0 +1,94 @@
/*
*
* 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.
*
*/
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/compression/stream_compression_identity.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#define OUTPUT_BLOCK_SIZE (1024)
/* Singleton context used for all identity streams. */
static grpc_stream_compression_context identity_ctx = {
.vtable = &grpc_stream_compression_identity_vtable};
static void grpc_stream_compression_pass_through(grpc_slice_buffer *in,
grpc_slice_buffer *out,
size_t *output_size,
size_t max_output_size) {
if (max_output_size >= in->length) {
if (output_size) {
*output_size = in->length;
}
grpc_slice_buffer_move_into(in, out);
} else {
if (output_size) {
*output_size = max_output_size;
}
grpc_slice_buffer_move_first(in, max_output_size, out);
}
}
static bool grpc_stream_compress_identity(grpc_stream_compression_context *ctx,
grpc_slice_buffer *in,
grpc_slice_buffer *out,
size_t *output_size,
size_t max_output_size,
grpc_stream_compression_flush flush) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_pass_through(in, out, output_size, max_output_size);
return true;
}
static bool grpc_stream_decompress_identity(
grpc_stream_compression_context *ctx, grpc_slice_buffer *in,
grpc_slice_buffer *out, size_t *output_size, size_t max_output_size,
bool *end_of_context) {
if (ctx == NULL) {
return false;
}
grpc_stream_compression_pass_through(in, out, output_size, max_output_size);
if (end_of_context) {
*end_of_context = false;
}
return true;
}
static grpc_stream_compression_context *
grpc_stream_compression_context_create_identity(
grpc_stream_compression_method method) {
GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS ||
method == GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS);
/* No context needed in this case. Use fake context instead. */
return (grpc_stream_compression_context *)&identity_ctx;
}
static void grpc_stream_compression_context_destroy_identity(
grpc_stream_compression_context *ctx) {
return;
}
const grpc_stream_compression_vtable grpc_stream_compression_identity_vtable = {
.compress = grpc_stream_compress_identity,
.decompress = grpc_stream_decompress_identity,
.context_create = grpc_stream_compression_context_create_identity,
.context_destroy = grpc_stream_compression_context_destroy_identity};

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

Loading…
Cancel
Save