Merge branch 'master' into health

pull/9205/head
yang-g 8 years ago
commit 55c6ebfd7a
  1. 1
      .gitignore
  2. 35
      .pylintrc
  3. 81
      BUILD
  4. 476
      CMakeLists.txt
  5. 217
      Makefile
  6. 2
      binding.gyp
  7. 98
      build.yaml
  8. 2
      config.m4
  9. 22
      gRPC-Core.podspec
  10. 1
      grpc.def
  11. 10
      grpc.gemspec
  12. 15
      include/grpc++/impl/codegen/call.h
  13. 9
      include/grpc++/impl/codegen/proto_utils.h
  14. 9
      include/grpc++/impl/codegen/server_context.h
  15. 8
      include/grpc++/impl/codegen/sync_stream.h
  16. 2
      include/grpc++/server.h
  17. 15
      include/grpc++/test/server_context_test_spouse.h
  18. 10
      include/grpc/grpc.h
  19. 8
      include/grpc/impl/codegen/grpc_types.h
  20. 63
      include/grpc/load_reporting.h
  21. 3
      include/grpc/support/useful.h
  22. 10
      package.xml
  23. 42
      src/core/ext/census/trace_label.h
  24. 63
      src/core/ext/census/trace_propagation.h
  25. 45
      src/core/ext/census/trace_status.h
  26. 50
      src/core/ext/census/trace_string.h
  27. 42
      src/core/ext/census/tracing.c
  28. 124
      src/core/ext/census/tracing.h
  29. 556
      src/core/ext/client_channel/client_channel.c
  30. 2
      src/core/ext/client_channel/client_channel_plugin.c
  31. 57
      src/core/ext/client_channel/http_proxy.c
  32. 4
      src/core/ext/client_channel/http_proxy.h
  33. 2
      src/core/ext/client_channel/lb_policy.c
  34. 25
      src/core/ext/client_channel/proxy_mapper.c
  35. 36
      src/core/ext/client_channel/proxy_mapper.h
  36. 52
      src/core/ext/client_channel/proxy_mapper_registry.c
  37. 16
      src/core/ext/client_channel/proxy_mapper_registry.h
  38. 24
      src/core/ext/client_channel/subchannel.c
  39. 3
      src/core/ext/client_channel/subchannel.h
  40. 180
      src/core/ext/lb_policy/grpclb/grpclb.c
  41. 77
      src/core/ext/lb_policy/grpclb/grpclb_channel.c
  42. 56
      src/core/ext/lb_policy/grpclb/grpclb_channel.h
  43. 107
      src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
  44. 2
      src/core/ext/lb_policy/pick_first/pick_first.c
  45. 9
      src/core/ext/lb_policy/round_robin/round_robin.c
  46. 20
      src/core/ext/load_reporting/load_reporting.c
  47. 17
      src/core/ext/load_reporting/load_reporting.h
  48. 18
      src/core/ext/load_reporting/load_reporting_filter.c
  49. 2
      src/core/ext/resolver/dns/native/dns_resolver.c
  50. 171
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  51. 92
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  52. 9
      src/core/ext/transport/chttp2/transport/frame_rst_stream.c
  53. 2
      src/core/ext/transport/chttp2/transport/frame_settings.h
  54. 57
      src/core/ext/transport/chttp2/transport/internal.h
  55. 20
      src/core/ext/transport/chttp2/transport/parsing.c
  56. 18
      src/core/ext/transport/chttp2/transport/writing.c
  57. 13
      src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
  58. 12
      src/core/ext/transport/cronet/transport/cronet_api_dummy.c
  59. 246
      src/core/ext/transport/cronet/transport/cronet_transport.c
  60. 43
      src/core/ext/transport/cronet/transport/cronet_transport.h
  61. 10
      src/core/lib/channel/compress_filter.c
  62. 3
      src/core/lib/channel/context.h
  63. 15
      src/core/lib/channel/http_server_filter.c
  64. 5
      src/core/lib/http/httpcli.c
  65. 3
      src/core/lib/http/httpcli.h
  66. 28
      src/core/lib/iomgr/combiner.c
  67. 23
      src/core/lib/iomgr/combiner.h
  68. 18
      src/core/lib/iomgr/ev_epoll_linux.c
  69. 70
      src/core/lib/iomgr/ev_poll_posix.c
  70. 9
      src/core/lib/iomgr/ev_posix.c
  71. 4
      src/core/lib/iomgr/ev_posix.h
  72. 87
      src/core/lib/iomgr/network_status_tracker.c
  73. 3
      src/core/lib/iomgr/pollset.h
  74. 3
      src/core/lib/iomgr/pollset_set.h
  75. 3
      src/core/lib/iomgr/pollset_set_uv.c
  76. 3
      src/core/lib/iomgr/pollset_set_windows.c
  77. 5
      src/core/lib/iomgr/pollset_uv.c
  78. 10
      src/core/lib/iomgr/pollset_windows.c
  79. 2
      src/core/lib/iomgr/resource_quota.c
  80. 38
      src/core/lib/iomgr/sockaddr_utils.c
  81. 4
      src/core/lib/iomgr/sockaddr_utils.h
  82. 331
      src/core/lib/iomgr/tcp_server_posix.c
  83. 10
      src/core/lib/iomgr/timer_generic.c
  84. 4
      src/core/lib/iomgr/udp_server.c
  85. 3
      src/core/lib/iomgr/udp_server.h
  86. 20
      src/core/lib/profiling/basic_timers.c
  87. 47
      src/core/lib/security/credentials/credentials.c
  88. 13
      src/core/lib/security/credentials/credentials.h
  89. 8
      src/core/lib/security/credentials/fake/fake_credentials.c
  90. 15
      src/core/lib/security/credentials/fake/fake_credentials.h
  91. 2
      src/core/lib/security/credentials/google_default/google_default_credentials.c
  92. 4
      src/core/lib/security/credentials/jwt/jwt_verifier.c
  93. 3
      src/core/lib/security/credentials/jwt/jwt_verifier.h
  94. 2
      src/core/lib/security/credentials/oauth2/oauth2_credentials.c
  95. 2
      src/core/lib/security/transport/client_auth_filter.c
  96. 70
      src/core/lib/security/transport/lb_targets_info.c
  97. 47
      src/core/lib/security/transport/lb_targets_info.h
  98. 141
      src/core/lib/security/transport/security_connector.c
  99. 7
      src/core/lib/security/transport/security_connector.h
  100. 4
      src/core/lib/security/transport/security_handshaker.c
  101. Some files were not shown because too many files have changed in this diff Show More

1
.gitignore vendored

@ -9,6 +9,7 @@ objs
cython_debug/ cython_debug/
python_build/ python_build/
python_format_venv/ python_format_venv/
python_pylint_venv/
.coverage* .coverage*
.eggs .eggs
htmlcov/ htmlcov/

@ -0,0 +1,35 @@
[MESSAGES CONTROL]
#TODO: Enable missing-docstring
#TODO: Enable too-few-public-methods
#TODO: Enable too-many-arguments
#TODO: Enable no-init
#TODO: Enable duplicate-code
#TODO: Enable invalid-name
#TODO: Enable suppressed-message
#TODO: Enable locally-disabled
#TODO: Enable protected-access
#TODO: Enable no-name-in-module
#TODO: Enable unused-argument
#TODO: Enable fixme
#TODO: Enable wrong-import-order
#TODO: Enable no-value-for-parameter
#TODO: Enable cyclic-import
#TODO: Enable unused-variable
#TODO: Enable redefined-outer-name
#TODO: Enable unused-import
#TODO: Enable too-many-instance-attributes
#TODO: Enable broad-except
#TODO: Enable too-many-locals
#TODO: Enable too-many-lines
#TODO: Enable redefined-variable-type
#TODO: Enable next-method-called
#TODO: Enable import-error
#TODO: Enable useless-else-on-loop
#TODO: Enable too-many-return-statements
#TODO: Enable too-many-nested-blocks
#TODO: Enable super-init-not-called
#TODO: Enable no-self-use
#TODO: Enable no-member
disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use,no-member

81
BUILD

@ -63,7 +63,7 @@ grpc_cc_library(
deps = [ deps = [
"census", "census",
"grpc_base", "grpc_base",
"grpc_lb_policy_grpclb", "grpc_lb_policy_grpclb_secure",
"grpc_lb_policy_pick_first", "grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin", "grpc_lb_policy_round_robin",
"grpc_load_reporting", "grpc_load_reporting",
@ -140,6 +140,7 @@ grpc_cc_library(
"grpc++_base", "grpc++_base",
"grpc++_codegen_base", "grpc++_codegen_base",
"grpc++_codegen_base_src", "grpc++_codegen_base_src",
"grpc++_codegen_proto",
], ],
) )
@ -284,9 +285,15 @@ grpc_cc_library(
"src/core/ext/census/resource.h", "src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h", "src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.h", "src/core/ext/census/trace_context.h",
"src/core/ext/census/trace_label.h",
"src/core/ext/census/trace_propagation.h",
"src/core/ext/census/trace_status.h",
"src/core/ext/census/trace_string.h",
"src/core/ext/census/tracing.h",
], ],
external_deps = [ external_deps = [
"nanopb", "nanopb",
"libssl",
], ],
language = "c", language = "c",
public_hdrs = [ public_hdrs = [
@ -520,13 +527,13 @@ grpc_cc_library(
"src/core/lib/surface/server.c", "src/core/lib/surface/server.c",
"src/core/lib/surface/validate_metadata.c", "src/core/lib/surface/validate_metadata.c",
"src/core/lib/surface/version.c", "src/core/lib/surface/version.c",
"src/core/lib/transport/bdp_estimator.c",
"src/core/lib/transport/byte_stream.c", "src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c", "src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/error_utils.c", "src/core/lib/transport/error_utils.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/bdp_estimator.c",
"src/core/lib/transport/service_config.c", "src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/status_conversion.c", "src/core/lib/transport/status_conversion.c",
@ -624,9 +631,10 @@ grpc_cc_library(
"src/core/lib/surface/completion_queue.h", "src/core/lib/surface/completion_queue.h",
"src/core/lib/surface/event_string.h", "src/core/lib/surface/event_string.h",
"src/core/lib/surface/init.h", "src/core/lib/surface/init.h",
"src/core/lib/surface/validate_metadata.h",
"src/core/lib/surface/lame_client.h", "src/core/lib/surface/lame_client.h",
"src/core/lib/surface/server.h", "src/core/lib/surface/server.h",
"src/core/lib/surface/validate_metadata.h",
"src/core/lib/transport/bdp_estimator.h",
"src/core/lib/transport/byte_stream.h", "src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h", "src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/error_utils.h", "src/core/lib/transport/error_utils.h",
@ -634,7 +642,6 @@ grpc_cc_library(
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/bdp_estimator.h",
"src/core/lib/transport/service_config.h", "src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/status_conversion.h", "src/core/lib/transport/status_conversion.h",
@ -650,6 +657,7 @@ grpc_cc_library(
"include/grpc/byte_buffer.h", "include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h", "include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h", "include/grpc/compression.h",
"include/grpc/load_reporting.h",
"include/grpc/grpc.h", "include/grpc/grpc.h",
"include/grpc/grpc_posix.h", "include/grpc/grpc_posix.h",
"include/grpc/grpc_security_constants.h", "include/grpc/grpc_security_constants.h",
@ -665,7 +673,6 @@ grpc_cc_library(
grpc_cc_library( grpc_cc_library(
name = "grpc_client_channel", name = "grpc_client_channel",
language = "c",
srcs = [ srcs = [
"src/core/ext/client_channel/channel_connectivity.c", "src/core/ext/client_channel/channel_connectivity.c",
"src/core/ext/client_channel/client_channel.c", "src/core/ext/client_channel/client_channel.c",
@ -709,6 +716,7 @@ grpc_cc_library(
"src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h", "src/core/ext/client_channel/uri_parser.h",
], ],
language = "c",
deps = [ deps = [
"grpc_base", "grpc_base",
], ],
@ -735,11 +743,13 @@ grpc_cc_library(
name = "grpc_lb_policy_grpclb", name = "grpc_lb_policy_grpclb",
srcs = [ srcs = [
"src/core/ext/lb_policy/grpclb/grpclb.c", "src/core/ext/lb_policy/grpclb/grpclb.c",
"src/core/ext/lb_policy/grpclb/grpclb_channel.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
], ],
hdrs = [ hdrs = [
"src/core/ext/lb_policy/grpclb/grpclb.h", "src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/grpclb_channel.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
], ],
@ -753,6 +763,31 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "grpc_lb_policy_grpclb_secure",
srcs = [
"src/core/ext/lb_policy/grpclb/grpclb.c",
"src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c",
"src/core/ext/lb_policy/grpclb/load_balancer_api.c",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
],
hdrs = [
"src/core/ext/lb_policy/grpclb/grpclb.h",
"src/core/ext/lb_policy/grpclb/grpclb_channel.h",
"src/core/ext/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
],
external_deps = [
"nanopb",
],
language = "c",
deps = [
"grpc_base",
"grpc_client_channel",
"grpc_secure",
],
)
grpc_cc_library( grpc_cc_library(
name = "grpc_lb_policy_pick_first", name = "grpc_lb_policy_pick_first",
srcs = [ srcs = [
@ -836,6 +871,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/plugin/plugin_credentials.c", "src/core/lib/security/credentials/plugin/plugin_credentials.c",
"src/core/lib/security/credentials/ssl/ssl_credentials.c", "src/core/lib/security/credentials/ssl/ssl_credentials.c",
"src/core/lib/security/transport/client_auth_filter.c", "src/core/lib/security/transport/client_auth_filter.c",
"src/core/lib/security/transport/lb_targets_info.c",
"src/core/lib/security/transport/secure_endpoint.c", "src/core/lib/security/transport/secure_endpoint.c",
"src/core/lib/security/transport/security_connector.c", "src/core/lib/security/transport/security_connector.c",
"src/core/lib/security/transport/security_handshaker.c", "src/core/lib/security/transport/security_handshaker.c",
@ -859,6 +895,7 @@ grpc_cc_library(
"src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/plugin/plugin_credentials.h",
"src/core/lib/security/credentials/ssl/ssl_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h",
"src/core/lib/security/transport/auth_filters.h", "src/core/lib/security/transport/auth_filters.h",
"src/core/lib/security/transport/lb_targets_info.h",
"src/core/lib/security/transport/secure_endpoint.h", "src/core/lib/security/transport/secure_endpoint.h",
"src/core/lib/security/transport/security_connector.h", "src/core/lib/security/transport/security_connector.h",
"src/core/lib/security/transport/security_handshaker.h", "src/core/lib/security/transport/security_handshaker.h",
@ -943,22 +980,21 @@ grpc_cc_library(
) )
grpc_cc_library( grpc_cc_library(
name = "grpc_transport_chttp2_client_connector", name = "grpc_transport_chttp2_client_connector",
hdrs = [ srcs = [
"src/core/ext/transport/chttp2/client/chttp2_connector.h", "src/core/ext/transport/chttp2/client/chttp2_connector.c",
], ],
srcs = [ hdrs = [
"src/core/ext/transport/chttp2/client/chttp2_connector.c", "src/core/ext/transport/chttp2/client/chttp2_connector.h",
], ],
language = "c", language = "c",
deps = [ deps = [
"grpc_transport_chttp2", "grpc_base",
"grpc_base", "grpc_client_channel",
"grpc_client_channel", "grpc_transport_chttp2",
], ],
) )
grpc_cc_library( grpc_cc_library(
name = "grpc_transport_chttp2_client_insecure", name = "grpc_transport_chttp2_client_insecure",
srcs = [ srcs = [
@ -1041,6 +1077,7 @@ grpc_cc_library(
], ],
hdrs = [ hdrs = [
"third_party/objective_c/Cronet/bidirectional_stream_c.h", "third_party/objective_c/Cronet/bidirectional_stream_c.h",
"src/core/ext/transport/cronet/transport/cronet_transport.h",
], ],
language = "c", language = "c",
public_hdrs = [ public_hdrs = [
@ -1241,13 +1278,13 @@ grpc_cc_library(
grpc_cc_library( grpc_cc_library(
name = "grpc++_config_proto", name = "grpc++_config_proto",
external_deps = [
"protobuf",
],
language = "c++", language = "c++",
public_hdrs = [ public_hdrs = [
"include/grpc++/impl/codegen/config_protobuf.h", "include/grpc++/impl/codegen/config_protobuf.h",
], ],
external_deps = [
"protobuf",
],
) )
grpc_cc_library( grpc_cc_library(

@ -442,6 +442,9 @@ add_dependencies(buildtests_c multiple_server_queues_test)
add_dependencies(buildtests_c murmur_hash_test) add_dependencies(buildtests_c murmur_hash_test)
add_dependencies(buildtests_c no_server_test) add_dependencies(buildtests_c no_server_test)
add_dependencies(buildtests_c percent_encoding_test) add_dependencies(buildtests_c percent_encoding_test)
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c pollset_set_test)
endif()
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_c resolve_address_posix_test) add_dependencies(buildtests_c resolve_address_posix_test)
endif() endif()
@ -567,6 +570,9 @@ add_dependencies(buildtests_cxx alarm_cpp_test)
add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx async_end2end_test)
add_dependencies(buildtests_cxx auth_property_iterator_test) add_dependencies(buildtests_cxx auth_property_iterator_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 bm_closure)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_fullstack) add_dependencies(buildtests_cxx bm_fullstack)
endif() endif()
add_dependencies(buildtests_cxx channel_arguments_test) add_dependencies(buildtests_cxx channel_arguments_test)
@ -612,6 +618,7 @@ add_dependencies(buildtests_cxx metrics_client)
add_dependencies(buildtests_cxx mock_test) add_dependencies(buildtests_cxx mock_test)
add_dependencies(buildtests_cxx noop-benchmark) add_dependencies(buildtests_cxx noop-benchmark)
add_dependencies(buildtests_cxx proto_server_reflection_test) add_dependencies(buildtests_cxx proto_server_reflection_test)
add_dependencies(buildtests_cxx proto_utils_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 qps_interarrival_test) add_dependencies(buildtests_cxx qps_interarrival_test)
endif() endif()
@ -697,6 +704,17 @@ add_library(gpr
src/core/lib/support/wrap_memcpy.c src/core/lib/support/wrap_memcpy.c
) )
if(WIN32 AND MSVC)
set_target_properties(gpr PROPERTIES COMPILE_PDB_NAME "gpr"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gpr.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(gpr target_include_directories(gpr
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -775,6 +793,17 @@ add_library(gpr_test_util
test/core/util/test_config.c test/core/util/test_config.c
) )
if(WIN32 AND MSVC)
set_target_properties(gpr_test_util PROPERTIES COMPILE_PDB_NAME "gpr_test_util"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/gpr_test_util.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(gpr_test_util target_include_directories(gpr_test_util
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -953,6 +982,7 @@ add_library(grpc
src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/plugin/plugin_credentials.c
src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c
src/core/lib/security/transport/client_auth_filter.c src/core/lib/security/transport/client_auth_filter.c
src/core/lib/security/transport/lb_targets_info.c
src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/secure_endpoint.c
src/core/lib/security/transport/security_connector.c src/core/lib/security/transport/security_connector.c
src/core/lib/security/transport/security_handshaker.c src/core/lib/security/transport/security_handshaker.c
@ -993,6 +1023,7 @@ add_library(grpc
src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create.c
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
src/core/ext/lb_policy/grpclb/grpclb.c src/core/ext/lb_policy/grpclb/grpclb.c
src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
src/core/ext/lb_policy/grpclb/load_balancer_api.c src/core/ext/lb_policy/grpclb/load_balancer_api.c
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
third_party/nanopb/pb_common.c third_party/nanopb/pb_common.c
@ -1021,6 +1052,17 @@ add_library(grpc
src/core/plugin_registry/grpc_plugin_registry.c src/core/plugin_registry/grpc_plugin_registry.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc PROPERTIES COMPILE_PDB_NAME "grpc"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc target_include_directories(grpc
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1048,6 +1090,7 @@ foreach(_hdr
include/grpc/grpc.h include/grpc/grpc.h
include/grpc/grpc_posix.h include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h include/grpc/slice.h
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
@ -1272,6 +1315,7 @@ add_library(grpc_cronet
src/core/lib/security/credentials/plugin/plugin_credentials.c src/core/lib/security/credentials/plugin/plugin_credentials.c
src/core/lib/security/credentials/ssl/ssl_credentials.c src/core/lib/security/credentials/ssl/ssl_credentials.c
src/core/lib/security/transport/client_auth_filter.c src/core/lib/security/transport/client_auth_filter.c
src/core/lib/security/transport/lb_targets_info.c
src/core/lib/security/transport/secure_endpoint.c src/core/lib/security/transport/secure_endpoint.c
src/core/lib/security/transport/security_connector.c src/core/lib/security/transport/security_connector.c
src/core/lib/security/transport/security_handshaker.c src/core/lib/security/transport/security_handshaker.c
@ -1287,6 +1331,17 @@ add_library(grpc_cronet
src/core/plugin_registry/grpc_cronet_plugin_registry.c src/core/plugin_registry/grpc_cronet_plugin_registry.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_cronet PROPERTIES COMPILE_PDB_NAME "grpc_cronet"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_cronet.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc_cronet target_include_directories(grpc_cronet
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1313,6 +1368,7 @@ foreach(_hdr
include/grpc/grpc.h include/grpc/grpc.h
include/grpc/grpc_posix.h include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h include/grpc/slice.h
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
@ -1378,6 +1434,7 @@ add_library(grpc_test_util
test/core/util/port_uv.c test/core/util/port_uv.c
test/core/util/port_windows.c test/core/util/port_windows.c
test/core/util/slice_splitter.c test/core/util/slice_splitter.c
test/core/util/trickle_endpoint.c
src/core/lib/channel/channel_args.c src/core/lib/channel/channel_args.c
src/core/lib/channel/channel_stack.c src/core/lib/channel/channel_stack.c
src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/channel_stack_builder.c
@ -1498,6 +1555,17 @@ add_library(grpc_test_util
src/core/lib/transport/transport_op_string.c src/core/lib/transport/transport_op_string.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_test_util PROPERTIES COMPILE_PDB_NAME "grpc_test_util"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_test_util.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc_test_util target_include_directories(grpc_test_util
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1524,6 +1592,7 @@ foreach(_hdr
include/grpc/grpc.h include/grpc/grpc.h
include/grpc/grpc_posix.h include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h include/grpc/slice.h
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
@ -1574,8 +1643,20 @@ add_library(grpc_test_util_unsecure
test/core/util/port_uv.c test/core/util/port_uv.c
test/core/util/port_windows.c test/core/util/port_windows.c
test/core/util/slice_splitter.c test/core/util/slice_splitter.c
test/core/util/trickle_endpoint.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_test_util_unsecure PROPERTIES COMPILE_PDB_NAME "grpc_test_util_unsecure"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_test_util_unsecure.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc_test_util_unsecure target_include_directories(grpc_test_util_unsecure
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1773,6 +1854,7 @@ add_library(grpc_unsecure
src/core/ext/load_reporting/load_reporting.c src/core/ext/load_reporting/load_reporting.c
src/core/ext/load_reporting/load_reporting_filter.c src/core/ext/load_reporting/load_reporting_filter.c
src/core/ext/lb_policy/grpclb/grpclb.c src/core/ext/lb_policy/grpclb/grpclb.c
src/core/ext/lb_policy/grpclb/grpclb_channel.c
src/core/ext/lb_policy/grpclb/load_balancer_api.c src/core/ext/lb_policy/grpclb/load_balancer_api.c
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
third_party/nanopb/pb_common.c third_party/nanopb/pb_common.c
@ -1797,6 +1879,17 @@ add_library(grpc_unsecure
src/core/plugin_registry/grpc_unsecure_plugin_registry.c src/core/plugin_registry/grpc_unsecure_plugin_registry.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_unsecure PROPERTIES COMPILE_PDB_NAME "grpc_unsecure"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_unsecure.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc_unsecure target_include_directories(grpc_unsecure
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1822,6 +1915,7 @@ foreach(_hdr
include/grpc/grpc.h include/grpc/grpc.h
include/grpc/grpc_posix.h include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h include/grpc/slice.h
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
@ -1868,6 +1962,17 @@ add_library(reconnect_server
test/core/util/reconnect_server.c test/core/util/reconnect_server.c
) )
if(WIN32 AND MSVC)
set_target_properties(reconnect_server PROPERTIES COMPILE_PDB_NAME "reconnect_server"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/reconnect_server.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(reconnect_server target_include_directories(reconnect_server
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1897,6 +2002,17 @@ add_library(test_tcp_server
test/core/util/test_tcp_server.c test/core/util/test_tcp_server.c
) )
if(WIN32 AND MSVC)
set_target_properties(test_tcp_server PROPERTIES COMPILE_PDB_NAME "test_tcp_server"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/test_tcp_server.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(test_tcp_server target_include_directories(test_tcp_server
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -1964,6 +2080,17 @@ add_library(grpc++
src/cpp/codegen/codegen_init.cc src/cpp/codegen/codegen_init.cc
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++ PROPERTIES COMPILE_PDB_NAME "grpc++"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc++ target_include_directories(grpc++
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -2079,6 +2206,8 @@ foreach(_hdr
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/proto_utils.h
include/grpc++/impl/codegen/config_protobuf.h
) )
string(REPLACE "include/" "" _path ${_hdr}) string(REPLACE "include/" "" _path ${_hdr})
get_filename_component(_path ${_path} PATH) get_filename_component(_path ${_path} PATH)
@ -2320,6 +2449,17 @@ add_library(grpc++_cronet
third_party/nanopb/pb_encode.c third_party/nanopb/pb_encode.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++_cronet PROPERTIES COMPILE_PDB_NAME "grpc++_cronet"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_cronet.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc++_cronet target_include_directories(grpc++_cronet
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -2442,6 +2582,7 @@ foreach(_hdr
include/grpc/grpc.h include/grpc/grpc.h
include/grpc/grpc_posix.h include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h include/grpc/grpc_security_constants.h
include/grpc/load_reporting.h
include/grpc/slice.h include/grpc/slice.h
include/grpc/slice_buffer.h include/grpc/slice_buffer.h
include/grpc/status.h include/grpc/status.h
@ -2473,6 +2614,17 @@ add_library(grpc++_proto_reflection_desc_db
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++_proto_reflection_desc_db PROPERTIES COMPILE_PDB_NAME "grpc++_proto_reflection_desc_db"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_proto_reflection_desc_db.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/reflection/v1alpha/reflection.proto src/proto/grpc/reflection/v1alpha/reflection.proto
) )
@ -2518,6 +2670,17 @@ add_library(grpc++_reflection
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++_reflection PROPERTIES COMPILE_PDB_NAME "grpc++_reflection"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_reflection.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/reflection/v1alpha/reflection.proto src/proto/grpc/reflection/v1alpha/reflection.proto
) )
@ -2561,39 +2724,21 @@ endif()
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
add_library(grpc++_test
src/cpp/test/server_context_test_spouse.cc
)
target_include_directories(grpc++_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${ZLIB_INCLUDE_DIR}
PRIVATE ${BENCHMARK}/include
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/include
PRIVATE third_party/googletest
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(grpc++_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_library(grpc++_test_config add_library(grpc++_test_config
test/cpp/util/test_config_cc.cc test/cpp/util/test_config_cc.cc
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++_test_config PROPERTIES COMPILE_PDB_NAME "grpc++_test_config"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_config.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc++_test_config target_include_directories(grpc++_test_config
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -2644,6 +2789,17 @@ add_library(grpc++_test_util
src/cpp/codegen/codegen_init.cc src/cpp/codegen/codegen_init.cc
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++_test_util PROPERTIES COMPILE_PDB_NAME "grpc++_test_util"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_test_util.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/health/v1/health.proto src/proto/grpc/health/v1/health.proto
) )
@ -2781,6 +2937,17 @@ add_library(grpc++_unsecure
src/cpp/codegen/codegen_init.cc src/cpp/codegen/codegen_init.cc
) )
if(WIN32 AND MSVC)
set_target_properties(grpc++_unsecure PROPERTIES COMPILE_PDB_NAME "grpc++_unsecure"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc++_unsecure.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc++_unsecure target_include_directories(grpc++_unsecure
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -2927,6 +3094,17 @@ add_library(grpc_cli_libs
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_cli_libs PROPERTIES COMPILE_PDB_NAME "grpc_cli_libs"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_cli_libs.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/reflection/v1alpha/reflection.proto src/proto/grpc/reflection/v1alpha/reflection.proto
) )
@ -2974,6 +3152,17 @@ add_library(grpc_plugin_support
src/compiler/ruby_generator.cc src/compiler/ruby_generator.cc
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_plugin_support PROPERTIES COMPILE_PDB_NAME "grpc_plugin_support"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_plugin_support.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc_plugin_support target_include_directories(grpc_plugin_support
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3030,6 +3219,17 @@ add_library(http2_client_main
test/cpp/interop/http2_client.cc test/cpp/interop/http2_client.cc
) )
if(WIN32 AND MSVC)
set_target_properties(http2_client_main PROPERTIES COMPILE_PDB_NAME "http2_client_main"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/http2_client_main.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/testing/empty.proto src/proto/grpc/testing/empty.proto
) )
@ -3076,6 +3276,17 @@ add_library(interop_client_helper
test/cpp/interop/client_helper.cc test/cpp/interop/client_helper.cc
) )
if(WIN32 AND MSVC)
set_target_properties(interop_client_helper PROPERTIES COMPILE_PDB_NAME "interop_client_helper"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_client_helper.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/testing/messages.proto src/proto/grpc/testing/messages.proto
) )
@ -3125,6 +3336,17 @@ add_library(interop_client_main
test/cpp/interop/interop_client.cc test/cpp/interop/interop_client.cc
) )
if(WIN32 AND MSVC)
set_target_properties(interop_client_main PROPERTIES COMPILE_PDB_NAME "interop_client_main"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_client_main.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/testing/empty.proto src/proto/grpc/testing/empty.proto
) )
@ -3170,6 +3392,17 @@ add_library(interop_server_helper
test/cpp/interop/server_helper.cc test/cpp/interop/server_helper.cc
) )
if(WIN32 AND MSVC)
set_target_properties(interop_server_helper PROPERTIES COMPILE_PDB_NAME "interop_server_helper"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_helper.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(interop_server_helper target_include_directories(interop_server_helper
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3215,6 +3448,17 @@ add_library(interop_server_lib
test/cpp/interop/interop_server.cc test/cpp/interop/interop_server.cc
) )
if(WIN32 AND MSVC)
set_target_properties(interop_server_lib PROPERTIES COMPILE_PDB_NAME "interop_server_lib"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_lib.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/testing/empty.proto src/proto/grpc/testing/empty.proto
) )
@ -3260,6 +3504,17 @@ add_library(interop_server_main
test/cpp/interop/interop_server_bootstrap.cc test/cpp/interop/interop_server_bootstrap.cc
) )
if(WIN32 AND MSVC)
set_target_properties(interop_server_main PROPERTIES COMPILE_PDB_NAME "interop_server_main"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/interop_server_main.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(interop_server_main target_include_directories(interop_server_main
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3318,6 +3573,17 @@ add_library(qps
test/cpp/util/benchmark_config.cc test/cpp/util/benchmark_config.cc
) )
if(WIN32 AND MSVC)
set_target_properties(qps PROPERTIES COMPILE_PDB_NAME "qps"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qps.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp(
src/proto/grpc/testing/messages.proto src/proto/grpc/testing/messages.proto
) )
@ -3363,6 +3629,17 @@ add_library(grpc_csharp_ext SHARED
src/csharp/ext/grpc_csharp_ext.c src/csharp/ext/grpc_csharp_ext.c
) )
if(WIN32 AND MSVC)
set_target_properties(grpc_csharp_ext PROPERTIES COMPILE_PDB_NAME "grpc_csharp_ext"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/grpc_csharp_ext.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(grpc_csharp_ext target_include_directories(grpc_csharp_ext
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3397,6 +3674,17 @@ add_library(bad_client_test
test/core/bad_client/bad_client.c test/core/bad_client/bad_client.c
) )
if(WIN32 AND MSVC)
set_target_properties(bad_client_test PROPERTIES COMPILE_PDB_NAME "bad_client_test"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bad_client_test.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(bad_client_test target_include_directories(bad_client_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3425,6 +3713,17 @@ add_library(bad_ssl_test_server
test/core/bad_ssl/server_common.c test/core/bad_ssl/server_common.c
) )
if(WIN32 AND MSVC)
set_target_properties(bad_ssl_test_server PROPERTIES COMPILE_PDB_NAME "bad_ssl_test_server"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bad_ssl_test_server.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(bad_ssl_test_server target_include_directories(bad_ssl_test_server
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3503,6 +3802,17 @@ add_library(end2end_tests
test/core/end2end/tests/write_buffering_at_end.c test/core/end2end/tests/write_buffering_at_end.c
) )
if(WIN32 AND MSVC)
set_target_properties(end2end_tests PROPERTIES COMPILE_PDB_NAME "end2end_tests"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_tests.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(end2end_tests target_include_directories(end2end_tests
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -3581,6 +3891,17 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/write_buffering_at_end.c test/core/end2end/tests/write_buffering_at_end.c
) )
if(WIN32 AND MSVC)
set_target_properties(end2end_nosec_tests PROPERTIES COMPILE_PDB_NAME "end2end_nosec_tests"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_nosec_tests.pdb
DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(end2end_nosec_tests target_include_directories(end2end_nosec_tests
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
@ -6155,6 +6476,35 @@ target_link_libraries(percent_encoding_test
gpr gpr
) )
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX)
add_executable(pollset_set_test
test/core/iomgr/pollset_set_test.c
)
target_include_directories(pollset_set_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 ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(pollset_set_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif()
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -7091,6 +7441,42 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
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_executable(bm_closure
test/cpp/microbenchmarks/bm_closure.cc
third_party/googletest/src/gtest-all.cc
)
target_include_directories(bm_closure
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 ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/include
PRIVATE third_party/googletest
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(bm_closure
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
benchmark
grpc_test_util
grpc
gpr_test_util
gpr
${_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(bm_fullstack add_executable(bm_fullstack
test/cpp/microbenchmarks/bm_fullstack.cc test/cpp/microbenchmarks/bm_fullstack.cc
third_party/googletest/src/gtest-all.cc third_party/googletest/src/gtest-all.cc
@ -8545,6 +8931,37 @@ target_link_libraries(proto_server_reflection_test
${_gRPC_GFLAGS_LIBRARIES} ${_gRPC_GFLAGS_LIBRARIES}
) )
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(proto_utils_test
test/cpp/codegen/proto_utils_test.cc
third_party/googletest/src/gtest-all.cc
)
target_include_directories(proto_utils_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 ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/include
PRIVATE third_party/googletest
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(proto_utils_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++
grpc
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS) endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -8982,7 +9399,6 @@ target_link_libraries(server_context_test_spouse_test
${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util grpc_test_util
grpc++_test
grpc++ grpc++
grpc grpc
gpr_test_util gpr_test_util

@ -212,6 +212,14 @@ CPPFLAGS_mutrace = -O3 -fno-omit-frame-pointer
LDFLAGS_mutrace = -rdynamic LDFLAGS_mutrace = -rdynamic
DEFINES_mutrace = NDEBUG DEFINES_mutrace = NDEBUG
VALID_CONFIG_counters = 1
CC_counters = $(DEFAULT_CC)
CXX_counters = $(DEFAULT_CXX)
LD_counters = $(DEFAULT_CC)
LDXX_counters = $(DEFAULT_CXX)
CPPFLAGS_counters = -O2 -DGPR_MU_COUNTERS
DEFINES_counters = NDEBUG
# General settings. # General settings.
@ -320,7 +328,7 @@ CXXFLAGS += -std=c++11
else else
CXXFLAGS += -std=c++0x CXXFLAGS += -std=c++0x
endif endif
CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
LDFLAGS += -g LDFLAGS += -g
CPPFLAGS += $(CPPFLAGS_$(CONFIG)) CPPFLAGS += $(CPPFLAGS_$(CONFIG))
@ -998,6 +1006,7 @@ no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer
percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test
pollset_set_test: $(BINDIR)/$(CONFIG)/pollset_set_test
resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test
resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test
resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test
@ -1034,6 +1043,7 @@ wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test
alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack
channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
@ -1073,6 +1083,7 @@ metrics_client: $(BINDIR)/$(CONFIG)/metrics_client
mock_test: $(BINDIR)/$(CONFIG)/mock_test mock_test: $(BINDIR)/$(CONFIG)/mock_test
noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark
proto_server_reflection_test: $(BINDIR)/$(CONFIG)/proto_server_reflection_test proto_server_reflection_test: $(BINDIR)/$(CONFIG)/proto_server_reflection_test
proto_utils_test: $(BINDIR)/$(CONFIG)/proto_utils_test
qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test qps_interarrival_test: $(BINDIR)/$(CONFIG)/qps_interarrival_test
qps_json_driver: $(BINDIR)/$(CONFIG)/qps_json_driver qps_json_driver: $(BINDIR)/$(CONFIG)/qps_json_driver
qps_openloop_test: $(BINDIR)/$(CONFIG)/qps_openloop_test qps_openloop_test: $(BINDIR)/$(CONFIG)/qps_openloop_test
@ -1248,9 +1259,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc
pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
ifeq ($(EMBED_OPENSSL),true) ifeq ($(EMBED_OPENSSL),true)
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_sign_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_verify_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_statistical_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_newhope_vectors_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
else else
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
endif endif
@ -1345,6 +1356,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/murmur_hash_test \ $(BINDIR)/$(CONFIG)/murmur_hash_test \
$(BINDIR)/$(CONFIG)/no_server_test \ $(BINDIR)/$(CONFIG)/no_server_test \
$(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/percent_encoding_test \
$(BINDIR)/$(CONFIG)/pollset_set_test \
$(BINDIR)/$(CONFIG)/resolve_address_posix_test \ $(BINDIR)/$(CONFIG)/resolve_address_posix_test \
$(BINDIR)/$(CONFIG)/resolve_address_test \ $(BINDIR)/$(CONFIG)/resolve_address_test \
$(BINDIR)/$(CONFIG)/resource_quota_test \ $(BINDIR)/$(CONFIG)/resource_quota_test \
@ -1439,6 +1451,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_fullstack \ $(BINDIR)/$(CONFIG)/bm_fullstack \
$(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \
@ -1471,6 +1484,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/mock_test \ $(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/noop-benchmark \ $(BINDIR)/$(CONFIG)/noop-benchmark \
$(BINDIR)/$(CONFIG)/proto_server_reflection_test \ $(BINDIR)/$(CONFIG)/proto_server_reflection_test \
$(BINDIR)/$(CONFIG)/proto_utils_test \
$(BINDIR)/$(CONFIG)/qps_interarrival_test \ $(BINDIR)/$(CONFIG)/qps_interarrival_test \
$(BINDIR)/$(CONFIG)/qps_json_driver \ $(BINDIR)/$(CONFIG)/qps_json_driver \
$(BINDIR)/$(CONFIG)/qps_openloop_test \ $(BINDIR)/$(CONFIG)/qps_openloop_test \
@ -1543,6 +1557,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_fullstack \ $(BINDIR)/$(CONFIG)/bm_fullstack \
$(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \
@ -1575,6 +1590,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/mock_test \ $(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/noop-benchmark \ $(BINDIR)/$(CONFIG)/noop-benchmark \
$(BINDIR)/$(CONFIG)/proto_server_reflection_test \ $(BINDIR)/$(CONFIG)/proto_server_reflection_test \
$(BINDIR)/$(CONFIG)/proto_utils_test \
$(BINDIR)/$(CONFIG)/qps_interarrival_test \ $(BINDIR)/$(CONFIG)/qps_interarrival_test \
$(BINDIR)/$(CONFIG)/qps_json_driver \ $(BINDIR)/$(CONFIG)/qps_json_driver \
$(BINDIR)/$(CONFIG)/qps_openloop_test \ $(BINDIR)/$(CONFIG)/qps_openloop_test \
@ -1758,6 +1774,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 )
$(E) "[RUN] Testing percent_encoding_test" $(E) "[RUN] Testing percent_encoding_test"
$(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 )
$(E) "[RUN] Testing pollset_set_test"
$(Q) $(BINDIR)/$(CONFIG)/pollset_set_test || ( echo test pollset_set_test failed ; exit 1 )
$(E) "[RUN] Testing resolve_address_posix_test" $(E) "[RUN] Testing resolve_address_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 )
$(E) "[RUN] Testing resolve_address_test" $(E) "[RUN] Testing resolve_address_test"
@ -1858,6 +1876,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing auth_property_iterator_test" $(E) "[RUN] Testing auth_property_iterator_test"
$(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
$(E) "[RUN] Testing bm_closure"
$(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 )
$(E) "[RUN] Testing bm_fullstack" $(E) "[RUN] Testing bm_fullstack"
$(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 )
$(E) "[RUN] Testing channel_arguments_test" $(E) "[RUN] Testing channel_arguments_test"
@ -1906,6 +1926,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 )
$(E) "[RUN] Testing proto_server_reflection_test" $(E) "[RUN] Testing proto_server_reflection_test"
$(Q) $(BINDIR)/$(CONFIG)/proto_server_reflection_test || ( echo test proto_server_reflection_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/proto_server_reflection_test || ( echo test proto_server_reflection_test failed ; exit 1 )
$(E) "[RUN] Testing proto_utils_test"
$(Q) $(BINDIR)/$(CONFIG)/proto_utils_test || ( echo test proto_utils_test failed ; exit 1 )
$(E) "[RUN] Testing qps_openloop_test" $(E) "[RUN] Testing qps_openloop_test"
$(Q) $(BINDIR)/$(CONFIG)/qps_openloop_test || ( echo test qps_openloop_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/qps_openloop_test || ( echo test qps_openloop_test failed ; exit 1 )
$(E) "[RUN] Testing round_robin_end2end_test" $(E) "[RUN] Testing round_robin_end2end_test"
@ -2809,6 +2831,7 @@ LIBGRPC_SRC = \
src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \
src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \
src/core/lib/security/transport/client_auth_filter.c \ src/core/lib/security/transport/client_auth_filter.c \
src/core/lib/security/transport/lb_targets_info.c \
src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/security_handshaker.c \
@ -2849,6 +2872,7 @@ LIBGRPC_SRC = \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
src/core/ext/lb_policy/grpclb/grpclb.c \ src/core/ext/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \ third_party/nanopb/pb_common.c \
@ -2883,6 +2907,7 @@ PUBLIC_HEADERS_C += \
include/grpc/grpc.h \ include/grpc/grpc.h \
include/grpc/grpc_posix.h \ include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \ include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \ include/grpc/slice.h \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
@ -3142,6 +3167,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \
src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \
src/core/lib/security/transport/client_auth_filter.c \ src/core/lib/security/transport/client_auth_filter.c \
src/core/lib/security/transport/lb_targets_info.c \
src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/security_handshaker.c \
@ -3163,6 +3189,7 @@ PUBLIC_HEADERS_C += \
include/grpc/grpc.h \ include/grpc/grpc.h \
include/grpc/grpc_posix.h \ include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \ include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \ include/grpc/slice.h \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
@ -3262,6 +3289,7 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/util/port_uv.c \ test/core/util/port_uv.c \
test/core/util/port_windows.c \ test/core/util/port_windows.c \
test/core/util/slice_splitter.c \ test/core/util/slice_splitter.c \
test/core/util/trickle_endpoint.c \
src/core/lib/channel/channel_args.c \ src/core/lib/channel/channel_args.c \
src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack.c \
src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/channel_stack_builder.c \
@ -3388,6 +3416,7 @@ PUBLIC_HEADERS_C += \
include/grpc/grpc.h \ include/grpc/grpc.h \
include/grpc/grpc_posix.h \ include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \ include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \ include/grpc/slice.h \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
@ -3462,6 +3491,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
test/core/util/port_uv.c \ test/core/util/port_uv.c \
test/core/util/port_windows.c \ test/core/util/port_windows.c \
test/core/util/slice_splitter.c \ test/core/util/slice_splitter.c \
test/core/util/trickle_endpoint.c \
PUBLIC_HEADERS_C += \ PUBLIC_HEADERS_C += \
@ -3659,6 +3689,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/load_reporting/load_reporting.c \ src/core/ext/load_reporting/load_reporting.c \
src/core/ext/load_reporting/load_reporting_filter.c \ src/core/ext/load_reporting/load_reporting_filter.c \
src/core/ext/lb_policy/grpclb/grpclb.c \ src/core/ext/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/grpclb_channel.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \ third_party/nanopb/pb_common.c \
@ -3689,6 +3720,7 @@ PUBLIC_HEADERS_C += \
include/grpc/grpc.h \ include/grpc/grpc.h \
include/grpc/grpc_posix.h \ include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \ include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \ include/grpc/slice.h \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
@ -3965,6 +3997,8 @@ PUBLIC_HEADERS_CXX += \
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/proto_utils.h \
include/grpc++/impl/codegen/config_protobuf.h \
LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_SRC)))) LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_SRC))))
@ -4351,6 +4385,7 @@ PUBLIC_HEADERS_CXX += \
include/grpc/grpc.h \ include/grpc/grpc.h \
include/grpc/grpc_posix.h \ include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \ include/grpc/grpc_security_constants.h \
include/grpc/load_reporting.h \
include/grpc/slice.h \ include/grpc/slice.h \
include/grpc/slice_buffer.h \ include/grpc/slice_buffer.h \
include/grpc/status.h \ include/grpc/status.h \
@ -4544,55 +4579,6 @@ $(OBJDIR)/$(CONFIG)/src/cpp/ext/proto_server_reflection.o: $(GENDIR)/src/proto/g
$(OBJDIR)/$(CONFIG)/src/cpp/ext/proto_server_reflection_plugin.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc $(OBJDIR)/$(CONFIG)/src/cpp/ext/proto_server_reflection_plugin.o: $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc
LIBGRPC++_TEST_SRC = \
src/cpp/test/server_context_test_spouse.cc \
PUBLIC_HEADERS_CXX += \
LIBGRPC++_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/libgrpc++_test.a: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
$(LIBDIR)/$(CONFIG)/libgrpc++_test.a: protobuf_dep_error
else
$(LIBDIR)/$(CONFIG)/libgrpc++_test.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_TEST_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_test.a
$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBGRPC++_TEST_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libgrpc++_test.a
endif
endif
endif
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(LIBGRPC++_TEST_OBJS:.o=.dep)
endif
endif
LIBGRPC++_TEST_CONFIG_SRC = \ LIBGRPC++_TEST_CONFIG_SRC = \
test/cpp/util/test_config_cc.cc \ test/cpp/util/test_config_cc.cc \
@ -11188,6 +11174,38 @@ endif
endif endif
POLLSET_SET_TEST_SRC = \
test/core/iomgr/pollset_set_test.c \
POLLSET_SET_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(POLLSET_SET_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/pollset_set_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/pollset_set_test: $(POLLSET_SET_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(POLLSET_SET_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/pollset_set_test
endif
$(OBJDIR)/$(CONFIG)/test/core/iomgr/pollset_set_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_pollset_set_test: $(POLLSET_SET_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(POLLSET_SET_TEST_OBJS:.o=.dep)
endif
endif
RESOLVE_ADDRESS_POSIX_TEST_SRC = \ RESOLVE_ADDRESS_POSIX_TEST_SRC = \
test/core/iomgr/resolve_address_posix_test.c \ test/core/iomgr/resolve_address_posix_test.c \
@ -12373,6 +12391,49 @@ endif
endif endif
BM_CLOSURE_SRC = \
test/cpp/microbenchmarks/bm_closure.cc \
BM_CLOSURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CLOSURE_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_closure: 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)/bm_closure: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_closure
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_closure.o: $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_bm_closure: $(BM_CLOSURE_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_CLOSURE_OBJS:.o=.dep)
endif
endif
BM_FULLSTACK_SRC = \ BM_FULLSTACK_SRC = \
test/cpp/microbenchmarks/bm_fullstack.cc \ test/cpp/microbenchmarks/bm_fullstack.cc \
@ -13989,6 +14050,49 @@ endif
endif endif
PROTO_UTILS_TEST_SRC = \
test/cpp/codegen/proto_utils_test.cc \
PROTO_UTILS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PROTO_UTILS_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/proto_utils_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)/proto_utils_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/proto_utils_test: $(PROTOBUF_DEP) $(PROTO_UTILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(PROTO_UTILS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/proto_utils_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/codegen/proto_utils_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
deps_proto_utils_test: $(PROTO_UTILS_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(PROTO_UTILS_TEST_OBJS:.o=.dep)
endif
endif
QPS_INTERARRIVAL_TEST_SRC = \ QPS_INTERARRIVAL_TEST_SRC = \
test/cpp/qps/qps_interarrival_test.cc \ test/cpp/qps/qps_interarrival_test.cc \
@ -14462,16 +14566,16 @@ $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: protobuf_dep_error
else else
$(BINDIR)/$(CONFIG)/server_context_test_spouse_test: $(PROTOBUF_DEP) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: $(PROTOBUF_DEP) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_context_test_spouse_test $(Q) $(LDXX) $(LDFLAGS) $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_context_test_spouse_test
endif endif
endif endif
$(OBJDIR)/$(CONFIG)/test/cpp/test/server_context_test_spouse_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/test/server_context_test_spouse_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_server_context_test_spouse_test: $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS:.o=.dep) deps_server_context_test_spouse_test: $(SERVER_CONTEXT_TEST_SPOUSE_TEST_OBJS:.o=.dep)
@ -17739,6 +17843,7 @@ ifneq ($(OPENSSL_DEP),)
# This is to ensure the embedded OpenSSL is built beforehand, properly # This is to ensure the embedded OpenSSL is built beforehand, properly
# installing headers to their final destination on the drive. We need this # installing headers to their final destination on the drive. We need this
# otherwise parallel compilation will fail if a source is compiled first. # otherwise parallel compilation will fail if a source is compiled first.
src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c: $(OPENSSL_DEP)
src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP)
src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP)
src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP)
@ -17760,6 +17865,7 @@ src/core/lib/security/credentials/oauth2/oauth2_credentials.c: $(OPENSSL_DEP)
src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP)
src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP)
src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP) src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP)
src/core/lib/security/transport/lb_targets_info.c: $(OPENSSL_DEP)
src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP) src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP)
src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP)
src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP) src/core/lib/security/transport/security_handshaker.c: $(OPENSSL_DEP)
@ -17782,7 +17888,6 @@ src/cpp/common/secure_create_auth_context.cc: $(OPENSSL_DEP)
src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP) src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP)
src/cpp/ext/proto_server_reflection_plugin.cc: $(OPENSSL_DEP) src/cpp/ext/proto_server_reflection_plugin.cc: $(OPENSSL_DEP)
src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP) src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP)
src/cpp/test/server_context_test_spouse.cc: $(OPENSSL_DEP)
src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP) src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP)
test/core/bad_client/bad_client.c: $(OPENSSL_DEP) test/core/bad_client/bad_client.c: $(OPENSSL_DEP)
test/core/bad_ssl/server_common.c: $(OPENSSL_DEP) test/core/bad_ssl/server_common.c: $(OPENSSL_DEP)

@ -758,6 +758,7 @@
'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/plugin/plugin_credentials.c',
'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c',
'src/core/lib/security/transport/client_auth_filter.c', 'src/core/lib/security/transport/client_auth_filter.c',
'src/core/lib/security/transport/lb_targets_info.c',
'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/secure_endpoint.c',
'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_connector.c',
'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/security_handshaker.c',
@ -798,6 +799,7 @@
'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
'src/core/ext/lb_policy/grpclb/grpclb.c', 'src/core/ext/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_common.c',

@ -31,6 +31,11 @@ filegroups:
- src/core/ext/census/resource.h - src/core/ext/census/resource.h
- src/core/ext/census/rpc_metric_id.h - src/core/ext/census/rpc_metric_id.h
- src/core/ext/census/trace_context.h - src/core/ext/census/trace_context.h
- src/core/ext/census/trace_label.h
- src/core/ext/census/trace_propagation.h
- src/core/ext/census/trace_status.h
- src/core/ext/census/trace_string.h
- src/core/ext/census/tracing.h
src: src:
- src/core/ext/census/base_resources.c - src/core/ext/census/base_resources.c
- src/core/ext/census/context.c - src/core/ext/census/context.c
@ -160,6 +165,7 @@ filegroups:
- include/grpc/grpc.h - include/grpc/grpc.h
- include/grpc/grpc_posix.h - include/grpc/grpc_posix.h
- include/grpc/grpc_security_constants.h - include/grpc/grpc_security_constants.h
- include/grpc/load_reporting.h
- include/grpc/slice.h - include/grpc/slice.h
- include/grpc/slice_buffer.h - include/grpc/slice_buffer.h
- include/grpc/status.h - include/grpc/status.h
@ -452,10 +458,28 @@ filegroups:
- name: grpc_lb_policy_grpclb - name: grpc_lb_policy_grpclb
headers: headers:
- src/core/ext/lb_policy/grpclb/grpclb.h - src/core/ext/lb_policy/grpclb/grpclb.h
- src/core/ext/lb_policy/grpclb/grpclb_channel.h
- src/core/ext/lb_policy/grpclb/load_balancer_api.h - src/core/ext/lb_policy/grpclb/load_balancer_api.h
- src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
src: src:
- src/core/ext/lb_policy/grpclb/grpclb.c - src/core/ext/lb_policy/grpclb/grpclb.c
- src/core/ext/lb_policy/grpclb/grpclb_channel.c
- src/core/ext/lb_policy/grpclb/load_balancer_api.c
- src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
plugin: grpc_lb_policy_grpclb
uses:
- grpc_base
- grpc_client_channel
- nanopb
- name: grpc_lb_policy_grpclb_secure
headers:
- src/core/ext/lb_policy/grpclb/grpclb.h
- src/core/ext/lb_policy/grpclb/grpclb_channel.h
- src/core/ext/lb_policy/grpclb/load_balancer_api.h
- src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
src:
- src/core/ext/lb_policy/grpclb/grpclb.c
- src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c
- src/core/ext/lb_policy/grpclb/load_balancer_api.c - src/core/ext/lb_policy/grpclb/load_balancer_api.c
- src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
plugin: grpc_lb_policy_grpclb plugin: grpc_lb_policy_grpclb
@ -518,6 +542,7 @@ filegroups:
- src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/plugin/plugin_credentials.h
- src/core/lib/security/credentials/ssl/ssl_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h
- src/core/lib/security/transport/auth_filters.h - src/core/lib/security/transport/auth_filters.h
- src/core/lib/security/transport/lb_targets_info.h
- src/core/lib/security/transport/secure_endpoint.h - src/core/lib/security/transport/secure_endpoint.h
- src/core/lib/security/transport/security_connector.h - src/core/lib/security/transport/security_connector.h
- src/core/lib/security/transport/security_handshaker.h - src/core/lib/security/transport/security_handshaker.h
@ -541,6 +566,7 @@ filegroups:
- src/core/lib/security/credentials/plugin/plugin_credentials.c - src/core/lib/security/credentials/plugin/plugin_credentials.c
- src/core/lib/security/credentials/ssl/ssl_credentials.c - src/core/lib/security/credentials/ssl/ssl_credentials.c
- src/core/lib/security/transport/client_auth_filter.c - src/core/lib/security/transport/client_auth_filter.c
- src/core/lib/security/transport/lb_targets_info.c
- src/core/lib/security/transport/secure_endpoint.c - src/core/lib/security/transport/secure_endpoint.c
- src/core/lib/security/transport/security_connector.c - src/core/lib/security/transport/security_connector.c
- src/core/lib/security/transport/security_handshaker.c - src/core/lib/security/transport/security_handshaker.c
@ -571,6 +597,7 @@ filegroups:
- test/core/util/port.h - test/core/util/port.h
- test/core/util/port_server_client.h - test/core/util/port_server_client.h
- test/core/util/slice_splitter.h - test/core/util/slice_splitter.h
- test/core/util/trickle_endpoint.h
src: src:
- test/core/end2end/cq_verifier.c - test/core/end2end/cq_verifier.c
- test/core/end2end/fake_resolver.c - test/core/end2end/fake_resolver.c
@ -588,6 +615,7 @@ filegroups:
- test/core/util/port_uv.c - test/core/util/port_uv.c
- test/core/util/port_windows.c - test/core/util/port_windows.c
- test/core/util/slice_splitter.c - test/core/util/slice_splitter.c
- test/core/util/trickle_endpoint.c
deps: deps:
- grpc - grpc
- gpr_test_util - gpr_test_util
@ -699,6 +727,7 @@ filegroups:
- include/grpc/grpc_security.h - include/grpc/grpc_security.h
- include/grpc/grpc_security_constants.h - include/grpc/grpc_security_constants.h
headers: headers:
- src/core/ext/transport/cronet/transport/cronet_transport.h
- third_party/objective_c/Cronet/bidirectional_stream_c.h - third_party/objective_c/Cronet/bidirectional_stream_c.h
src: src:
- src/core/ext/transport/cronet/client/secure/cronet_channel_create.c - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
@ -877,6 +906,12 @@ filegroups:
language: c++ language: c++
src: src:
- src/proto/grpc/reflection/v1alpha/reflection.proto - src/proto/grpc/reflection/v1alpha/reflection.proto
- name: grpc++_test
language: c++
public_headers:
- include/grpc++/test/server_context_test_spouse.h
deps:
- grpc++
- name: thrift_util - name: thrift_util
language: c++ language: c++
public_headers: public_headers:
@ -917,7 +952,7 @@ libs:
- grpc_transport_chttp2_client_secure - grpc_transport_chttp2_client_secure
- grpc_transport_chttp2_server_insecure - grpc_transport_chttp2_server_insecure
- grpc_transport_chttp2_client_insecure - grpc_transport_chttp2_client_insecure
- grpc_lb_policy_grpclb - grpc_lb_policy_grpclb_secure
- grpc_lb_policy_pick_first - grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin - grpc_lb_policy_round_robin
- grpc_resolver_dns_native - grpc_resolver_dns_native
@ -1071,6 +1106,7 @@ libs:
filegroups: filegroups:
- grpc++_base - grpc++_base
- grpc++_codegen_base - grpc++_codegen_base
- grpc++_codegen_proto
- grpc++_codegen_base_src - grpc++_codegen_base_src
secure: check secure: check
vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}' vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
@ -1123,15 +1159,6 @@ libs:
- grpc++ - grpc++
filegroups: filegroups:
- grpc++_reflection_proto - grpc++_reflection_proto
- name: grpc++_test
build: private
language: c++
headers:
- include/grpc++/test/server_context_test_spouse.h
src:
- src/cpp/test/server_context_test_spouse.cc
deps:
- grpc++
- name: grpc++_test_config - name: grpc++_test_config
build: private build: private
language: c++ language: c++
@ -2513,6 +2540,20 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: pollset_set_test
build: test
language: c
src:
- test/core/iomgr/pollset_set_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
exclude_iomgrs:
- uv
platforms:
- linux
- name: resolve_address_posix_test - name: resolve_address_posix_test
build: test build: test
language: c language: c
@ -2953,6 +2994,23 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: bm_closure
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_closure.cc
deps:
- benchmark
- grpc_test_util
- grpc
- gpr_test_util
- gpr
args:
- --benchmark_min_time=0
platforms:
- mac
- linux
- posix
- name: bm_fullstack - name: bm_fullstack
build: test build: test
language: c++ language: c++
@ -3464,6 +3522,18 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: proto_utils_test
gtest: true
build: test
language: c++
src:
- test/cpp/codegen/proto_utils_test.cc
deps:
- grpc++
- grpc
filegroups:
- grpc++_codegen_base
- grpc++_codegen_proto
- name: qps_interarrival_test - name: qps_interarrival_test
build: test build: test
run: false run: false
@ -3634,11 +3704,12 @@ targets:
- test/cpp/test/server_context_test_spouse_test.cc - test/cpp/test/server_context_test_spouse_test.cc
deps: deps:
- grpc_test_util - grpc_test_util
- grpc++_test
- grpc++ - grpc++
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
uses:
- grpc++_test
- name: server_crash_test - name: server_crash_test
gtest: true gtest: true
cpu_cost: 0.1 cpu_cost: 0.1
@ -3847,6 +3918,9 @@ configs:
basicprof: basicprof:
CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
DEFINES: NDEBUG DEFINES: NDEBUG
counters:
CPPFLAGS: -O2 -DGPR_MU_COUNTERS
DEFINES: NDEBUG
dbg: dbg:
CPPFLAGS: -O0 CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG DEFINES: _DEBUG DEBUG
@ -3923,7 +3997,7 @@ defaults:
CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
-D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
global: global:
CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
LDFLAGS: -g LDFLAGS: -g
zlib: zlib:
CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration CFLAGS: -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-implicit-function-declaration

@ -237,6 +237,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/credentials/plugin/plugin_credentials.c \ src/core/lib/security/credentials/plugin/plugin_credentials.c \
src/core/lib/security/credentials/ssl/ssl_credentials.c \ src/core/lib/security/credentials/ssl/ssl_credentials.c \
src/core/lib/security/transport/client_auth_filter.c \ src/core/lib/security/transport/client_auth_filter.c \
src/core/lib/security/transport/lb_targets_info.c \
src/core/lib/security/transport/secure_endpoint.c \ src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \ src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/security_handshaker.c \ src/core/lib/security/transport/security_handshaker.c \
@ -277,6 +278,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
src/core/ext/lb_policy/grpclb/grpclb.c \ src/core/ext/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \ third_party/nanopb/pb_common.c \

@ -162,6 +162,7 @@ Pod::Spec.new do |s|
'include/grpc/grpc.h', 'include/grpc/grpc.h',
'include/grpc/grpc_posix.h', 'include/grpc/grpc_posix.h',
'include/grpc/grpc_security_constants.h', 'include/grpc/grpc_security_constants.h',
'include/grpc/load_reporting.h',
'include/grpc/slice.h', 'include/grpc/slice.h',
'include/grpc/slice_buffer.h', 'include/grpc/slice_buffer.h',
'include/grpc/status.h', 'include/grpc/status.h',
@ -388,6 +389,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/auth_filters.h',
'src/core/lib/security/transport/lb_targets_info.h',
'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/secure_endpoint.h',
'src/core/lib/security/transport/security_connector.h', 'src/core/lib/security/transport/security_connector.h',
'src/core/lib/security/transport/security_handshaker.h', 'src/core/lib/security/transport/security_handshaker.h',
@ -420,6 +422,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/uri_parser.h', 'src/core/ext/client_channel/uri_parser.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/ext/lb_policy/grpclb/grpclb.h', 'src/core/ext/lb_policy/grpclb/grpclb.h',
'src/core/ext/lb_policy/grpclb/grpclb_channel.h',
'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'third_party/nanopb/pb.h', 'third_party/nanopb/pb.h',
@ -439,6 +442,11 @@ Pod::Spec.new do |s|
'src/core/ext/census/resource.h', 'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h', 'src/core/ext/census/rpc_metric_id.h',
'src/core/ext/census/trace_context.h', 'src/core/ext/census/trace_context.h',
'src/core/ext/census/trace_label.h',
'src/core/ext/census/trace_propagation.h',
'src/core/ext/census/trace_status.h',
'src/core/ext/census/trace_string.h',
'src/core/ext/census/tracing.h',
'src/core/lib/surface/init.c', 'src/core/lib/surface/init.c',
'src/core/lib/channel/channel_args.c', 'src/core/lib/channel/channel_args.c',
'src/core/lib/channel/channel_stack.c', 'src/core/lib/channel/channel_stack.c',
@ -596,6 +604,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/plugin/plugin_credentials.c', 'src/core/lib/security/credentials/plugin/plugin_credentials.c',
'src/core/lib/security/credentials/ssl/ssl_credentials.c', 'src/core/lib/security/credentials/ssl/ssl_credentials.c',
'src/core/lib/security/transport/client_auth_filter.c', 'src/core/lib/security/transport/client_auth_filter.c',
'src/core/lib/security/transport/lb_targets_info.c',
'src/core/lib/security/transport/secure_endpoint.c', 'src/core/lib/security/transport/secure_endpoint.c',
'src/core/lib/security/transport/security_connector.c', 'src/core/lib/security/transport/security_connector.c',
'src/core/lib/security/transport/security_handshaker.c', 'src/core/lib/security/transport/security_handshaker.c',
@ -636,6 +645,7 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
'src/core/ext/lb_policy/grpclb/grpclb.c', 'src/core/ext/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_common.c',
@ -813,6 +823,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/transport/auth_filters.h', 'src/core/lib/security/transport/auth_filters.h',
'src/core/lib/security/transport/lb_targets_info.h',
'src/core/lib/security/transport/secure_endpoint.h', 'src/core/lib/security/transport/secure_endpoint.h',
'src/core/lib/security/transport/security_connector.h', 'src/core/lib/security/transport/security_connector.h',
'src/core/lib/security/transport/security_handshaker.h', 'src/core/lib/security/transport/security_handshaker.h',
@ -845,6 +856,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/uri_parser.h', 'src/core/ext/client_channel/uri_parser.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/ext/lb_policy/grpclb/grpclb.h', 'src/core/ext/lb_policy/grpclb/grpclb.h',
'src/core/ext/lb_policy/grpclb/grpclb_channel.h',
'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'third_party/nanopb/pb.h', 'third_party/nanopb/pb.h',
@ -863,12 +875,18 @@ Pod::Spec.new do |s|
'src/core/ext/census/mlog.h', 'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h', 'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h', 'src/core/ext/census/rpc_metric_id.h',
'src/core/ext/census/trace_context.h' 'src/core/ext/census/trace_context.h',
'src/core/ext/census/trace_label.h',
'src/core/ext/census/trace_propagation.h',
'src/core/ext/census/trace_status.h',
'src/core/ext/census/trace_string.h',
'src/core/ext/census/tracing.h'
end end
s.subspec 'Cronet-Interface' do |ss| s.subspec 'Cronet-Interface' do |ss|
ss.header_mappings_dir = 'include/grpc' ss.header_mappings_dir = 'include/grpc'
ss.source_files = 'include/grpc/grpc_cronet.h' ss.source_files = 'include/grpc/grpc_cronet.h',
'src/core/ext/transport/cronet/transport/cronet_transport.h'
end end
s.subspec 'Cronet-Implementation' do |ss| s.subspec 'Cronet-Implementation' do |ss|

@ -69,6 +69,7 @@ EXPORTS
grpc_channel_create_registered_call grpc_channel_create_registered_call
grpc_call_start_batch grpc_call_start_batch
grpc_call_get_peer grpc_call_get_peer
grpc_call_set_load_reporting_cost_context
grpc_census_call_set_context grpc_census_call_set_context
grpc_census_call_get_context grpc_census_call_get_context
grpc_channel_get_target grpc_channel_get_target

@ -143,6 +143,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/grpc.h ) s.files += %w( include/grpc/grpc.h )
s.files += %w( include/grpc/grpc_posix.h ) s.files += %w( include/grpc/grpc_posix.h )
s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/grpc_security_constants.h )
s.files += %w( include/grpc/load_reporting.h )
s.files += %w( include/grpc/slice.h ) s.files += %w( include/grpc/slice.h )
s.files += %w( include/grpc/slice_buffer.h ) s.files += %w( include/grpc/slice_buffer.h )
s.files += %w( include/grpc/status.h ) s.files += %w( include/grpc/status.h )
@ -305,6 +306,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
s.files += %w( src/core/lib/security/transport/auth_filters.h ) s.files += %w( src/core/lib/security/transport/auth_filters.h )
s.files += %w( src/core/lib/security/transport/lb_targets_info.h )
s.files += %w( src/core/lib/security/transport/secure_endpoint.h ) s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
s.files += %w( src/core/lib/security/transport/security_connector.h ) s.files += %w( src/core/lib/security/transport/security_connector.h )
s.files += %w( src/core/lib/security/transport/security_handshaker.h ) s.files += %w( src/core/lib/security/transport/security_handshaker.h )
@ -337,6 +339,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/uri_parser.h ) s.files += %w( src/core/ext/client_channel/uri_parser.h )
s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h ) s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.h ) s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.h )
s.files += %w( src/core/ext/lb_policy/grpclb/grpclb_channel.h )
s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h )
s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
s.files += %w( third_party/nanopb/pb.h ) s.files += %w( third_party/nanopb/pb.h )
@ -356,6 +359,11 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/resource.h ) s.files += %w( src/core/ext/census/resource.h )
s.files += %w( src/core/ext/census/rpc_metric_id.h ) s.files += %w( src/core/ext/census/rpc_metric_id.h )
s.files += %w( src/core/ext/census/trace_context.h ) s.files += %w( src/core/ext/census/trace_context.h )
s.files += %w( src/core/ext/census/trace_label.h )
s.files += %w( src/core/ext/census/trace_propagation.h )
s.files += %w( src/core/ext/census/trace_status.h )
s.files += %w( src/core/ext/census/trace_string.h )
s.files += %w( src/core/ext/census/tracing.h )
s.files += %w( src/core/lib/surface/init.c ) s.files += %w( src/core/lib/surface/init.c )
s.files += %w( src/core/lib/channel/channel_args.c ) s.files += %w( src/core/lib/channel/channel_args.c )
s.files += %w( src/core/lib/channel/channel_stack.c ) s.files += %w( src/core/lib/channel/channel_stack.c )
@ -513,6 +521,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c )
s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c )
s.files += %w( src/core/lib/security/transport/client_auth_filter.c ) s.files += %w( src/core/lib/security/transport/client_auth_filter.c )
s.files += %w( src/core/lib/security/transport/lb_targets_info.c )
s.files += %w( src/core/lib/security/transport/secure_endpoint.c ) s.files += %w( src/core/lib/security/transport/secure_endpoint.c )
s.files += %w( src/core/lib/security/transport/security_connector.c ) s.files += %w( src/core/lib/security/transport/security_connector.c )
s.files += %w( src/core/lib/security/transport/security_handshaker.c ) s.files += %w( src/core/lib/security/transport/security_handshaker.c )
@ -553,6 +562,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c )
s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.c ) s.files += %w( src/core/ext/lb_policy/grpclb/grpclb.c )
s.files += %w( src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c )
s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c )
s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
s.files += %w( third_party/nanopb/pb_common.c ) s.files += %w( third_party/nanopb/pb_common.c )

@ -618,7 +618,17 @@ class Call final {
public: public:
/* call is owned by the caller */ /* call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq) Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), cq_(cq), call_(call) {} : call_hook_(call_hook),
cq_(cq),
call_(call),
max_receive_message_size_(-1) {}
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_receive_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_receive_message_size_(max_receive_message_size) {}
void PerformOps(CallOpSetInterface* ops) { void PerformOps(CallOpSetInterface* ops) {
call_hook_->PerformOpsOnCall(ops, this); call_hook_->PerformOpsOnCall(ops, this);
@ -627,10 +637,13 @@ class Call final {
grpc_call* call() const { return call_; } grpc_call* call() const { return call_; }
CompletionQueue* cq() const { return cq_; } CompletionQueue* cq() const { return cq_; }
int max_receive_message_size() const { return max_receive_message_size_; }
private: private:
CallHook* call_hook_; CallHook* call_hook_;
CompletionQueue* cq_; CompletionQueue* cq_;
grpc_call* call_; grpc_call* call_;
int max_receive_message_size_;
}; };
} // namespace grpc } // namespace grpc

@ -50,6 +50,8 @@ extern CoreCodegenInterface* g_core_codegen_interface;
namespace internal { namespace internal {
class GrpcBufferWriterPeer;
const int kGrpcBufferWriterMaxBufferLength = 8192; const int kGrpcBufferWriterMaxBufferLength = 8192;
class GrpcBufferWriter final class GrpcBufferWriter final
@ -91,13 +93,18 @@ class GrpcBufferWriter final
&slice_, GRPC_SLICE_LENGTH(slice_) - count); &slice_, GRPC_SLICE_LENGTH(slice_) - count);
g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
} }
have_backup_ = true; // It's dangerous to keep an inlined grpc_slice as the backup slice, since
// on a following Next() call, a reference will be returned to this slice
// via GRPC_SLICE_START_PTR, which will not be an adddress held by
// slice_buffer_.
have_backup_ = backup_slice_.refcount != NULL;
byte_count_ -= count; byte_count_ -= count;
} }
grpc::protobuf::int64 ByteCount() const override { return byte_count_; } grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
private: private:
friend class GrpcBufferWriterPeer;
const int block_size_; const int block_size_;
int64_t byte_count_; int64_t byte_count_;
grpc_slice_buffer* slice_buffer_; grpc_slice_buffer* slice_buffer_;

@ -36,6 +36,10 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <vector>
#include <grpc/impl/codegen/compression_types.h>
#include <grpc/load_reporting.h>
#include <grpc++/impl/codegen/config.h> #include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/create_auth_context.h> #include <grpc++/impl/codegen/create_auth_context.h>
@ -43,14 +47,12 @@
#include <grpc++/impl/codegen/security/auth_context.h> #include <grpc++/impl/codegen/security/auth_context.h>
#include <grpc++/impl/codegen/string_ref.h> #include <grpc++/impl/codegen/string_ref.h>
#include <grpc++/impl/codegen/time.h> #include <grpc++/impl/codegen/time.h>
#include <grpc/impl/codegen/compression_types.h>
struct grpc_metadata; struct grpc_metadata;
struct grpc_call; struct grpc_call;
struct census_context; struct census_context;
namespace grpc { namespace grpc {
class ClientContext; class ClientContext;
template <class W, class R> template <class W, class R>
class ServerAsyncReader; class ServerAsyncReader;
@ -143,6 +145,9 @@ class ServerContext {
} }
void set_compression_algorithm(grpc_compression_algorithm algorithm); void set_compression_algorithm(grpc_compression_algorithm algorithm);
// Set the load reporting costs in \a cost_data for the call.
void SetLoadReportingCosts(const std::vector<grpc::string>& cost_data);
std::shared_ptr<const AuthContext> auth_context() const { std::shared_ptr<const AuthContext> auth_context() const {
if (auth_context_.get() == nullptr) { if (auth_context_.get() == nullptr) {
auth_context_ = CreateAuthContext(call_); auth_context_ = CreateAuthContext(call_);

@ -160,7 +160,7 @@ class ClientReader final : public ClientReaderInterface<R> {
} }
bool NextMessageSize(uint32_t* sz) override { bool NextMessageSize(uint32_t* sz) override {
*sz = INT_MAX; *sz = call_.max_receive_message_size();
return true; return true;
} }
@ -310,7 +310,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
} }
bool NextMessageSize(uint32_t* sz) override { bool NextMessageSize(uint32_t* sz) override {
*sz = INT_MAX; *sz = call_.max_receive_message_size();
return true; return true;
} }
@ -382,7 +382,7 @@ class ServerReader final : public ServerReaderInterface<R> {
} }
bool NextMessageSize(uint32_t* sz) override { bool NextMessageSize(uint32_t* sz) override {
*sz = INT_MAX; *sz = call_->max_receive_message_size();
return true; return true;
} }
@ -474,7 +474,7 @@ class ServerReaderWriterBody final {
} }
bool NextMessageSize(uint32_t* sz) { bool NextMessageSize(uint32_t* sz) {
*sz = INT_MAX; *sz = call_->max_receive_message_size();
return true; return true;
} }

@ -86,6 +86,8 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
virtual void PreSynchronousRequest(ServerContext* context) = 0; virtual void PreSynchronousRequest(ServerContext* context) = 0;
/// Called after application callback for each synchronous server request /// Called after application callback for each synchronous server request
virtual void PostSynchronousRequest(ServerContext* context) = 0; virtual void PostSynchronousRequest(ServerContext* context) = 0;
/// Called before server is started.
virtual void PreServerStart(Server* server) {}
}; };
/// Set the global callback object. Can only be called once. Does not take /// Set the global callback object. Can only be called once. Does not take
/// ownership of callbacks, and expects the pointed to object to be alive /// ownership of callbacks, and expects the pointed to object to be alive

@ -48,10 +48,23 @@ class ServerContextTestSpouse {
// Inject client metadata to the ServerContext for the test. The test spouse // Inject client metadata to the ServerContext for the test. The test spouse
// must be alive when ServerContext::client_metadata is called. // must be alive when ServerContext::client_metadata is called.
void AddClientMetadata(const grpc::string& key, const grpc::string& value); void AddClientMetadata(const grpc::string& key, const grpc::string& value) {
client_metadata_storage_.insert(
std::pair<grpc::string, grpc::string>(key, value));
ctx_->client_metadata_.map()->clear();
for (auto iter = client_metadata_storage_.begin();
iter != client_metadata_storage_.end(); ++iter) {
ctx_->client_metadata_.map()->insert(
std::pair<grpc::string_ref, grpc::string_ref>(
iter->first.c_str(),
grpc::string_ref(iter->second.data(), iter->second.size())));
}
}
std::multimap<grpc::string, grpc::string> GetInitialMetadata() const { std::multimap<grpc::string, grpc::string> GetInitialMetadata() const {
return ctx_->initial_metadata_; return ctx_->initial_metadata_;
} }
std::multimap<grpc::string, grpc::string> GetTrailingMetadata() const { std::multimap<grpc::string, grpc::string> GetTrailingMetadata() const {
return ctx_->trailing_metadata_; return ctx_->trailing_metadata_;
} }

@ -229,14 +229,20 @@ GRPCAPI grpc_call_error grpc_call_start_batch(grpc_call *call,
functionality. Instead, use grpc_auth_context. */ functionality. Instead, use grpc_auth_context. */
GRPCAPI char *grpc_call_get_peer(grpc_call *call); GRPCAPI char *grpc_call_get_peer(grpc_call *call);
struct grpc_load_reporting_cost_context;
/* Associate costs contained in \a cost_context to \a call. */
GRPCAPI void grpc_call_set_load_reporting_cost_context(
grpc_call *call, struct grpc_load_reporting_cost_context *context);
struct census_context; struct census_context;
/* Set census context for a call; Must be called before first call to /** Set census context for a call; Must be called before first call to
grpc_call_start_batch(). */ grpc_call_start_batch(). */
GRPCAPI void grpc_census_call_set_context(grpc_call *call, GRPCAPI void grpc_census_call_set_context(grpc_call *call,
struct census_context *context); struct census_context *context);
/* Retrieve the calls current census context. */ /** Retrieve the calls current census context. */
GRPCAPI struct census_context *grpc_census_call_get_context(grpc_call *call); GRPCAPI struct census_context *grpc_census_call_get_context(grpc_call *call);
/** Return a newly allocated string representing the target a channel was /** Return a newly allocated string representing the target a channel was

@ -179,6 +179,8 @@ typedef struct {
Larger values give lower CPU usage for large messages, but more head of line Larger values give lower CPU usage for large messages, but more head of line
blocking for small messages. */ blocking for small messages. */
#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? */
#define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe"
/** Minimum time (in milliseconds) between successive ping frames being sent */ /** Minimum time (in milliseconds) between successive ping frames being sent */
#define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \ #define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \
"grpc.http2.min_time_between_pings_ms" "grpc.http2.min_time_between_pings_ms"
@ -220,12 +222,18 @@ typedef struct {
/** If non-zero, a pointer to a buffer pool (use grpc_resource_quota_arg_vtable /** If non-zero, a pointer to a buffer pool (use grpc_resource_quota_arg_vtable
to fetch an appropriate pointer arg vtable) */ to fetch an appropriate pointer arg vtable) */
#define GRPC_ARG_RESOURCE_QUOTA "grpc.resource_quota" #define GRPC_ARG_RESOURCE_QUOTA "grpc.resource_quota"
/** If non-zero, expand wildcard addresses to a list of local addresses. */
#define GRPC_ARG_EXPAND_WILDCARD_ADDRS "grpc.expand_wildcard_addrs"
/** Service config data in JSON form. Not intended for use outside of tests. */ /** Service config data in JSON form. Not intended for use outside of tests. */
#define GRPC_ARG_SERVICE_CONFIG "grpc.service_config" #define GRPC_ARG_SERVICE_CONFIG "grpc.service_config"
/** LB policy name. */ /** LB policy name. */
#define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name" #define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name"
/** The grpc_socket_mutator instance that set the socket options. A pointer. */ /** The grpc_socket_mutator instance that set the socket options. A pointer. */
#define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator" #define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator"
/** If non-zero, Cronet transport will coalesce packets to fewer frames when
* possible. */
#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \
"grpc.use_cronet_packet_coalescing"
/** \} */ /** \} */
/** Result of a grpc call. If the caller satisfies the prerequisites of a /** Result of a grpc call. If the caller satisfies the prerequisites of a

@ -0,0 +1,63 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_LOAD_REPORTING_H
#define GRPC_LOAD_REPORTING_H
#include <grpc/impl/codegen/port_platform.h>
#include <grpc/slice.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Metadata key for the gRPC LB load balancer token.
*
* The value corresponding to this key is an opaque token that is given to the
* frontend as part of each pick; the frontend sends this token to the backend
* in each request it sends when using that pick. The token is used by the
* backend to verify the request and to allow the backend to report load to the
* gRPC LB system. */
#define GRPC_LB_TOKEN_MD_KEY "lb-token"
/** A sequence of values for load reporting purposes */
typedef struct grpc_load_reporting_cost_context {
grpc_slice *values;
size_t values_count;
} grpc_load_reporting_cost_context;
#ifdef __cplusplus
}
#endif
#endif /* GRPC_LOAD_REPORTING_H */

@ -74,4 +74,7 @@
#define GPR_ICMP(a, b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0)) #define GPR_ICMP(a, b) ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0))
#define GPR_HASH_POINTER(x, range) \
((((size_t)x) >> 4) ^ (((size_t)x) >> 9) ^ (((size_t)x) >> 14)) % (range)
#endif /* GRPC_SUPPORT_USEFUL_H */ #endif /* GRPC_SUPPORT_USEFUL_H */

@ -152,6 +152,7 @@
<file baseinstalldir="/" name="include/grpc/grpc.h" role="src" /> <file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" /> <file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" /> <file baseinstalldir="/" name="include/grpc/grpc_security_constants.h" role="src" />
<file baseinstalldir="/" name="include/grpc/load_reporting.h" role="src" />
<file baseinstalldir="/" name="include/grpc/slice.h" role="src" /> <file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" /> <file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/status.h" role="src" /> <file baseinstalldir="/" name="include/grpc/status.h" role="src" />
@ -314,6 +315,7 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/lb_targets_info.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" />
@ -346,6 +348,7 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" /> <file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
@ -365,6 +368,11 @@
<file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_context.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/census/trace_context.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_label.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_propagation.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_status.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_string.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/tracing.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/channel/channel_stack.c" role="src" />
@ -522,6 +530,7 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/lb_targets_info.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.c" role="src" />
@ -562,6 +571,7 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/load_balancer_api.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" /> <file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />

@ -31,23 +31,31 @@
* *
*/ */
#include <grpc++/test/server_context_test_spouse.h> #ifndef GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H
#define GRPC_CORE_EXT_CENSUS_TRACE_LABEL_H
namespace grpc { #include "src/core/ext/census/trace_string.h"
namespace testing {
void ServerContextTestSpouse::AddClientMetadata(const grpc::string& key, /* Trace label (key/value pair) stores a label name and the label value. The
const grpc::string& value) { value can be one of trace_string/int64_t/bool. */
client_metadata_storage_.insert( typedef struct trace_label {
std::pair<grpc::string, grpc::string>(key, value)); trace_string key;
ctx_->client_metadata_.map()->clear(); enum label_type {
for (auto iter = client_metadata_storage_.begin(); /* Unknown value for debugging/error purposes */
iter != client_metadata_storage_.end(); ++iter) { LABEL_UNKNOWN = 0,
ctx_->client_metadata_.map()->insert( /* A string value */
std::pair<grpc::string_ref, grpc::string_ref>(iter->first.c_str(), LABEL_STRING = 1,
iter->second.c_str())); /* An integer value. */
} LABEL_INT = 2,
} /* A boolean value. */
LABEL_BOOL = 3,
} value_type;
} // namespace testing union value {
} // namespace grpc trace_string label_str;
int64_t label_int;
bool label_bool;
} value;
} trace_label;
#endif

@ -0,0 +1,63 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H
#define GRPC_CORE_EXT_CENSUS_TRACE_PROPAGATION_H
#include "src/core/ext/census/tracing.h"
/* Encoding and decoding functions for receiving and sending trace contexts
over the wire. Only RPC libraries should be calling these
functions. These functions return the number of bytes encoded/decoded
(0 if a failure has occurred). buf_size indicates the size of the
input/output buffer. trace_span_context is a struct that includes the
trace ID, span ID, and a set of option flags (is_sampled, etc.). */
/* Converts a span context to a binary byte buffer. */
size_t trace_span_context_to_binary(const trace_span_context *ctxt,
uint8_t *buf, size_t buf_size);
/* Reads a binary byte buffer and populates a span context structure. */
size_t binary_to_trace_span_context(const uint8_t *buf, size_t buf_size,
trace_span_context *ctxt);
/* Converts a span context to an http metadata compatible string. */
size_t trace_span_context_to_http_format(const trace_span_context *ctxt,
char *buf, size_t buf_size);
/* Reads an http metadata compatible string and populates a span context
structure. */
size_t http_format_to_trace_span_context(const char *buf, size_t buf_size,
trace_span_context *ctxt);
#endif

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

@ -0,0 +1,50 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_CENSUS_TRACE_STRING_H
#define GRPC_CORE_EXT_CENSUS_TRACE_STRING_H
#include <grpc/slice.h>
/* String struct for tracing messages. Since this is a C API, we do not have
access to a string class. This is intended for use by higher level
languages which wrap around the C API, as most of them have a string class.
This will also be more efficient when copying, as we have an explicitly
specified length. Also, grpc_slice has reference counting which allows for
interning. */
typedef struct trace_string {
char *string;
size_t length;
} trace_string;
#endif

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,21 +31,41 @@
* *
*/ */
//#include "src/core/ext/census/tracing.h" #include "src/core/ext/census/tracing.h"
#include <grpc/census.h> #include <grpc/census.h>
#include <stdlib.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <openssl/rand.h>
#include "src/core/ext/census/mlog.h"
/* TODO(aveitch): These are all placeholder implementations. */ void trace_start_span(const trace_span_context *span_ctxt,
const trace_string name, const start_span_options *opts,
trace_span_context *new_span_ctxt,
bool has_remote_parent) {
// Noop implementation.
}
void trace_add_span_annotation(const trace_string description,
const trace_label *labels, const size_t n_labels,
trace_span_context *span_ctxt) {
// Noop implementation.
}
int census_trace_mask(const census_context *context) { void trace_add_span_network_event_annotation(const trace_string description,
abort(); const trace_label *labels,
return CENSUS_TRACE_MASK_NONE; const size_t n_labels,
const gpr_timespec timestamp,
bool sent, uint64_t id,
trace_span_context *span_ctxt) {
// Noop implementation.
} }
void census_set_trace_mask(int trace_mask) { abort(); } void trace_add_span_labels(const trace_label *labels, const size_t n_labels,
trace_span_context *span_ctxt) {
// Noop implementation.
}
void census_trace_print(census_context *context, uint32_t type, void trace_end_span(const trace_status *status, trace_span_context *span_ctxt) {
const char *buffer, size_t n) { // Noop implementation.
abort();
} }

@ -0,0 +1,124 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_CENSUS_TRACING_H
#define GRPC_CORE_EXT_CENSUS_TRACING_H
#include <grpc/support/time.h>
#include <stdbool.h>
#include "src/core/ext/census/trace_context.h"
#include "src/core/ext/census/trace_label.h"
#include "src/core/ext/census/trace_status.h"
/* This is the low level tracing API that other languages will interface with.
This is not intended to be accessed by the end-user, therefore it has been
designed with performance in mind rather than ease of use. */
/* The tracing level. */
enum TraceLevel {
/* Annotations on this context will be silently discarded. */
NO_TRACING = 0,
/* Annotations will not be saved to a persistent store. They will be
available via local APIs only. This setting is not propagated to child
spans. */
TRANSIENT_TRACING = 1,
/* Annotations are recorded for the entire distributed trace and they are
saved to a persistent store. This setting is propagated to child spans. */
PERSISTENT_TRACING = 2,
};
typedef struct trace_span_context {
/* Trace span context stores Span ID, Trace ID, and option flags. */
/* Trace ID is 128 bits split into 2 64-bit chunks (hi and lo). */
uint64_t trace_id_hi;
uint64_t trace_id_lo;
/* Span ID is 64 bits. */
uint64_t span_id;
/* Span-options is 32-bit value which contains flag options. */
uint32_t span_options;
} trace_span_context;
typedef struct start_span_options {
/* If set, this will override the Span.local_start_time for the Span. */
gpr_timespec local_start_timestamp;
/* Linked spans can be used to identify spans that are linked to this span in
a different trace. This can be used (for example) in batching operations,
where a single batch handler processes multiple requests from different
traces. If set, points to a list of Spans are linked to the created Span.*/
trace_span_context *linked_spans;
/* The number of linked spans. */
size_t n_linked_spans;
} start_span_options;
/* Create a new child Span (or root if parent is NULL), with parent being the
designated Span. The child span will have the provided name and starting
span options (optional). The bool has_remote_parent marks whether the
context refers to a remote parent span or not. */
void trace_start_span(const trace_span_context *span_ctxt,
const trace_string name, const start_span_options *opts,
trace_span_context *new_span_ctxt,
bool has_remote_parent);
/* Add a new Annotation to the Span. Annotations consist of a description
(trace_string) and a set of n labels (trace_label). This can be populated
with arbitrary user data. */
void trace_add_span_annotation(const trace_string description,
const trace_label *labels, const size_t n_labels,
trace_span_context *span_ctxt);
/* Add a new NetworkEvent annotation to a Span. This function is only intended
to be used by RPC systems (either client or server), not by higher level
applications. The timestamp type will be system-defined, the sent argument
designates whether this is a network send event (client request, server
reply)or receive (server request, client reply). The id argument corresponds
to Span.Annotation.NetworkEvent.id from the data model, and serves to uniquely
identify each network message. */
void trace_add_span_network_event(const trace_string description,
const trace_label *labels,
const size_t n_labels,
const gpr_timespec timestamp, bool sent,
uint64_t id, trace_span_context *span_ctxt);
/* Add a set of labels to the Span. These will correspond to the field
Span.labels in the data model. */
void trace_add_span_labels(const trace_label *labels, const size_t n_labels,
trace_span_context *span_ctxt);
/* Mark the end of Span Execution with the given status. Only the timing of the
first EndSpan call for a given Span will be recorded, and implementations are
free to ignore all further calls using the Span. EndSpanOptions can
optionally be NULL. */
void trace_end_span(const trace_status *status, trace_span_context *span_ctxt);
#endif

@ -44,13 +44,14 @@
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/ext/client_channel/http_connect_handshaker.h" #include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/http_proxy.h"
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/subchannel.h" #include "src/core/ext/client_channel/subchannel.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/channel/deadline_filter.h" #include "src/core/lib/channel/deadline_filter.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
@ -153,10 +154,6 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
*/ */
typedef struct client_channel_channel_data { typedef struct client_channel_channel_data {
/** server name */
char *server_name;
/** HTTP CONNECT proxy to use, if any */
char *proxy_name;
/** resolver for this channel */ /** resolver for this channel */
grpc_resolver *resolver; grpc_resolver *resolver;
/** have we started resolving this channel */ /** have we started resolving this channel */
@ -164,13 +161,10 @@ typedef struct client_channel_channel_data {
/** client channel factory */ /** client channel factory */
grpc_client_channel_factory *client_channel_factory; grpc_client_channel_factory *client_channel_factory;
/** mutex protecting all variables below in this data structure */ /** combiner protecting all variables below in this data structure */
gpr_mu mu; grpc_combiner *combiner;
/** currently active load balancer */ /** currently active load balancer */
char *lb_policy_name;
grpc_lb_policy *lb_policy; grpc_lb_policy *lb_policy;
/** service config in JSON form */
char *service_config_json;
/** maps method names to method_parameters structs */ /** maps method names to method_parameters structs */
grpc_slice_hash_table *method_params_table; grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */ /** incoming resolver result - set by resolver.next() */
@ -187,6 +181,13 @@ typedef struct client_channel_channel_data {
grpc_channel_stack *owning_stack; grpc_channel_stack *owning_stack;
/** interested parties (owned) */ /** interested parties (owned) */
grpc_pollset_set *interested_parties; grpc_pollset_set *interested_parties;
/* the following properties are guarded by a mutex since API's require them
to be instantaniously available */
gpr_mu info_mu;
char *info_lb_policy_name;
/** service config in JSON form */
char *info_service_config_json;
} channel_data; } channel_data;
/** We create one watcher for each new lb_policy that is returned from a /** We create one watcher for each new lb_policy that is returned from a
@ -222,32 +223,23 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
} }
static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx, static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
lb_policy_connectivity_watcher *w, void *arg, grpc_error *error) {
grpc_error *error) { lb_policy_connectivity_watcher *w = arg;
grpc_connectivity_state publish_state = w->state; grpc_connectivity_state publish_state = w->state;
/* check if the notification is for a stale policy */ /* check if the notification is for the latest policy */
if (w->lb_policy != w->chand->lb_policy) return; if (w->lb_policy == w->chand->lb_policy) {
if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) { publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE; grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver); GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel"); w->chand->lb_policy = NULL;
w->chand->lb_policy = NULL; }
} set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state, GRPC_ERROR_REF(error), "lb_changed");
GRPC_ERROR_REF(error), "lb_changed"); if (w->state != GRPC_CHANNEL_SHUTDOWN) {
if (w->state != GRPC_CHANNEL_SHUTDOWN) { watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state); }
} }
}
static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
lb_policy_connectivity_watcher *w = arg;
gpr_mu_lock(&w->chand->mu);
on_lb_policy_state_changed_locked(exec_ctx, w, error);
gpr_mu_unlock(&w->chand->mu);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy"); GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
gpr_free(w); gpr_free(w);
@ -260,16 +252,16 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy"); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
w->chand = chand; w->chand = chand;
grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w, grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
grpc_schedule_on_exec_ctx); grpc_combiner_scheduler(chand->combiner, false));
w->state = current_state; w->state = current_state;
w->lb_policy = lb_policy; w->lb_policy = lb_policy;
grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state, grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
&w->on_changed); &w->on_changed);
} }
static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg, static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_error *error) { void *arg, grpc_error *error) {
channel_data *chand = arg; channel_data *chand = arg;
char *lb_policy_name = NULL; char *lb_policy_name = NULL;
grpc_lb_policy *lb_policy = NULL; grpc_lb_policy *lb_policy = NULL;
@ -317,17 +309,6 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
// Use pick_first if nothing was specified and we didn't select grpclb // Use pick_first if nothing was specified and we didn't select grpclb
// above. // above.
if (lb_policy_name == NULL) lb_policy_name = "pick_first"; if (lb_policy_name == NULL) lb_policy_name = "pick_first";
// If using a proxy, add channel arg for server in HTTP CONNECT request.
if (chand->proxy_name != NULL) {
grpc_arg new_arg;
new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
new_arg.type = GRPC_ARG_STRING;
new_arg.value.string = chand->server_name;
grpc_channel_args *tmp_args = chand->resolver_result;
chand->resolver_result =
grpc_channel_args_copy_and_add(chand->resolver_result, &new_arg, 1);
grpc_channel_args_destroy(exec_ctx, tmp_args);
}
// Instantiate LB policy. // Instantiate LB policy.
grpc_lb_policy_args lb_policy_args; grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result; lb_policy_args.args = chand->resolver_result;
@ -368,17 +349,18 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
chand->interested_parties); chand->interested_parties);
} }
gpr_mu_lock(&chand->mu); gpr_mu_lock(&chand->info_mu);
if (lb_policy_name != NULL) { if (lb_policy_name != NULL) {
gpr_free(chand->lb_policy_name); gpr_free(chand->info_lb_policy_name);
chand->lb_policy_name = lb_policy_name; chand->info_lb_policy_name = lb_policy_name;
} }
old_lb_policy = chand->lb_policy; old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy; chand->lb_policy = lb_policy;
if (service_config_json != NULL) { if (service_config_json != NULL) {
gpr_free(chand->service_config_json); gpr_free(chand->info_service_config_json);
chand->service_config_json = service_config_json; chand->info_service_config_json = service_config_json;
} }
gpr_mu_unlock(&chand->info_mu);
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table); grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
} }
@ -406,7 +388,6 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result, grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
&chand->on_resolver_result_changed); &chand->on_resolver_result_changed);
gpr_mu_unlock(&chand->mu);
} else { } else {
if (chand->resolver != NULL) { if (chand->resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, chand->resolver); grpc_resolver_shutdown(exec_ctx, chand->resolver);
@ -419,7 +400,6 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs, GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
GPR_ARRAY_SIZE(refs)), GPR_ARRAY_SIZE(refs)),
"resolver_gone"); "resolver_gone");
gpr_mu_unlock(&chand->mu);
} }
if (exit_idle) { if (exit_idle) {
@ -441,20 +421,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_UNREF(state_error); GRPC_ERROR_UNREF(state_error);
} }
static void cc_start_transport_op(grpc_exec_ctx *exec_ctx, static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_channel_element *elem, grpc_error *error_ignored) {
grpc_transport_op *op) { grpc_transport_op *op = arg;
grpc_channel_element *elem = op->transport_private.args[0];
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
GPR_ASSERT(op->set_accept_stream == false);
if (op->bind_pollset != NULL) {
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
op->bind_pollset);
}
gpr_mu_lock(&chand->mu);
if (op->on_connectivity_state_change != NULL) { if (op->on_connectivity_state_change != NULL) {
grpc_connectivity_state_notify_on_state_change( grpc_connectivity_state_notify_on_state_change(
exec_ctx, &chand->state_tracker, op->connectivity_state, exec_ctx, &chand->state_tracker, op->connectivity_state,
@ -497,25 +469,48 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
} }
GRPC_ERROR_UNREF(op->disconnect_with_error); GRPC_ERROR_UNREF(op->disconnect_with_error);
} }
gpr_mu_unlock(&chand->mu); GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
}
static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_transport_op *op) {
channel_data *chand = elem->channel_data;
GPR_ASSERT(op->set_accept_stream == false);
if (op->bind_pollset != NULL) {
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
op->bind_pollset);
}
op->transport_private.args[0] = elem;
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
grpc_closure_sched(
exec_ctx, grpc_closure_init(
&op->transport_private.closure, start_transport_op_locked,
op, grpc_combiner_scheduler(chand->combiner, false)),
GRPC_ERROR_NONE);
} }
static void cc_get_channel_info(grpc_exec_ctx *exec_ctx, static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
const grpc_channel_info *info) { const grpc_channel_info *info) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
gpr_mu_lock(&chand->mu); gpr_mu_lock(&chand->info_mu);
if (info->lb_policy_name != NULL) { if (info->lb_policy_name != NULL) {
*info->lb_policy_name = chand->lb_policy_name == NULL *info->lb_policy_name = chand->info_lb_policy_name == NULL
? NULL ? NULL
: gpr_strdup(chand->lb_policy_name); : gpr_strdup(chand->info_lb_policy_name);
} }
if (info->service_config_json != NULL) { if (info->service_config_json != NULL) {
*info->service_config_json = chand->service_config_json == NULL *info->service_config_json =
? NULL chand->info_service_config_json == NULL
: gpr_strdup(chand->service_config_json); ? NULL
: gpr_strdup(chand->info_service_config_json);
} }
gpr_mu_unlock(&chand->mu); gpr_mu_unlock(&chand->info_mu);
} }
/* Constructor for channel_data */ /* Constructor for channel_data */
@ -527,11 +522,12 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(args->is_last); GPR_ASSERT(args->is_last);
GPR_ASSERT(elem->filter == &grpc_client_channel_filter); GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
// Initialize data members. // Initialize data members.
gpr_mu_init(&chand->mu); chand->combiner = grpc_combiner_create(NULL);
gpr_mu_init(&chand->info_mu);
chand->owning_stack = args->channel_stack; chand->owning_stack = args->channel_stack;
grpc_closure_init(&chand->on_resolver_result_changed, grpc_closure_init(&chand->on_resolver_result_changed,
on_resolver_result_changed, chand, on_resolver_result_changed_locked, chand,
grpc_schedule_on_exec_ctx); grpc_combiner_scheduler(chand->combiner, false));
chand->interested_parties = grpc_pollset_set_create(); chand->interested_parties = grpc_pollset_set_create();
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
"client_channel"); "client_channel");
@ -542,24 +538,21 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(arg->type == GRPC_ARG_POINTER); GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
grpc_client_channel_factory_ref(arg->value.pointer.p); grpc_client_channel_factory_ref(arg->value.pointer.p);
chand->client_channel_factory = arg->value.pointer.p; chand->client_channel_factory = arg->value.pointer.p;
// Instantiate resolver. // Get server name to resolve, using proxy mapper if needed.
arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI); arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL); GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING); GPR_ASSERT(arg->type == GRPC_ARG_STRING);
grpc_uri *uri = grpc_uri_parse(arg->value.string, true); char *proxy_name = NULL;
if (uri == NULL) return GRPC_ERROR_CREATE("cannot parse server URI"); grpc_channel_args *new_args = NULL;
if (uri->path[0] == '\0') { grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
grpc_uri_destroy(uri); &proxy_name, &new_args);
return GRPC_ERROR_CREATE("server URI is missing path"); // Instantiate resolver.
}
chand->server_name =
gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
grpc_uri_destroy(uri);
chand->proxy_name = grpc_get_http_proxy_server();
char *name_to_resolve =
chand->proxy_name == NULL ? arg->value.string : chand->proxy_name;
chand->resolver = grpc_resolver_create( chand->resolver = grpc_resolver_create(
exec_ctx, name_to_resolve, args->channel_args, chand->interested_parties); exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
new_args != NULL ? new_args : args->channel_args,
chand->interested_parties);
if (proxy_name != NULL) gpr_free(proxy_name);
if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
if (chand->resolver == NULL) { if (chand->resolver == NULL) {
return GRPC_ERROR_CREATE("resolver creation failed"); return GRPC_ERROR_CREATE("resolver creation failed");
} }
@ -570,8 +563,6 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx, static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) { grpc_channel_element *elem) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
gpr_free(chand->server_name);
gpr_free(chand->proxy_name);
if (chand->resolver != NULL) { if (chand->resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, chand->resolver); grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
@ -585,14 +576,15 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
chand->interested_parties); chand->interested_parties);
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel"); GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
} }
gpr_free(chand->lb_policy_name); gpr_free(chand->info_lb_policy_name);
gpr_free(chand->service_config_json); gpr_free(chand->info_service_config_json);
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table); grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
} }
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker); grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
grpc_pollset_set_destroy(chand->interested_parties); grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
gpr_mu_destroy(&chand->mu); GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
gpr_mu_destroy(&chand->info_mu);
} }
/************************************************************************* /*************************************************************************
@ -635,8 +627,6 @@ typedef struct client_channel_call_data {
grpc_subchannel_call */ grpc_subchannel_call */
gpr_atm subchannel_call; gpr_atm subchannel_call;
gpr_mu mu;
subchannel_creation_phase creation_phase; subchannel_creation_phase creation_phase;
grpc_connected_subchannel *connected_subchannel; grpc_connected_subchannel *connected_subchannel;
grpc_polling_entity *pollent; grpc_polling_entity *pollent;
@ -681,52 +671,32 @@ static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
typedef struct {
grpc_transport_stream_op **ops;
size_t nops;
grpc_subchannel_call *call;
} retry_ops_args;
static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
retry_ops_args *a = args;
size_t i;
for (i = 0; i < a->nops; i++) {
grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
}
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
gpr_free(a->ops);
gpr_free(a);
}
static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
if (calld->waiting_ops_count == 0) { if (calld->waiting_ops_count == 0) {
return; return;
} }
retry_ops_args *a = gpr_malloc(sizeof(*a)); grpc_subchannel_call *call = GET_CALL(calld);
a->ops = calld->waiting_ops; grpc_transport_stream_op **ops = calld->waiting_ops;
a->nops = calld->waiting_ops_count; size_t nops = calld->waiting_ops_count;
a->call = GET_CALL(calld); if (call == CANCELLED_CALL) {
if (a->call == CANCELLED_CALL) {
gpr_free(a);
fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED); fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
return; return;
} }
calld->waiting_ops = NULL; calld->waiting_ops = NULL;
calld->waiting_ops_count = 0; calld->waiting_ops_count = 0;
calld->waiting_ops_capacity = 0; calld->waiting_ops_capacity = 0;
GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops"); for (size_t i = 0; i < nops; i++) {
grpc_closure_sched( grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
exec_ctx, grpc_closure_create(retry_ops, a, grpc_schedule_on_exec_ctx), }
GRPC_ERROR_NONE); gpr_free(ops);
} }
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
grpc_call_element *elem = arg; grpc_call_element *elem = arg;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
gpr_mu_lock(&calld->mu);
GPR_ASSERT(calld->creation_phase == GPR_ASSERT(calld->creation_phase ==
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL); GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent, grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
@ -762,7 +732,6 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
(gpr_atm)(uintptr_t)subchannel_call); (gpr_atm)(uintptr_t)subchannel_call);
retry_waiting_locked(exec_ctx, calld); retry_waiting_locked(exec_ctx, calld);
} }
gpr_mu_unlock(&calld->mu);
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
} }
@ -788,37 +757,35 @@ typedef struct {
/** Return true if subchannel is available immediately (in which case on_ready /** Return true if subchannel is available immediately (in which case on_ready
should not be called), or false otherwise (in which case on_ready should be should not be called), or false otherwise (in which case on_ready should be
called when the subchannel is available). */ called when the subchannel is available). */
static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static bool pick_subchannel_locked(
grpc_metadata_batch *initial_metadata, grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
uint32_t initial_metadata_flags, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
grpc_connected_subchannel **connected_subchannel, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
grpc_closure *on_ready, grpc_error *error); grpc_error *error);
static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
continue_picking_args *cpa = arg; continue_picking_args *cpa = arg;
if (cpa->connected_subchannel == NULL) { if (cpa->connected_subchannel == NULL) {
/* cancelled, do nothing */ /* cancelled, do nothing */
} else if (error != GRPC_ERROR_NONE) { } else if (error != GRPC_ERROR_NONE) {
grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error)); grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
} else { } else {
call_data *calld = cpa->elem->call_data; if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
gpr_mu_lock(&calld->mu); cpa->initial_metadata_flags,
if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata, cpa->connected_subchannel, cpa->on_ready,
cpa->initial_metadata_flags, cpa->connected_subchannel, GRPC_ERROR_NONE)) {
cpa->on_ready, GRPC_ERROR_NONE)) {
grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
} }
gpr_mu_unlock(&calld->mu);
} }
gpr_free(cpa); gpr_free(cpa);
} }
static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static bool pick_subchannel_locked(
grpc_metadata_batch *initial_metadata, grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
uint32_t initial_metadata_flags, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
grpc_connected_subchannel **connected_subchannel, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
grpc_closure *on_ready, grpc_error *error) { grpc_error *error) {
GPR_TIMER_BEGIN("pick_subchannel", 0); GPR_TIMER_BEGIN("pick_subchannel", 0);
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
@ -828,7 +795,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GPR_ASSERT(connected_subchannel); GPR_ASSERT(connected_subchannel);
gpr_mu_lock(&chand->mu);
if (initial_metadata == NULL) { if (initial_metadata == NULL) {
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy, grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
@ -844,7 +810,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1)); GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
} }
} }
gpr_mu_unlock(&chand->mu);
GPR_TIMER_END("pick_subchannel", 0); GPR_TIMER_END("pick_subchannel", 0);
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
return true; return true;
@ -853,7 +818,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
grpc_lb_policy *lb_policy = chand->lb_policy; grpc_lb_policy *lb_policy = chand->lb_policy;
GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel"); GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
gpr_mu_unlock(&chand->mu);
// If the application explicitly set wait_for_ready, use that. // If the application explicitly set wait_for_ready, use that.
// Otherwise, if the service config specified a value for this // Otherwise, if the service config specified a value for this
// method, use that. // method, use that.
@ -892,88 +856,66 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
cpa->connected_subchannel = connected_subchannel; cpa->connected_subchannel = connected_subchannel;
cpa->on_ready = on_ready; cpa->on_ready = on_ready;
cpa->elem = elem; cpa->elem = elem;
grpc_closure_init(&cpa->closure, continue_picking, cpa, grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
grpc_schedule_on_exec_ctx); grpc_combiner_scheduler(chand->combiner, true));
grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure, grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} else { } else {
grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected")); grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
} }
gpr_mu_unlock(&chand->mu);
GPR_TIMER_END("pick_subchannel", 0); GPR_TIMER_END("pick_subchannel", 0);
return false; return false;
} }
// The logic here is fairly complicated, due to (a) the fact that we static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
// need to handle the case where we receive the send op before the grpc_transport_stream_op *op,
// initial metadata op, and (b) the need for efficiency, especially in grpc_call_element *elem) {
// the streaming case.
// TODO(ctiller): Explain this more thoroughly.
static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
GRPC_CALL_LOG_OP(GPR_INFO, elem, op); call_data *calld = elem->call_data;
grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op); grpc_subchannel_call *call;
/* try to (atomically) get the call */
grpc_subchannel_call *call = GET_CALL(calld);
GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
if (call == CANCELLED_CALL) {
grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
GPR_TIMER_END("cc_start_transport_stream_op", 0);
return;
}
if (call != NULL) {
grpc_subchannel_call_process_op(exec_ctx, call, op);
GPR_TIMER_END("cc_start_transport_stream_op", 0);
return;
}
/* we failed; lock and figure out what to do */
gpr_mu_lock(&calld->mu);
retry:
/* need to recheck that another thread hasn't set the call */ /* need to recheck that another thread hasn't set the call */
call = GET_CALL(calld); call = GET_CALL(calld);
if (call == CANCELLED_CALL) { if (call == CANCELLED_CALL) {
gpr_mu_unlock(&calld->mu);
grpc_transport_stream_op_finish_with_failure( grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error)); exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
GPR_TIMER_END("cc_start_transport_stream_op", 0); /* early out */
return; return;
} }
if (call != NULL) { if (call != NULL) {
gpr_mu_unlock(&calld->mu);
grpc_subchannel_call_process_op(exec_ctx, call, op); grpc_subchannel_call_process_op(exec_ctx, call, op);
GPR_TIMER_END("cc_start_transport_stream_op", 0); /* early out */
return; return;
} }
/* if this is a cancellation, then we can raise our cancelled flag */ /* if this is a cancellation, then we can raise our cancelled flag */
if (op->cancel_error != GRPC_ERROR_NONE) { if (op->cancel_error != GRPC_ERROR_NONE) {
if (!gpr_atm_rel_cas(&calld->subchannel_call, 0, if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
(gpr_atm)(uintptr_t)CANCELLED_CALL)) { (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
goto retry; /* recurse to retry */
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
/* early out */
return;
} else { } else {
// Stash a copy of cancel_error in our call data, so that we can use /* Stash a copy of cancel_error in our call data, so that we can use
// it for subsequent operations. This ensures that if the call is it for subsequent operations. This ensures that if the call is
// cancelled before any ops are passed down (e.g., if the deadline cancelled before any ops are passed down (e.g., if the deadline
// is in the past when the call starts), we can return the right is in the past when the call starts), we can return the right
// error to the caller when the first op does get passed down. error to the caller when the first op does get passed down. */
calld->cancel_error = GRPC_ERROR_REF(op->cancel_error); calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
switch (calld->creation_phase) { switch (calld->creation_phase) {
case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING: case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error)); fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
break; break;
case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL: case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel, pick_subchannel_locked(exec_ctx, elem, NULL, 0,
NULL, GRPC_ERROR_REF(op->cancel_error)); &calld->connected_subchannel, NULL,
GRPC_ERROR_REF(op->cancel_error));
break; break;
} }
gpr_mu_unlock(&calld->mu);
grpc_transport_stream_op_finish_with_failure( grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(op->cancel_error)); exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
GPR_TIMER_END("cc_start_transport_stream_op", 0); /* early out */
return; return;
} }
} }
@ -982,16 +924,16 @@ retry:
calld->connected_subchannel == NULL && calld->connected_subchannel == NULL &&
op->send_initial_metadata != NULL) { op->send_initial_metadata != NULL) {
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL; calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
grpc_closure_init(&calld->next_step, subchannel_ready, elem, grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
grpc_schedule_on_exec_ctx); grpc_combiner_scheduler(chand->combiner, true));
GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel"); GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
/* If a subchannel is not available immediately, the polling entity from /* If a subchannel is not available immediately, the polling entity from
call_data should be provided to channel_data's interested_parties, so call_data should be provided to channel_data's interested_parties, so
that IO of the lb_policy and resolver could be done under it. */ that IO of the lb_policy and resolver could be done under it. */
if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata, if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
op->send_initial_metadata_flags, op->send_initial_metadata_flags,
&calld->connected_subchannel, &calld->next_step, &calld->connected_subchannel, &calld->next_step,
GRPC_ERROR_NONE)) { GRPC_ERROR_NONE)) {
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
} else { } else {
@ -1014,31 +956,89 @@ retry:
gpr_atm_rel_store(&calld->subchannel_call, gpr_atm_rel_store(&calld->subchannel_call,
(gpr_atm)(uintptr_t)subchannel_call); (gpr_atm)(uintptr_t)subchannel_call);
retry_waiting_locked(exec_ctx, calld); retry_waiting_locked(exec_ctx, calld);
goto retry; /* recurse to retry */
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
/* early out */
return;
} }
/* nothing to be done but wait */ /* nothing to be done but wait */
add_waiting_locked(calld, op); add_waiting_locked(calld, op);
gpr_mu_unlock(&calld->mu); }
static void cc_start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_error *error_ignored) {
GPR_TIMER_BEGIN("cc_start_transport_stream_op_locked", 0);
grpc_transport_stream_op *op = arg;
grpc_call_element *elem = op->handler_private.args[0];
call_data *calld = elem->call_data;
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
"start_transport_stream_op");
GPR_TIMER_END("cc_start_transport_stream_op_locked", 0);
}
/* The logic here is fairly complicated, due to (a) the fact that we
need to handle the case where we receive the send op before the
initial metadata op, and (b) the need for efficiency, especially in
the streaming case.
We use double-checked locking to initially see if initialization has been
performed. If it has not, we acquire the combiner and perform initialization.
If it has, we proceed on the fast path. */
static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
/* try to (atomically) get the call */
grpc_subchannel_call *call = GET_CALL(calld);
GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
if (call == CANCELLED_CALL) {
grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
GPR_TIMER_END("cc_start_transport_stream_op", 0);
/* early out */
return;
}
if (call != NULL) {
grpc_subchannel_call_process_op(exec_ctx, call, op);
GPR_TIMER_END("cc_start_transport_stream_op", 0);
/* early out */
return;
}
/* we failed; lock and figure out what to do */
GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
op->handler_private.args[0] = elem;
grpc_closure_sched(
exec_ctx,
grpc_closure_init(&op->handler_private.closure,
cc_start_transport_stream_op_locked, op,
grpc_combiner_scheduler(chand->combiner, false)),
GRPC_ERROR_NONE);
GPR_TIMER_END("cc_start_transport_stream_op", 0); GPR_TIMER_END("cc_start_transport_stream_op", 0);
} }
// Gets data from the service config. Invoked when the resolver returns // Gets data from the service config. Invoked when the resolver returns
// its initial result. // its initial result.
static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg, static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
grpc_call_element *elem = arg; grpc_call_element *elem = arg;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
// If this is an error, there's no point in looking at the service config. // If this is an error, there's no point in looking at the service config.
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
// Get the method config table from channel data. // Get the method config table from channel data.
gpr_mu_lock(&chand->mu);
grpc_slice_hash_table *method_params_table = NULL; grpc_slice_hash_table *method_params_table = NULL;
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
method_params_table = method_params_table =
grpc_slice_hash_table_ref(chand->method_params_table); grpc_slice_hash_table_ref(chand->method_params_table);
} }
gpr_mu_unlock(&chand->mu);
// If the method config table was present, use it. // If the method config table was present, use it.
if (method_params_table != NULL) { if (method_params_table != NULL) {
const method_parameters *method_params = grpc_method_config_table_get( const method_parameters *method_params = grpc_method_config_table_get(
@ -1048,7 +1048,6 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0; gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
if (have_method_timeout || if (have_method_timeout ||
method_params->wait_for_ready != WAIT_FOR_READY_UNSET) { method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
gpr_mu_lock(&calld->mu);
if (have_method_timeout) { if (have_method_timeout) {
const gpr_timespec per_method_deadline = const gpr_timespec per_method_deadline =
gpr_time_add(calld->call_start_time, method_params->timeout); gpr_time_add(calld->call_start_time, method_params->timeout);
@ -1062,7 +1061,6 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
calld->wait_for_ready_from_service_config = calld->wait_for_ready_from_service_config =
method_params->wait_for_ready; method_params->wait_for_ready;
} }
gpr_mu_unlock(&calld->mu);
} }
} }
grpc_slice_hash_table_unref(exec_ctx, method_params_table); grpc_slice_hash_table_unref(exec_ctx, method_params_table);
@ -1071,43 +1069,25 @@ static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
} }
/* Constructor for call_data */ static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, void *arg,
grpc_call_element *elem, grpc_error *error_ignored) {
grpc_call_element_args *args) { grpc_call_element *elem = arg;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
// Initialize data members.
grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
calld->path = grpc_slice_ref_internal(args->path);
calld->call_start_time = args->start_time;
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
calld->cancel_error = GRPC_ERROR_NONE;
gpr_atm_rel_store(&calld->subchannel_call, 0);
gpr_mu_init(&calld->mu);
calld->connected_subchannel = NULL;
calld->waiting_ops = NULL;
calld->waiting_ops_count = 0;
calld->waiting_ops_capacity = 0;
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
calld->owning_call = args->call_stack;
calld->pollent = NULL;
// If the resolver has already returned results, then we can access // If the resolver has already returned results, then we can access
// the service config parameters immediately. Otherwise, we need to // the service config parameters immediately. Otherwise, we need to
// defer that work until the resolver returns an initial result. // defer that work until the resolver returns an initial result.
// TODO(roth): This code is almost but not quite identical to the code // TODO(roth): This code is almost but not quite identical to the code
// in read_service_config() above. It would be nice to find a way to // in read_service_config() above. It would be nice to find a way to
// combine them, to avoid having to maintain it twice. // combine them, to avoid having to maintain it twice.
gpr_mu_lock(&chand->mu);
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
// We already have a resolver result, so check for service config. // We already have a resolver result, so check for service config.
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_slice_hash_table *method_params_table = grpc_slice_hash_table *method_params_table =
grpc_slice_hash_table_ref(chand->method_params_table); grpc_slice_hash_table_ref(chand->method_params_table);
gpr_mu_unlock(&chand->mu);
method_parameters *method_params = grpc_method_config_table_get( method_parameters *method_params = grpc_method_config_table_get(
exec_ctx, method_params_table, args->path); exec_ctx, method_params_table, calld->path);
if (method_params != NULL) { if (method_params != NULL) {
if (gpr_time_cmp(method_params->timeout, if (gpr_time_cmp(method_params->timeout,
gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) { gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
@ -1121,24 +1101,53 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
} }
} }
grpc_slice_hash_table_unref(exec_ctx, method_params_table); grpc_slice_hash_table_unref(exec_ctx, method_params_table);
} else {
gpr_mu_unlock(&chand->mu);
} }
} else { } else {
// We don't yet have a resolver result, so register a callback to // We don't yet have a resolver result, so register a callback to
// get the service config data once the resolver returns. // get the service config data once the resolver returns.
// Take a reference to the call stack to be owned by the callback. // Take a reference to the call stack to be owned by the callback.
GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config"); GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
grpc_closure_init(&calld->read_service_config, read_service_config, elem, grpc_closure_init(&calld->read_service_config, read_service_config_locked,
grpc_schedule_on_exec_ctx); elem, grpc_combiner_scheduler(chand->combiner, false));
grpc_closure_list_append(&chand->waiting_for_config_closures, grpc_closure_list_append(&chand->waiting_for_config_closures,
&calld->read_service_config, GRPC_ERROR_NONE); &calld->read_service_config, GRPC_ERROR_NONE);
gpr_mu_unlock(&chand->mu);
} }
// Start the deadline timer with the current deadline value. If we // Start the deadline timer with the current deadline value. If we
// do not yet have service config data, then the timer may be reset // do not yet have service config data, then the timer may be reset
// later. // later.
grpc_deadline_state_start(exec_ctx, elem, calld->deadline); grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
"initial_read_service_config");
}
/* Constructor for call_data */
static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_call_element_args *args) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
// Initialize data members.
grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
calld->path = grpc_slice_ref_internal(args->path);
calld->call_start_time = args->start_time;
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
calld->cancel_error = GRPC_ERROR_NONE;
gpr_atm_rel_store(&calld->subchannel_call, 0);
calld->connected_subchannel = NULL;
calld->waiting_ops = NULL;
calld->waiting_ops_count = 0;
calld->waiting_ops_capacity = 0;
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
calld->owning_call = args->call_stack;
calld->pollent = NULL;
GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
grpc_closure_sched(
exec_ctx,
grpc_closure_init(&calld->read_service_config,
initial_read_service_config_locked, elem,
grpc_combiner_scheduler(chand->combiner, false)),
GRPC_ERROR_NONE);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -1156,7 +1165,6 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
} }
GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING); GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
gpr_mu_destroy(&calld->mu);
GPR_ASSERT(calld->waiting_ops_count == 0); GPR_ASSERT(calld->waiting_ops_count == 0);
if (calld->connected_subchannel != NULL) { if (calld->connected_subchannel != NULL) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel, GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
@ -1192,26 +1200,36 @@ const grpc_channel_filter grpc_client_channel_filter = {
"client-channel", "client-channel",
}; };
static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
channel_data *chand = arg;
if (chand->lb_policy != NULL) {
grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
} else {
chand->exit_idle_when_lb_policy_arrives = true;
if (!chand->started_resolving && chand->resolver != NULL) {
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
chand->started_resolving = true;
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
&chand->on_resolver_result_changed);
}
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
}
grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) { grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_connectivity_state out; grpc_connectivity_state out =
gpr_mu_lock(&chand->mu); grpc_connectivity_state_check(&chand->state_tracker);
out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
if (out == GRPC_CHANNEL_IDLE && try_to_connect) { if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
if (chand->lb_policy != NULL) { GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy); grpc_closure_sched(
} else { exec_ctx,
chand->exit_idle_when_lb_policy_arrives = true; grpc_closure_create(try_to_connect_locked, chand,
if (!chand->started_resolving && chand->resolver != NULL) { grpc_combiner_scheduler(chand->combiner, false)),
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); GRPC_ERROR_NONE);
chand->started_resolving = true;
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
&chand->on_resolver_result_changed);
}
}
} }
gpr_mu_unlock(&chand->mu);
return out; return out;
} }
@ -1219,6 +1237,7 @@ typedef struct {
channel_data *chand; channel_data *chand;
grpc_pollset *pollset; grpc_pollset *pollset;
grpc_closure *on_complete; grpc_closure *on_complete;
grpc_connectivity_state *state;
grpc_closure my_closure; grpc_closure my_closure;
} external_connectivity_watcher; } external_connectivity_watcher;
@ -1231,7 +1250,16 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
"external_connectivity_watcher"); "external_connectivity_watcher");
gpr_free(w); gpr_free(w);
follow_up->cb(exec_ctx, follow_up->cb_arg, error); grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
}
static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
external_connectivity_watcher *w = arg;
grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
grpc_schedule_on_exec_ctx);
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
} }
void grpc_client_channel_watch_connectivity_state( void grpc_client_channel_watch_connectivity_state(
@ -1242,13 +1270,13 @@ void grpc_client_channel_watch_connectivity_state(
w->chand = chand; w->chand = chand;
w->pollset = pollset; w->pollset = pollset;
w->on_complete = on_complete; w->on_complete = on_complete;
w->state = state;
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset); grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
grpc_schedule_on_exec_ctx);
GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
"external_connectivity_watcher"); "external_connectivity_watcher");
gpr_mu_lock(&chand->mu); grpc_closure_sched(
grpc_connectivity_state_notify_on_state_change( exec_ctx,
exec_ctx, &chand->state_tracker, state, &w->my_closure); grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
gpr_mu_unlock(&chand->mu); grpc_combiner_scheduler(chand->combiner, true)),
GRPC_ERROR_NONE);
} }

@ -39,6 +39,7 @@
#include "src/core/ext/client_channel/client_channel.h" #include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/http_connect_handshaker.h" #include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/http_proxy.h"
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h" #include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
@ -82,6 +83,7 @@ void grpc_client_channel_init(void) {
grpc_lb_policy_registry_init(); grpc_lb_policy_registry_init();
grpc_resolver_registry_init(); grpc_resolver_registry_init();
grpc_proxy_mapper_registry_init(); grpc_proxy_mapper_registry_init();
grpc_register_http_proxy_mapper();
grpc_subchannel_index_init(); grpc_subchannel_index_init();
grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN, grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
set_default_host_if_unset, NULL); set_default_host_if_unset, NULL);

@ -40,10 +40,13 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/uri_parser.h" #include "src/core/ext/client_channel/uri_parser.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/support/env.h" #include "src/core/lib/support/env.h"
char* grpc_get_http_proxy_server() { static char* grpc_get_http_proxy_server() {
char* uri_str = gpr_getenv("http_proxy"); char* uri_str = gpr_getenv("http_proxy");
if (uri_str == NULL) return NULL; if (uri_str == NULL) return NULL;
grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */); grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */);
@ -66,3 +69,55 @@ done:
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
return proxy_name; return proxy_name;
} }
static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
grpc_proxy_mapper* mapper,
const char* server_uri,
const grpc_channel_args* args,
char** name_to_resolve,
grpc_channel_args** new_args) {
*name_to_resolve = grpc_get_http_proxy_server();
if (*name_to_resolve == NULL) return false;
grpc_uri* uri = grpc_uri_parse(server_uri, false /* suppress_errors */);
if (uri == NULL || uri->path[0] == '\0') {
gpr_log(GPR_ERROR,
"'http_proxy' environment variable set, but cannot "
"parse server URI '%s' -- not using proxy",
server_uri);
if (uri != NULL) grpc_uri_destroy(uri);
return false;
}
if (strcmp(uri->scheme, "unix") == 0) {
gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'",
server_uri);
grpc_uri_destroy(uri);
return false;
}
grpc_arg new_arg;
new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
new_arg.type = GRPC_ARG_STRING;
new_arg.value.string = uri->path[0] == '/' ? uri->path + 1 : uri->path;
*new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
grpc_uri_destroy(uri);
return true;
}
static bool proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
grpc_proxy_mapper* mapper,
const grpc_resolved_address* address,
const grpc_channel_args* args,
grpc_resolved_address** new_address,
grpc_channel_args** new_args) {
return false;
}
static void proxy_mapper_destroy(grpc_proxy_mapper* mapper) {}
static const grpc_proxy_mapper_vtable proxy_mapper_vtable = {
proxy_mapper_map_name, proxy_mapper_map_address, proxy_mapper_destroy};
static grpc_proxy_mapper proxy_mapper = {&proxy_mapper_vtable};
void grpc_register_http_proxy_mapper() {
grpc_proxy_mapper_register(true /* at_start */, &proxy_mapper);
}

@ -34,8 +34,6 @@
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H #ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H #define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
/// Returns the name of the proxy to use, or NULL if no proxy is configured. void grpc_register_http_proxy_mapper();
/// Caller takes ownership of result.
char* grpc_get_http_proxy_server();
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H */

@ -94,7 +94,7 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
gpr_atm old_val = gpr_atm old_val =
ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF")); ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
if (old_val == 1) { if (old_val == 1) {
grpc_pollset_set_destroy(policy->interested_parties); grpc_pollset_set_destroy(exec_ctx, policy->interested_parties);
policy->vtable->destroy(exec_ctx, policy); policy->vtable->destroy(exec_ctx, policy);
} }
} }

@ -38,13 +38,24 @@ void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
mapper->vtable = vtable; mapper->vtable = vtable;
} }
bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
const grpc_resolved_address* address, grpc_proxy_mapper* mapper,
const grpc_channel_args* args, const char* server_uri,
grpc_resolved_address** new_address, const grpc_channel_args* args,
grpc_channel_args** new_args) { char** name_to_resolve,
return mapper->vtable->map(exec_ctx, mapper, address, args, new_address, grpc_channel_args** new_args) {
new_args); return mapper->vtable->map_name(exec_ctx, mapper, server_uri, args,
name_to_resolve, new_args);
}
bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
grpc_proxy_mapper* mapper,
const grpc_resolved_address* address,
const grpc_channel_args* args,
grpc_resolved_address** new_address,
grpc_channel_args** new_args) {
return mapper->vtable->map_address(exec_ctx, mapper, address, args,
new_address, new_args);
} }
void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) { void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) {

@ -43,15 +43,22 @@
typedef struct grpc_proxy_mapper grpc_proxy_mapper; typedef struct grpc_proxy_mapper grpc_proxy_mapper;
typedef struct { typedef struct {
/// Determines the proxy name to resolve for \a server_uri.
/// If no proxy is needed, returns false.
/// Otherwise, sets \a name_to_resolve, optionally sets \a new_args,
/// and returns true.
bool (*map_name)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
const char* server_uri, const grpc_channel_args* args,
char** name_to_resolve, grpc_channel_args** new_args);
/// Determines the proxy address to use to contact \a address. /// Determines the proxy address to use to contact \a address.
/// If no proxy is needed, returns false. /// If no proxy is needed, returns false.
/// Otherwise, sets \a new_address, optionally sets \a new_args, and /// Otherwise, sets \a new_address, optionally sets \a new_args, and
/// returns true. /// returns true.
bool (*map)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, bool (*map_address)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
const grpc_resolved_address* address, const grpc_resolved_address* address,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_resolved_address** new_address,
grpc_channel_args** new_args); grpc_channel_args** new_args);
/// Destroys \a mapper. /// Destroys \a mapper.
void (*destroy)(grpc_proxy_mapper* mapper); void (*destroy)(grpc_proxy_mapper* mapper);
} grpc_proxy_mapper_vtable; } grpc_proxy_mapper_vtable;
@ -63,11 +70,20 @@ struct grpc_proxy_mapper {
void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable, void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
grpc_proxy_mapper* mapper); grpc_proxy_mapper* mapper);
bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper, bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
const grpc_resolved_address* address, grpc_proxy_mapper* mapper,
const grpc_channel_args* args, const char* server_uri,
grpc_resolved_address** new_address, const grpc_channel_args* args,
grpc_channel_args** new_args); char** name_to_resolve,
grpc_channel_args** new_args);
bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
grpc_proxy_mapper* mapper,
const grpc_resolved_address* address,
const grpc_channel_args* args,
grpc_resolved_address** new_address,
grpc_channel_args** new_args);
void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper); void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */

@ -61,15 +61,28 @@ static void grpc_proxy_mapper_list_register(grpc_proxy_mapper_list* list,
++list->num_mappers; ++list->num_mappers;
} }
static bool grpc_proxy_mapper_list_map(grpc_exec_ctx* exec_ctx, static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx,
grpc_proxy_mapper_list* list, grpc_proxy_mapper_list* list,
const grpc_resolved_address* address, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
for (size_t i = 0; i < list->num_mappers; ++i) { for (size_t i = 0; i < list->num_mappers; ++i) {
if (grpc_proxy_mapper_map(exec_ctx, list->list[i], address, args, if (grpc_proxy_mapper_map_name(exec_ctx, list->list[i], server_uri, args,
new_address, new_args)) { name_to_resolve, new_args)) {
return true;
}
}
return false;
}
static bool grpc_proxy_mapper_list_map_address(
grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list,
const grpc_resolved_address* address, const grpc_channel_args* args,
grpc_resolved_address** new_address, grpc_channel_args** new_args) {
for (size_t i = 0; i < list->num_mappers; ++i) {
if (grpc_proxy_mapper_map_address(exec_ctx, list->list[i], address, args,
new_address, new_args)) {
return true; return true;
} }
} }
@ -101,11 +114,20 @@ void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper) {
grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper); grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
} }
bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
const grpc_resolved_address* address, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, char** name_to_resolve,
grpc_channel_args** new_args) { grpc_channel_args** new_args) {
return grpc_proxy_mapper_list_map(exec_ctx, &g_proxy_mapper_list, address, return grpc_proxy_mapper_list_map_name(exec_ctx, &g_proxy_mapper_list,
args, new_address, new_args); server_uri, args, name_to_resolve,
new_args);
}
bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
const grpc_resolved_address* address,
const grpc_channel_args* args,
grpc_resolved_address** new_address,
grpc_channel_args** new_args) {
return grpc_proxy_mapper_list_map_address(
exec_ctx, &g_proxy_mapper_list, address, args, new_address, new_args);
} }

@ -44,10 +44,16 @@ void grpc_proxy_mapper_registry_shutdown();
/// the list. Otherwise, it will be added to the end. /// the list. Otherwise, it will be added to the end.
void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper); void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper);
bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx, bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
const grpc_resolved_address* address, const char* server_uri,
const grpc_channel_args* args, const grpc_channel_args* args,
grpc_resolved_address** new_address, char** name_to_resolve,
grpc_channel_args** new_args); grpc_channel_args** new_args);
bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
const grpc_resolved_address* address,
const grpc_channel_args* args,
grpc_resolved_address** new_address,
grpc_channel_args** new_args);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */

@ -217,7 +217,7 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
grpc_slice_unref_internal(exec_ctx, c->initial_connect_string); grpc_slice_unref_internal(exec_ctx, c->initial_connect_string);
grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker); grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
grpc_connector_unref(exec_ctx, c->connector); grpc_connector_unref(exec_ctx, c->connector);
grpc_pollset_set_destroy(c->pollset_set); grpc_pollset_set_destroy(exec_ctx, c->pollset_set);
grpc_subchannel_key_destroy(exec_ctx, c->key); grpc_subchannel_key_destroy(exec_ctx, c->key);
gpr_free(c); gpr_free(c);
} }
@ -336,8 +336,8 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_set_initial_connect_string(&addr, &c->initial_connect_string); grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
grpc_resolved_address *new_address = NULL; grpc_resolved_address *new_address = NULL;
grpc_channel_args *new_args = NULL; grpc_channel_args *new_args = NULL;
if (grpc_proxy_mappers_map(exec_ctx, addr, args->args, &new_address, if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address,
&new_args)) { &new_args)) {
GPR_ASSERT(new_address != NULL); GPR_ASSERT(new_address != NULL);
gpr_free(addr); gpr_free(addr);
addr = new_address; addr = new_address;
@ -419,7 +419,7 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
grpc_error **error) { grpc_error **error) {
grpc_connectivity_state state; grpc_connectivity_state state;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
state = grpc_connectivity_state_check(&c->state_tracker, error); state = grpc_connectivity_state_get(&c->state_tracker, error);
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
return state; return state;
} }
@ -788,7 +788,8 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack(
return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
} }
static void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { static void grpc_uri_to_sockaddr(const char *uri_str,
grpc_resolved_address *addr) {
grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */);
GPR_ASSERT(uri != NULL); GPR_ASSERT(uri != NULL);
if (strcmp(uri->scheme, "ipv4") == 0) { if (strcmp(uri->scheme, "ipv4") == 0) {
@ -803,14 +804,19 @@ static void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) {
void grpc_get_subchannel_address_arg(const grpc_channel_args *args, void grpc_get_subchannel_address_arg(const grpc_channel_args *args,
grpc_resolved_address *addr) { grpc_resolved_address *addr) {
const char *addr_uri_str = grpc_get_subchannel_address_uri_arg(args);
memset(addr, 0, sizeof(*addr));
if (*addr_uri_str != '\0') {
grpc_uri_to_sockaddr(addr_uri_str, addr);
}
}
const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args) {
const grpc_arg *addr_arg = const grpc_arg *addr_arg =
grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS);
GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy.
GPR_ASSERT(addr_arg->type == GRPC_ARG_STRING); GPR_ASSERT(addr_arg->type == GRPC_ARG_STRING);
memset(addr, 0, sizeof(*addr)); return addr_arg->value.string;
if (*addr_arg->value.string != '\0') {
grpc_uri_to_sockaddr(addr_arg->value.string, addr);
}
} }
grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) { grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) {

@ -178,6 +178,9 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
void grpc_get_subchannel_address_arg(const grpc_channel_args *args, void grpc_get_subchannel_address_arg(const grpc_channel_args *args,
grpc_resolved_address *addr); grpc_resolved_address *addr);
/// Returns the URI string for the address to connect to.
const char *grpc_get_subchannel_address_uri_arg(const grpc_channel_args *args);
/// Returns a new channel arg encoding the subchannel address as a string. /// Returns a new channel arg encoding the subchannel address as a string.
/// Caller is responsible for freeing the string. /// Caller is responsible for freeing the string.
grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr); grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr);

@ -112,11 +112,13 @@
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/parse_address.h" #include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/lb_policy/grpclb/grpclb.h" #include "src/core/ext/lb_policy/grpclb/grpclb.h"
#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" #include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr.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/slice/slice_hash_table.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/support/backoff.h" #include "src/core/lib/support/backoff.h"
@ -490,9 +492,8 @@ static grpc_lb_addresses *process_serverlist_locked(
static bool update_lb_connectivity_status_locked( static bool update_lb_connectivity_status_locked(
grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy, grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) { grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
grpc_error *curr_state_error; const grpc_connectivity_state curr_glb_state =
const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check( grpc_connectivity_state_check(&glb_policy->state_tracker);
&glb_policy->state_tracker, &curr_state_error);
/* The new connectivity status is a function of the previous one and the new /* The new connectivity status is a function of the previous one and the new
* input coming from the status of the RR policy. * input coming from the status of the RR policy.
@ -751,6 +752,96 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void destroy_balancer_name(grpc_exec_ctx *exec_ctx,
void *balancer_name) {
gpr_free(balancer_name);
}
static void *copy_balancer_name(void *balancer_name) {
return gpr_strdup(balancer_name);
}
static grpc_slice_hash_table_entry targets_info_entry_create(
const char *address, const char *balancer_name) {
static const grpc_slice_hash_table_vtable vtable = {destroy_balancer_name,
copy_balancer_name};
grpc_slice_hash_table_entry entry;
entry.key = grpc_slice_from_copied_string(address);
entry.value = (void *)balancer_name;
entry.vtable = &vtable;
return entry;
}
/* Returns the target URI for the LB service whose addresses are in \a
* addresses. Using this URI, a bidirectional streaming channel will be created
* for the reception of load balancing updates.
*
* The output argument \a targets_info will be updated to contain a mapping of
* "LB server address" to "balancer name", as reported by the naming system.
* This mapping will be propagated via the channel arguments of the
* aforementioned LB streaming channel, to be used by the security connector for
* secure naming checks. The user is responsible for freeing \a targets_info. */
static char *get_lb_uri_target_addresses(grpc_exec_ctx *exec_ctx,
const grpc_lb_addresses *addresses,
grpc_slice_hash_table **targets_info) {
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;
}
/* All input addresses come from a resolver that claims they are LB services.
* It's the resolver's responsibility to make sure this policy is only
* instantiated and used in that case. Otherwise, something has gone wrong. */
GPR_ASSERT(num_grpclb_addrs > 0);
grpc_slice_hash_table_entry *targets_info_entries =
gpr_malloc(sizeof(*targets_info_entries) * num_grpclb_addrs);
/* construct a target ipvX://ip1:port1,ip2:port2,... from the addresses in \a
* addresses */
/* TODO(dgq): support mixed ip version */
char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
size_t addr_index = 0;
for (size_t i = 0; i < addresses->num_addresses; i++) {
if (addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
if (addresses->addresses[i].is_balancer) {
char *addr_str;
GPR_ASSERT(grpc_sockaddr_to_string(
&addr_str, &addresses->addresses[i].address, true) > 0);
targets_info_entries[addr_index] = targets_info_entry_create(
addr_str, addresses->addresses[i].balancer_name);
addr_strs[addr_index++] = addr_str;
}
}
GPR_ASSERT(addr_index == num_grpclb_addrs);
size_t uri_path_len;
char *uri_path = gpr_strjoin_sep((const char **)addr_strs, num_grpclb_addrs,
",", &uri_path_len);
for (size_t i = 0; i < num_grpclb_addrs; i++) gpr_free(addr_strs[i]);
gpr_free(addr_strs);
char *target_uri_str = NULL;
/* TODO(dgq): Don't assume all addresses will share the scheme of the first
* one */
gpr_asprintf(&target_uri_str, "%s:%s",
grpc_sockaddr_get_uri_scheme(&addresses->addresses[0].address),
uri_path);
gpr_free(uri_path);
*targets_info =
grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries);
for (size_t i = 0; i < num_grpclb_addrs; i++) {
grpc_slice_unref_internal(exec_ctx, targets_info_entries[i].key);
}
gpr_free(targets_info_entries);
return target_uri_str;
}
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory, grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) { grpc_lb_policy_args *args) {
@ -788,85 +879,30 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
} }
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
/* All input addresses in addresses come from a resolver that claims
* they are LB services. It's the resolver's responsibility to make sure
* this policy is only instantiated and used in that case.
*
* Create a client channel over them to communicate with a LB service */
glb_policy->cc_factory = args->client_channel_factory; glb_policy->cc_factory = args->client_channel_factory;
glb_policy->args = grpc_channel_args_copy(args->args); glb_policy->args = grpc_channel_args_copy(args->args);
GPR_ASSERT(glb_policy->cc_factory != NULL); GPR_ASSERT(glb_policy->cc_factory != NULL);
/* construct a target from the addresses in args, given in the form grpc_slice_hash_table *targets_info = NULL;
* ipvX://ip1:port1,ip2:port2,... /* Create a client channel over them to communicate with a LB service */
* TODO(dgq): support mixed ip version */ char *lb_service_target_addresses =
char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs); get_lb_uri_target_addresses(exec_ctx, addresses, &targets_info);
size_t addr_index = 0; grpc_channel_args *lb_channel_args =
for (size_t i = 0; i < addresses->num_addresses; i++) { get_lb_channel_args(exec_ctx, targets_info, args->args);
if (addresses->addresses[i].user_data != NULL) { glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
gpr_log(GPR_ERROR, exec_ctx, lb_service_target_addresses, args->client_channel_factory,
"This LB policy doesn't support user data. It will be ignored"); lb_channel_args);
} grpc_slice_hash_table_unref(exec_ctx, targets_info);
if (addresses->addresses[i].is_balancer) { grpc_channel_args_destroy(exec_ctx, lb_channel_args);
if (addr_index == 0) { gpr_free(lb_service_target_addresses);
addr_strs[addr_index++] =
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
} else {
GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
&addresses->addresses[i].address,
true) > 0);
}
}
}
size_t uri_path_len;
char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
num_grpclb_addrs, ",", &uri_path_len);
/* Create a channel to talk to the LBs.
*
* We strip out the channel arg for the LB policy name, since we want
* to use the default (pick_first) in this case.
*
* We also strip out the channel arg for the resolved addresses, since
* that will be generated by the name resolver used in the LB channel.
* Note that the LB channel will use the sockaddr resolver, so this
* won't actually generate a query to DNS (or some other name service).
* However, the addresses returned by the sockaddr resolver will have
* is_balancer=false, whereas our own addresses have is_balancer=true.
* We need the LB channel to return addresses with is_balancer=false
* so that it does not wind up recursively using the grpclb LB policy,
* as per the special case logic in client_channel.c.
*
* Finally, we also strip out the channel arg for the server URI,
* since that will be different for the LB channel than for the parent
* channel. (The client channel factory will re-add this arg with
* the right value.)
*/
static const char *keys_to_remove[] = {
GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, glb_policy->cc_factory, target_uri_str,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
grpc_channel_args_destroy(exec_ctx, new_args);
gpr_free(target_uri_str);
for (size_t i = 0; i < num_grpclb_addrs; i++) {
gpr_free(addr_strs[i]);
}
gpr_free(addr_strs);
if (glb_policy->lb_channel == NULL) { if (glb_policy->lb_channel == NULL) {
gpr_free(glb_policy); gpr_free(glb_policy);
return NULL; return NULL;
} }
grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable); grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
gpr_mu_init(&glb_policy->mu); gpr_mu_init(&glb_policy->mu);
grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
"grpclb"); "grpclb");
return &glb_policy->base; return &glb_policy->base;
} }
@ -1061,8 +1097,8 @@ static grpc_connectivity_state glb_check_connectivity(
glb_lb_policy *glb_policy = (glb_lb_policy *)pol; glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
grpc_connectivity_state st; grpc_connectivity_state st;
gpr_mu_lock(&glb_policy->mu); gpr_mu_lock(&glb_policy->mu);
st = grpc_connectivity_state_check(&glb_policy->state_tracker, st = grpc_connectivity_state_get(&glb_policy->state_tracker,
connectivity_error); connectivity_error);
gpr_mu_unlock(&glb_policy->mu); gpr_mu_unlock(&glb_policy->mu);
return st; return st;
} }

@ -0,0 +1,77 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/support/string.h"
grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
grpc_client_channel_factory *client_channel_factory,
grpc_channel_args *args) {
grpc_channel *lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, client_channel_factory, lb_service_target_addresses,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, args);
return lb_channel;
}
grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table *targets_info,
const grpc_channel_args *args) {
/* We strip out the channel arg for the LB policy name, since we want
* to use the default (pick_first) in this case.
*
* We also strip out the channel arg for the resolved addresses, since
* that will be generated by the name resolver used in the LB channel.
* Note that the LB channel will use the sockaddr resolver, so this
* won't actually generate a query to DNS (or some other name service).
* However, the addresses returned by the sockaddr resolver will have
* is_balancer=false, whereas our own addresses have is_balancer=true.
* We need the LB channel to return addresses with is_balancer=false
* so that it does not wind up recursively using the grpclb LB policy,
* as per the special case logic in client_channel.c.
*
* Lastly, we also strip out the channel arg for the server URI,
* since that will be different for the LB channel than for the parent
* channel (the client channel factory will re-add this arg with
* the right value). */
static const char *keys_to_remove[] = {
GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
return grpc_channel_args_copy_and_remove(args, keys_to_remove,
GPR_ARRAY_SIZE(keys_to_remove));
}

@ -0,0 +1,56 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H
#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H
#include "src/core/ext/client_channel/lb_policy_factory.h"
#include "src/core/lib/slice/slice_hash_table.h"
/** Create the channel used for communicating with an LB service.
* Note that an LB *service* may be comprised of several LB *servers*.
*
* \a lb_service_target_addresses is the target URI containing the addresses
* from resolving the LB service's name (eg, ipv4:10.0.0.1:1234,10.2.3.4:9876).
* \a client_channel_factory will be used for the creation of the LB channel,
* alongside the channel args passed in \a args. */
grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
grpc_client_channel_factory *client_channel_factory,
grpc_channel_args *args);
grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table *targets_info,
const grpc_channel_args *args);
#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H */

@ -0,0 +1,107 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/lb_targets_info.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
grpc_channel *grpc_lb_policy_grpclb_create_lb_channel(
grpc_exec_ctx *exec_ctx, const char *lb_service_target_addresses,
grpc_client_channel_factory *client_channel_factory,
grpc_channel_args *args) {
grpc_channel_args *new_args = args;
grpc_channel_credentials *channel_credentials =
grpc_channel_credentials_find_in_args(args);
if (channel_credentials != NULL) {
/* Substitute the channel credentials with a version without call
* credentials: the load balancer is not necessarily trusted to handle
* bearer token credentials */
static const char *keys_to_remove[] = {GRPC_ARG_CHANNEL_CREDENTIALS};
grpc_channel_credentials *creds_sans_call_creds =
grpc_channel_credentials_duplicate_without_call_credentials(
channel_credentials);
GPR_ASSERT(creds_sans_call_creds != NULL);
grpc_arg args_to_add[] = {
grpc_channel_credentials_to_arg(creds_sans_call_creds)};
/* Create the new set of channel args */
new_args = grpc_channel_args_copy_and_add_and_remove(
args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
grpc_channel_credentials_unref(exec_ctx, creds_sans_call_creds);
}
grpc_channel *lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, client_channel_factory, lb_service_target_addresses,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
if (channel_credentials != NULL) {
grpc_channel_args_destroy(exec_ctx, new_args);
}
return lb_channel;
}
grpc_channel_args *get_lb_channel_args(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table *targets_info,
const grpc_channel_args *args) {
const grpc_arg targets_info_arg =
grpc_lb_targets_info_create_channel_arg(targets_info);
/* We strip out the channel arg for the LB policy name, since we want
* to use the default (pick_first) in this case.
*
* We also strip out the channel arg for the resolved addresses, since
* that will be generated by the name resolver used in the LB channel.
* Note that the LB channel will use the sockaddr resolver, so this
* won't actually generate a query to DNS (or some other name service).
* However, the addresses returned by the sockaddr resolver will have
* is_balancer=false, whereas our own addresses have is_balancer=true.
* We need the LB channel to return addresses with is_balancer=false
* so that it does not wind up recursively using the grpclb LB policy,
* as per the special case logic in client_channel.c.
*
* Lastly, we also strip out the channel arg for the server URI,
* since that will be different for the LB channel than for the parent
* channel (the client channel factory will re-add this arg with
* the right value). */
static const char *keys_to_remove[] = {
GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
/* Add the targets info table to be used for secure naming */
return grpc_channel_args_copy_and_add_and_remove(
args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &targets_info_arg,
1);
}

@ -398,7 +398,7 @@ static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
grpc_connectivity_state st; grpc_connectivity_state st;
gpr_mu_lock(&p->mu); gpr_mu_lock(&p->mu);
st = grpc_connectivity_state_check(&p->state_tracker, error); st = grpc_connectivity_state_get(&p->state_tracker, error);
gpr_mu_unlock(&p->mu); gpr_mu_unlock(&p->mu);
return st; return st;
} }

@ -655,7 +655,7 @@ static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
round_robin_lb_policy *p = (round_robin_lb_policy *)pol; round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
grpc_connectivity_state st; grpc_connectivity_state st;
gpr_mu_lock(&p->mu); gpr_mu_lock(&p->mu);
st = grpc_connectivity_state_check(&p->state_tracker, error); st = grpc_connectivity_state_get(&p->state_tracker, error);
gpr_mu_unlock(&p->mu); gpr_mu_unlock(&p->mu);
return st; return st;
} }
@ -739,6 +739,13 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
sc_args.args = new_args; sc_args.args = new_args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args); exec_ctx, args->client_channel_factory, &sc_args);
if (grpc_lb_round_robin_trace) {
char *address_uri =
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
gpr_log(GPR_DEBUG, "Created subchannel %p for address uri %s",
(void *)subchannel, address_uri);
gpr_free(address_uri);
}
grpc_channel_args_destroy(exec_ctx, new_args); grpc_channel_args_destroy(exec_ctx, new_args);
if (subchannel != NULL) { if (subchannel != NULL) {

@ -34,14 +34,34 @@
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <grpc/load_reporting.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include "src/core/ext/load_reporting/load_reporting.h" #include "src/core/ext/load_reporting/load_reporting.h"
#include "src/core/ext/load_reporting/load_reporting_filter.h" #include "src/core/ext/load_reporting/load_reporting_filter.h"
#include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
static void destroy_lr_cost_context(void *c) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_load_reporting_cost_context *cost_ctx = c;
for (size_t i = 0; i < cost_ctx->values_count; ++i) {
grpc_slice_unref_internal(&exec_ctx, cost_ctx->values[i]);
}
grpc_exec_ctx_finish(&exec_ctx);
gpr_free(cost_ctx->values);
gpr_free(cost_ctx);
}
void grpc_call_set_load_reporting_cost_context(
grpc_call *call, grpc_load_reporting_cost_context *ctx) {
grpc_call_context_set(call, GRPC_CONTEXT_LR_COST, ctx,
destroy_lr_cost_context);
}
static bool is_load_reporting_enabled(const grpc_channel_args *a) { static bool is_load_reporting_enabled(const grpc_channel_args *a) {
if (a == NULL) return false; if (a == NULL) return false;
for (size_t i = 0; i < a->num_args; i++) { for (size_t i = 0; i < a->num_args; i++) {

@ -35,23 +35,8 @@
#define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H #define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/channel/channel_stack.h"
/** Metadata key for the gRPC LB load balancer token.
*
* The value corresponding to this key is an opaque token that is given to the
* frontend as part of each pick; the frontend sends this token to the backend
* in each request it sends when using that pick. The token is used by the
* backend to verify the request and to allow the backend to report load to the
* gRPC LB system. */
#define GRPC_LB_TOKEN_MD_KEY "lb-token"
/** Metadata key for gRPC LB cost reporting. #include "src/core/lib/channel/channel_stack.h"
*
* The value corresponding to this key is an opaque binary blob reported by the
* backend as part of its trailing metadata containing cost information for the
* call. */
#define GRPC_LB_COST_MD_KEY "lb-cost-bin"
/** Identifiers for the invocation point of the users LR callback */ /** Identifiers for the invocation point of the users LR callback */
typedef enum grpc_load_reporting_source { typedef enum grpc_load_reporting_source {

@ -31,11 +31,13 @@
* *
*/ */
#include <string.h>
#include <grpc/load_reporting.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include <string.h>
#include "src/core/ext/load_reporting/load_reporting.h" #include "src/core/ext/load_reporting/load_reporting.h"
#include "src/core/ext/load_reporting/load_reporting_filter.h" #include "src/core/ext/load_reporting/load_reporting_filter.h"
@ -46,8 +48,6 @@
typedef struct call_data { typedef struct call_data {
intptr_t id; /**< an id unique to the call */ intptr_t id; /**< an id unique to the call */
bool have_trailing_md_string;
grpc_slice trailing_md_string;
bool have_initial_md_string; bool have_initial_md_string;
grpc_slice initial_md_string; grpc_slice initial_md_string;
bool have_service_method; bool have_service_method;
@ -142,9 +142,6 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (calld->have_initial_md_string) { if (calld->have_initial_md_string) {
grpc_slice_unref_internal(exec_ctx, calld->initial_md_string); grpc_slice_unref_internal(exec_ctx, calld->initial_md_string);
} }
if (calld->have_trailing_md_string) {
grpc_slice_unref_internal(exec_ctx, calld->trailing_md_string);
}
if (calld->have_service_method) { if (calld->have_service_method) {
grpc_slice_unref_internal(exec_ctx, calld->service_method); grpc_slice_unref_internal(exec_ctx, calld->service_method);
} }
@ -201,15 +198,6 @@ static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
/* substitute our callback for the higher callback */ /* substitute our callback for the higher callback */
calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready; calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready;
op->recv_initial_metadata_ready = &calld->on_initial_md_ready; op->recv_initial_metadata_ready = &calld->on_initial_md_ready;
} else if (op->send_trailing_metadata) {
if (op->send_trailing_metadata->idx.named.lb_cost_bin != NULL) {
calld->trailing_md_string = grpc_slice_ref_internal(
GRPC_MDVALUE(op->send_trailing_metadata->idx.named.lb_cost_bin->md));
calld->have_trailing_md_string = true;
grpc_metadata_batch_remove(
exec_ctx, op->send_trailing_metadata,
op->send_trailing_metadata->idx.named.lb_cost_bin);
}
} }
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(exec_ctx, elem, op);

@ -244,7 +244,7 @@ static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
if (r->resolved_result != NULL) { if (r->resolved_result != NULL) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result); grpc_channel_args_destroy(exec_ctx, r->resolved_result);
} }
grpc_pollset_set_destroy(r->interested_parties); grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
gpr_free(r->name_to_resolve); gpr_free(r->name_to_resolve);
gpr_free(r->default_port); gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(exec_ctx, r->channel_args);

@ -40,10 +40,15 @@
#include "src/core/ext/client_channel/client_channel.h" #include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/uri_parser.h"
#include "src/core/ext/transport/chttp2/client/chttp2_connector.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/lb_targets_info.h"
#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/security/transport/security_connector.h"
#include "src/core/lib/slice/slice_hash_table.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
@ -53,12 +58,114 @@ static void client_channel_factory_ref(
static void client_channel_factory_unref( static void client_channel_factory_unref(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {} grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {}
static grpc_subchannel_args *get_secure_naming_subchannel_args(
grpc_exec_ctx *exec_ctx, const grpc_subchannel_args *args) {
grpc_channel_credentials *channel_credentials =
grpc_channel_credentials_find_in_args(args->args);
if (channel_credentials == NULL) {
gpr_log(GPR_ERROR,
"Can't create subchannel: channel credentials missing for secure "
"channel.");
return NULL;
}
// Make sure security connector does not already exist in args.
if (grpc_security_connector_find_in_args(args->args) != NULL) {
gpr_log(GPR_ERROR,
"Can't create subchannel: security connector already present in "
"channel args.");
return NULL;
}
// To which address are we connecting? By default, use the server URI.
const grpc_arg *server_uri_arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(server_uri_arg != NULL);
GPR_ASSERT(server_uri_arg->type == GRPC_ARG_STRING);
const char *server_uri_str = server_uri_arg->value.string;
GPR_ASSERT(server_uri_str != NULL);
grpc_uri *server_uri =
grpc_uri_parse(server_uri_str, true /* supress errors */);
GPR_ASSERT(server_uri != NULL);
const char *server_uri_path;
server_uri_path =
server_uri->path[0] == '/' ? server_uri->path + 1 : server_uri->path;
const grpc_slice_hash_table *targets_info =
grpc_lb_targets_info_find_in_args(args->args);
char *target_name_to_check = NULL;
if (targets_info != NULL) { // LB channel
// Find the balancer name for the target.
const char *target_uri_str =
grpc_get_subchannel_address_uri_arg(args->args);
grpc_uri *target_uri =
grpc_uri_parse(target_uri_str, false /* suppress errors */);
GPR_ASSERT(target_uri != NULL);
if (target_uri->path[0] != '\0') { // "path" may be empty
const grpc_slice key = grpc_slice_from_static_string(
target_uri->path[0] == '/' ? target_uri->path + 1 : target_uri->path);
const char *value = grpc_slice_hash_table_get(targets_info, key);
if (value != NULL) target_name_to_check = gpr_strdup(value);
grpc_slice_unref_internal(exec_ctx, key);
}
if (target_name_to_check == NULL) {
// If the target name to check hasn't already been set, fall back to using
// SERVER_URI
target_name_to_check = gpr_strdup(server_uri_path);
}
grpc_uri_destroy(target_uri);
} else { // regular channel: the secure name is the original server URI.
target_name_to_check = gpr_strdup(server_uri_path);
}
grpc_uri_destroy(server_uri);
GPR_ASSERT(target_name_to_check != NULL);
grpc_channel_security_connector *subchannel_security_connector = NULL;
// Create the security connector using the credentials and target name.
grpc_channel_args *new_args_from_connector = NULL;
const grpc_security_status security_status =
grpc_channel_credentials_create_security_connector(
exec_ctx, channel_credentials, target_name_to_check, args->args,
&subchannel_security_connector, &new_args_from_connector);
if (security_status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR,
"Failed to create secure subchannel for secure name '%s'",
target_name_to_check);
gpr_free(target_name_to_check);
return NULL;
}
gpr_free(target_name_to_check);
grpc_arg new_security_connector_arg =
grpc_security_connector_to_arg(&subchannel_security_connector->base);
grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
new_args_from_connector != NULL ? new_args_from_connector : args->args,
&new_security_connector_arg, 1);
GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, &subchannel_security_connector->base,
"lb_channel_create");
if (new_args_from_connector != NULL) {
grpc_channel_args_destroy(exec_ctx, new_args_from_connector);
}
grpc_subchannel_args *final_sc_args = gpr_malloc(sizeof(*final_sc_args));
memcpy(final_sc_args, args, sizeof(*args));
final_sc_args->args = new_args;
return final_sc_args;
}
static grpc_subchannel *client_channel_factory_create_subchannel( static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const grpc_subchannel_args *args) { const grpc_subchannel_args *args) {
grpc_subchannel_args *subchannel_args =
get_secure_naming_subchannel_args(exec_ctx, args);
if (subchannel_args == NULL) {
gpr_log(
GPR_ERROR,
"Failed to create subchannel arguments during subchannel creation.");
return NULL;
}
grpc_connector *connector = grpc_chttp2_connector_create(); grpc_connector *connector = grpc_chttp2_connector_create();
grpc_subchannel *s = grpc_subchannel_create(exec_ctx, connector, args); grpc_subchannel *s =
grpc_subchannel_create(exec_ctx, connector, subchannel_args);
grpc_connector_unref(exec_ctx, connector); grpc_connector_unref(exec_ctx, connector);
grpc_channel_args_destroy(exec_ctx,
(grpc_channel_args *)subchannel_args->args);
gpr_free(subchannel_args);
return s; return s;
} }
@ -91,10 +198,10 @@ static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
static grpc_client_channel_factory client_channel_factory = { static grpc_client_channel_factory client_channel_factory = {
&client_channel_factory_vtable}; &client_channel_factory_vtable};
/* Create a secure client channel: // Create a secure client channel:
Asynchronously: - resolve target // Asynchronously: - resolve target
- connect to it (trying alternatives as presented) // - connect to it (trying alternatives as presented)
- perform handshakes */ // - perform handshakes
grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
const char *target, const char *target,
const grpc_channel_args *args, const grpc_channel_args *args,
@ -103,47 +210,25 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
GRPC_API_TRACE( GRPC_API_TRACE(
"grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
"reserved=%p)", "reserved=%p)",
4, (creds, target, args, reserved)); 4, ((void *)creds, target, (void *)args, (void *)reserved));
GPR_ASSERT(reserved == NULL); GPR_ASSERT(reserved == NULL);
// Make sure security connector does not already exist in args. grpc_channel *channel = NULL;
if (grpc_find_security_connector_in_args(args) != NULL) { if (creds != NULL) {
gpr_log(GPR_ERROR, "Cannot set security context in channel args."); // Add channel args containing the client channel factory and channel
// credentials.
grpc_arg args_to_add[] = {
grpc_client_channel_factory_create_channel_arg(&client_channel_factory),
grpc_channel_credentials_to_arg(creds)};
grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
// Create channel.
channel = client_channel_factory_create_channel(
&exec_ctx, &client_channel_factory, target,
GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
// Clean up.
grpc_channel_args_destroy(&exec_ctx, new_args);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
return grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL,
"Security connector exists in channel args.");
}
// Create security connector and construct new channel args.
grpc_channel_security_connector *security_connector;
grpc_channel_args *new_args_from_connector;
if (grpc_channel_credentials_create_security_connector(
&exec_ctx, creds, target, args, &security_connector,
&new_args_from_connector) != GRPC_SECURITY_OK) {
grpc_exec_ctx_finish(&exec_ctx);
return grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
}
// Add channel args containing the client channel factory and security
// connector.
grpc_arg args_to_add[2];
args_to_add[0] =
grpc_client_channel_factory_create_channel_arg(&client_channel_factory);
args_to_add[1] = grpc_security_connector_to_arg(&security_connector->base);
grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
new_args_from_connector != NULL ? new_args_from_connector : args,
args_to_add, GPR_ARRAY_SIZE(args_to_add));
if (new_args_from_connector != NULL) {
grpc_channel_args_destroy(&exec_ctx, new_args_from_connector);
} }
// Create channel.
grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &client_channel_factory, target,
GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
// Clean up.
GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &security_connector->base,
"secure_client_channel_factory_create_channel");
grpc_channel_args_destroy(&exec_ctx, new_args);
grpc_exec_ctx_finish(&exec_ctx);
return channel != NULL ? channel return channel != NULL ? channel
: grpc_lame_client_channel_create( : grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL, target, GRPC_STATUS_INTERNAL,

@ -168,7 +168,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_map_destroy(&t->stream_map); grpc_chttp2_stream_map_destroy(&t->stream_map);
grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
grpc_combiner_destroy(exec_ctx, t->combiner); GRPC_COMBINER_UNREF(exec_ctx, t->combiner, "chttp2_transport");
cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed")); cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
@ -265,7 +265,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
.gain_d = 0, .gain_d = 0,
.initial_control_value = log2(DEFAULT_WINDOW), .initial_control_value = log2(DEFAULT_WINDOW),
.min_control_value = -1, .min_control_value = -1,
.max_control_value = 22, .max_control_value = 25,
.integral_range = 10}); .integral_range = 10});
grpc_chttp2_goaway_parser_init(&t->goaway_parser); grpc_chttp2_goaway_parser_init(&t->goaway_parser);
@ -292,6 +292,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
t->sent_local_settings = 0; t->sent_local_settings = 0;
t->write_buffer_size = DEFAULT_WINDOW; t->write_buffer_size = DEFAULT_WINDOW;
t->enable_bdp_probe = true;
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(
@ -358,6 +359,10 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer( t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
&channel_args->args[i], &channel_args->args[i],
(grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE}); (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE});
} else if (0 ==
strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) {
t->enable_bdp_probe = grpc_channel_arg_get_integer(
&channel_args->args[i], (grpc_integer_options){1, 0, 1});
} else { } else {
static const struct { static const struct {
const char *channel_arg_name; const char *channel_arg_name;
@ -564,6 +569,14 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
GRPC_ERROR_UNREF(s->read_closed_error); GRPC_ERROR_UNREF(s->read_closed_error);
GRPC_ERROR_UNREF(s->write_closed_error); GRPC_ERROR_UNREF(s->write_closed_error);
if (s->incoming_window_delta > 0) {
GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(
"destroy", t, s, s->incoming_window_delta);
} else if (s->incoming_window_delta < 0) {
GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(
"destroy", t, s, -s->incoming_window_delta);
}
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream"); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
GPR_TIMER_END("destroy_stream", 0); GPR_TIMER_END("destroy_stream", 0);
@ -1028,8 +1041,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
GPR_TIMER_BEGIN("perform_stream_op_locked", 0); GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
grpc_transport_stream_op *op = stream_op; grpc_transport_stream_op *op = stream_op;
grpc_chttp2_transport *t = op->transport_private.args[0]; grpc_chttp2_transport *t = op->handler_private.args[0];
grpc_chttp2_stream *s = op->transport_private.args[1]; grpc_chttp2_stream *s = op->handler_private.args[1];
if (grpc_http_trace) { if (grpc_http_trace) {
char *str = grpc_transport_stream_op_string(op); char *str = grpc_transport_stream_op_string(op);
@ -1250,13 +1263,13 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
gpr_free(str); gpr_free(str);
} }
op->transport_private.args[0] = gt; op->handler_private.args[0] = gt;
op->transport_private.args[1] = gs; op->handler_private.args[1] = gs;
GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op"); GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
grpc_closure_sched( grpc_closure_sched(
exec_ctx, exec_ctx,
grpc_closure_init( grpc_closure_init(
&op->transport_private.closure, perform_stream_op_locked, op, &op->handler_private.closure, perform_stream_op_locked, op,
grpc_combiner_scheduler(t->combiner, op->covered_by_poller)), grpc_combiner_scheduler(t->combiner, op->covered_by_poller)),
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
GPR_TIMER_END("perform_stream_op", 0); GPR_TIMER_END("perform_stream_op", 0);
@ -1796,13 +1809,13 @@ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) { if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) {
return; return;
} }
if (grpc_bdp_estimator_trace) {
gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string,
(int)bdp);
}
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp); push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp);
} }
/*******************************************************************************
* INPUT PROCESSING - PARSING
*/
static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) { grpc_chttp2_transport *t) {
grpc_http_parser parser; grpc_http_parser parser;
@ -1908,33 +1921,36 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
&t->read_action_locked); &t->read_action_locked);
if (need_bdp_ping) { if (t->enable_bdp_probe) {
GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping"); if (need_bdp_ping) {
grpc_bdp_estimator_schedule_ping(&t->bdp_estimator); GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
send_ping_locked(exec_ctx, t, grpc_bdp_estimator_schedule_ping(&t->bdp_estimator);
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE, send_ping_locked(exec_ctx, t,
&t->start_bdp_ping_locked, &t->finish_bdp_ping_locked); GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
} &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked);
int64_t estimate = -1;
if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
double target = 1 + log2((double)estimate);
double memory_pressure = grpc_resource_quota_get_memory_pressure(
grpc_resource_user_quota(grpc_endpoint_get_resource_user(t->ep)));
if (memory_pressure > 0.8) {
target *= 1 - GPR_MIN(1, (memory_pressure - 0.8) / 0.1);
} }
double bdp_error = target - grpc_pid_controller_last(&t->pid_controller);
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); int64_t estimate = -1;
gpr_timespec dt_timespec = gpr_time_sub(now, t->last_pid_update); if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
double dt = (double)dt_timespec.tv_sec + dt_timespec.tv_nsec * 1e-9; double target = 1 + log2((double)estimate);
if (dt > 0.1) { double memory_pressure = grpc_resource_quota_get_memory_pressure(
dt = 0.1; grpc_resource_user_quota(grpc_endpoint_get_resource_user(t->ep)));
if (memory_pressure > 0.8) {
target *= 1 - GPR_MIN(1, (memory_pressure - 0.8) / 0.1);
}
double bdp_error =
target - grpc_pid_controller_last(&t->pid_controller);
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec dt_timespec = gpr_time_sub(now, t->last_pid_update);
double dt = (double)dt_timespec.tv_sec + dt_timespec.tv_nsec * 1e-9;
if (dt > 0.1) {
dt = 0.1;
}
double log2_bdp_guess =
grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
t->last_pid_update = now;
} }
double log2_bdp_guess =
grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
t->last_pid_update = now;
} }
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading"); GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
} else { } else {
@ -2046,8 +2062,8 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
(int64_t)have_already) { (int64_t)have_already) {
write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED; write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
} }
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window_delta, GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s,
add_max_recv_bytes); add_max_recv_bytes);
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window, GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
add_max_recv_bytes); add_max_recv_bytes);
if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size - if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size -

@ -109,8 +109,13 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx,
(((uint32_t)p->reason_bytes[3])); (((uint32_t)p->reason_bytes[3]));
grpc_error *error = GRPC_ERROR_NONE; grpc_error *error = GRPC_ERROR_NONE;
if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) { if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) {
error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"), char *message;
GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); gpr_asprintf(&message, "Received RST_STREAM with error code %d", reason);
error = grpc_error_set_int(
grpc_error_set_str(GRPC_ERROR_CREATE("RST_STREAM"),
GRPC_ERROR_STR_GRPC_MESSAGE, message),
GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason);
gpr_free(message);
} }
grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error); grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, true, error);
} }

@ -87,7 +87,7 @@ extern const grpc_chttp2_setting_parameters
grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS]; grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
/* Create a settings frame by diffing old & new, and updating old to be new */ /* Create a settings frame by diffing old & new, and updating old to be new */
grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new, grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *newval,
uint32_t force_mask, size_t count); uint32_t force_mask, size_t count);
/* Create an ack settings frame */ /* Create an ack settings frame */
grpc_slice grpc_chttp2_settings_ack_create(void); grpc_slice grpc_chttp2_settings_ack_create(void);

@ -227,6 +227,9 @@ struct grpc_chttp2_transport {
/** is there a read request to the endpoint outstanding? */ /** is there a read request to the endpoint outstanding? */
uint8_t endpoint_reading; uint8_t endpoint_reading;
/** should we probe bdp? */
bool enable_bdp_probe;
/** various lists of streams */ /** various lists of streams */
grpc_chttp2_stream_list lists[STREAM_LIST_COUNT]; grpc_chttp2_stream_list lists[STREAM_LIST_COUNT];
@ -268,10 +271,6 @@ struct grpc_chttp2_transport {
/** data to write next write */ /** data to write next write */
grpc_slice_buffer qbuf; grpc_slice_buffer qbuf;
/** window available to announce to peer */
int64_t announce_incoming_window;
/** how much window would we like to have for incoming_window */
uint32_t connection_window_target;
/** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set? /** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set?
*/ */
uint32_t write_buffer_size; uint32_t write_buffer_size;
@ -325,6 +324,16 @@ struct grpc_chttp2_transport {
/** window available for peer to send to us */ /** window available for peer to send to us */
int64_t incoming_window; int64_t incoming_window;
/** calculating what we should give for incoming window:
we track the total amount of flow control over initial window size
across all streams: this is data that we want to receive right now (it
has an outstanding read)
and the total amount of flow control under initial window size across all
streams: this is data we've read early
we want to adjust incoming_window such that:
incoming_window = total_over - max(bdp - total_under, 0) */
int64_t stream_total_over_incoming_window;
int64_t stream_total_under_incoming_window;
/* deframing */ /* deframing */
grpc_chttp2_deframe_transport_state deframe_state; grpc_chttp2_deframe_transport_state deframe_state;
@ -631,6 +640,44 @@ typedef enum {
GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \ GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \
amount) amount)
#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE( \
phase, transport, dst_context) \
if (dst_context->incoming_window_delta < 0) { \
transport->stream_total_under_incoming_window += \
dst_context->incoming_window_delta; \
} else if (dst_context->incoming_window_delta > 0) { \
transport->stream_total_over_incoming_window -= \
dst_context->incoming_window_delta; \
}
#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE( \
phase, transport, dst_context) \
if (dst_context->incoming_window_delta < 0) { \
transport->stream_total_under_incoming_window -= \
dst_context->incoming_window_delta; \
} else if (dst_context->incoming_window_delta > 0) { \
transport->stream_total_over_incoming_window += \
dst_context->incoming_window_delta; \
}
#define GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA( \
phase, transport, dst_context, amount) \
GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \
dst_context); \
GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, \
incoming_window_delta, amount); \
GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
dst_context);
#define GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA( \
phase, transport, dst_context, amount) \
GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \
dst_context); \
GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, \
incoming_window_delta, amount); \
GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
dst_context);
#define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \ #define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \
dst_var, amount) \ dst_var, amount) \
do { \ do { \
@ -749,4 +796,6 @@ void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_error *error); grpc_chttp2_stream *s, grpc_error *error);
uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */

@ -376,15 +376,6 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
return err; return err;
} }
uint32_t target_incoming_window = GPR_MAX(
t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
1024);
GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
incoming_frame_size);
if (t->incoming_window <= target_incoming_window / 2) {
grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control");
}
if (s != NULL) { if (s != NULL) {
if (incoming_frame_size > if (incoming_frame_size >
s->incoming_window_delta + s->incoming_window_delta +
@ -402,8 +393,8 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
return err; return err;
} }
GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window_delta, GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s,
incoming_frame_size); incoming_frame_size);
if ((int64_t)t->settings[GRPC_SENT_SETTINGS] if ((int64_t)t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] +
(int64_t)s->incoming_window_delta - (int64_t)s->announce_window <= (int64_t)s->incoming_window_delta - (int64_t)s->announce_window <=
@ -417,6 +408,13 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
s->received_bytes += incoming_frame_size; s->received_bytes += incoming_frame_size;
} }
uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
incoming_frame_size);
if (t->incoming_window <= target_incoming_window / 2) {
grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control");
}
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -152,6 +152,17 @@ static bool stream_ref_if_not_destroyed(gpr_refcount *r) {
return true; return true;
} }
uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) {
return (uint32_t)GPR_MAX(
(int64_t)((1u << 31) - 1),
t->stream_total_over_incoming_window +
(int64_t)GPR_MAX(
t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
t->stream_total_under_incoming_window,
0));
}
bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) { grpc_chttp2_transport *t) {
grpc_chttp2_stream *s; grpc_chttp2_stream *s;
@ -310,13 +321,12 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
/* if the grpc_chttp2_transport is ready to send a window update, do so here /* if the grpc_chttp2_transport is ready to send a window update, do so here
also; 3/4 is a magic number that will likely get tuned soon */ also; 3/4 is a magic number that will likely get tuned soon */
uint32_t target_incoming_window = GPR_MAX( uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
1024);
uint32_t threshold_to_send_transport_window_update = uint32_t threshold_to_send_transport_window_update =
t->outbuf.count > 0 ? 3 * target_incoming_window / 4 t->outbuf.count > 0 ? 3 * target_incoming_window / 4
: target_incoming_window / 2; : target_incoming_window / 2;
if (t->incoming_window <= threshold_to_send_transport_window_update) { if (t->incoming_window <= threshold_to_send_transport_window_update &&
t->incoming_window != target_incoming_window) {
maybe_initiate_ping(exec_ctx, t, maybe_initiate_ping(exec_ctx, t,
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE); GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE);
uint32_t announced = (uint32_t)GPR_CLAMP( uint32_t announced = (uint32_t)GPR_CLAMP(

@ -39,6 +39,7 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/ext/transport/cronet/transport/cronet_transport.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/transport_impl.h" #include "src/core/lib/transport/transport_impl.h"
@ -54,16 +55,14 @@ extern grpc_transport_vtable grpc_cronet_vtable;
GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( GRPCAPI grpc_channel *grpc_cronet_secure_channel_create(
void *engine, const char *target, const grpc_channel_args *args, void *engine, const char *target, const grpc_channel_args *args,
void *reserved) { void *reserved) {
cronet_transport *ct = gpr_malloc(sizeof(cronet_transport));
ct->base.vtable = &grpc_cronet_vtable;
ct->engine = engine;
ct->host = gpr_malloc(strlen(target) + 1);
strcpy(ct->host, target);
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"grpc_create_cronet_transport: stream_engine = %p, target=%s", engine, "grpc_create_cronet_transport: stream_engine = %p, target=%s", engine,
ct->host); target);
grpc_transport *ct =
grpc_create_cronet_transport(engine, target, args, reserved);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
return grpc_channel_create(&exec_ctx, target, args, return grpc_channel_create(&exec_ctx, target, args,
GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct); GRPC_CLIENT_DIRECT_CHANNEL, ct);
} }

@ -80,4 +80,16 @@ void bidirectional_stream_cancel(bidirectional_stream* stream) {
GPR_ASSERT(0); GPR_ASSERT(0);
} }
void bidirectional_stream_disable_auto_flush(bidirectional_stream* stream,
bool disable_auto_flush) {
GPR_ASSERT(0);
}
void bidirectional_stream_delay_request_headers_until_flush(
bidirectional_stream* stream, bool delay_headers_until_flush) {
GPR_ASSERT(0);
}
void bidirectional_stream_flush(bidirectional_stream* stream) { GPR_ASSERT(0); }
#endif /* GRPC_COMPILE_WITH_CRONET */ #endif /* GRPC_COMPILE_WITH_CRONET */

@ -88,7 +88,7 @@ enum e_op_id {
/* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */ /* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */
static void on_request_headers_sent(bidirectional_stream *); static void on_stream_ready(bidirectional_stream *);
static void on_response_headers_received( static void on_response_headers_received(
bidirectional_stream *, const bidirectional_stream_header_array *, bidirectional_stream *, const bidirectional_stream_header_array *,
const char *); const char *);
@ -100,7 +100,7 @@ static void on_succeeded(bidirectional_stream *);
static void on_failed(bidirectional_stream *, int); static void on_failed(bidirectional_stream *, int);
static void on_canceled(bidirectional_stream *); static void on_canceled(bidirectional_stream *);
static bidirectional_stream_callback cronet_callbacks = { static bidirectional_stream_callback cronet_callbacks = {
on_request_headers_sent, on_stream_ready,
on_response_headers_received, on_response_headers_received,
on_read_completed, on_read_completed,
on_write_completed, on_write_completed,
@ -114,6 +114,7 @@ struct grpc_cronet_transport {
grpc_transport base; /* must be first element in this structure */ grpc_transport base; /* must be first element in this structure */
stream_engine *engine; stream_engine *engine;
char *host; char *host;
bool use_packet_coalescing;
}; };
typedef struct grpc_cronet_transport grpc_cronet_transport; typedef struct grpc_cronet_transport grpc_cronet_transport;
@ -152,6 +153,9 @@ struct op_state {
bool state_callback_received[OP_NUM_OPS]; bool state_callback_received[OP_NUM_OPS];
bool fail_state; bool fail_state;
bool flush_read; bool flush_read;
bool flush_cronet_when_ready;
bool pending_write_for_trailer;
bool unprocessed_send_message;
grpc_error *cancel_error; grpc_error *cancel_error;
/* data structure for storing data coming from server */ /* data structure for storing data coming from server */
struct read_state rs; struct read_state rs;
@ -175,7 +179,7 @@ struct op_storage {
struct stream_obj { struct stream_obj {
struct op_and_state *oas; struct op_and_state *oas;
grpc_transport_stream_op *curr_op; grpc_transport_stream_op *curr_op;
grpc_cronet_transport curr_ct; grpc_cronet_transport *curr_ct;
grpc_stream *curr_gs; grpc_stream *curr_gs;
bidirectional_stream *cbs; bidirectional_stream *cbs;
bidirectional_stream_header_array header_array; bidirectional_stream_header_array header_array;
@ -274,6 +278,9 @@ static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op *op) {
new_op->next = storage->head; new_op->next = storage->head;
storage->head = new_op; storage->head = new_op;
storage->num_pending_ops++; storage->num_pending_ops++;
if (op->send_message) {
s->state.unprocessed_send_message = true;
}
CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op, CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op,
storage->num_pending_ops); storage->num_pending_ops);
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
@ -406,9 +413,10 @@ static void on_succeeded(bidirectional_stream *stream) {
/* /*
Cronet callback Cronet callback
*/ */
static void on_request_headers_sent(bidirectional_stream *stream) { static void on_stream_ready(bidirectional_stream *stream) {
CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream); CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream);
stream_obj *s = (stream_obj *)stream->annotation; stream_obj *s = (stream_obj *)stream->annotation;
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
gpr_mu_lock(&s->mu); gpr_mu_lock(&s->mu);
s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true; s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true;
s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true; s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true;
@ -417,6 +425,14 @@ static void on_request_headers_sent(bidirectional_stream *stream) {
gpr_free(s->header_array.headers); gpr_free(s->header_array.headers);
s->header_array.headers = NULL; s->header_array.headers = NULL;
} }
/* Send the initial metadata on wire if there is no SEND_MESSAGE or
* SEND_TRAILING_METADATA ops pending */
if (t->use_packet_coalescing) {
if (s->state.flush_cronet_when_ready) {
CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_flush (%p)", s->cbs);
bidirectional_stream_flush(stream);
}
}
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
execute_from_storage(s); execute_from_storage(s);
} }
@ -528,6 +544,7 @@ static void on_response_trailers_received(
CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream, CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream,
trailers); trailers);
stream_obj *s = (stream_obj *)stream->annotation; stream_obj *s = (stream_obj *)stream->annotation;
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
gpr_mu_lock(&s->mu); gpr_mu_lock(&s->mu);
memset(&s->state.rs.trailing_metadata, 0, memset(&s->state.rs.trailing_metadata, 0,
sizeof(s->state.rs.trailing_metadata)); sizeof(s->state.rs.trailing_metadata));
@ -558,6 +575,10 @@ static void on_response_trailers_received(
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
s->state.state_callback_received[OP_SEND_MESSAGE] = false; s->state.state_callback_received[OP_SEND_MESSAGE] = false;
bidirectional_stream_write(s->cbs, "", 0, true); bidirectional_stream_write(s->cbs, "", 0, true);
if (t->use_packet_coalescing) {
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
bidirectional_stream_flush(s->cbs);
}
s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true; s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true;
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
@ -607,7 +628,7 @@ static void convert_metadata_to_cronet_headers(
curr = curr->next; curr = curr->next;
num_headers_available++; num_headers_available++;
} }
/* Allocate enough memory. It is freed in the on_request_headers_sent callback /* Allocate enough memory. It is freed in the on_stream_ready callback
*/ */
bidirectional_stream_header *headers = bidirectional_stream_header *headers =
(bidirectional_stream_header *)gpr_malloc( (bidirectional_stream_header *)gpr_malloc(
@ -687,8 +708,10 @@ static bool header_has_authority(grpc_linked_mdelem *head) {
executed. This is the heart of the state machine. executed. This is the heart of the state machine.
*/ */
static bool op_can_be_run(grpc_transport_stream_op *curr_op, static bool op_can_be_run(grpc_transport_stream_op *curr_op,
struct op_state *stream_state, struct stream_obj *s, struct op_state *op_state,
struct op_state *op_state, enum e_op_id op_id) { enum e_op_id op_id) {
struct op_state *stream_state = &s->state;
grpc_cronet_transport *t = s->curr_ct;
bool result = true; bool result = true;
/* When call is canceled, every op can be run, except under following /* When call is canceled, every op can be run, except under following
conditions conditions
@ -755,12 +778,14 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op,
else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
result = false; result = false;
/* we haven't sent message yet */ /* we haven't sent message yet */
else if (curr_op->send_message && else if (stream_state->unprocessed_send_message &&
!stream_state->state_op_done[OP_SEND_MESSAGE]) !stream_state->state_op_done[OP_SEND_MESSAGE])
result = false; result = false;
/* we haven't got on_write_completed for the send yet */ /* we haven't got on_write_completed for the send yet */
else if (stream_state->state_op_done[OP_SEND_MESSAGE] && else if (stream_state->state_op_done[OP_SEND_MESSAGE] &&
!stream_state->state_callback_received[OP_SEND_MESSAGE]) !stream_state->state_callback_received[OP_SEND_MESSAGE] &&
!(t->use_packet_coalescing &&
stream_state->pending_write_for_trailer))
result = false; result = false;
} else if (op_id == OP_CANCEL_ERROR) { } else if (op_id == OP_CANCEL_ERROR) {
/* already executed */ /* already executed */
@ -833,24 +858,28 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
struct op_and_state *oas) { struct op_and_state *oas) {
grpc_transport_stream_op *stream_op = &oas->op; grpc_transport_stream_op *stream_op = &oas->op;
struct stream_obj *s = oas->s; struct stream_obj *s = oas->s;
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
struct op_state *stream_state = &s->state; struct op_state *stream_state = &s->state;
enum e_op_result result = NO_ACTION_POSSIBLE; enum e_op_result result = NO_ACTION_POSSIBLE;
if (stream_op->send_initial_metadata && if (stream_op->send_initial_metadata &&
op_can_be_run(stream_op, stream_state, &oas->state, op_can_be_run(stream_op, s, &oas->state, OP_SEND_INITIAL_METADATA)) {
OP_SEND_INITIAL_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas);
/* Start new cronet stream. It is destroyed in on_succeeded, on_canceled, /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled,
* on_failed */ * on_failed */
GPR_ASSERT(s->cbs == NULL); GPR_ASSERT(s->cbs == NULL);
GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]); GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]);
s->cbs = bidirectional_stream_create(s->curr_ct.engine, s->curr_gs, s->cbs =
&cronet_callbacks); bidirectional_stream_create(t->engine, s->curr_gs, &cronet_callbacks);
CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs); CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs);
if (t->use_packet_coalescing) {
bidirectional_stream_disable_auto_flush(s->cbs, true);
bidirectional_stream_delay_request_headers_until_flush(s->cbs, true);
}
char *url = NULL; char *url = NULL;
const char *method = "POST"; const char *method = "POST";
s->header_array.headers = NULL; s->header_array.headers = NULL;
convert_metadata_to_cronet_headers( convert_metadata_to_cronet_headers(
stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url, stream_op->send_initial_metadata->list.head, t->host, &url,
&s->header_array.headers, &s->header_array.count, &method); &s->header_array.headers, &s->header_array.count, &method);
s->header_array.capacity = s->header_array.count; s->header_array.capacity = s->header_array.count;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url);
@ -862,30 +891,16 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
gpr_free((void *)s->header_array.headers[header_index].value); gpr_free((void *)s->header_array.headers[header_index].value);
} }
stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
result = ACTION_TAKEN_WITH_CALLBACK; if (t->use_packet_coalescing) {
} else if (stream_op->recv_initial_metadata && if (!stream_op->send_message && !stream_op->send_trailing_metadata) {
op_can_be_run(stream_op, stream_state, &oas->state, s->state.flush_cronet_when_ready = true;
OP_RECV_INITIAL_METADATA)) { }
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas);
if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} else if (stream_state->state_callback_received[OP_FAILED]) {
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} else {
grpc_chttp2_incoming_metadata_buffer_publish(
exec_ctx, &oas->s->state.rs.initial_metadata,
stream_op->recv_initial_metadata);
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} }
stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true; result = ACTION_TAKEN_WITH_CALLBACK;
result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_op->send_message && } else if (stream_op->send_message &&
op_can_be_run(stream_op, stream_state, &oas->state, op_can_be_run(stream_op, s, &oas->state, OP_SEND_MESSAGE)) {
OP_SEND_MESSAGE)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas);
stream_state->unprocessed_send_message = false;
if (stream_state->state_callback_received[OP_FAILED]) { if (stream_state->state_callback_received[OP_FAILED]) {
result = NO_ACTION_POSSIBLE; result = NO_ACTION_POSSIBLE;
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
@ -916,16 +931,63 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->state_callback_received[OP_SEND_MESSAGE] = false; stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer, bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer,
(int)write_buffer_size, false); (int)write_buffer_size, false);
result = ACTION_TAKEN_WITH_CALLBACK; if (t->use_packet_coalescing) {
if (!stream_op->send_trailing_metadata) {
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
bidirectional_stream_flush(s->cbs);
result = ACTION_TAKEN_WITH_CALLBACK;
} else {
stream_state->pending_write_for_trailer = true;
result = ACTION_TAKEN_NO_CALLBACK;
}
} else {
result = ACTION_TAKEN_WITH_CALLBACK;
}
} else { } else {
result = NO_ACTION_POSSIBLE; result = NO_ACTION_POSSIBLE;
} }
} }
stream_state->state_op_done[OP_SEND_MESSAGE] = true; stream_state->state_op_done[OP_SEND_MESSAGE] = true;
oas->state.state_op_done[OP_SEND_MESSAGE] = true; oas->state.state_op_done[OP_SEND_MESSAGE] = true;
} else if (stream_op->send_trailing_metadata &&
op_can_be_run(stream_op, s, &oas->state,
OP_SEND_TRAILING_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas);
if (stream_state->state_callback_received[OP_FAILED]) {
result = NO_ACTION_POSSIBLE;
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
} else {
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
bidirectional_stream_write(s->cbs, "", 0, true);
if (t->use_packet_coalescing) {
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
bidirectional_stream_flush(s->cbs);
}
result = ACTION_TAKEN_WITH_CALLBACK;
}
stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
} else if (stream_op->recv_initial_metadata &&
op_can_be_run(stream_op, s, &oas->state,
OP_RECV_INITIAL_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas);
if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} else if (stream_state->state_callback_received[OP_FAILED]) {
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} else {
grpc_chttp2_incoming_metadata_buffer_publish(
exec_ctx, &oas->s->state.rs.initial_metadata,
stream_op->recv_initial_metadata);
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
}
stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_op->recv_message && } else if (stream_op->recv_message &&
op_can_be_run(stream_op, stream_state, &oas->state, op_can_be_run(stream_op, s, &oas->state, OP_RECV_MESSAGE)) {
OP_RECV_MESSAGE)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas);
if (stream_state->state_op_done[OP_CANCEL_ERROR]) { if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
CRONET_LOG(GPR_DEBUG, "Stream is cancelled."); CRONET_LOG(GPR_DEBUG, "Stream is cancelled.");
@ -980,6 +1042,16 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
stream_state->state_op_done[OP_RECV_MESSAGE] = true; stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true;
/* Extra read to trigger on_succeed */
stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
stream_state->rs.received_bytes = 0;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
stream_state->state_op_done[OP_READ_REQ_MADE] =
true; /* Indicates that at least one read request has been made */
bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
stream_state->rs.remaining_bytes);
result = ACTION_TAKEN_NO_CALLBACK; result = ACTION_TAKEN_NO_CALLBACK;
} }
} else if (stream_state->rs.remaining_bytes == 0) { } else if (stream_state->rs.remaining_bytes == 0) {
@ -1027,7 +1099,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
result = ACTION_TAKEN_NO_CALLBACK; result = ACTION_TAKEN_NO_CALLBACK;
} }
} else if (stream_op->recv_trailing_metadata && } else if (stream_op->recv_trailing_metadata &&
op_can_be_run(stream_op, stream_state, &oas->state, op_can_be_run(stream_op, s, &oas->state,
OP_RECV_TRAILING_METADATA)) { OP_RECV_TRAILING_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
if (oas->s->state.rs.trailing_metadata_valid) { if (oas->s->state.rs.trailing_metadata_valid) {
@ -1038,23 +1110,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
} }
stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true; stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
result = ACTION_TAKEN_NO_CALLBACK; result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_op->send_trailing_metadata &&
op_can_be_run(stream_op, stream_state, &oas->state,
OP_SEND_TRAILING_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas);
if (stream_state->state_callback_received[OP_FAILED]) {
result = NO_ACTION_POSSIBLE;
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
} else {
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
bidirectional_stream_write(s->cbs, "", 0, true);
result = ACTION_TAKEN_WITH_CALLBACK;
}
stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
} else if (stream_op->cancel_error && } else if (stream_op->cancel_error &&
op_can_be_run(stream_op, stream_state, &oas->state, op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) {
OP_CANCEL_ERROR)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas);
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs); CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
if (s->cbs) { if (s->cbs) {
@ -1068,8 +1125,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->cancel_error = GRPC_ERROR_REF(stream_op->cancel_error); stream_state->cancel_error = GRPC_ERROR_REF(stream_op->cancel_error);
} }
} else if (stream_op->on_complete && } else if (stream_op->on_complete &&
op_can_be_run(stream_op, stream_state, &oas->state, op_can_be_run(stream_op, s, &oas->state, OP_ON_COMPLETE)) {
OP_ON_COMPLETE)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas);
if (stream_state->state_op_done[OP_CANCEL_ERROR]) { if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
grpc_closure_sched(exec_ctx, stream_op->on_complete, grpc_closure_sched(exec_ctx, stream_op->on_complete,
@ -1133,6 +1189,12 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
sizeof(s->state.state_callback_received)); sizeof(s->state.state_callback_received));
s->state.fail_state = s->state.flush_read = false; s->state.fail_state = s->state.flush_read = false;
s->state.cancel_error = NULL; s->state.cancel_error = NULL;
s->state.flush_cronet_when_ready = s->state.pending_write_for_trailer = false;
s->state.unprocessed_send_message = false;
s->curr_gs = gs;
s->curr_ct = (grpc_cronet_transport *)gt;
gpr_mu_init(&s->mu); gpr_mu_init(&s->mu);
return 0; return 0;
} }
@ -1148,8 +1210,6 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_transport_stream_op *op) { grpc_stream *gs, grpc_transport_stream_op *op) {
CRONET_LOG(GPR_DEBUG, "perform_stream_op"); CRONET_LOG(GPR_DEBUG, "perform_stream_op");
stream_obj *s = (stream_obj *)gs; stream_obj *s = (stream_obj *)gs;
s->curr_gs = gs;
memcpy(&s->curr_ct, gt, sizeof(grpc_cronet_transport));
add_to_storage(s, op); add_to_storage(s, op);
if (op->send_initial_metadata && if (op->send_initial_metadata &&
header_has_authority(op->send_initial_metadata->list.head)) { header_has_authority(op->send_initial_metadata->list.head)) {
@ -1197,14 +1257,58 @@ static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx,
static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_transport_op *op) {} grpc_transport_op *op) {}
const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj), static const grpc_transport_vtable grpc_cronet_vtable = {
"cronet_http", sizeof(stream_obj),
init_stream, "cronet_http",
set_pollset_do_nothing, init_stream,
set_pollset_set_do_nothing, set_pollset_do_nothing,
perform_stream_op, set_pollset_set_do_nothing,
perform_op, perform_stream_op,
destroy_stream, perform_op,
destroy_transport, destroy_stream,
get_peer, destroy_transport,
get_endpoint}; get_peer,
get_endpoint};
grpc_transport *grpc_create_cronet_transport(void *engine, const char *target,
const grpc_channel_args *args,
void *reserved) {
grpc_cronet_transport *ct = gpr_malloc(sizeof(grpc_cronet_transport));
if (!ct) {
goto error;
}
ct->base.vtable = &grpc_cronet_vtable;
ct->engine = engine;
ct->host = gpr_malloc(strlen(target) + 1);
if (!ct->host) {
goto error;
}
strcpy(ct->host, target);
ct->use_packet_coalescing = true;
if (args) {
for (size_t i = 0; i < args->num_args; i++) {
if (0 ==
strcmp(args->args[i].key, GRPC_ARG_USE_CRONET_PACKET_COALESCING)) {
if (args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
GRPC_ARG_USE_CRONET_PACKET_COALESCING);
} else {
ct->use_packet_coalescing = (args->args[i].value.integer != 0);
}
}
}
}
return &ct->base;
error:
if (ct) {
if (ct->host) {
gpr_free(ct->host);
}
gpr_free(ct);
}
return NULL;
}

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

@ -105,7 +105,6 @@ static grpc_error *process_send_initial_metadata(
static grpc_error *process_send_initial_metadata( static grpc_error *process_send_initial_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_metadata_batch *initial_metadata) { grpc_metadata_batch *initial_metadata) {
grpc_error *error;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;
/* Parse incoming request for compression. If any, it'll be available /* Parse incoming request for compression. If any, it'll be available
@ -144,10 +143,13 @@ static grpc_error *process_send_initial_metadata(
calld->has_compression_algorithm = 1; /* GPR_TRUE */ calld->has_compression_algorithm = 1; /* GPR_TRUE */
} }
grpc_error *error = GRPC_ERROR_NONE;
/* hint compression algorithm */ /* hint compression algorithm */
error = grpc_metadata_batch_add_tail( if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
exec_ctx, initial_metadata, &calld->compression_algorithm_storage, error = grpc_metadata_batch_add_tail(
grpc_compression_encoding_mdelem(calld->compression_algorithm)); exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
grpc_compression_encoding_mdelem(calld->compression_algorithm));
}
if (error != GRPC_ERROR_NONE) return error; if (error != GRPC_ERROR_NONE) return error;

@ -50,6 +50,9 @@ typedef enum {
/// Reserved for traffic_class_context. /// Reserved for traffic_class_context.
GRPC_CONTEXT_TRAFFIC, GRPC_CONTEXT_TRAFFIC,
/// Costs for Load Reporting.
GRPC_CONTEXT_LR_COST,
GRPC_CONTEXT_COUNT GRPC_CONTEXT_COUNT
} grpc_context_index; } grpc_context_index;

@ -198,14 +198,17 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_STR_KEY, ":path")); GRPC_ERROR_STR_KEY, ":path"));
} }
if (b->idx.named.host != NULL) { if (b->idx.named.host != NULL && b->idx.named.authority == NULL) {
grpc_linked_mdelem *el = b->idx.named.host;
grpc_mdelem md = GRPC_MDELEM_REF(el->md);
grpc_metadata_batch_remove(exec_ctx, b, el);
add_error( add_error(
error_name, &error, error_name, &error,
grpc_metadata_batch_substitute( grpc_metadata_batch_add_head(
exec_ctx, b, b->idx.named.host, exec_ctx, b, el, grpc_mdelem_from_slices(
grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY,
exec_ctx, GRPC_MDSTR_AUTHORITY, grpc_slice_ref_internal(GRPC_MDVALUE(md)))));
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.host->md))))); GRPC_MDELEM_UNREF(exec_ctx, md);
} }
if (b->idx.named.authority == NULL) { if (b->idx.named.authority == NULL) {

@ -93,8 +93,9 @@ void grpc_httpcli_context_init(grpc_httpcli_context *context) {
context->pollset_set = grpc_pollset_set_create(); context->pollset_set = grpc_pollset_set_create();
} }
void grpc_httpcli_context_destroy(grpc_httpcli_context *context) { void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
grpc_pollset_set_destroy(context->pollset_set); grpc_httpcli_context *context) {
grpc_pollset_set_destroy(exec_ctx, context->pollset_set);
} }
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req, static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,

@ -83,7 +83,8 @@ typedef struct grpc_httpcli_request {
typedef struct grpc_http_response grpc_httpcli_response; typedef struct grpc_http_response grpc_httpcli_response;
void grpc_httpcli_context_init(grpc_httpcli_context *context); void grpc_httpcli_context_init(grpc_httpcli_context *context);
void grpc_httpcli_context_destroy(grpc_httpcli_context *context); void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
grpc_httpcli_context *context);
/* Asynchronously perform a HTTP GET. /* Asynchronously perform a HTTP GET.
'context' specifies the http context under which to do the get 'context' specifies the http context under which to do the get

@ -72,6 +72,7 @@ struct grpc_combiner {
bool final_list_covered_by_poller; bool final_list_covered_by_poller;
grpc_closure_list final_list; grpc_closure_list final_list;
grpc_closure offload; grpc_closure offload;
gpr_refcount refs;
}; };
static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx, static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx,
@ -126,6 +127,7 @@ static bool is_covered_by_poller(grpc_combiner *lock) {
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) {
grpc_combiner *lock = gpr_malloc(sizeof(*lock)); grpc_combiner *lock = gpr_malloc(sizeof(*lock));
gpr_ref_init(&lock->refs, 1);
lock->next_combiner_on_this_exec_ctx = NULL; lock->next_combiner_on_this_exec_ctx = NULL;
lock->time_to_execute_final_list = false; lock->time_to_execute_final_list = false;
lock->optional_workqueue = optional_workqueue; lock->optional_workqueue = optional_workqueue;
@ -152,7 +154,7 @@ static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
gpr_free(lock); gpr_free(lock);
} }
void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED); gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED);
GRPC_COMBINER_TRACE(gpr_log( GRPC_COMBINER_TRACE(gpr_log(
GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
@ -161,6 +163,30 @@ void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
} }
} }
#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
#define GRPC_COMBINER_DEBUG_SPAM(op, delta) \
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, \
"combiner[%p] %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \
gpr_atm_no_barrier_load(&lock->refs.count), \
gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason);
#else
#define GRPC_COMBINER_DEBUG_SPAM(op, delta)
#endif
void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
GRPC_COMBINER_DEBUG_SPAM("UNREF", -1);
if (gpr_unref(&lock->refs)) {
start_destroy(exec_ctx, lock);
}
}
grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
GRPC_COMBINER_DEBUG_SPAM(" REF", 1);
gpr_ref(&lock->refs);
return lock;
}
static void push_last_on_exec_ctx(grpc_exec_ctx *exec_ctx, static void push_last_on_exec_ctx(grpc_exec_ctx *exec_ctx,
grpc_combiner *lock) { grpc_combiner *lock) {
lock->next_combiner_on_this_exec_ctx = NULL; lock->next_combiner_on_this_exec_ctx = NULL;

@ -48,8 +48,27 @@
// Initialize the lock, with an optional workqueue to shift load to when // Initialize the lock, with an optional workqueue to shift load to when
// necessary // necessary
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue);
// Destroy the lock
void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); //#define GRPC_COMBINER_REFCOUNT_DEBUG
#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
#define GRPC_COMBINER_DEBUG_ARGS \
, const char *file, int line, const char *reason
#define GRPC_COMBINER_REF(combiner, reason) \
grpc_combiner_ref((combiner), __FILE__, __LINE__, (reason))
#define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
grpc_combiner_unref((exec_ctx), (combiner), __FILE__, __LINE__, (reason))
#else
#define GRPC_COMBINER_DEBUG_ARGS
#define GRPC_COMBINER_REF(combiner, reason) grpc_combiner_ref((combiner))
#define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
grpc_combiner_unref((exec_ctx), (combiner))
#endif
// Ref/unref the lock, for when we're sharing the lock ownership
// Prefer to use the macros above
grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
// Fetch a scheduler to schedule closures against // Fetch a scheduler to schedule closures against
grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *lock, grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *lock,
bool covered_by_poller); bool covered_by_poller);

@ -1405,16 +1405,6 @@ static void pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->po.mu); gpr_mu_destroy(&pollset->po.mu);
} }
static void pollset_reset(grpc_pollset *pollset) {
GPR_ASSERT(pollset->shutting_down);
GPR_ASSERT(!pollset_has_workers(pollset));
pollset->shutting_down = false;
pollset->finish_shutdown_called = false;
pollset->kicked_without_pollers = false;
pollset->shutdown_done = NULL;
GPR_ASSERT(pollset->po.pi == NULL);
}
static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx, static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx,
polling_island *pi) { polling_island *pi) {
if (gpr_mu_trylock(&pi->workqueue_read_mu)) { if (gpr_mu_trylock(&pi->workqueue_read_mu)) {
@ -1852,13 +1842,12 @@ static grpc_pollset_set *pollset_set_create(void) {
return pss; return pss;
} }
static void pollset_set_destroy(grpc_pollset_set *pss) { static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pss) {
gpr_mu_destroy(&pss->po.mu); gpr_mu_destroy(&pss->po.mu);
if (pss->po.pi != NULL) { if (pss->po.pi != NULL) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; PI_UNREF(exec_ctx, pss->po.pi, "pss_destroy");
PI_UNREF(&exec_ctx, pss->po.pi, "pss_destroy");
grpc_exec_ctx_finish(&exec_ctx);
} }
gpr_free(pss); gpr_free(pss);
@ -1958,7 +1947,6 @@ static const grpc_event_engine_vtable vtable = {
.pollset_init = pollset_init, .pollset_init = pollset_init,
.pollset_shutdown = pollset_shutdown, .pollset_shutdown = pollset_shutdown,
.pollset_reset = pollset_reset,
.pollset_destroy = pollset_destroy, .pollset_destroy = pollset_destroy,
.pollset_work = pollset_work, .pollset_work = pollset_work,
.pollset_kick = pollset_kick, .pollset_kick = pollset_kick,

@ -149,7 +149,7 @@ static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec,
static bool fd_is_orphaned(grpc_fd *fd); static bool fd_is_orphaned(grpc_fd *fd);
/* Reference counting for fds */ /* Reference counting for fds */
/*#define GRPC_FD_REF_COUNT_DEBUG*/ //#define GRPC_FD_REF_COUNT_DEBUG
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifdef GRPC_FD_REF_COUNT_DEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
static void fd_unref(grpc_fd *fd, const char *reason, const char *file, static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
@ -191,6 +191,7 @@ struct grpc_pollset {
int kicked_without_pollers; int kicked_without_pollers;
grpc_closure *shutdown_done; grpc_closure *shutdown_done;
grpc_closure_list idle_jobs; grpc_closure_list idle_jobs;
int pollset_set_count;
/* all polled fds */ /* all polled fds */
size_t fd_count; size_t fd_count;
size_t fd_capacity; size_t fd_capacity;
@ -228,7 +229,7 @@ static grpc_error *pollset_kick_ext(grpc_pollset *p,
/* Return 1 if the pollset has active threads in pollset_work (pollset must /* Return 1 if the pollset has active threads in pollset_work (pollset must
* be locked) */ * be locked) */
static int pollset_has_workers(grpc_pollset *pollset); static bool pollset_has_workers(grpc_pollset *pollset);
/******************************************************************************* /*******************************************************************************
* pollset_set definitions * pollset_set definitions
@ -282,8 +283,8 @@ cv_fd_table g_cvfds;
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
gpr_atm_no_barrier_load(&fd->refst), (int)gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); (int)gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
#else #else
#define REF_BY(fd, n, reason) ref_by(fd, n) #define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(fd, n, reason) unref_by(fd, n) #define UNREF_BY(fd, n, reason) unref_by(fd, n)
@ -297,8 +298,8 @@ static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_atm old; gpr_atm old;
gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
gpr_atm_no_barrier_load(&fd->refst), (int)gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); (int)gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
#else #else
static void unref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) {
gpr_atm old; gpr_atm old;
@ -658,10 +659,18 @@ static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
worker->next->prev = worker->prev; worker->next->prev = worker->prev;
} }
static int pollset_has_workers(grpc_pollset *p) { static bool pollset_has_workers(grpc_pollset *p) {
return p->root_worker.next != &p->root_worker; return p->root_worker.next != &p->root_worker;
} }
static bool pollset_in_pollset_sets(grpc_pollset *p) {
return p->pollset_set_count;
}
static bool pollset_has_observers(grpc_pollset *p) {
return pollset_has_workers(p) || pollset_in_pollset_sets(p);
}
static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) {
if (pollset_has_workers(p)) { if (pollset_has_workers(p)) {
grpc_pollset_worker *w = p->root_worker.next; grpc_pollset_worker *w = p->root_worker.next;
@ -800,6 +809,7 @@ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
pollset->fd_count = 0; pollset->fd_count = 0;
pollset->fd_capacity = 0; pollset->fd_capacity = 0;
pollset->fds = NULL; pollset->fds = NULL;
pollset->pollset_set_count = 0;
} }
static void pollset_destroy(grpc_pollset *pollset) { static void pollset_destroy(grpc_pollset *pollset) {
@ -815,16 +825,6 @@ static void pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu); gpr_mu_destroy(&pollset->mu);
} }
static void pollset_reset(grpc_pollset *pollset) {
GPR_ASSERT(pollset->shutting_down);
GPR_ASSERT(!pollset_has_workers(pollset));
GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
GPR_ASSERT(pollset->fd_count == 0);
pollset->shutting_down = 0;
pollset->called_shutdown = 0;
pollset->kicked_without_pollers = 0;
}
static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd) { grpc_fd *fd) {
gpr_mu_lock(&pollset->mu); gpr_mu_lock(&pollset->mu);
@ -1071,7 +1071,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
if (pollset->shutting_down) { if (pollset->shutting_down) {
if (pollset_has_workers(pollset)) { if (pollset_has_workers(pollset)) {
pollset_kick(pollset, NULL); pollset_kick(pollset, NULL);
} else if (!pollset->called_shutdown) { } else if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
pollset->called_shutdown = 1; pollset->called_shutdown = 1;
gpr_mu_unlock(&pollset->mu); gpr_mu_unlock(&pollset->mu);
finish_shutdown(exec_ctx, pollset); finish_shutdown(exec_ctx, pollset);
@ -1103,7 +1103,7 @@ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
if (!pollset_has_workers(pollset)) { if (!pollset_has_workers(pollset)) {
grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs); grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs);
} }
if (!pollset->called_shutdown && !pollset_has_workers(pollset)) { if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
pollset->called_shutdown = 1; pollset->called_shutdown = 1;
finish_shutdown(exec_ctx, pollset); finish_shutdown(exec_ctx, pollset);
} }
@ -1137,12 +1137,27 @@ static grpc_pollset_set *pollset_set_create(void) {
return pollset_set; return pollset_set;
} }
static void pollset_set_destroy(grpc_pollset_set *pollset_set) { static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set) {
size_t i; size_t i;
gpr_mu_destroy(&pollset_set->mu); gpr_mu_destroy(&pollset_set->mu);
for (i = 0; i < pollset_set->fd_count; i++) { for (i = 0; i < pollset_set->fd_count; i++) {
GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
} }
for (i = 0; i < pollset_set->pollset_count; i++) {
grpc_pollset *pollset = pollset_set->pollsets[i];
gpr_mu_lock(&pollset->mu);
pollset->pollset_set_count--;
/* check shutdown */
if (pollset->shutting_down && !pollset->called_shutdown &&
!pollset_has_observers(pollset)) {
pollset->called_shutdown = 1;
gpr_mu_unlock(&pollset->mu);
finish_shutdown(exec_ctx, pollset);
} else {
gpr_mu_unlock(&pollset->mu);
}
}
gpr_free(pollset_set->pollsets); gpr_free(pollset_set->pollsets);
gpr_free(pollset_set->pollset_sets); gpr_free(pollset_set->pollset_sets);
gpr_free(pollset_set->fds); gpr_free(pollset_set->fds);
@ -1153,6 +1168,9 @@ static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_pollset_set *pollset_set,
grpc_pollset *pollset) { grpc_pollset *pollset) {
size_t i, j; size_t i, j;
gpr_mu_lock(&pollset->mu);
pollset->pollset_set_count++;
gpr_mu_unlock(&pollset->mu);
gpr_mu_lock(&pollset_set->mu); gpr_mu_lock(&pollset_set->mu);
if (pollset_set->pollset_count == pollset_set->pollset_capacity) { if (pollset_set->pollset_count == pollset_set->pollset_capacity) {
pollset_set->pollset_capacity = pollset_set->pollset_capacity =
@ -1188,6 +1206,17 @@ static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
} }
} }
gpr_mu_unlock(&pollset_set->mu); gpr_mu_unlock(&pollset_set->mu);
gpr_mu_lock(&pollset->mu);
pollset->pollset_set_count--;
/* check shutdown */
if (pollset->shutting_down && !pollset->called_shutdown &&
!pollset_has_observers(pollset)) {
pollset->called_shutdown = 1;
gpr_mu_unlock(&pollset->mu);
finish_shutdown(exec_ctx, pollset);
} else {
gpr_mu_unlock(&pollset->mu);
}
} }
static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
@ -1514,7 +1543,6 @@ static const grpc_event_engine_vtable vtable = {
.pollset_init = pollset_init, .pollset_init = pollset_init,
.pollset_shutdown = pollset_shutdown, .pollset_shutdown = pollset_shutdown,
.pollset_reset = pollset_reset,
.pollset_destroy = pollset_destroy, .pollset_destroy = pollset_destroy,
.pollset_work = pollset_work, .pollset_work = pollset_work,
.pollset_kick = pollset_kick, .pollset_kick = pollset_kick,

@ -191,10 +191,6 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
g_event_engine->pollset_shutdown(exec_ctx, pollset, closure); g_event_engine->pollset_shutdown(exec_ctx, pollset, closure);
} }
void grpc_pollset_reset(grpc_pollset *pollset) {
g_event_engine->pollset_reset(pollset);
}
void grpc_pollset_destroy(grpc_pollset *pollset) { void grpc_pollset_destroy(grpc_pollset *pollset) {
g_event_engine->pollset_destroy(pollset); g_event_engine->pollset_destroy(pollset);
} }
@ -219,8 +215,9 @@ grpc_pollset_set *grpc_pollset_set_create(void) {
return g_event_engine->pollset_set_create(); return g_event_engine->pollset_set_create();
} }
void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) { void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx,
g_event_engine->pollset_set_destroy(pollset_set); grpc_pollset_set *pollset_set) {
g_event_engine->pollset_set_destroy(exec_ctx, pollset_set);
} }
void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,

@ -64,7 +64,6 @@ typedef struct grpc_event_engine_vtable {
void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu); void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu);
void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure); grpc_closure *closure);
void (*pollset_reset)(grpc_pollset *pollset);
void (*pollset_destroy)(grpc_pollset *pollset); void (*pollset_destroy)(grpc_pollset *pollset);
grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now, grpc_pollset_worker **worker, gpr_timespec now,
@ -75,7 +74,8 @@ typedef struct grpc_event_engine_vtable {
struct grpc_fd *fd); struct grpc_fd *fd);
grpc_pollset_set *(*pollset_set_create)(void); grpc_pollset_set *(*pollset_set_create)(void);
void (*pollset_set_destroy)(grpc_pollset_set *pollset_set); void (*pollset_set_destroy)(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set);
void (*pollset_set_add_pollset)(grpc_exec_ctx *exec_ctx, void (*pollset_set_add_pollset)(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_pollset_set *pollset_set,
grpc_pollset *pollset); grpc_pollset *pollset);

@ -31,95 +31,18 @@
* *
*/ */
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/endpoint.h"
typedef struct endpoint_ll_node { void grpc_network_status_shutdown(void) {}
grpc_endpoint *ep;
struct endpoint_ll_node *next;
} endpoint_ll_node;
static endpoint_ll_node *head = NULL;
static gpr_mu g_endpoint_mutex;
void grpc_network_status_shutdown(void) {
if (head != NULL) {
gpr_log(GPR_ERROR,
"Memory leaked as not all network endpoints were shut down");
}
gpr_mu_destroy(&g_endpoint_mutex);
}
void grpc_network_status_init(void) { void grpc_network_status_init(void) {
gpr_mu_init(&g_endpoint_mutex);
// TODO(makarandd): Install callback with OS to monitor network status. // TODO(makarandd): Install callback with OS to monitor network status.
} }
void grpc_destroy_network_status_monitor() { void grpc_destroy_network_status_monitor() {}
for (endpoint_ll_node *curr = head; curr != NULL;) {
endpoint_ll_node *next = curr->next;
gpr_free(curr);
curr = next;
}
gpr_mu_destroy(&g_endpoint_mutex);
}
void grpc_network_status_register_endpoint(grpc_endpoint *ep) {
gpr_mu_lock(&g_endpoint_mutex);
if (head == NULL) {
head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
head->ep = ep;
head->next = NULL;
} else {
endpoint_ll_node *prev_head = head;
head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
head->ep = ep;
head->next = prev_head;
}
gpr_mu_unlock(&g_endpoint_mutex);
}
void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) { void grpc_network_status_register_endpoint(grpc_endpoint *ep) { (void)ep; }
gpr_mu_lock(&g_endpoint_mutex);
GPR_ASSERT(head);
bool found = false;
endpoint_ll_node *prev = head;
// if we're unregistering the head, just move head to the next
if (ep == head->ep) {
head = head->next;
gpr_free(prev);
found = true;
} else {
for (endpoint_ll_node *curr = head->next; curr != NULL; curr = curr->next) {
if (ep == curr->ep) {
prev->next = curr->next;
gpr_free(curr);
found = true;
break;
}
prev = curr;
}
}
gpr_mu_unlock(&g_endpoint_mutex);
GPR_ASSERT(found);
}
// Walk the linked-list from head and execute shutdown. It is possible that void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) { (void)ep; }
// other threads might be in the process of shutdown as well, but that has
// no side effect since endpoint shutdown is idempotent.
void grpc_network_status_shutdown_all_endpoints() {
gpr_mu_lock(&g_endpoint_mutex);
if (head == NULL) {
gpr_mu_unlock(&g_endpoint_mutex);
return;
}
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
for (endpoint_ll_node *curr = head; curr != NULL; curr = curr->next) { void grpc_network_status_shutdown_all_endpoints() {}
curr->ep->vtable->shutdown(&exec_ctx, curr->ep,
GRPC_ERROR_CREATE("Network unavailable"));
}
gpr_mu_unlock(&g_endpoint_mutex);
grpc_exec_ctx_finish(&exec_ctx);
}

@ -58,9 +58,6 @@ void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
* pollset's mutex must be held */ * pollset's mutex must be held */
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure); grpc_closure *closure);
/** Reset the pollset to its initial state (perhaps with some cached objects);
* must have been previously shutdown */
void grpc_pollset_reset(grpc_pollset *pollset);
void grpc_pollset_destroy(grpc_pollset *pollset); void grpc_pollset_destroy(grpc_pollset *pollset);
/* Do some work on a pollset. /* Do some work on a pollset.

@ -44,7 +44,8 @@
typedef struct grpc_pollset_set grpc_pollset_set; typedef struct grpc_pollset_set grpc_pollset_set;
grpc_pollset_set *grpc_pollset_set_create(void); grpc_pollset_set *grpc_pollset_set_create(void);
void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set); void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set);
void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_pollset_set *pollset_set,
grpc_pollset *pollset); grpc_pollset *pollset);

@ -41,7 +41,8 @@ grpc_pollset_set* grpc_pollset_set_create(void) {
return (grpc_pollset_set*)((intptr_t)0xdeafbeef); return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
} }
void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {} void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set) {}
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx, void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set, grpc_pollset_set* pollset_set,

@ -42,7 +42,8 @@ grpc_pollset_set* grpc_pollset_set_create(void) {
return (grpc_pollset_set*)((intptr_t)0xdeafbeef); return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
} }
void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {} void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set) {}
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx, void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set, grpc_pollset_set* pollset_set,

@ -97,11 +97,6 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
} }
} }
void grpc_pollset_reset(grpc_pollset *pollset) {
GPR_ASSERT(pollset->shutting_down);
pollset->shutting_down = 0;
}
static void timer_run_cb(uv_timer_t *timer) {} static void timer_run_cb(uv_timer_t *timer) {}
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,

@ -117,16 +117,6 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
void grpc_pollset_destroy(grpc_pollset *pollset) {} void grpc_pollset_destroy(grpc_pollset *pollset) {}
void grpc_pollset_reset(grpc_pollset *pollset) {
GPR_ASSERT(pollset->shutting_down);
GPR_ASSERT(
!has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
pollset->shutting_down = 0;
pollset->is_iocp_worker = 0;
pollset->kicked_without_pollers = 0;
pollset->on_shutdown = NULL;
}
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl, grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) { gpr_timespec now, gpr_timespec deadline) {

@ -599,7 +599,7 @@ grpc_resource_quota *grpc_resource_quota_create(const char *name) {
void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx, void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx,
grpc_resource_quota *resource_quota) { grpc_resource_quota *resource_quota) {
if (gpr_unref(&resource_quota->refs)) { if (gpr_unref(&resource_quota->refs)) {
grpc_combiner_destroy(exec_ctx, resource_quota->combiner); GRPC_COMBINER_UNREF(exec_ctx, resource_quota->combiner, "resource_quota");
gpr_free(resource_quota->name); gpr_free(resource_quota->name);
gpr_free(resource_quota); gpr_free(resource_quota);
} }

@ -190,31 +190,37 @@ int grpc_sockaddr_to_string(char **out,
} }
char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) { char *grpc_sockaddr_to_uri(const grpc_resolved_address *resolved_addr) {
char *temp;
char *result;
grpc_resolved_address addr_normalized; grpc_resolved_address addr_normalized;
const struct sockaddr *addr;
if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) { if (grpc_sockaddr_is_v4mapped(resolved_addr, &addr_normalized)) {
resolved_addr = &addr_normalized; resolved_addr = &addr_normalized;
} }
const char *scheme = grpc_sockaddr_get_uri_scheme(resolved_addr);
if (scheme == NULL || strcmp("unix", scheme) == 0) {
return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
}
char *path = NULL;
char *uri_str = NULL;
if (grpc_sockaddr_to_string(&path, resolved_addr,
false /* suppress errors */) &&
scheme != NULL) {
gpr_asprintf(&uri_str, "%s:%s", scheme, path);
}
gpr_free(path);
return uri_str != NULL ? uri_str : NULL;
}
addr = (const struct sockaddr *)resolved_addr->addr; const char *grpc_sockaddr_get_uri_scheme(
const grpc_resolved_address *resolved_addr) {
const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
switch (addr->sa_family) { switch (addr->sa_family) {
case AF_INET: case AF_INET:
grpc_sockaddr_to_string(&temp, resolved_addr, 0); return "ipv4";
gpr_asprintf(&result, "ipv4:%s", temp);
gpr_free(temp);
return result;
case AF_INET6: case AF_INET6:
grpc_sockaddr_to_string(&temp, resolved_addr, 0); return "ipv6";
gpr_asprintf(&result, "ipv6:%s", temp); case AF_UNIX:
gpr_free(temp); return "unix";
return result;
default:
return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
} }
return NULL;
} }
int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) { int grpc_sockaddr_get_port(const grpc_resolved_address *resolved_addr) {

@ -84,6 +84,10 @@ int grpc_sockaddr_set_port(const grpc_resolved_address *addr, int port);
int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr, int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
int normalize); int normalize);
/* Returns the URI string corresponding to \a addr */
char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr); char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr);
/* Returns the URI scheme corresponding to \a addr */
const char *grpc_sockaddr_get_uri_scheme(const grpc_resolved_address *addr);
#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */ #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */

@ -44,6 +44,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <ifaddrs.h>
#include <limits.h> #include <limits.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
@ -115,6 +116,8 @@ struct grpc_tcp_server {
bool shutdown; bool shutdown;
/* use SO_REUSEPORT */ /* use SO_REUSEPORT */
bool so_reuseport; bool so_reuseport;
/* expand wildcard addresses to a list of all local addresses */
bool expand_wildcard_addrs;
/* linked list of server ports */ /* linked list of server ports */
grpc_tcp_listener *head; grpc_tcp_listener *head;
@ -161,6 +164,7 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
s->so_reuseport = has_so_reuseport; s->so_reuseport = has_so_reuseport;
s->resource_quota = grpc_resource_quota_create(NULL); s->resource_quota = grpc_resource_quota_create(NULL);
s->expand_wildcard_addrs = false;
for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) { for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) { if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
if (args->args[i].type == GRPC_ARG_INTEGER) { if (args->args[i].type == GRPC_ARG_INTEGER) {
@ -183,6 +187,15 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA
" must be a pointer to a buffer pool"); " must be a pointer to a buffer pool");
} }
} else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) {
if (args->args[i].type == GRPC_ARG_INTEGER) {
s->expand_wildcard_addrs = (args->args[i].value.integer != 0);
} else {
grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
gpr_free(s);
return GRPC_ERROR_CREATE(GRPC_ARG_EXPAND_WILDCARD_ADDRS
" must be an integer");
}
} }
} }
gpr_ref_init(&s->refs, 1); gpr_ref_init(&s->refs, 1);
@ -504,9 +517,224 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
return err; return err;
} }
/* Insert count new listeners after listener. Every new listener will have the /* If successful, add a listener to s for addr, set *dsmode for the socket, and
same listen address as listener (SO_REUSEPORT must be enabled). Every new return the *listener. */
listener is a sibling of listener. */ static grpc_error *add_addr_to_server(grpc_tcp_server *s,
const grpc_resolved_address *addr,
unsigned port_index, unsigned fd_index,
grpc_dualstack_mode *dsmode,
grpc_tcp_listener **listener) {
grpc_resolved_address addr4_copy;
int fd;
grpc_error *err =
grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd);
if (err != GRPC_ERROR_NONE) {
return err;
}
if (*dsmode == GRPC_DSMODE_IPV4 &&
grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
addr = &addr4_copy;
}
return add_socket_to_server(s, fd, addr, port_index, fd_index, listener);
}
/* Bind to "::" to get a port number not used by any address. */
static grpc_error *get_unused_port(int *port) {
grpc_resolved_address wild;
grpc_sockaddr_make_wildcard6(0, &wild);
grpc_dualstack_mode dsmode;
int fd;
grpc_error *err =
grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd);
if (err != GRPC_ERROR_NONE) {
return err;
}
if (dsmode == GRPC_DSMODE_IPV4) {
grpc_sockaddr_make_wildcard4(0, &wild);
}
if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) {
err = GRPC_OS_ERROR(errno, "bind");
close(fd);
return err;
}
if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) !=
0) {
err = GRPC_OS_ERROR(errno, "getsockname");
close(fd);
return err;
}
close(fd);
*port = grpc_sockaddr_get_port(&wild);
return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE;
}
/* Return the listener in s with address addr or NULL. */
static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s,
grpc_resolved_address *addr) {
grpc_tcp_listener *l;
gpr_mu_lock(&s->mu);
for (l = s->head; l != NULL; l = l->next) {
if (l->addr.len != addr->len) {
continue;
}
if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) {
break;
}
}
gpr_mu_unlock(&s->mu);
return l;
}
/* Get all addresses assigned to network interfaces on the machine and create a
listener for each. requested_port is the port to use for every listener, or 0
to select one random port that will be used for every listener. Set *out_port
to the port selected. Return GRPC_ERROR_NONE only if all listeners were
added. */
static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s,
unsigned port_index,
int requested_port,
int *out_port) {
struct ifaddrs *ifa = NULL;
struct ifaddrs *ifa_it;
unsigned fd_index = 0;
grpc_tcp_listener *sp = NULL;
grpc_error *err = GRPC_ERROR_NONE;
if (requested_port == 0) {
/* Note: There could be a race where some local addrs can listen on the
selected port and some can't. The sane way to handle this would be to
retry by recreating the whole grpc_tcp_server. Backing out individual
listeners and orphaning the FDs looks like too much trouble. */
if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) {
return err;
} else if (requested_port <= 0) {
return GRPC_ERROR_CREATE("Bad get_unused_port()");
}
gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port);
}
if (getifaddrs(&ifa) != 0 || ifa == NULL) {
return GRPC_OS_ERROR(errno, "getifaddrs");
}
for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
grpc_resolved_address addr;
char *addr_str = NULL;
grpc_dualstack_mode dsmode;
grpc_tcp_listener *new_sp = NULL;
const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
if (ifa_it->ifa_addr == NULL) {
continue;
} else if (ifa_it->ifa_addr->sa_family == AF_INET) {
addr.len = sizeof(struct sockaddr_in);
} else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
addr.len = sizeof(struct sockaddr_in6);
} else {
continue;
}
memcpy(addr.addr, ifa_it->ifa_addr, addr.len);
if (!grpc_sockaddr_set_port(&addr, requested_port)) {
/* Should never happen, because we check sa_family above. */
err = GRPC_ERROR_CREATE("Failed to set port");
break;
}
if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
addr_str = gpr_strdup("<error>");
}
gpr_log(GPR_DEBUG,
"Adding local addr from interface %s flags 0x%x to server: %s",
ifa_name, ifa_it->ifa_flags, addr_str);
/* We could have multiple interfaces with the same address (e.g., bonding),
so look for duplicates. */
if (find_listener_with_addr(s, &addr) != NULL) {
gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
ifa_name);
gpr_free(addr_str);
continue;
}
if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode,
&new_sp)) != GRPC_ERROR_NONE) {
char *err_str = NULL;
grpc_error *root_err;
if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
err_str = gpr_strdup("Failed to add listener");
}
root_err = GRPC_ERROR_CREATE(err_str);
gpr_free(err_str);
gpr_free(addr_str);
err = grpc_error_add_child(root_err, err);
break;
} else {
GPR_ASSERT(requested_port == new_sp->port);
++fd_index;
if (sp != NULL) {
new_sp->is_sibling = 1;
sp->sibling = new_sp;
}
sp = new_sp;
}
gpr_free(addr_str);
}
freeifaddrs(ifa);
if (err != GRPC_ERROR_NONE) {
return err;
} else if (sp == NULL) {
return GRPC_ERROR_CREATE("No local addresses");
} else {
*out_port = sp->port;
return GRPC_ERROR_NONE;
}
}
/* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s,
unsigned port_index,
int requested_port,
int *out_port) {
grpc_resolved_address wild4;
grpc_resolved_address wild6;
unsigned fd_index = 0;
grpc_dualstack_mode dsmode;
grpc_tcp_listener *sp = NULL;
grpc_tcp_listener *sp2 = NULL;
grpc_error *v6_err = GRPC_ERROR_NONE;
grpc_error *v4_err = GRPC_ERROR_NONE;
*out_port = -1;
if (s->expand_wildcard_addrs) {
return add_all_local_addrs_to_server(s, port_index, requested_port,
out_port);
}
grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
/* Try listening on IPv6 first. */
if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode,
&sp)) == GRPC_ERROR_NONE) {
++fd_index;
requested_port = *out_port = sp->port;
if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) {
return GRPC_ERROR_NONE;
}
}
/* If we got a v6-only socket or nothing, try adding 0.0.0.0. */
grpc_sockaddr_set_port(&wild4, requested_port);
if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode,
&sp2)) == GRPC_ERROR_NONE) {
*out_port = sp2->port;
if (sp != NULL) {
sp2->is_sibling = 1;
sp->sibling = sp2;
}
}
if (*out_port > 0) {
GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err);
GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err);
return GRPC_ERROR_NONE;
} else {
grpc_error *root_err =
GRPC_ERROR_CREATE("Failed to add any wildcard listeners");
GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE);
root_err = grpc_error_add_child(root_err, v6_err);
root_err = grpc_error_add_child(root_err, v4_err);
return root_err;
}
}
static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) { static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
grpc_tcp_listener *sp = NULL; grpc_tcp_listener *sp = NULL;
char *addr_str; char *addr_str;
@ -559,19 +787,13 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
const grpc_resolved_address *addr, const grpc_resolved_address *addr,
int *out_port) { int *out_port) {
grpc_tcp_listener *sp; grpc_tcp_listener *sp;
grpc_tcp_listener *sp2 = NULL;
int fd;
grpc_dualstack_mode dsmode;
grpc_resolved_address addr6_v4mapped;
grpc_resolved_address wild4;
grpc_resolved_address wild6;
grpc_resolved_address addr4_copy;
grpc_resolved_address *allocated_addr = NULL;
grpc_resolved_address sockname_temp; grpc_resolved_address sockname_temp;
int port; grpc_resolved_address addr6_v4mapped;
int requested_port = grpc_sockaddr_get_port(addr);
unsigned port_index = 0; unsigned port_index = 0;
unsigned fd_index = 0; grpc_dualstack_mode dsmode;
grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE}; grpc_error *err;
*out_port = -1;
if (s->tail != NULL) { if (s->tail != NULL) {
port_index = s->tail->port_index + 1; port_index = s->tail->port_index + 1;
} }
@ -579,85 +801,34 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
/* Check if this is a wildcard port, and if so, try to keep the port the same /* Check if this is a wildcard port, and if so, try to keep the port the same
as some previously created listener. */ as some previously created listener. */
if (grpc_sockaddr_get_port(addr) == 0) { if (requested_port == 0) {
for (sp = s->head; sp; sp = sp->next) { for (sp = s->head; sp; sp = sp->next) {
sockname_temp.len = sizeof(struct sockaddr_storage); sockname_temp.len = sizeof(struct sockaddr_storage);
if (0 == getsockname(sp->fd, (struct sockaddr *)sockname_temp.addr, if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr,
(socklen_t *)&sockname_temp.len)) { (socklen_t *)&sockname_temp.len)) {
port = grpc_sockaddr_get_port(&sockname_temp); int used_port = grpc_sockaddr_get_port(&sockname_temp);
if (port > 0) { if (used_port > 0) {
allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address));
memcpy(allocated_addr, addr, addr->len); grpc_sockaddr_set_port(&sockname_temp, used_port);
grpc_sockaddr_set_port(allocated_addr, port); requested_port = used_port;
addr = allocated_addr; addr = &sockname_temp;
break; break;
} }
} }
} }
} }
if (grpc_sockaddr_is_wildcard(addr, &requested_port)) {
sp = NULL; return add_wildcard_addrs_to_server(s, port_index, requested_port,
out_port);
}
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
addr = &addr6_v4mapped; addr = &addr6_v4mapped;
} }
if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) ==
/* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ GRPC_ERROR_NONE) {
if (grpc_sockaddr_is_wildcard(addr, &port)) {
grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
/* Try listening on IPv6 first. */
addr = &wild6;
errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
if (errs[0] == GRPC_ERROR_NONE) {
errs[0] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
goto done;
}
if (sp != NULL) {
++fd_index;
}
/* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
if (port == 0 && sp != NULL) {
grpc_sockaddr_set_port(&wild4, sp->port);
}
}
addr = &wild4;
}
errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
if (errs[1] == GRPC_ERROR_NONE) {
if (dsmode == GRPC_DSMODE_IPV4 &&
grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
addr = &addr4_copy;
}
sp2 = sp;
errs[1] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
if (sp2 != NULL && sp != NULL) {
sp2->sibling = sp;
sp->is_sibling = 1;
}
}
done:
gpr_free(allocated_addr);
if (sp != NULL) {
*out_port = sp->port; *out_port = sp->port;
GRPC_ERROR_UNREF(errs[0]);
GRPC_ERROR_UNREF(errs[1]);
return GRPC_ERROR_NONE;
} else {
*out_port = -1;
char *addr_str = grpc_sockaddr_to_uri(addr);
grpc_error *err = grpc_error_set_str(
GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
GPR_ARRAY_SIZE(errs)),
GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
GRPC_ERROR_UNREF(errs[0]);
GRPC_ERROR_UNREF(errs[1]);
gpr_free(addr_str);
return err;
} }
return err;
} }
/* Return listener at port_index or NULL. Should only be called with s->mu /* Return listener at port_index or NULL. Should only be called with s->mu

@ -121,12 +121,6 @@ void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
g_initialized = false; g_initialized = false;
} }
/* This is a cheap, but good enough, pointer hash for sharding the tasks: */
static size_t shard_idx(const grpc_timer *info) {
size_t x = (size_t)info;
return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1);
}
static double ts_to_dbl(gpr_timespec ts) { static double ts_to_dbl(gpr_timespec ts) {
return (double)ts.tv_sec + 1e-9 * ts.tv_nsec; return (double)ts.tv_sec + 1e-9 * ts.tv_nsec;
} }
@ -181,7 +175,7 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
gpr_timespec deadline, grpc_closure *closure, gpr_timespec deadline, grpc_closure *closure,
gpr_timespec now) { gpr_timespec now) {
int is_first_timer = 0; int is_first_timer = 0;
shard_type *shard = &g_shards[shard_idx(timer)]; shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
GPR_ASSERT(deadline.clock_type == g_clock_type); GPR_ASSERT(deadline.clock_type == g_clock_type);
GPR_ASSERT(now.clock_type == g_clock_type); GPR_ASSERT(now.clock_type == g_clock_type);
timer->closure = closure; timer->closure = closure;
@ -247,7 +241,7 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
return; return;
} }
shard_type *shard = &g_shards[shard_idx(timer)]; shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
gpr_mu_lock(&shard->mu); gpr_mu_lock(&shard->mu);
if (!timer->triggered) { if (!timer->triggered) {
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED); grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);

@ -178,7 +178,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
/* Call the orphan_cb to signal that the FD is about to be closed and /* Call the orphan_cb to signal that the FD is about to be closed and
* should no longer be used. */ * should no longer be used. */
GPR_ASSERT(sp->orphan_cb); GPR_ASSERT(sp->orphan_cb);
sp->orphan_cb(sp->emfd); sp->orphan_cb(exec_ctx, sp->emfd);
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
"udp_listener_shutdown"); "udp_listener_shutdown");
@ -204,7 +204,7 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
if (s->active_ports) { if (s->active_ports) {
for (sp = s->head; sp; sp = sp->next) { for (sp = s->head; sp; sp = sp->next) {
GPR_ASSERT(sp->orphan_cb); GPR_ASSERT(sp->orphan_cb);
sp->orphan_cb(sp->emfd); sp->orphan_cb(exec_ctx, sp->emfd);
grpc_fd_shutdown(exec_ctx, sp->emfd, grpc_fd_shutdown(exec_ctx, sp->emfd,
GRPC_ERROR_CREATE("Server destroyed")); GRPC_ERROR_CREATE("Server destroyed"));
} }

@ -54,7 +54,8 @@ typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx,
grpc_fd *emfd); grpc_fd *emfd);
/* Called when the grpc_fd is about to be orphaned (and the FD closed). */ /* Called when the grpc_fd is about to be orphaned (and the FD closed). */
typedef void (*grpc_udp_server_orphan_cb)(grpc_fd *emfd); typedef void (*grpc_udp_server_orphan_cb)(grpc_exec_ctx *exec_ctx,
grpc_fd *emfd);
/* Create a server, initially not bound to any ports */ /* Create a server, initially not bound to any ports */
grpc_udp_server *grpc_udp_server_create(void); grpc_udp_server *grpc_udp_server_create(void);

@ -43,6 +43,9 @@
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "src/core/lib/support/env.h"
typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type; typedef enum { BEGIN = '{', END = '}', MARK = '.' } marker_type;
@ -74,7 +77,7 @@ typedef struct gpr_timer_log_list {
static __thread gpr_timer_log *g_thread_log; static __thread gpr_timer_log *g_thread_log;
static gpr_once g_once_init = GPR_ONCE_INIT; static gpr_once g_once_init = GPR_ONCE_INIT;
static FILE *output_file; static FILE *output_file;
static const char *output_filename = "latency_trace.txt"; static const char *output_filename_or_null = NULL;
static pthread_mutex_t g_mu; static pthread_mutex_t g_mu;
static pthread_cond_t g_cv; static pthread_cond_t g_cv;
static gpr_timer_log_list g_in_progress_logs; static gpr_timer_log_list g_in_progress_logs;
@ -85,6 +88,17 @@ static __thread int g_thread_id;
static int g_next_thread_id; static int g_next_thread_id;
static int g_writing_enabled = 1; static int g_writing_enabled = 1;
static const char *output_filename() {
if (output_filename_or_null == NULL) {
output_filename_or_null = gpr_getenv("LATENCY_TRACE");
if (output_filename_or_null == NULL ||
strlen(output_filename_or_null) == 0) {
output_filename_or_null = "latency_trace.txt";
}
}
return output_filename_or_null;
}
static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) { static int timer_log_push_back(gpr_timer_log_list *list, gpr_timer_log *log) {
if (list->head == NULL) { if (list->head == NULL) {
list->head = list->tail = log; list->head = list->tail = log;
@ -134,7 +148,7 @@ static void timer_log_remove(gpr_timer_log_list *list, gpr_timer_log *log) {
static void write_log(gpr_timer_log *log) { static void write_log(gpr_timer_log *log) {
size_t i; size_t i;
if (output_file == NULL) { if (output_file == NULL) {
output_file = fopen(output_filename, "w"); output_file = fopen(output_filename(), "w");
} }
for (i = 0; i < log->num_entries; i++) { for (i = 0; i < log->num_entries; i++) {
gpr_timer_entry *entry = &(log->log[i]); gpr_timer_entry *entry = &(log->log[i]);
@ -198,7 +212,7 @@ static void finish_writing(void) {
} }
void gpr_timers_set_log_filename(const char *filename) { void gpr_timers_set_log_filename(const char *filename) {
output_filename = filename; output_filename_or_null = filename;
} }
static void init_output() { static void init_output() {

@ -160,6 +160,53 @@ grpc_channel_credentials_duplicate_without_call_credentials(
} }
} }
static void credentials_pointer_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
grpc_channel_credentials_unref(exec_ctx, p);
}
static void *credentials_pointer_arg_copy(void *p) {
return grpc_channel_credentials_ref(p);
}
static int credentials_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
static const grpc_arg_pointer_vtable credentials_pointer_vtable = {
credentials_pointer_arg_copy, credentials_pointer_arg_destroy,
credentials_pointer_cmp};
grpc_arg grpc_channel_credentials_to_arg(
grpc_channel_credentials *credentials) {
grpc_arg result;
result.type = GRPC_ARG_POINTER;
result.key = GRPC_ARG_CHANNEL_CREDENTIALS;
result.value.pointer.vtable = &credentials_pointer_vtable;
result.value.pointer.p = credentials;
return result;
}
grpc_channel_credentials *grpc_channel_credentials_from_arg(
const grpc_arg *arg) {
if (strcmp(arg->key, GRPC_ARG_CHANNEL_CREDENTIALS)) return NULL;
if (arg->type != GRPC_ARG_POINTER) {
gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
GRPC_ARG_CHANNEL_CREDENTIALS);
return NULL;
}
return arg->value.pointer.p;
}
grpc_channel_credentials *grpc_channel_credentials_find_in_args(
const grpc_channel_args *args) {
size_t i;
if (args == NULL) return NULL;
for (i = 0; i < args->num_args; i++) {
grpc_channel_credentials *credentials =
grpc_channel_credentials_from_arg(&args->args[i]);
if (credentials != NULL) return credentials;
}
return NULL;
}
grpc_server_credentials *grpc_server_credentials_ref( grpc_server_credentials *grpc_server_credentials_ref(
grpc_server_credentials *creds) { grpc_server_credentials *creds) {
if (creds == NULL) return NULL; if (creds == NULL) return NULL;

@ -100,6 +100,8 @@ void grpc_override_well_known_credentials_path_getter(
/* --- grpc_channel_credentials. --- */ /* --- grpc_channel_credentials. --- */
#define GRPC_ARG_CHANNEL_CREDENTIALS "grpc.channel_credentials"
typedef struct { typedef struct {
void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c); void (*destruct)(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *c);
@ -140,6 +142,17 @@ grpc_channel_credentials *
grpc_channel_credentials_duplicate_without_call_credentials( grpc_channel_credentials_duplicate_without_call_credentials(
grpc_channel_credentials *creds); grpc_channel_credentials *creds);
/* Util to encapsulate the channel credentials in a channel arg. */
grpc_arg grpc_channel_credentials_to_arg(grpc_channel_credentials *credentials);
/* Util to get the channel credentials from a channel arg. */
grpc_channel_credentials *grpc_channel_credentials_from_arg(
const grpc_arg *arg);
/* Util to find the channel credentials from channel args. */
grpc_channel_credentials *grpc_channel_credentials_find_in_args(
const grpc_channel_args *args);
/* --- grpc_credentials_md. --- */ /* --- grpc_credentials_md. --- */
typedef struct { typedef struct {

@ -35,13 +35,13 @@
#include <string.h> #include <string.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/executor.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/support/string.h"
/* -- Fake transport security credentials. -- */ /* -- Fake transport security credentials. -- */
static grpc_security_status fake_transport_security_create_security_connector( static grpc_security_status fake_transport_security_create_security_connector(
@ -49,7 +49,7 @@ static grpc_security_status fake_transport_security_create_security_connector(
grpc_call_credentials *call_creds, const char *target, grpc_call_credentials *call_creds, const char *target,
const grpc_channel_args *args, grpc_channel_security_connector **sc, const grpc_channel_args *args, grpc_channel_security_connector **sc,
grpc_channel_args **new_args) { grpc_channel_args **new_args) {
*sc = grpc_fake_channel_security_connector_create(call_creds); *sc = grpc_fake_channel_security_connector_create(call_creds, target, args);
return GRPC_SECURITY_OK; return GRPC_SECURITY_OK;
} }

@ -38,6 +38,21 @@
/* -- Fake transport security credentials. -- */ /* -- Fake transport security credentials. -- */
/* Used to verify the target names given to the fake transport security
* connector.
*
* Its syntax by example:
* For LB channels:
* "backend_target_1,backend_target_2,...;lb_target_1,lb_target_2,..."
* For regular channels:
* "backend_taget_1,backend_target_2,..."
*
* That is to say, LB channels have a heading list of LB targets separated from
* the list of backend targets by a semicolon. For non-LB channels, only the
* latter is present. */
#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \
"grpc.test_only.fake_security.expected_target"
/* Creates a fake transport security credentials object for testing. */ /* Creates a fake transport security credentials object for testing. */
grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);

@ -154,7 +154,7 @@ static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) {
} }
gpr_mu_unlock(g_polling_mu); gpr_mu_unlock(g_polling_mu);
grpc_httpcli_context_destroy(&context); grpc_httpcli_context_destroy(exec_ctx, &context);
grpc_closure_init(&destroy_closure, destroy_pollset, grpc_closure_init(&destroy_closure, destroy_pollset,
grpc_polling_entity_pollset(&detector.pollent), grpc_polling_entity_pollset(&detector.pollent),
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);

@ -898,10 +898,10 @@ grpc_jwt_verifier *grpc_jwt_verifier_create(
return v; return v;
} }
void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) { void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *v) {
size_t i; size_t i;
if (v == NULL) return; if (v == NULL) return;
grpc_httpcli_context_destroy(&v->http_ctx); grpc_httpcli_context_destroy(exec_ctx, &v->http_ctx);
if (v->mappings != NULL) { if (v->mappings != NULL) {
for (i = 0; i < v->num_mappings; i++) { for (i = 0; i < v->num_mappings; i++) {
gpr_free(v->mappings[i].email_domain); gpr_free(v->mappings[i].email_domain);

@ -109,7 +109,8 @@ grpc_jwt_verifier *grpc_jwt_verifier_create(
size_t num_mappings); size_t num_mappings);
/*The verifier must not be destroyed if there are still outstanding callbacks.*/ /*The verifier must not be destroyed if there are still outstanding callbacks.*/
void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier); void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx,
grpc_jwt_verifier *verifier);
/* User provided callback that will be called when the verification of the JWT /* User provided callback that will be called when the verification of the JWT
is done (maybe in another thread). is done (maybe in another thread).

@ -124,7 +124,7 @@ static void oauth2_token_fetcher_destruct(grpc_exec_ctx *exec_ctx,
(grpc_oauth2_token_fetcher_credentials *)creds; (grpc_oauth2_token_fetcher_credentials *)creds;
grpc_credentials_md_store_unref(exec_ctx, c->access_token_md); grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->mu);
grpc_httpcli_context_destroy(&c->httpcli_context); grpc_httpcli_context_destroy(exec_ctx, &c->httpcli_context);
} }
grpc_credentials_status grpc_credentials_status

@ -335,7 +335,7 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
grpc_security_connector *sc = grpc_security_connector *sc =
grpc_find_security_connector_in_args(args->channel_args); grpc_security_connector_find_in_args(args->channel_args);
grpc_auth_context *auth_context = grpc_auth_context *auth_context =
grpc_find_auth_context_in_args(args->channel_args); grpc_find_auth_context_in_args(args->channel_args);

@ -0,0 +1,70 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/security/transport/lb_targets_info.h"
/* Channel arg key for the mapping of LB server addresses to their names for
* secure naming purposes. */
#define GRPC_ARG_LB_SECURE_NAMING_MAP "grpc.lb_secure_naming_map"
static void *targets_info_copy(void *p) { return grpc_slice_hash_table_ref(p); }
static void targets_info_destroy(grpc_exec_ctx *exec_ctx, void *p) {
grpc_slice_hash_table_unref(exec_ctx, p);
}
static int targets_info_cmp(void *a, void *b) { return GPR_ICMP(a, b); }
static const grpc_arg_pointer_vtable server_to_balancer_names_vtable = {
targets_info_copy, targets_info_destroy, targets_info_cmp};
grpc_arg grpc_lb_targets_info_create_channel_arg(
grpc_slice_hash_table *targets_info) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_LB_SECURE_NAMING_MAP;
arg.value.pointer.p = targets_info;
arg.value.pointer.vtable = &server_to_balancer_names_vtable;
return arg;
}
grpc_slice_hash_table *grpc_lb_targets_info_find_in_args(
const grpc_channel_args *args) {
const grpc_arg *targets_info_arg =
grpc_channel_args_find(args, GRPC_ARG_LB_SECURE_NAMING_MAP);
if (targets_info_arg != NULL) {
GPR_ASSERT(targets_info_arg->type == GRPC_ARG_POINTER);
return targets_info_arg->value.pointer.p;
}
return NULL;
}

@ -0,0 +1,47 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H
#define GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H
#include "src/core/lib/slice/slice_hash_table.h"
/** Return a channel argument containing \a targets_info. */
grpc_arg grpc_lb_targets_info_create_channel_arg(
grpc_slice_hash_table *targets_info);
/** Return the instance of targets info in \a args or NULL */
grpc_slice_hash_table *grpc_lb_targets_info_find_in_args(
const grpc_channel_args *args);
#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_LB_TARGETS_INFO_H */

@ -43,10 +43,13 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/transport/chttp2/alpn/alpn.h" #include "src/core/ext/transport/chttp2/alpn/alpn.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "src/core/lib/security/transport/lb_targets_info.h"
#include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/secure_endpoint.h"
#include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/support/env.h" #include "src/core/lib/support/env.h"
@ -205,23 +208,23 @@ static const grpc_arg_pointer_vtable connector_pointer_vtable = {
grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) { grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) {
grpc_arg result; grpc_arg result;
result.type = GRPC_ARG_POINTER; result.type = GRPC_ARG_POINTER;
result.key = GRPC_SECURITY_CONNECTOR_ARG; result.key = GRPC_ARG_SECURITY_CONNECTOR;
result.value.pointer.vtable = &connector_pointer_vtable; result.value.pointer.vtable = &connector_pointer_vtable;
result.value.pointer.p = sc; result.value.pointer.p = sc;
return result; return result;
} }
grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) { grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) {
if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL; if (strcmp(arg->key, GRPC_ARG_SECURITY_CONNECTOR)) return NULL;
if (arg->type != GRPC_ARG_POINTER) { if (arg->type != GRPC_ARG_POINTER) {
gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type,
GRPC_SECURITY_CONNECTOR_ARG); GRPC_ARG_SECURITY_CONNECTOR);
return NULL; return NULL;
} }
return arg->value.pointer.p; return arg->value.pointer.p;
} }
grpc_security_connector *grpc_find_security_connector_in_args( grpc_security_connector *grpc_security_connector_find_in_args(
const grpc_channel_args *args) { const grpc_channel_args *args) {
size_t i; size_t i;
if (args == NULL) return NULL; if (args == NULL) return NULL;
@ -235,11 +238,21 @@ grpc_security_connector *grpc_find_security_connector_in_args(
/* -- Fake implementation. -- */ /* -- Fake implementation. -- */
typedef struct {
grpc_channel_security_connector base;
char *target;
char *expected_targets;
bool is_lb_channel;
} grpc_fake_channel_security_connector;
static void fake_channel_destroy(grpc_exec_ctx *exec_ctx, static void fake_channel_destroy(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc) { grpc_security_connector *sc) {
grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; grpc_fake_channel_security_connector *c =
grpc_call_credentials_unref(exec_ctx, c->request_metadata_creds); (grpc_fake_channel_security_connector *)sc;
gpr_free(sc); grpc_call_credentials_unref(exec_ctx, c->base.request_metadata_creds);
gpr_free(c->target);
gpr_free(c->expected_targets);
gpr_free(c);
} }
static void fake_server_destroy(grpc_exec_ctx *exec_ctx, static void fake_server_destroy(grpc_exec_ctx *exec_ctx,
@ -247,6 +260,68 @@ static void fake_server_destroy(grpc_exec_ctx *exec_ctx,
gpr_free(sc); gpr_free(sc);
} }
static bool fake_check_target(const char *target_type, const char *target,
const char *set_str) {
GPR_ASSERT(target_type != NULL);
GPR_ASSERT(target != NULL);
char **set = NULL;
size_t set_size = 0;
gpr_string_split(set_str, ",", &set, &set_size);
bool found = false;
for (size_t i = 0; i < set_size; ++i) {
if (set[i] != NULL && strcmp(target, set[i]) == 0) found = true;
}
for (size_t i = 0; i < set_size; ++i) {
gpr_free(set[i]);
}
gpr_free(set);
return found;
}
static void fake_secure_name_check(const char *target,
const char *expected_targets,
bool is_lb_channel) {
if (expected_targets == NULL) return;
char **lbs_and_backends = NULL;
size_t lbs_and_backends_size = 0;
bool success = false;
gpr_string_split(expected_targets, ";", &lbs_and_backends,
&lbs_and_backends_size);
if (lbs_and_backends_size > 2 || lbs_and_backends_size == 0) {
gpr_log(GPR_ERROR, "Invalid expected targets arg value: '%s'",
expected_targets);
goto done;
}
if (is_lb_channel) {
if (lbs_and_backends_size != 2) {
gpr_log(GPR_ERROR,
"Invalid expected targets arg value: '%s'. Expectations for LB "
"channels must be of the form 'be1,be2,be3,...;lb1,lb2,...",
expected_targets);
goto done;
}
if (!fake_check_target("LB", target, lbs_and_backends[1])) {
gpr_log(GPR_ERROR, "LB target '%s' not found in expected set '%s'",
target, lbs_and_backends[1]);
goto done;
}
success = true;
} else {
if (!fake_check_target("Backend", target, lbs_and_backends[0])) {
gpr_log(GPR_ERROR, "Backend target '%s' not found in expected set '%s'",
target, lbs_and_backends[0]);
goto done;
}
success = true;
}
done:
for (size_t i = 0; i < lbs_and_backends_size; ++i) {
gpr_free(lbs_and_backends[i]);
}
gpr_free(lbs_and_backends);
if (!success) abort();
}
static void fake_check_peer(grpc_exec_ctx *exec_ctx, static void fake_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer, grpc_security_connector *sc, tsi_peer peer,
grpc_auth_context **auth_context, grpc_auth_context **auth_context,
@ -277,12 +352,28 @@ static void fake_check_peer(grpc_exec_ctx *exec_ctx,
grpc_auth_context_add_cstring_property( grpc_auth_context_add_cstring_property(
*auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, *auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_FAKE_TRANSPORT_SECURITY_TYPE); GRPC_FAKE_TRANSPORT_SECURITY_TYPE);
end: end:
grpc_closure_sched(exec_ctx, on_peer_checked, error); grpc_closure_sched(exec_ctx, on_peer_checked, error);
tsi_peer_destruct(&peer); tsi_peer_destruct(&peer);
} }
static void fake_channel_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer,
grpc_auth_context **auth_context,
grpc_closure *on_peer_checked) {
fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
grpc_fake_channel_security_connector *c =
(grpc_fake_channel_security_connector *)sc;
fake_secure_name_check(c->target, c->expected_targets, c->is_lb_channel);
}
static void fake_server_check_peer(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, tsi_peer peer,
grpc_auth_context **auth_context,
grpc_closure *on_peer_checked) {
fake_check_peer(exec_ctx, sc, peer, auth_context, on_peer_checked);
}
static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx, static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc, grpc_channel_security_connector *sc,
const char *host, const char *host,
@ -313,22 +404,32 @@ static void fake_server_add_handshakers(grpc_exec_ctx *exec_ctx,
} }
static grpc_security_connector_vtable fake_channel_vtable = { static grpc_security_connector_vtable fake_channel_vtable = {
fake_channel_destroy, fake_check_peer}; fake_channel_destroy, fake_channel_check_peer};
static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy, static grpc_security_connector_vtable fake_server_vtable = {
fake_check_peer}; fake_server_destroy, fake_server_check_peer};
grpc_channel_security_connector *grpc_fake_channel_security_connector_create( grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_call_credentials *request_metadata_creds) { grpc_call_credentials *request_metadata_creds, const char *target,
grpc_channel_security_connector *c = gpr_malloc(sizeof(*c)); const grpc_channel_args *args) {
grpc_fake_channel_security_connector *c = gpr_malloc(sizeof(*c));
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.base.refcount, 1);
c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
c->base.vtable = &fake_channel_vtable; c->base.base.vtable = &fake_channel_vtable;
c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); c->base.request_metadata_creds =
c->check_call_host = fake_channel_check_call_host; grpc_call_credentials_ref(request_metadata_creds);
c->add_handshakers = fake_channel_add_handshakers; c->base.check_call_host = fake_channel_check_call_host;
return c; c->base.add_handshakers = fake_channel_add_handshakers;
c->target = gpr_strdup(target);
const grpc_arg *expected_target_arg =
grpc_channel_args_find(args, GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS);
if (expected_target_arg != NULL) {
GPR_ASSERT(expected_target_arg->type == GRPC_ARG_STRING);
c->expected_targets = gpr_strdup(expected_target_arg->value.string);
}
c->is_lb_channel = (grpc_lb_targets_info_find_in_args(args) != NULL);
return &c->base;
} }
grpc_server_security_connector *grpc_fake_server_security_connector_create( grpc_server_security_connector *grpc_fake_server_security_connector_create(

@ -57,7 +57,7 @@ typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status;
typedef struct grpc_security_connector grpc_security_connector; typedef struct grpc_security_connector grpc_security_connector;
#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector" #define GRPC_ARG_SECURITY_CONNECTOR "grpc.security_connector"
typedef struct { typedef struct {
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc);
@ -115,7 +115,7 @@ grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg); grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg);
/* Util to find the connector from channel args. */ /* Util to find the connector from channel args. */
grpc_security_connector *grpc_find_security_connector_in_args( grpc_security_connector *grpc_security_connector_find_in_args(
const grpc_channel_args *args); const grpc_channel_args *args);
/* --- channel_security_connector object. --- /* --- channel_security_connector object. ---
@ -175,7 +175,8 @@ void grpc_server_security_connector_add_handshakers(
/* For TESTING ONLY! /* For TESTING ONLY!
Creates a fake connector that emulates real channel security. */ Creates a fake connector that emulates real channel security. */
grpc_channel_security_connector *grpc_fake_channel_security_connector_create( grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_call_credentials *request_metadata_creds); grpc_call_credentials *request_metadata_creds, const char *target,
const grpc_channel_args *args);
/* For TESTING ONLY! /* For TESTING ONLY!
Creates a fake connector that emulates real server security. */ Creates a fake connector that emulates real server security. */

@ -451,7 +451,7 @@ static void client_handshaker_factory_add_handshakers(
grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory, grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory,
const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
grpc_channel_security_connector *security_connector = grpc_channel_security_connector *security_connector =
(grpc_channel_security_connector *)grpc_find_security_connector_in_args( (grpc_channel_security_connector *)grpc_security_connector_find_in_args(
args); args);
grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector, grpc_channel_security_connector_add_handshakers(exec_ctx, security_connector,
handshake_mgr); handshake_mgr);
@ -461,7 +461,7 @@ static void server_handshaker_factory_add_handshakers(
grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf, grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf,
const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) {
grpc_server_security_connector *security_connector = grpc_server_security_connector *security_connector =
(grpc_server_security_connector *)grpc_find_security_connector_in_args( (grpc_server_security_connector *)grpc_security_connector_find_in_args(
args); args);
grpc_server_security_connector_add_handshakers(exec_ctx, security_connector, grpc_server_security_connector_add_handshakers(exec_ctx, security_connector,
handshake_mgr); handshake_mgr);

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

Loading…
Cancel
Save