Merge branch 'master' into tmt_cleanup

pull/20614/head
Vijay Pai 5 years ago
commit 621955e39e
  1. 21
      BUILD
  2. 2
      BUILD.gn
  3. 60
      CMakeLists.txt
  4. 64
      Makefile
  5. 2
      WORKSPACE
  6. 8
      bazel/generate_cc.bzl
  7. 8
      bazel/generate_objc.bzl
  8. 8
      bazel/grpc_build_system.bzl
  9. 8
      bazel/grpc_deps.bzl
  10. 122
      bazel/protobuf.bzl
  11. 66
      bazel/python_rules.bzl
  12. 47
      bazel/test/python_test_repo/BUILD
  13. 11
      bazel/test/python_test_repo/helloworld.py
  14. 76
      bazel/test/python_test_repo/helloworld_moved.py
  15. 27
      build.yaml
  16. 1
      config.m4
  17. 1
      config.w32
  18. 2
      doc/core/transport_explainer.md
  19. 3
      gRPC-Core.podspec
  20. 2
      grpc.gemspec
  21. 16
      grpc.gyp
  22. 52
      include/grpcpp/impl/codegen/async_stream_impl.h
  23. 11
      include/grpcpp/impl/codegen/async_unary_call_impl.h
  24. 33
      include/grpcpp/impl/codegen/call_op_set.h
  25. 8
      include/grpcpp/impl/codegen/callback_common.h
  26. 16
      include/grpcpp/impl/codegen/client_callback_impl.h
  27. 2
      include/grpcpp/impl/codegen/client_interceptor.h
  28. 3
      include/grpcpp/impl/codegen/core_codegen.h
  29. 1
      include/grpcpp/impl/codegen/core_codegen_interface.h
  30. 2
      include/grpcpp/impl/codegen/proto_buffer_writer.h
  31. 20
      include/grpcpp/impl/codegen/service_type.h
  32. 4
      include/grpcpp/security/tls_credentials_options.h
  33. 7
      include/grpcpp/test/server_context_test_spouse.h
  34. 2
      package.xml
  35. 2
      setup.py
  36. 133
      src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
  37. 71
      src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
  38. 8
      src/core/ext/filters/client_channel/service_config.h
  39. 123
      src/core/ext/filters/client_channel/xds/xds_api.cc
  40. 9
      src/core/ext/filters/client_channel/xds/xds_api.h
  41. 450
      src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
  42. 99
      src/core/ext/filters/client_channel/xds/xds_bootstrap.h
  43. 5
      src/core/ext/filters/client_channel/xds/xds_channel.cc
  44. 4
      src/core/ext/filters/client_channel/xds/xds_channel.h
  45. 29
      src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
  46. 175
      src/core/ext/filters/client_channel/xds/xds_client.cc
  47. 74
      src/core/ext/filters/client_channel/xds/xds_client.h
  48. 40
      src/core/ext/transport/chttp2/transport/flow_control.h
  49. 2
      src/core/lib/gprpp/memory.h
  50. 2
      src/core/lib/iomgr/exec_ctx.h
  51. 2
      src/core/lib/iomgr/executor/threadpool.h
  52. 2
      src/core/lib/iomgr/udp_server.h
  53. 2
      src/core/lib/json/json.h
  54. 4
      src/core/lib/json/json_string.cc
  55. 1
      src/core/lib/surface/call.cc
  56. 2
      src/core/lib/transport/transport.h
  57. 20
      src/cpp/client/secure_credentials.cc
  58. 37
      src/cpp/common/channel_arguments.cc
  59. 16
      src/cpp/common/channel_filter.h
  60. 3
      src/cpp/common/core_codegen.cc
  61. 10
      src/cpp/common/tls_credentials_options.cc
  62. 16
      src/cpp/common/tls_credentials_options_util.cc
  63. 18
      src/cpp/ext/proto_server_reflection.cc
  64. 4
      src/cpp/ext/proto_server_reflection_plugin.cc
  65. 17
      src/cpp/server/channelz/channelz_service.cc
  66. 5
      src/cpp/server/channelz/channelz_service_plugin.cc
  67. 4
      src/cpp/server/health/default_health_check_service.h
  68. 23
      src/cpp/server/secure_server_credentials.cc
  69. 67
      src/cpp/server/server_builder.cc
  70. 83
      src/cpp/server/server_cc.cc
  71. 17
      src/cpp/server/server_context.cc
  72. 13
      src/cpp/thread_manager/thread_manager.cc
  73. 3
      src/cpp/thread_manager/thread_manager.h
  74. 4
      src/csharp/Grpc.Core.Api/RpcException.cs
  75. 100
      src/php/docker/README.md
  76. 2
      src/python/grpcio/grpc/_cython/BUILD.bazel
  77. 18
      src/python/grpcio/grpc/_cython/_cygrpc/aio/call.pyx.pxi
  78. 4
      src/python/grpcio/grpc/_cython/_cygrpc/aio/channel.pyx.pxi
  79. 27
      src/python/grpcio/grpc/_cython/_cygrpc/aio/rpc_error.pxd.pxi
  80. 35
      src/python/grpcio/grpc/_cython/_cygrpc/aio/rpc_error.pyx.pxi
  81. 1
      src/python/grpcio/grpc/_cython/cygrpc.pyx
  82. 26
      src/python/grpcio/grpc/experimental/aio/__init__.py
  83. 28
      src/python/grpcio/grpc/experimental/aio/_channel.py
  84. 1
      src/python/grpcio/grpc_core_dependencies.py
  85. 2
      src/python/grpcio_channelz/setup.py
  86. 2
      src/python/grpcio_health_checking/setup.py
  87. 2
      src/python/grpcio_reflection/setup.py
  88. 1
      src/python/grpcio_status/setup.py
  89. 1
      src/python/grpcio_tests/tests_aio/tests.json
  90. 33
      src/python/grpcio_tests/tests_aio/unit/channel_test.py
  91. 40
      src/python/grpcio_tests/tests_aio/unit/init_test.py
  92. 5
      src/python/grpcio_tests/tests_aio/unit/sync_server.py
  93. 2
      templates/CMakeLists.txt.template
  94. 2
      templates/tools/dockerfile/bazel.include
  95. 10
      test/core/bad_client/bad_client.cc
  96. 2
      test/core/bad_client/tests/bad_streaming_id.cc
  97. 2
      test/core/bad_client/tests/badreq.cc
  98. 2
      test/core/bad_client/tests/connection_prefix.cc
  99. 2
      test/core/bad_client/tests/duplicate_header.cc
  100. 2
      test/core/bad_client/tests/headers.cc
  101. Some files were not shown because too many files have changed in this diff Show More

21
BUILD

@ -320,6 +320,7 @@ grpc_cc_library(
"grpc_common",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_xds",
"grpc_resolver_xds",
],
)
@ -336,6 +337,7 @@ grpc_cc_library(
"grpc_common",
"grpc_lb_policy_grpclb_secure",
"grpc_lb_policy_xds_secure",
"grpc_resolver_xds_secure",
"grpc_secure",
"grpc_transport_chttp2_client_secure",
"grpc_transport_chttp2_server_secure",
@ -994,7 +996,6 @@ grpc_cc_library(
"grpc_resolver_fake",
"grpc_resolver_dns_native",
"grpc_resolver_sockaddr",
"grpc_resolver_xds",
"grpc_transport_chttp2_client_insecure",
"grpc_transport_chttp2_server_insecure",
"grpc_transport_inproc",
@ -1256,12 +1257,14 @@ grpc_cc_library(
name = "grpc_xds_client",
srcs = [
"src/core/ext/filters/client_channel/xds/xds_api.cc",
"src/core/ext/filters/client_channel/xds/xds_bootstrap.cc",
"src/core/ext/filters/client_channel/xds/xds_client.cc",
"src/core/ext/filters/client_channel/xds/xds_channel.cc",
"src/core/ext/filters/client_channel/xds/xds_client_stats.cc",
],
hdrs = [
"src/core/ext/filters/client_channel/xds/xds_api.h",
"src/core/ext/filters/client_channel/xds/xds_bootstrap.h",
"src/core/ext/filters/client_channel/xds/xds_client.h",
"src/core/ext/filters/client_channel/xds/xds_channel.h",
"src/core/ext/filters/client_channel/xds/xds_channel_args.h",
@ -1279,12 +1282,14 @@ grpc_cc_library(
name = "grpc_xds_client_secure",
srcs = [
"src/core/ext/filters/client_channel/xds/xds_api.cc",
"src/core/ext/filters/client_channel/xds/xds_bootstrap.cc",
"src/core/ext/filters/client_channel/xds/xds_client.cc",
"src/core/ext/filters/client_channel/xds/xds_channel_secure.cc",
"src/core/ext/filters/client_channel/xds/xds_client_stats.cc",
],
hdrs = [
"src/core/ext/filters/client_channel/xds/xds_api.h",
"src/core/ext/filters/client_channel/xds/xds_bootstrap.h",
"src/core/ext/filters/client_channel/xds/xds_client.h",
"src/core/ext/filters/client_channel/xds/xds_channel.h",
"src/core/ext/filters/client_channel/xds/xds_channel_args.h",
@ -1577,6 +1582,20 @@ grpc_cc_library(
deps = [
"grpc_base",
"grpc_client_channel",
"grpc_xds_client",
],
)
grpc_cc_library(
name = "grpc_resolver_xds_secure",
srcs = [
"src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc",
],
language = "c++",
deps = [
"grpc_base",
"grpc_client_channel",
"grpc_xds_client_secure",
],
)

@ -298,6 +298,8 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/subchannel_pool_interface.h",
"src/core/ext/filters/client_channel/xds/xds_api.cc",
"src/core/ext/filters/client_channel/xds/xds_api.h",
"src/core/ext/filters/client_channel/xds/xds_bootstrap.cc",
"src/core/ext/filters/client_channel/xds/xds_bootstrap.h",
"src/core/ext/filters/client_channel/xds/xds_channel.h",
"src/core/ext/filters/client_channel/xds/xds_channel_args.h",
"src/core/ext/filters/client_channel/xds/xds_channel_secure.cc",

@ -731,6 +731,7 @@ add_dependencies(buildtests_cxx transport_security_common_api_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx writes_per_rpc_test)
endif()
add_dependencies(buildtests_cxx xds_bootstrap_test)
add_dependencies(buildtests_cxx xds_end2end_test)
add_dependencies(buildtests_cxx bad_streaming_id_bad_client_test)
add_dependencies(buildtests_cxx badreq_bad_client_test)
@ -1310,6 +1311,7 @@ add_library(grpc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
src/core/ext/filters/client_channel/xds/xds_api.cc
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
src/core/ext/filters/client_channel/xds/xds_client.cc
src/core/ext/filters/client_channel/xds/xds_client_stats.cc
@ -2819,14 +2821,8 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
src/core/ext/filters/client_channel/xds/xds_api.cc
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
src/core/ext/filters/client_channel/xds/xds_channel.cc
src/core/ext/filters/client_channel/xds/xds_client.cc
src/core/ext/filters/client_channel/xds/xds_client_stats.cc
@ -2850,6 +2846,13 @@ add_library(grpc_unsecure
src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c
src/core/ext/upb-generated/envoy/type/percent.upb.c
src/core/ext/upb-generated/envoy/type/range.upb.c
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
src/core/ext/filters/census/grpc_context.cc
@ -16797,6 +16800,47 @@ endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(xds_bootstrap_test
test/core/client_channel/xds_bootstrap_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(xds_bootstrap_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_UPB_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_GRPC_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(xds_bootstrap_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc++
grpc
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(xds_end2end_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
@ -19472,7 +19516,7 @@ generate_pkgconfig(
"gRPC"
"high performance general RPC framework"
"${gRPC_CORE_VERSION}"
"gpr"
"gpr openssl"
"-lgrpc -laddress_sorting -lcares -lz"
""
"grpc.pc")

@ -1296,6 +1296,7 @@ transport_connectivity_state_test: $(BINDIR)/$(CONFIG)/transport_connectivity_st
transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test
transport_security_common_api_test: $(BINDIR)/$(CONFIG)/transport_security_common_api_test
writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test
xds_bootstrap_test: $(BINDIR)/$(CONFIG)/xds_bootstrap_test
xds_end2end_test: $(BINDIR)/$(CONFIG)/xds_end2end_test
public_headers_must_be_c89: $(BINDIR)/$(CONFIG)/public_headers_must_be_c89
boringssl_ssl_test: $(BINDIR)/$(CONFIG)/boringssl_ssl_test
@ -1767,6 +1768,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/transport_pid_controller_test \
$(BINDIR)/$(CONFIG)/transport_security_common_api_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \
$(BINDIR)/$(CONFIG)/xds_bootstrap_test \
$(BINDIR)/$(CONFIG)/xds_end2end_test \
$(BINDIR)/$(CONFIG)/boringssl_ssl_test \
$(BINDIR)/$(CONFIG)/boringssl_crypto_test \
@ -1937,6 +1939,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/transport_pid_controller_test \
$(BINDIR)/$(CONFIG)/transport_security_common_api_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \
$(BINDIR)/$(CONFIG)/xds_bootstrap_test \
$(BINDIR)/$(CONFIG)/xds_end2end_test \
$(BINDIR)/$(CONFIG)/bad_streaming_id_bad_client_test \
$(BINDIR)/$(CONFIG)/badreq_bad_client_test \
@ -2483,6 +2486,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/transport_security_common_api_test || ( echo test transport_security_common_api_test failed ; exit 1 )
$(E) "[RUN] Testing writes_per_rpc_test"
$(Q) $(BINDIR)/$(CONFIG)/writes_per_rpc_test || ( echo test writes_per_rpc_test failed ; exit 1 )
$(E) "[RUN] Testing xds_bootstrap_test"
$(Q) $(BINDIR)/$(CONFIG)/xds_bootstrap_test || ( echo test xds_bootstrap_test failed ; exit 1 )
$(E) "[RUN] Testing xds_end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/xds_end2end_test || ( echo test xds_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing bad_streaming_id_bad_client_test"
@ -3853,6 +3858,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc \
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc \
src/core/ext/filters/client_channel/xds/xds_client.cc \
src/core/ext/filters/client_channel/xds/xds_client_stats.cc \
@ -5314,14 +5320,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc \
src/core/ext/filters/client_channel/xds/xds_channel.cc \
src/core/ext/filters/client_channel/xds/xds_client.cc \
src/core/ext/filters/client_channel/xds/xds_client_stats.cc \
@ -5345,6 +5345,13 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c \
src/core/ext/upb-generated/envoy/type/percent.upb.c \
src/core/ext/upb-generated/envoy/type/range.upb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
src/core/ext/filters/census/grpc_context.cc \
@ -20023,6 +20030,49 @@ endif
endif
XDS_BOOTSTRAP_TEST_SRC = \
test/core/client_channel/xds_bootstrap_test.cc \
XDS_BOOTSTRAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(XDS_BOOTSTRAP_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/xds_bootstrap_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.5.0+.
$(BINDIR)/$(CONFIG)/xds_bootstrap_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/xds_bootstrap_test: $(PROTOBUF_DEP) $(XDS_BOOTSTRAP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(XDS_BOOTSTRAP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/xds_bootstrap_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/client_channel/xds_bootstrap_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_xds_bootstrap_test: $(XDS_BOOTSTRAP_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(XDS_BOOTSTRAP_TEST_OBJS:.o=.dep)
endif
endif
XDS_END2END_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/xds/ads_for_test.pb.cc $(GENDIR)/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/xds/eds_for_test.pb.cc $(GENDIR)/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc \

@ -23,8 +23,6 @@ load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
# Create toolchain configuration for remote execution.
rbe_autoconfig(
name = "rbe_default",
# use exec_properties instead of deprecated remote_execution_properties
use_legacy_platform_definition = False,
)
load("@bazel_toolchains//rules:environments.bzl", "clang_env")

@ -6,7 +6,7 @@ directly.
load(
"//bazel:protobuf.bzl",
"get_include_protoc_args",
"get_include_directory",
"get_plugin_args",
"get_proto_root",
"proto_path_to_generated_filename",
@ -107,8 +107,10 @@ def generate_cc_impl(ctx):
arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out]
tools = []
arguments += get_include_protoc_args(includes)
arguments += [
"--proto_path={}".format(get_include_directory(i))
for i in includes
]
# Include the output directory so that protoc puts the generated code in the
# right directory.
arguments += ["--proto_path={0}{1}".format(dir_out, proto_root)]

@ -1,6 +1,6 @@
load(
"//bazel:protobuf.bzl",
"get_include_protoc_args",
"get_include_directory",
"get_plugin_args",
"proto_path_to_generated_filename",
)
@ -55,7 +55,11 @@ def _generate_objc_impl(ctx):
arguments += ["--objc_out=" + dir_out]
arguments += ["--proto_path=."]
arguments += get_include_protoc_args(protos)
arguments += [
"--proto_path={}".format(get_include_directory(i))
for i in protos
]
# Include the output directory so that protoc puts the generated code in the
# right directory.
arguments += ["--proto_path={}".format(dir_out)]

@ -31,10 +31,6 @@ load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
# The set of pollers to test against if a test exercises polling
POLLERS = ["epollex", "epoll1", "poll"]
# set exec_properties = LARGE_MACHINE, to run the test on a large machine
# see //third_party/toolchains/machine_size for details
LARGE_MACHINE = { "gceMachineType" : "n1-standard-8"}
def if_not_windows(a):
return select({
"//:windows": [],
@ -169,7 +165,7 @@ def ios_cc_test(
deps = ios_test_deps,
)
def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = None, tags = [], exec_compatible_with = [], exec_properties = {}):
def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = None, tags = [], exec_compatible_with = []):
copts = if_mac(["-DGRPC_CFSTREAM"])
if language.upper() == "C":
copts = copts + if_not_windows(["-std=c99"])
@ -183,7 +179,6 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data
"size": size,
"timeout": timeout,
"exec_compatible_with": exec_compatible_with,
"exec_properties": exec_properties,
}
if uses_polling:
# the vanilla version of the test should run on platforms that only
@ -212,7 +207,6 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data
] + args["args"],
tags = (tags + ["no_windows", "no_mac"]),
exec_compatible_with = exec_compatible_with,
exec_properties = exec_properties,
)
else:
# the test behavior doesn't depend on polling, just generate the test

@ -176,11 +176,11 @@ def grpc_deps():
# list of releases is at https://releases.bazel.build/bazel-toolchains.html
http_archive(
name = "bazel_toolchains",
sha256 = "e9bab54199722935f239cb1cd56a80be2ac3c3843e1a6d3492e2bc11f9c21daf",
strip_prefix = "bazel-toolchains-1.0.0",
sha256 = "22ca5b8115c8673ecb627a02b606529e813961e447933863fccdf325cc5f999f",
strip_prefix = "bazel-toolchains-0.29.5",
urls = [
"https://github.com/bazelbuild/bazel-toolchains/releases/download/1.0.0/bazel-toolchains-1.0.0.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/1.0.0.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/releases/download/0.29.5/bazel-toolchains-0.29.5.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/0.29.5.tar.gz",
],
)

@ -1,6 +1,7 @@
"""Utility functions for generating protobuf code."""
_PROTO_EXTENSION = ".proto"
_VIRTUAL_IMPORTS = "/_virtual_imports/"
def well_known_proto_libs():
return [
@ -56,39 +57,37 @@ def proto_path_to_generated_filename(proto_path, fmt_str):
"""
return fmt_str.format(_strip_proto_extension(proto_path))
def _get_include_directory(include):
directory = include.path
def get_include_directory(source_file):
"""Returns the include directory path for the source_file. I.e. all of the
include statements within the given source_file are calculated relative to
the directory returned by this method.
The returned directory path can be used as the "--proto_path=" argument
value.
Args:
source_file: A proto file.
Returns:
The include directory path for the source_file.
"""
directory = source_file.path
prefix_len = 0
virtual_imports = "/_virtual_imports/"
if not include.is_source and virtual_imports in include.path:
root, relative = include.path.split(virtual_imports, 2)
result = root + virtual_imports + relative.split("/", 1)[0]
if is_in_virtual_imports(source_file):
root, relative = source_file.path.split(_VIRTUAL_IMPORTS, 2)
result = root + _VIRTUAL_IMPORTS + relative.split("/", 1)[0]
return result
if not include.is_source and directory.startswith(include.root.path):
prefix_len = len(include.root.path) + 1
if not source_file.is_source and directory.startswith(source_file.root.path):
prefix_len = len(source_file.root.path) + 1
if directory.startswith("external", prefix_len):
external_separator = directory.find("/", prefix_len)
repository_separator = directory.find("/", external_separator + 1)
return directory[:repository_separator]
else:
return include.root.path if include.root.path else "."
def get_include_protoc_args(includes):
"""Returns protoc args that imports protos relative to their import root.
Args:
includes: A list of included proto files.
Returns:
A list of arguments to be passed to protoc. For example, ["--proto_path=."].
"""
return [
"--proto_path={}".format(_get_include_directory(include))
for include in includes
]
return source_file.root.path if source_file.root.path else "."
def get_plugin_args(plugin, flags, dir_out, generate_mocks):
"""Returns arguments configuring protoc to use a plugin for a language.
@ -111,9 +110,13 @@ def get_plugin_args(plugin, flags, dir_out, generate_mocks):
]
def _get_staged_proto_file(context, source_file):
if source_file.dirname == context.label.package:
if source_file.dirname == context.label.package or \
is_in_virtual_imports(source_file):
# Current target and source_file are in same package
return source_file
else:
# Current target and source_file are in different packages (most
# probably even in different repositories)
copied_proto = context.actions.declare_file(source_file.basename)
context.actions.run_shell(
inputs = [source_file],
@ -123,7 +126,6 @@ def _get_staged_proto_file(context, source_file):
)
return copied_proto
def protos_from_context(context):
"""Copies proto files to the appropriate location.
@ -139,7 +141,6 @@ def protos_from_context(context):
protos.append(_get_staged_proto_file(context, file))
return protos
def includes_from_deps(deps):
"""Get includes from rule dependencies."""
return [
@ -152,20 +153,77 @@ def get_proto_arguments(protos, genfiles_dir_path):
"""Get the protoc arguments specifying which protos to compile."""
arguments = []
for proto in protos:
massaged_path = proto.path
if massaged_path.startswith(genfiles_dir_path):
massaged_path = proto.path[len(genfiles_dir_path) + 1:]
arguments.append(massaged_path)
strip_prefix_len = 0
if is_in_virtual_imports(proto):
incl_directory = get_include_directory(proto)
if proto.path.startswith(incl_directory):
strip_prefix_len = len(incl_directory) + 1
elif proto.path.startswith(genfiles_dir_path):
strip_prefix_len = len(genfiles_dir_path) + 1
arguments.append(proto.path[strip_prefix_len:])
return arguments
def declare_out_files(protos, context, generated_file_format):
"""Declares and returns the files to be generated."""
out_file_paths = []
for proto in protos:
if not is_in_virtual_imports(proto):
out_file_paths.append(proto.basename)
else:
path = proto.path[proto.path.index(_VIRTUAL_IMPORTS) + 1:]
out_file_paths.append(path)
return [
context.actions.declare_file(
proto_path_to_generated_filename(
proto.basename,
out_file_path,
generated_file_format,
),
)
for proto in protos
for out_file_path in out_file_paths
]
def get_out_dir(protos, context):
""" Returns the calculated value for --<lang>_out= protoc argument based on
the input source proto files and current context.
Args:
protos: A list of protos to be used as source files in protoc command
context: A ctx object for the rule.
Returns:
The value of --<lang>_out= argument.
"""
at_least_one_virtual = 0
for proto in protos:
if is_in_virtual_imports(proto):
at_least_one_virtual = True
elif at_least_one_virtual:
fail("Proto sources must be either all virtual imports or all real")
if at_least_one_virtual:
out_dir = get_include_directory(protos[0])
ws_root = protos[0].owner.workspace_root
if ws_root and out_dir.find(ws_root) >= 0:
out_dir = "".join(out_dir.rsplit(ws_root, 1))
return struct(
path = out_dir,
import_path = out_dir[out_dir.find(_VIRTUAL_IMPORTS) + 1:],
)
return struct(path = context.genfiles_dir.path, import_path = None)
def is_in_virtual_imports(source_file, virtual_folder = _VIRTUAL_IMPORTS):
"""Determines if source_file is virtual (is placed in _virtual_imports
subdirectory). The output of all proto_library targets which use
import_prefix and/or strip_import_prefix arguments is placed under
_virtual_imports directory.
Args:
source_file: A proto file.
virtual_folder: The virtual folder name (is set to "_virtual_imports"
by default)
Returns:
True if source_file is located under _virtual_imports, False otherwise.
"""
return not source_file.is_source and virtual_folder in source_file.path

@ -2,13 +2,13 @@
load(
"//bazel:protobuf.bzl",
"get_include_protoc_args",
"get_include_directory",
"get_plugin_args",
"get_proto_root",
"protos_from_context",
"includes_from_deps",
"get_proto_arguments",
"declare_out_files",
"get_out_dir",
)
_GENERATED_PROTO_FORMAT = "{}_pb2.py"
@ -17,17 +17,17 @@ _GENERATED_GRPC_PROTO_FORMAT = "{}_pb2_grpc.py"
def _generate_py_impl(context):
protos = protos_from_context(context)
includes = includes_from_deps(context.attr.deps)
proto_root = get_proto_root(context.label.workspace_root)
out_files = declare_out_files(protos, context, _GENERATED_PROTO_FORMAT)
tools = [context.executable._protoc]
out_dir = get_out_dir(protos, context)
arguments = ([
"--python_out={}".format(
context.genfiles_dir.path,
),
] + get_include_protoc_args(includes) + [
"--proto_path={}".format(context.genfiles_dir.path)
for proto in protos
"--python_out={}".format(out_dir.path),
] + [
"--proto_path={}".format(get_include_directory(i))
for i in includes
] + [
"--proto_path={}".format(context.genfiles_dir.path),
])
arguments += get_proto_arguments(protos, context.genfiles_dir.path)
@ -39,7 +39,18 @@ def _generate_py_impl(context):
arguments = arguments,
mnemonic = "ProtocInvocation",
)
return struct(files = depset(out_files))
imports = []
if out_dir.import_path:
imports.append("__main__/%s" % out_dir.import_path)
return [
DefaultInfo(files = depset(direct = out_files)),
PyInfo(
transitive_sources = depset(),
imports = depset(direct = imports),
),
]
_generate_pb2_src = rule(
attrs = {
@ -82,32 +93,35 @@ def py_proto_library(
native.py_library(
name = name,
srcs = [":{}".format(codegen_target)],
deps = ["@com_google_protobuf//:protobuf_python"],
deps = [
"@com_google_protobuf//:protobuf_python",
":{}".format(codegen_target),
],
**kwargs
)
def _generate_pb2_grpc_src_impl(context):
protos = protos_from_context(context)
includes = includes_from_deps(context.attr.deps)
proto_root = get_proto_root(context.label.workspace_root)
out_files = declare_out_files(protos, context, _GENERATED_GRPC_PROTO_FORMAT)
plugin_flags = ["grpc_2_0"] + context.attr.strip_prefixes
arguments = []
tools = [context.executable._protoc, context.executable._plugin]
out_dir = get_out_dir(protos, context)
arguments += get_plugin_args(
context.executable._plugin,
plugin_flags,
context.genfiles_dir.path,
out_dir.path,
False,
)
arguments += get_include_protoc_args(includes)
arguments += [
"--proto_path={}".format(context.genfiles_dir.path)
for proto in protos
"--proto_path={}".format(get_include_directory(i))
for i in includes
]
arguments += ["--proto_path={}".format(context.genfiles_dir.path)]
arguments += get_proto_arguments(protos, context.genfiles_dir.path)
context.actions.run(
@ -118,8 +132,18 @@ def _generate_pb2_grpc_src_impl(context):
arguments = arguments,
mnemonic = "ProtocInvocation",
)
return struct(files = depset(out_files))
imports = []
if out_dir.import_path:
imports.append("__main__/%s" % out_dir.import_path)
return [
DefaultInfo(files = depset(direct = out_files)),
PyInfo(
transitive_sources = depset(),
imports = depset(direct = imports),
),
]
_generate_pb2_grpc_src = rule(
attrs = {
@ -185,7 +209,11 @@ def py_grpc_library(
srcs = [
":{}".format(codegen_grpc_target),
],
deps = [Label("//src/python/grpcio/grpc:grpcio")] + deps,
deps = [
Label("//src/python/grpcio/grpc:grpcio"),
] + deps + [
":{}".format(codegen_grpc_target)
],
**kwargs
)

@ -14,7 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_proto_library", "py_grpc_library")
load(
"@com_github_grpc_grpc//bazel:python_rules.bzl",
"py_proto_library",
"py_grpc_library",
"py2and3_test",
)
package(default_testonly = 1)
@ -48,7 +53,7 @@ py_proto_library(
deps = ["@com_google_protobuf//:timestamp_proto"],
)
py_test(
py2and3_test(
name = "import_test",
main = "helloworld.py",
srcs = ["helloworld.py"],
@ -58,5 +63,41 @@ py_test(
":duration_py_pb2",
":timestamp_py_pb2",
],
python_version = "PY3",
)
# Test compatibility of py_proto_library and py_grpc_library rules with
# proto_library targets as deps when the latter use import_prefix and/or
# strip_import_prefix arguments
proto_library(
name = "helloworld_moved_proto",
srcs = ["helloworld.proto"],
deps = [
"@com_google_protobuf//:duration_proto",
"@com_google_protobuf//:timestamp_proto",
],
import_prefix = "google/cloud",
strip_import_prefix = ""
)
py_proto_library(
name = "helloworld_moved_py_pb2",
deps = [":helloworld_moved_proto"],
)
py_grpc_library(
name = "helloworld_moved_py_pb2_grpc",
srcs = [":helloworld_moved_proto"],
deps = [":helloworld_moved_py_pb2"],
)
py2and3_test(
name = "import_moved_test",
main = "helloworld_moved.py",
srcs = ["helloworld_moved.py"],
deps = [
":helloworld_moved_py_pb2",
":helloworld_moved_py_pb2_grpc",
":duration_py_pb2",
":timestamp_py_pb2",
],
)

@ -20,7 +20,9 @@ import unittest
import grpc
import duration_pb2
from google.protobuf import duration_pb2
from google.protobuf import timestamp_pb2
from concurrent import futures
import helloworld_pb2
import helloworld_pb2_grpc
@ -31,7 +33,8 @@ _SERVER_ADDRESS = '{}:0'.format(_HOST)
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
request_in_flight = datetime.now() - request.request_initation.ToDatetime()
request_in_flight = datetime.datetime.now() - \
request.request_initiation.ToDatetime()
request_duration = duration_pb2.Duration()
request_duration.FromTimedelta(request_in_flight)
return helloworld_pb2.HelloReply(
@ -53,7 +56,7 @@ def _listening_server():
class ImportTest(unittest.TestCase):
def run():
def test_import(self):
with _listening_server() as port:
with grpc.insecure_channel('{}:{}'.format(_HOST, port)) as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
@ -65,7 +68,7 @@ class ImportTest(unittest.TestCase):
),
wait_for_ready=True)
self.assertEqual(response.message, "Hello, you!")
self.assertGreater(response.request_duration.microseconds, 0)
self.assertGreater(response.request_duration.nanos, 0)
if __name__ == '__main__':

@ -0,0 +1,76 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Python implementation of the GRPC helloworld.Greeter client."""
import contextlib
import datetime
import logging
import unittest
import grpc
from google.protobuf import duration_pb2
from google.protobuf import timestamp_pb2
from concurrent import futures
from google.cloud import helloworld_pb2
from google.cloud import helloworld_pb2_grpc
_HOST = 'localhost'
_SERVER_ADDRESS = '{}:0'.format(_HOST)
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
request_in_flight = datetime.datetime.now() - \
request.request_initiation.ToDatetime()
request_duration = duration_pb2.Duration()
request_duration.FromTimedelta(request_in_flight)
return helloworld_pb2.HelloReply(
message='Hello, %s!' % request.name,
request_duration=request_duration,
)
@contextlib.contextmanager
def _listening_server():
server = grpc.server(futures.ThreadPoolExecutor())
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
port = server.add_insecure_port(_SERVER_ADDRESS)
server.start()
try:
yield port
finally:
server.stop(0)
class ImportTest(unittest.TestCase):
def test_import(self):
with _listening_server() as port:
with grpc.insecure_channel('{}:{}'.format(_HOST, port)) as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
request_timestamp = timestamp_pb2.Timestamp()
request_timestamp.GetCurrentTime()
response = stub.SayHello(helloworld_pb2.HelloRequest(
name='you',
request_initiation=request_timestamp,
),
wait_for_ready=True)
self.assertEqual(response.message, "Hello, you!")
self.assertGreater(response.request_duration.nanos, 0)
if __name__ == '__main__':
logging.basicConfig()
unittest.main()

@ -1230,6 +1230,16 @@ filegroups:
uses:
- grpc_base
- grpc_client_channel
- grpc_xds_client
- name: grpc_resolver_xds_secure
src:
- src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
plugin: grpc_resolver_xds
uses:
- grpc_base
- grpc_client_channel
- grpc_secure
- grpc_xds_client_secure
- name: grpc_secure
public_headers:
- include/grpc/grpc_security.h
@ -1538,12 +1548,14 @@ filegroups:
- name: grpc_xds_client
headers:
- src/core/ext/filters/client_channel/xds/xds_api.h
- src/core/ext/filters/client_channel/xds/xds_bootstrap.h
- src/core/ext/filters/client_channel/xds/xds_channel.h
- src/core/ext/filters/client_channel/xds/xds_channel_args.h
- src/core/ext/filters/client_channel/xds/xds_client.h
- src/core/ext/filters/client_channel/xds/xds_client_stats.h
src:
- src/core/ext/filters/client_channel/xds/xds_api.cc
- src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
- src/core/ext/filters/client_channel/xds/xds_channel.cc
- src/core/ext/filters/client_channel/xds/xds_client.cc
- src/core/ext/filters/client_channel/xds/xds_client_stats.cc
@ -1554,12 +1566,14 @@ filegroups:
- name: grpc_xds_client_secure
headers:
- src/core/ext/filters/client_channel/xds/xds_api.h
- src/core/ext/filters/client_channel/xds/xds_bootstrap.h
- src/core/ext/filters/client_channel/xds/xds_channel.h
- src/core/ext/filters/client_channel/xds/xds_channel_args.h
- src/core/ext/filters/client_channel/xds/xds_client.h
- src/core/ext/filters/client_channel/xds/xds_client_stats.h
src:
- src/core/ext/filters/client_channel/xds/xds_api.cc
- src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
- src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
- src/core/ext/filters/client_channel/xds/xds_client.cc
- src/core/ext/filters/client_channel/xds/xds_client_stats.cc
@ -1674,7 +1688,7 @@ libs:
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_resolver_fake
- grpc_resolver_xds
- grpc_resolver_xds_secure
- grpc_secure
- census
- grpc_client_idle_filter
@ -6012,6 +6026,17 @@ targets:
- mac
- linux
- posix
- name: xds_bootstrap_test
gtest: true
build: test
language: c++
src:
- test/core/client_channel/xds_bootstrap_test.cc
deps:
- grpc_test_util
- grpc++
- grpc
- gpr
- name: xds_end2end_test
gtest: true
build: test

@ -418,6 +418,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \
src/core/ext/filters/client_channel/xds/xds_bootstrap.cc \
src/core/ext/filters/client_channel/xds/xds_channel_secure.cc \
src/core/ext/filters/client_channel/xds/xds_client.cc \
src/core/ext/filters/client_channel/xds/xds_client_stats.cc \

@ -388,6 +388,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\resolver\\fake\\fake_resolver.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\xds.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_api.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_bootstrap.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_channel_secure.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_client.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_client_stats.cc " +

@ -100,7 +100,7 @@ There are other possible sample timelines. For example, for client-side streamin
through an `AsyncNotifyWhenDone` API in C++
1. Client: send\_initial\_metadata, recv\_message, recv\_trailing\_metadata
- At API-level, that's a client invoking a client-side streaming call. The
send\_initial\_metadata is the call invocation, the recv\_message colects
send\_initial\_metadata is the call invocation, the recv\_message collects
the final response from the server, and the recv\_trailing\_metadata gets
the `grpc::Status` value that will be returned from the call
1. Client: send\_message / Server: recv\_message

@ -556,6 +556,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
'src/core/ext/filters/client_channel/xds/xds_api.h',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.h',
'src/core/ext/filters/client_channel/xds/xds_channel.h',
'src/core/ext/filters/client_channel/xds/xds_channel_args.h',
'src/core/ext/filters/client_channel/xds/xds_client.h',
@ -918,6 +919,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.cc',
'src/core/ext/filters/client_channel/xds/xds_channel_secure.cc',
'src/core/ext/filters/client_channel/xds/xds_client.cc',
'src/core/ext/filters/client_channel/xds/xds_client_stats.cc',
@ -1294,6 +1296,7 @@ Pod::Spec.new do |s|
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
'src/core/ext/filters/client_channel/xds/xds_api.h',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.h',
'src/core/ext/filters/client_channel/xds/xds_channel.h',
'src/core/ext/filters/client_channel/xds/xds_channel_args.h',
'src/core/ext/filters/client_channel/xds/xds_client.h',

@ -486,6 +486,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_api.h )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_bootstrap.h )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_channel.h )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_channel_args.h )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_client.h )
@ -848,6 +849,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/xds.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_api.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_bootstrap.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_channel_secure.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_client.cc )
s.files += %w( src/core/ext/filters/client_channel/xds/xds_client_stats.cc )

@ -556,6 +556,7 @@
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.cc',
'src/core/ext/filters/client_channel/xds/xds_channel_secure.cc',
'src/core/ext/filters/client_channel/xds/xds_client.cc',
'src/core/ext/filters/client_channel/xds/xds_client_stats.cc',
@ -1415,14 +1416,8 @@
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.cc',
'src/core/ext/filters/client_channel/xds/xds_channel.cc',
'src/core/ext/filters/client_channel/xds/xds_client.cc',
'src/core/ext/filters/client_channel/xds/xds_client_stats.cc',
@ -1446,6 +1441,13 @@
'src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c',
'src/core/ext/upb-generated/envoy/type/percent.upb.c',
'src/core/ext/upb-generated/envoy/type/range.upb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
'src/core/ext/filters/census/grpc_context.cc',

@ -198,7 +198,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientAsyncReader));
GPR_CODEGEN_ASSERT(size == sizeof(ClientAsyncReader));
}
// This operator should never be called as the memory should be freed as part
@ -206,10 +206,10 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void StartCall(void* tag) override {
assert(!started_);
GPR_CODEGEN_ASSERT(!started_);
started_ = true;
StartCallInternal(tag);
}
@ -223,7 +223,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
/// calling code can access the received metadata through the
/// \a ClientContext.
void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
@ -232,7 +232,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
}
void Read(R* msg, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
@ -247,7 +247,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata received from the server.
void Finish(::grpc::Status* status, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
@ -269,7 +269,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
if (start) {
StartCallInternal(tag);
} else {
assert(tag == nullptr);
GPR_CODEGEN_ASSERT(tag == nullptr);
}
}
@ -347,7 +347,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientAsyncWriter));
GPR_CODEGEN_ASSERT(size == sizeof(ClientAsyncWriter));
}
// This operator should never be called as the memory should be freed as part
@ -355,10 +355,10 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void StartCall(void* tag) override {
assert(!started_);
GPR_CODEGEN_ASSERT(!started_);
started_ = true;
StartCallInternal(tag);
}
@ -371,7 +371,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
/// associated with this call is updated, and the calling code can access
/// the received metadata through the \a ClientContext.
void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
@ -380,7 +380,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
}
void Write(const W& msg, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
@ -388,7 +388,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
}
void Write(const W& msg, ::grpc::WriteOptions options, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
write_ops_.set_output_tag(tag);
if (options.is_last_message()) {
options.set_buffer_hint();
@ -400,7 +400,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
}
void WritesDone(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
write_ops_.set_output_tag(tag);
write_ops_.ClientSendClose();
call_.PerformOps(&write_ops_);
@ -414,7 +414,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
/// - attempts to fill in the \a response parameter passed to this class's
/// constructor with the server's response message.
void Finish(::grpc::Status* status, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
@ -435,7 +435,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
if (start) {
StartCallInternal(tag);
} else {
assert(tag == nullptr);
GPR_CODEGEN_ASSERT(tag == nullptr);
}
}
@ -515,7 +515,7 @@ class ClientAsyncReaderWriter final
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientAsyncReaderWriter));
GPR_CODEGEN_ASSERT(size == sizeof(ClientAsyncReaderWriter));
}
// This operator should never be called as the memory should be freed as part
@ -523,10 +523,10 @@ class ClientAsyncReaderWriter final
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void StartCall(void* tag) override {
assert(!started_);
GPR_CODEGEN_ASSERT(!started_);
started_ = true;
StartCallInternal(tag);
}
@ -539,7 +539,7 @@ class ClientAsyncReaderWriter final
/// is updated with it, and then the receiving initial metadata can
/// be accessed through this \a ClientContext.
void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
@ -548,7 +548,7 @@ class ClientAsyncReaderWriter final
}
void Read(R* msg, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
@ -558,7 +558,7 @@ class ClientAsyncReaderWriter final
}
void Write(const W& msg, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
@ -566,7 +566,7 @@ class ClientAsyncReaderWriter final
}
void Write(const W& msg, ::grpc::WriteOptions options, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
write_ops_.set_output_tag(tag);
if (options.is_last_message()) {
options.set_buffer_hint();
@ -578,7 +578,7 @@ class ClientAsyncReaderWriter final
}
void WritesDone(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
write_ops_.set_output_tag(tag);
write_ops_.ClientSendClose();
call_.PerformOps(&write_ops_);
@ -589,7 +589,7 @@ class ClientAsyncReaderWriter final
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server.
void Finish(::grpc::Status* status, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
@ -607,7 +607,7 @@ class ClientAsyncReaderWriter final
if (start) {
StartCallInternal(tag);
} else {
assert(tag == nullptr);
GPR_CODEGEN_ASSERT(tag == nullptr);
}
}

@ -19,7 +19,6 @@
#ifndef GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_IMPL_H
#define GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_IMPL_H
#include <assert.h>
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/channel_interface.h>
#include <grpcpp/impl/codegen/client_context_impl.h>
@ -97,7 +96,7 @@ class ClientAsyncResponseReader final
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientAsyncResponseReader));
GPR_CODEGEN_ASSERT(size == sizeof(ClientAsyncResponseReader));
}
// This operator should never be called as the memory should be freed as part
@ -105,10 +104,10 @@ class ClientAsyncResponseReader final
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void StartCall() override {
assert(!started_);
GPR_CODEGEN_ASSERT(!started_);
started_ = true;
StartCallInternal();
}
@ -120,7 +119,7 @@ class ClientAsyncResponseReader final
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server.
void ReadInitialMetadata(void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
single_buf.set_output_tag(tag);
@ -135,7 +134,7 @@ class ClientAsyncResponseReader final
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server.
void Finish(R* msg, ::grpc::Status* status, void* tag) override {
assert(started_);
GPR_CODEGEN_ASSERT(started_);
if (initial_metadata_read_) {
finish_buf.set_output_tag(tag);
finish_buf.RecvMessage(msg);

@ -19,14 +19,12 @@
#ifndef GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
#define GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
#include <assert.h>
#include <array>
#include <cstring>
#include <functional>
#include <map>
#include <memory>
#include <vector>
#include <grpc/impl/codegen/compression_types.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpcpp/impl/codegen/byte_buffer.h>
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/call_hook.h>
@ -42,10 +40,6 @@
#include <grpcpp/impl/codegen/slice.h>
#include <grpcpp/impl/codegen/string_ref.h>
#include <grpc/impl/codegen/atm.h>
#include <grpc/impl/codegen/compression_types.h>
#include <grpc/impl/codegen/grpc_types.h>
namespace grpc {
extern CoreCodegenInterface* g_core_codegen_interface;
@ -940,18 +934,29 @@ class CallOpSet : public CallOpSetInterface,
this->Op4::AddOp(ops, &nops);
this->Op5::AddOp(ops, &nops);
this->Op6::AddOp(ops, &nops);
GPR_CODEGEN_ASSERT(GRPC_CALL_OK ==
g_core_codegen_interface->grpc_call_start_batch(
call_.call(), ops, nops, core_cq_tag(), nullptr));
grpc_call_error err = g_core_codegen_interface->grpc_call_start_batch(
call_.call(), ops, nops, core_cq_tag(), nullptr);
if (err != GRPC_CALL_OK) {
// A failure here indicates an API misuse; for example, doing a Write
// while another Write is already pending on the same RPC or invoking
// WritesDone multiple times
gpr_log(GPR_ERROR, "API misuse of type %s observed",
g_core_codegen_interface->grpc_call_error_to_string(err));
GPR_CODEGEN_ASSERT(false);
}
}
// Should be called after interceptors are done running on the finalize result
// path
void ContinueFinalizeResultAfterInterception() override {
done_intercepting_ = true;
GPR_CODEGEN_ASSERT(GRPC_CALL_OK ==
g_core_codegen_interface->grpc_call_start_batch(
call_.call(), nullptr, 0, core_cq_tag(), nullptr));
// The following call_start_batch is internally-generated so no need for an
// explanatory log on failure.
GPR_CODEGEN_ASSERT(g_core_codegen_interface->grpc_call_start_batch(
call_.call(), nullptr, 0, core_cq_tag(), nullptr) ==
GRPC_CALL_OK);
}
private:

@ -70,7 +70,7 @@ class CallbackWithStatusTag
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(CallbackWithStatusTag));
GPR_CODEGEN_ASSERT(size == sizeof(CallbackWithStatusTag));
}
// This operator should never be called as the memory should be freed as part
@ -78,7 +78,7 @@ class CallbackWithStatusTag
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
CallbackWithStatusTag(grpc_call* call, std::function<void(Status)> f,
CompletionQueueTag* ops)
@ -134,7 +134,7 @@ class CallbackWithSuccessTag
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(CallbackWithSuccessTag));
GPR_CODEGEN_ASSERT(size == sizeof(CallbackWithSuccessTag));
}
// This operator should never be called as the memory should be freed as part
@ -142,7 +142,7 @@ class CallbackWithSuccessTag
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
CallbackWithSuccessTag() : call_(nullptr) {}

@ -422,7 +422,7 @@ class ClientCallbackReaderWriterImpl
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientCallbackReaderWriterImpl));
GPR_CODEGEN_ASSERT(size == sizeof(ClientCallbackReaderWriterImpl));
}
// This operator should never be called as the memory should be freed as part
@ -430,7 +430,7 @@ class ClientCallbackReaderWriterImpl
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void MaybeFinish() {
if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
@ -634,7 +634,7 @@ class ClientCallbackReaderImpl
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientCallbackReaderImpl));
GPR_CODEGEN_ASSERT(size == sizeof(ClientCallbackReaderImpl));
}
// This operator should never be called as the memory should be freed as part
@ -642,7 +642,7 @@ class ClientCallbackReaderImpl
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void MaybeFinish() {
if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
@ -774,7 +774,7 @@ class ClientCallbackWriterImpl
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientCallbackWriterImpl));
GPR_CODEGEN_ASSERT(size == sizeof(ClientCallbackWriterImpl));
}
// This operator should never be called as the memory should be freed as part
@ -782,7 +782,7 @@ class ClientCallbackWriterImpl
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void MaybeFinish() {
if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
@ -962,7 +962,7 @@ class ClientCallbackUnaryImpl final : public experimental::ClientCallbackUnary {
public:
// always allocated against a call arena, no memory free required
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(ClientCallbackUnaryImpl));
GPR_CODEGEN_ASSERT(size == sizeof(ClientCallbackUnaryImpl));
}
// This operator should never be called as the memory should be freed as part
@ -970,7 +970,7 @@ class ClientCallbackUnaryImpl final : public experimental::ClientCallbackUnary {
// delete to the operator new so that some compilers will not complain (see
// https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { assert(0); }
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
void StartCall() override {
// This call initiates two batches, each with a callback

@ -145,6 +145,8 @@ class ClientRpcInfo {
// No interceptors to register
return;
}
// NOTE: The following is not a range-based for loop because it will only
// iterate over a portion of the creators vector.
for (auto it = creators.begin() + interceptor_pos; it != creators.end();
++it) {
auto* interceptor = (*it)->CreateClientInterceptor(this);

@ -73,7 +73,8 @@ class CoreCodegen final : public CoreCodegenInterface {
void* reserved) override;
void grpc_call_ref(grpc_call* call) override;
void grpc_call_unref(grpc_call* call) override;
virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) override;
void* grpc_call_arena_alloc(grpc_call* call, size_t length) override;
const char* grpc_call_error_to_string(grpc_call_error error) override;
grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) override;
void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;

@ -114,6 +114,7 @@ class CoreCodegenInterface {
virtual void grpc_call_ref(grpc_call* call) = 0;
virtual void grpc_call_unref(grpc_call* call) = 0;
virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) = 0;
virtual const char* grpc_call_error_to_string(grpc_call_error error) = 0;
virtual grpc_slice grpc_empty_slice() = 0;
virtual grpc_slice grpc_slice_malloc(size_t length) = 0;
virtual void grpc_slice_unref(grpc_slice slice) = 0;

@ -86,7 +86,7 @@ class ProtoBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
// or our maximum allocation size
// 3. Provide the slice start and size available
// 4. Add the slice being returned to the slice buffer
size_t remain = total_size_ - byte_count_;
size_t remain = static_cast<size_t>(total_size_ - byte_count_);
if (have_backup_) {
/// If we have a backup slice, we should use it first
slice_ = backup_slice_;

@ -63,8 +63,8 @@ class Service {
virtual ~Service() {}
bool has_async_methods() const {
for (auto it = methods_.begin(); it != methods_.end(); ++it) {
if (*it && (*it)->handler() == nullptr) {
for (const auto& method : methods_) {
if (method && method->handler() == nullptr) {
return true;
}
}
@ -72,9 +72,9 @@ class Service {
}
bool has_synchronous_methods() const {
for (auto it = methods_.begin(); it != methods_.end(); ++it) {
if (*it &&
(*it)->api_type() == internal::RpcServiceMethod::ApiType::SYNC) {
for (const auto& method : methods_) {
if (method &&
method->api_type() == internal::RpcServiceMethod::ApiType::SYNC) {
return true;
}
}
@ -82,10 +82,10 @@ class Service {
}
bool has_callback_methods() const {
for (auto it = methods_.begin(); it != methods_.end(); ++it) {
if (*it && ((*it)->api_type() ==
for (const auto& method : methods_) {
if (method && (method->api_type() ==
internal::RpcServiceMethod::ApiType::CALL_BACK ||
(*it)->api_type() ==
method->api_type() ==
internal::RpcServiceMethod::ApiType::RAW_CALL_BACK)) {
return true;
}
@ -94,8 +94,8 @@ class Service {
}
bool has_generic_methods() const {
for (auto it = methods_.begin(); it != methods_.end(); ++it) {
if (it->get() == nullptr) {
for (const auto& method : methods_) {
if (method.get() == nullptr) {
return true;
}
}

@ -125,7 +125,7 @@ struct TlsCredentialReloadInterface {
/** A callback that invokes the credential reload. **/
virtual int Schedule(TlsCredentialReloadArg* arg) = 0;
/** A callback that cancels a credential reload request. **/
virtual void Cancel(TlsCredentialReloadArg* arg) {}
virtual void Cancel(TlsCredentialReloadArg* /* arg */) {}
};
/** TLS credential reloag config, wraps grpc_tls_credential_reload_config. It is
@ -227,7 +227,7 @@ struct TlsServerAuthorizationCheckInterface {
/** A callback that invokes the server authorization check. **/
virtual int Schedule(TlsServerAuthorizationCheckArg* arg) = 0;
/** A callback that cancels a server authorization check request. **/
virtual void Cancel(TlsServerAuthorizationCheckArg* arg) {}
virtual void Cancel(TlsServerAuthorizationCheckArg* /* arg */) {}
};
/** TLS server authorization check config, wraps

@ -37,12 +37,11 @@ class ServerContextTestSpouse {
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) {
for (const auto& item : client_metadata_storage_) {
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())));
item.first.c_str(),
grpc::string_ref(item.second.data(), item.second.size())));
}
}

@ -491,6 +491,7 @@
<file baseinstalldir="/" name="src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_bootstrap.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_channel_args.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_client.h" role="src" />
@ -853,6 +854,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/xds.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_bootstrap.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_channel_secure.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_client.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/xds/xds_client_stats.cc" role="src" />

@ -81,6 +81,8 @@ CLASSIFIERS = [
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'License :: OSI Approved :: Apache Software License',
]

@ -76,17 +76,13 @@ constexpr char kXds[] = "xds_experimental";
class ParsedXdsConfig : public LoadBalancingPolicy::Config {
public:
ParsedXdsConfig(const char* balancer_name,
RefCountedPtr<LoadBalancingPolicy::Config> child_policy,
ParsedXdsConfig(RefCountedPtr<LoadBalancingPolicy::Config> child_policy,
RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy)
: balancer_name_(balancer_name),
child_policy_(std::move(child_policy)),
: child_policy_(std::move(child_policy)),
fallback_policy_(std::move(fallback_policy)) {}
const char* name() const override { return kXds; }
const char* balancer_name() const { return balancer_name_; };
RefCountedPtr<LoadBalancingPolicy::Config> child_policy() const {
return child_policy_;
}
@ -96,7 +92,6 @@ class ParsedXdsConfig : public LoadBalancingPolicy::Config {
}
private:
const char* balancer_name_ = nullptr;
RefCountedPtr<LoadBalancingPolicy::Config> child_policy_;
RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy_;
};
@ -370,12 +365,6 @@ class XdsLb : public LoadBalancingPolicy {
void ShutdownLocked() override;
// Parses the xds config given the JSON node of the first child of XdsConfig.
// If parsing succeeds, updates \a balancer_name, and updates \a
// child_policy_config_ and \a fallback_policy_config_ if they are also
// found. Does nothing upon failure.
void ParseLbConfig(const ParsedXdsConfig* xds_config);
// Methods for dealing with fallback state.
void MaybeCancelFallbackAtStartupChecks();
static void OnFallbackTimerLocked(void* arg, grpc_error* error);
@ -384,19 +373,25 @@ class XdsLb : public LoadBalancingPolicy {
const char* name, const grpc_channel_args* args);
void MaybeExitFallbackMode();
XdsClient* xds_client() const {
return xds_client_from_channel_ != nullptr ? xds_client_from_channel_.get()
: xds_client_.get();
}
// Name of the backend server to connect to.
const char* server_name_ = nullptr;
// Name of the balancer to connect to.
UniquePtr<char> balancer_name_;
// Current channel args from the resolver.
const grpc_channel_args* args_ = nullptr;
// Internal state.
bool shutting_down_ = false;
// The xds client.
// The xds client and endpoint watcher.
// If we get the XdsClient from the channel, we store it in
// xds_client_from_channel_; if we create it ourselves, we store it in
// xds_client_.
RefCountedPtr<XdsClient> xds_client_from_channel_;
OrphanablePtr<XdsClient> xds_client_;
// A pointer to the endpoint watcher, to be used when cancelling the watch.
// Note that this is not owned, so this pointer must never be derefernced.
@ -594,6 +589,10 @@ class XdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
: xds_policy_(std::move(xds_policy)) {}
void OnEndpointChanged(EdsUpdate update) override {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
gpr_log(GPR_INFO, "[xdslb %p] Received EDS update from xds client",
xds_policy_.get());
}
// If the balancer tells us to drop all the calls, we should exit fallback
// mode immediately.
if (update.drop_all) xds_policy_->MaybeExitFallbackMode();
@ -661,6 +660,7 @@ class XdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
XdsLb::XdsLb(Args args)
: LoadBalancingPolicy(std::move(args)),
xds_client_from_channel_(XdsClient::GetFromChannelArgs(*args.args)),
lb_fallback_timeout_ms_(grpc_channel_args_find_integer(
args.args, GRPC_ARG_XDS_FALLBACK_TIMEOUT_MS,
{GRPC_XDS_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX})),
@ -671,6 +671,11 @@ XdsLb::XdsLb(Args args)
args.args, GRPC_ARG_XDS_FAILOVER_TIMEOUT_MS,
{GRPC_XDS_DEFAULT_FAILOVER_TIMEOUT_MS, 0, INT_MAX})),
priority_list_(this) {
if (xds_client_from_channel_ != nullptr &&
GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
gpr_log(GPR_INFO, "[xdslb %p] Using xds client %p from channel", this,
xds_client_from_channel_.get());
}
// Record server name.
const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI);
const char* server_uri = grpc_channel_arg_get_string(arg);
@ -713,22 +718,21 @@ void XdsLb::ShutdownLocked() {
pending_fallback_policy_.reset();
// Cancel the endpoint watch here instead of in our dtor, because the
// watcher holds a ref to us.
if (xds_client_ != nullptr) {
xds_client_->CancelEndpointDataWatch(StringView(server_name_),
xds_client()->CancelEndpointDataWatch(StringView(server_name_),
endpoint_watcher_);
xds_client_->RemoveClientStats(StringView(server_name_), &client_stats_);
xds_client()->RemoveClientStats(StringView(server_name_), &client_stats_);
xds_client_from_channel_.reset();
xds_client_.reset();
}
}
//
// public methods
//
void XdsLb::ResetBackoffLocked() {
// TODO(roth): When we instantiate the XdsClient in the resolver
// instead of in this LB policy, this should be done in the resolver
// instead of here.
// When the XdsClient is instantiated in the resolver instead of in this
// LB policy, this is done via the resolver, so we don't need to do it
// for xds_client_from_channel_ here.
if (xds_client_ != nullptr) xds_client_->ResetBackoff();
priority_list_.ResetBackoffLocked();
if (fallback_policy_ != nullptr) {
@ -739,52 +743,47 @@ void XdsLb::ResetBackoffLocked() {
}
}
void XdsLb::ParseLbConfig(const ParsedXdsConfig* xds_config) {
if (xds_config == nullptr || xds_config->balancer_name() == nullptr) return;
// TODO(yashykt) : does this need to be a gpr_strdup
// TODO(juanlishen): Read balancer name from bootstrap file.
balancer_name_ = UniquePtr<char>(gpr_strdup(xds_config->balancer_name()));
child_policy_config_ = xds_config->child_policy();
fallback_policy_config_ = xds_config->fallback_policy();
}
void XdsLb::UpdateLocked(UpdateArgs args) {
const bool is_initial_update = xds_client_ == nullptr;
ParseLbConfig(static_cast<const ParsedXdsConfig*>(args.config.get()));
// TODO(roth): This check should go away once we are getting the xds
// server from the bootstrap file.
if (balancer_name_ == nullptr) {
gpr_log(GPR_ERROR, "[xdslb %p] LB config parsing fails.", this);
return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
gpr_log(GPR_INFO, "[xdslb %p] Received update", this);
}
const bool is_initial_update = args_ == nullptr;
// Update config.
auto* xds_config = static_cast<const ParsedXdsConfig*>(args.config.get());
child_policy_config_ = xds_config->child_policy();
fallback_policy_config_ = xds_config->fallback_policy();
// Update fallback address list.
fallback_backend_addresses_ = std::move(args.addresses);
// Update args.
grpc_channel_args_destroy(args_);
args_ = args.args;
args.args = nullptr;
// Create an xds client if we don't have one yet.
if (xds_client_ == nullptr) {
xds_client_ = MakeOrphanable<XdsClient>(
combiner(), interested_parties(), balancer_name_.get(),
StringView(server_name_), nullptr /* service config watcher */, *args_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
gpr_log(GPR_INFO, "[xdslb %p] Created xds client %p", this,
xds_client_.get());
}
endpoint_watcher_ = New<EndpointWatcher>(Ref());
xds_client_->WatchEndpointData(
StringView(server_name_),
UniquePtr<XdsClient::EndpointWatcherInterface>(endpoint_watcher_));
xds_client_->AddClientStats(StringView(server_name_), &client_stats_);
}
// Update priority list.
priority_list_.UpdateLocked();
// Update the existing fallback policy. The fallback policy config and/or the
// fallback addresses may be new.
if (fallback_policy_ != nullptr) UpdateFallbackPolicyLocked();
// If this is the initial update, start the fallback-at-startup checks.
if (is_initial_update) {
// Initialize XdsClient.
if (xds_client_from_channel_ == nullptr) {
grpc_error* error = GRPC_ERROR_NONE;
xds_client_ = MakeOrphanable<XdsClient>(
combiner(), interested_parties(), StringView(server_name_),
nullptr /* service config watcher */, *args_, &error);
// TODO(roth): If we decide that we care about fallback mode, add
// proper error handling here.
GPR_ASSERT(error == GRPC_ERROR_NONE);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_trace)) {
gpr_log(GPR_INFO, "[xdslb %p] Created xds client %p", this,
xds_client_.get());
}
}
auto watcher = MakeUnique<EndpointWatcher>(Ref());
endpoint_watcher_ = watcher.get();
xds_client()->WatchEndpointData(StringView(server_name_),
std::move(watcher));
xds_client()->AddClientStats(StringView(server_name_), &client_stats_);
// Start fallback-at-startup checks.
grpc_millis deadline = ExecCtx::Get()->Now() + lb_fallback_timeout_ms_;
Ref(DEBUG_LOCATION, "on_fallback_timer").release(); // Held by closure
GRPC_CLOSURE_INIT(&lb_on_fallback_, &XdsLb::OnFallbackTimerLocked, this,
@ -1715,32 +1714,18 @@ class XdsFactory : public LoadBalancingPolicyFactory {
// xds was mentioned as a policy in the deprecated loadBalancingPolicy
// field or in the client API.
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:loadBalancingPolicy error:Xds Parser has required field - "
"balancerName. Please use loadBalancingConfig field of service "
"config instead.");
"field:loadBalancingPolicy error:xds policy requires configuration. "
"Please use loadBalancingConfig field of service config instead.");
return nullptr;
}
GPR_DEBUG_ASSERT(strcmp(json->key, name()) == 0);
InlinedVector<grpc_error*, 3> error_list;
const char* balancer_name = nullptr;
RefCountedPtr<LoadBalancingPolicy::Config> child_policy;
RefCountedPtr<LoadBalancingPolicy::Config> fallback_policy;
for (const grpc_json* field = json->child; field != nullptr;
field = field->next) {
if (field->key == nullptr) continue;
if (strcmp(field->key, "balancerName") == 0) {
if (balancer_name != nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:balancerName error:Duplicate entry"));
}
if (field->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:balancerName error:type should be string"));
continue;
}
balancer_name = field->value;
} else if (strcmp(field->key, "childPolicy") == 0) {
if (strcmp(field->key, "childPolicy") == 0) {
if (child_policy != nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:childPolicy error:Duplicate entry"));
@ -1768,7 +1753,7 @@ class XdsFactory : public LoadBalancingPolicyFactory {
}
if (error_list.empty()) {
return RefCountedPtr<LoadBalancingPolicy::Config>(New<ParsedXdsConfig>(
balancer_name, std::move(child_policy), std::move(fallback_policy)));
std::move(child_policy), std::move(fallback_policy)));
} else {
*error = GRPC_ERROR_CREATE_FROM_VECTOR("Xds Parser", &error_list);
return nullptr;

@ -19,39 +19,84 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/filters/client_channel/xds/xds_client.h"
#include "src/core/lib/gprpp/string_view.h"
namespace grpc_core {
namespace {
//
// XdsResolver
//
class XdsResolver : public Resolver {
public:
explicit XdsResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
args_(grpc_channel_args_copy(args.args)) {}
args_(grpc_channel_args_copy(args.args)),
interested_parties_(args.pollset_set) {
char* path = args.uri->path;
if (path[0] == '/') ++path;
server_name_.reset(gpr_strdup(path));
}
~XdsResolver() override { grpc_channel_args_destroy(args_); }
void StartLocked() override;
void ShutdownLocked() override{};
void ShutdownLocked() override { xds_client_.reset(); }
private:
class ServiceConfigWatcher : public XdsClient::ServiceConfigWatcherInterface {
public:
explicit ServiceConfigWatcher(RefCountedPtr<XdsResolver> resolver)
: resolver_(std::move(resolver)) {}
void OnServiceConfigChanged(
RefCountedPtr<ServiceConfig> service_config) override;
void OnError(grpc_error* error) override;
private:
RefCountedPtr<XdsResolver> resolver_;
};
UniquePtr<char> server_name_;
const grpc_channel_args* args_;
grpc_pollset_set* interested_parties_;
OrphanablePtr<XdsClient> xds_client_;
};
void XdsResolver::StartLocked() {
static const char* service_config =
"{\n"
" \"loadBalancingConfig\":[\n"
" { \"xds_experimental\":{} }\n"
" ]\n"
"}";
void XdsResolver::ServiceConfigWatcher::OnServiceConfigChanged(
RefCountedPtr<ServiceConfig> service_config) {
grpc_arg xds_client_arg = resolver_->xds_client_->MakeChannelArg();
Result result;
result.args =
grpc_channel_args_copy_and_add(resolver_->args_, &xds_client_arg, 1);
result.service_config = std::move(service_config);
resolver_->result_handler()->ReturnResult(std::move(result));
}
void XdsResolver::ServiceConfigWatcher::OnError(grpc_error* error) {
grpc_arg xds_client_arg = resolver_->xds_client_->MakeChannelArg();
Result result;
result.args = args_;
args_ = nullptr;
result.args =
grpc_channel_args_copy_and_add(resolver_->args_, &xds_client_arg, 1);
result.service_config_error = error;
resolver_->result_handler()->ReturnResult(std::move(result));
}
void XdsResolver::StartLocked() {
grpc_error* error = GRPC_ERROR_NONE;
result.service_config = ServiceConfig::Create(service_config, &error);
result_handler()->ReturnResult(std::move(result));
xds_client_ = MakeOrphanable<XdsClient>(
combiner(), interested_parties_, StringView(server_name_.get()),
MakeUnique<ServiceConfigWatcher>(Ref()), *args_, &error);
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR,
"Failed to create xds client -- channel will remain in "
"TRANSIENT_FAILURE: %s",
grpc_error_string(error));
result_handler()->ReturnError(error);
}
}
//

@ -69,14 +69,14 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
public:
virtual ~Parser() = default;
virtual UniquePtr<ParsedConfig> ParseGlobalParams(const grpc_json* json,
grpc_error** error) {
virtual UniquePtr<ParsedConfig> ParseGlobalParams(
const grpc_json* /* json */, grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr);
return nullptr;
}
virtual UniquePtr<ParsedConfig> ParsePerMethodParams(const grpc_json* json,
grpc_error** error) {
virtual UniquePtr<ParsedConfig> ParsePerMethodParams(
const grpc_json* /* json */, grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr);
return nullptr;
}

@ -49,7 +49,6 @@ namespace {
constexpr char kEdsTypeUrl[] =
"type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
constexpr char kEndpointRequired[] = "endpointRequired";
} // namespace
@ -101,22 +100,113 @@ bool XdsDropConfig::ShouldDrop(const UniquePtr<char>** category_name) const {
return false;
}
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name) {
namespace {
void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
const XdsBootstrap::MetadataValue& value);
void PopulateListValue(upb_arena* arena, google_protobuf_ListValue* list_value,
const std::vector<XdsBootstrap::MetadataValue>& values) {
for (const auto& value : values) {
auto* value_pb = google_protobuf_ListValue_add_values(list_value, arena);
PopulateMetadataValue(arena, value_pb, value);
}
}
void PopulateMetadata(
upb_arena* arena, google_protobuf_Struct* metadata_pb,
const Map<const char*, XdsBootstrap::MetadataValue, StringLess>& metadata) {
for (const auto& p : metadata) {
google_protobuf_Struct_FieldsEntry* field =
google_protobuf_Struct_add_fields(metadata_pb, arena);
google_protobuf_Struct_FieldsEntry_set_key(field,
upb_strview_makez(p.first));
google_protobuf_Value* value =
google_protobuf_Struct_FieldsEntry_mutable_value(field, arena);
PopulateMetadataValue(arena, value, p.second);
}
}
void PopulateMetadataValue(upb_arena* arena, google_protobuf_Value* value_pb,
const XdsBootstrap::MetadataValue& value) {
switch (value.type) {
case XdsBootstrap::MetadataValue::Type::MD_NULL:
google_protobuf_Value_set_null_value(value_pb, 0);
break;
case XdsBootstrap::MetadataValue::Type::DOUBLE:
google_protobuf_Value_set_number_value(value_pb, value.double_value);
break;
case XdsBootstrap::MetadataValue::Type::STRING:
google_protobuf_Value_set_string_value(
value_pb, upb_strview_makez(value.string_value));
break;
case XdsBootstrap::MetadataValue::Type::BOOL:
google_protobuf_Value_set_bool_value(value_pb, value.bool_value);
break;
case XdsBootstrap::MetadataValue::Type::STRUCT: {
google_protobuf_Struct* struct_value =
google_protobuf_Value_mutable_struct_value(value_pb, arena);
PopulateMetadata(arena, struct_value, value.struct_value);
break;
}
case XdsBootstrap::MetadataValue::Type::LIST: {
google_protobuf_ListValue* list_value =
google_protobuf_Value_mutable_list_value(value_pb, arena);
PopulateListValue(arena, list_value, value.list_value);
break;
}
}
}
void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node,
const char* build_version, envoy_api_v2_core_Node* node_msg) {
if (node != nullptr) {
if (node->id != nullptr) {
envoy_api_v2_core_Node_set_id(node_msg, upb_strview_makez(node->id));
}
if (node->cluster != nullptr) {
envoy_api_v2_core_Node_set_cluster(node_msg,
upb_strview_makez(node->cluster));
}
if (!node->metadata.empty()) {
google_protobuf_Struct* metadata =
envoy_api_v2_core_Node_mutable_metadata(node_msg, arena);
PopulateMetadata(arena, metadata, node->metadata);
}
if (node->locality_region != nullptr || node->locality_zone != nullptr ||
node->locality_subzone != nullptr) {
envoy_api_v2_core_Locality* locality =
envoy_api_v2_core_Node_mutable_locality(node_msg, arena);
if (node->locality_region != nullptr) {
envoy_api_v2_core_Locality_set_region(
locality, upb_strview_makez(node->locality_region));
}
if (node->locality_zone != nullptr) {
envoy_api_v2_core_Locality_set_zone(
locality, upb_strview_makez(node->locality_zone));
}
if (node->locality_subzone != nullptr) {
envoy_api_v2_core_Locality_set_sub_zone(
locality, upb_strview_makez(node->locality_subzone));
}
}
}
envoy_api_v2_core_Node_set_build_version(node_msg,
upb_strview_makez(build_version));
}
} // namespace
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name,
const XdsBootstrap::Node* node,
const char* build_version) {
upb::Arena arena;
// Create a request.
envoy_api_v2_DiscoveryRequest* request =
envoy_api_v2_DiscoveryRequest_new(arena.ptr());
envoy_api_v2_core_Node* node =
envoy_api_v2_core_Node* node_msg =
envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
google_protobuf_Struct* metadata =
envoy_api_v2_core_Node_mutable_metadata(node, arena.ptr());
google_protobuf_Struct_FieldsEntry* field =
google_protobuf_Struct_add_fields(metadata, arena.ptr());
google_protobuf_Struct_FieldsEntry_set_key(
field, upb_strview_makez(kEndpointRequired));
google_protobuf_Value* value =
google_protobuf_Struct_FieldsEntry_mutable_value(field, arena.ptr());
google_protobuf_Value_set_bool_value(value, true);
PopulateNode(arena.ptr(), node, build_version, node_msg);
envoy_api_v2_DiscoveryRequest_add_resource_names(
request, upb_strview_makez(server_name), arena.ptr());
envoy_api_v2_DiscoveryRequest_set_type_url(request,
@ -326,11 +416,18 @@ grpc_slice LrsRequestEncode(
} // namespace
grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name) {
grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
const XdsBootstrap::Node* node,
const char* build_version) {
upb::Arena arena;
// Create a request.
envoy_service_load_stats_v2_LoadStatsRequest* request =
envoy_service_load_stats_v2_LoadStatsRequest_new(arena.ptr());
// Populate node.
envoy_api_v2_core_Node* node_msg =
envoy_service_load_stats_v2_LoadStatsRequest_mutable_node(request,
arena.ptr());
PopulateNode(arena.ptr(), node, build_version, node_msg);
// Add cluster stats. There is only one because we only use one server name in
// one channel.
envoy_api_v2_endpoint_ClusterStats* cluster_stats =

@ -26,6 +26,7 @@
#include <grpc/slice_buffer.h>
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
#include "src/core/ext/filters/client_channel/xds/xds_client_stats.h"
namespace grpc_core {
@ -139,7 +140,9 @@ struct EdsUpdate {
struct CdsUpdate {};
// Creates an EDS request querying \a service_name.
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name);
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name,
const XdsBootstrap::Node* node,
const char* build_version);
// Parses the EDS response and returns the args to update locality map. If there
// is any error, the output update is invalid.
@ -147,7 +150,9 @@ grpc_error* XdsEdsResponseDecodeAndParse(const grpc_slice& encoded_response,
EdsUpdate* update);
// Creates an LRS request querying \a server_name.
grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name);
grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
const XdsBootstrap::Node* node,
const char* build_version);
// Creates an LRS request sending client-side load reports. If all the counters
// in \a client_stats are zero, returns empty slice.

@ -0,0 +1,450 @@
//
// Copyright 2019 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
#include <errno.h>
#include <stdlib.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/slice/slice_internal.h"
namespace grpc_core {
UniquePtr<XdsBootstrap> XdsBootstrap::ReadFromFile(grpc_error** error) {
UniquePtr<char> path(gpr_getenv("GRPC_XDS_BOOTSTRAP"));
if (path == nullptr) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"GRPC_XDS_BOOTSTRAP env var not set");
return nullptr;
}
grpc_slice contents;
*error = grpc_load_file(path.get(), /*add_null_terminator=*/true, &contents);
if (*error != GRPC_ERROR_NONE) return nullptr;
return MakeUnique<XdsBootstrap>(contents, error);
}
XdsBootstrap::XdsBootstrap(grpc_slice contents, grpc_error** error)
: contents_(contents) {
tree_ = grpc_json_parse_string_with_len(
reinterpret_cast<char*>(GPR_SLICE_START_PTR(contents_)),
GPR_SLICE_LENGTH(contents_));
if (tree_ == nullptr) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"failed to parse bootstrap file JSON");
return;
}
if (tree_->type != GRPC_JSON_OBJECT || tree_->key != nullptr) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"malformed JSON in bootstrap file");
return;
}
InlinedVector<grpc_error*, 1> error_list;
bool seen_xds_server = false;
bool seen_node = false;
for (grpc_json* child = tree_->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
} else if (strcmp(child->key, "xds_server") == 0) {
if (child->type != GRPC_JSON_OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"xds_server\" field is not an object"));
}
if (seen_xds_server) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"xds_server\" field"));
}
seen_xds_server = true;
grpc_error* parse_error = ParseXdsServer(child);
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
} else if (strcmp(child->key, "node") == 0) {
if (child->type != GRPC_JSON_OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"node\" field is not an object"));
}
if (seen_node) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"node\" field"));
}
seen_node = true;
grpc_error* parse_error = ParseNode(child);
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
}
}
if (!seen_xds_server) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"xds_server\" field not present"));
}
*error = GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing xds bootstrap file",
&error_list);
}
XdsBootstrap::~XdsBootstrap() {
grpc_json_destroy(tree_);
grpc_slice_unref_internal(contents_);
}
grpc_error* XdsBootstrap::ParseXdsServer(grpc_json* json) {
InlinedVector<grpc_error*, 1> error_list;
server_uri_ = nullptr;
bool seen_channel_creds = false;
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
} else if (strcmp(child->key, "server_uri") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"server_uri\" field is not a string"));
}
if (server_uri_ != nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"server_uri\" field"));
}
server_uri_ = child->value;
} else if (strcmp(child->key, "channel_creds") == 0) {
if (child->type != GRPC_JSON_ARRAY) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"channel_creds\" field is not an array"));
}
if (seen_channel_creds) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"channel_creds\" field"));
}
seen_channel_creds = true;
grpc_error* parse_error = ParseChannelCredsArray(child);
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
}
}
if (server_uri_ == nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"server_uri\" field not present"));
}
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"xds_server\" object",
&error_list);
}
grpc_error* XdsBootstrap::ParseChannelCredsArray(grpc_json* json) {
InlinedVector<grpc_error*, 1> error_list;
size_t idx = 0;
for (grpc_json *child = json->child; child != nullptr;
child = child->next, ++idx) {
if (child->key != nullptr) {
char* msg;
gpr_asprintf(&msg, "array element %" PRIuPTR " key is not null", idx);
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
}
if (child->type != GRPC_JSON_OBJECT) {
char* msg;
gpr_asprintf(&msg, "array element %" PRIuPTR " is not an object", idx);
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
} else {
grpc_error* parse_error = ParseChannelCreds(child, idx);
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
}
}
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"channel_creds\" array",
&error_list);
}
grpc_error* XdsBootstrap::ParseChannelCreds(grpc_json* json, size_t idx) {
InlinedVector<grpc_error*, 1> error_list;
ChannelCreds channel_creds;
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
} else if (strcmp(child->key, "type") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"type\" field is not a string"));
}
if (channel_creds.type != nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"type\" field"));
}
channel_creds.type = child->value;
} else if (strcmp(child->key, "config") == 0) {
if (child->type != GRPC_JSON_OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"config\" field is not an object"));
}
if (channel_creds.config != nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"config\" field"));
}
channel_creds.config = child;
}
}
if (channel_creds.type != nullptr) channel_creds_.push_back(channel_creds);
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
// string is not static in this case.
if (error_list.empty()) return GRPC_ERROR_NONE;
char* msg;
gpr_asprintf(&msg, "errors parsing index %" PRIuPTR, idx);
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
for (size_t i = 0; i < error_list.size(); ++i) {
error = grpc_error_add_child(error, error_list[i]);
}
return error;
}
grpc_error* XdsBootstrap::ParseNode(grpc_json* json) {
InlinedVector<grpc_error*, 1> error_list;
node_ = MakeUnique<Node>();
bool seen_metadata = false;
bool seen_locality = false;
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
} else if (strcmp(child->key, "id") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"id\" field is not a string"));
}
if (node_->id != nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"id\" field"));
}
node_->id = child->value;
} else if (strcmp(child->key, "cluster") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"cluster\" field is not a string"));
}
if (node_->cluster != nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"cluster\" field"));
}
node_->cluster = child->value;
} else if (strcmp(child->key, "locality") == 0) {
if (child->type != GRPC_JSON_OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"locality\" field is not an object"));
}
if (seen_locality) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"locality\" field"));
}
seen_locality = true;
grpc_error* parse_error = ParseLocality(child);
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
} else if (strcmp(child->key, "metadata") == 0) {
if (child->type != GRPC_JSON_OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"metadata\" field is not an object"));
}
if (seen_metadata) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"metadata\" field"));
}
seen_metadata = true;
InlinedVector<grpc_error*, 1> parse_errors =
ParseMetadataStruct(child, &node_->metadata);
if (!parse_errors.empty()) {
grpc_error* parse_error = GRPC_ERROR_CREATE_FROM_VECTOR(
"errors parsing \"metadata\" object", &parse_errors);
error_list.push_back(parse_error);
}
}
}
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"node\" object",
&error_list);
}
grpc_error* XdsBootstrap::ParseLocality(grpc_json* json) {
InlinedVector<grpc_error*, 1> error_list;
node_->locality_region = nullptr;
node_->locality_zone = nullptr;
node_->locality_subzone = nullptr;
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
} else if (strcmp(child->key, "region") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"region\" field is not a string"));
}
if (node_->locality_region != nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"region\" field"));
}
node_->locality_region = child->value;
} else if (strcmp(child->key, "zone") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"zone\" field is not a string"));
}
if (node_->locality_zone != nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("duplicate \"zone\" field"));
}
node_->locality_zone = child->value;
} else if (strcmp(child->key, "subzone") == 0) {
if (child->type != GRPC_JSON_STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"\"subzone\" field is not a string"));
}
if (node_->locality_subzone != nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"duplicate \"subzone\" field"));
}
node_->locality_subzone = child->value;
}
}
return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"locality\" object",
&error_list);
}
InlinedVector<grpc_error*, 1> XdsBootstrap::ParseMetadataStruct(
grpc_json* json,
Map<const char*, XdsBootstrap::MetadataValue, StringLess>* result) {
InlinedVector<grpc_error*, 1> error_list;
for (grpc_json* child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON key is null"));
continue;
}
if (result->find(child->key) != result->end()) {
char* msg;
gpr_asprintf(&msg, "duplicate metadata key \"%s\"", child->key);
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
gpr_free(msg);
}
MetadataValue& value = (*result)[child->key];
grpc_error* parse_error = ParseMetadataValue(child, 0, &value);
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
}
return error_list;
}
InlinedVector<grpc_error*, 1> XdsBootstrap::ParseMetadataList(
grpc_json* json, std::vector<MetadataValue>* result) {
InlinedVector<grpc_error*, 1> error_list;
size_t idx = 0;
for (grpc_json *child = json->child; child != nullptr;
child = child->next, ++idx) {
if (child->key != nullptr) {
char* msg;
gpr_asprintf(&msg, "JSON key is non-null for index %" PRIuPTR, idx);
error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg));
gpr_free(msg);
}
result->emplace_back();
grpc_error* parse_error = ParseMetadataValue(child, idx, &result->back());
if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error);
}
return error_list;
}
grpc_error* XdsBootstrap::ParseMetadataValue(grpc_json* json, size_t idx,
MetadataValue* result) {
grpc_error* error = GRPC_ERROR_NONE;
auto context_func = [json, idx]() {
char* context;
if (json->key != nullptr) {
gpr_asprintf(&context, "key \"%s\"", json->key);
} else {
gpr_asprintf(&context, "index %" PRIuPTR, idx);
}
return context;
};
switch (json->type) {
case GRPC_JSON_STRING:
result->type = MetadataValue::Type::STRING;
result->string_value = json->value;
break;
case GRPC_JSON_NUMBER:
result->type = MetadataValue::Type::DOUBLE;
errno = 0; // To distinguish error.
result->double_value = strtod(json->value, nullptr);
if (errno != 0) {
char* context = context_func();
char* msg;
gpr_asprintf(&msg, "error parsing numeric value for %s: \"%s\"",
context, json->value);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(context);
gpr_free(msg);
}
break;
case GRPC_JSON_TRUE:
result->type = MetadataValue::Type::BOOL;
result->bool_value = true;
break;
case GRPC_JSON_FALSE:
result->type = MetadataValue::Type::BOOL;
result->bool_value = false;
break;
case GRPC_JSON_NULL:
result->type = MetadataValue::Type::MD_NULL;
break;
case GRPC_JSON_ARRAY: {
result->type = MetadataValue::Type::LIST;
InlinedVector<grpc_error*, 1> error_list =
ParseMetadataList(json, &result->list_value);
if (!error_list.empty()) {
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
// string is not static in this case.
char* context = context_func();
char* msg;
gpr_asprintf(&msg, "errors parsing struct for %s", context);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(context);
gpr_free(msg);
for (size_t i = 0; i < error_list.size(); ++i) {
error = grpc_error_add_child(error, error_list[i]);
}
}
break;
}
case GRPC_JSON_OBJECT: {
result->type = MetadataValue::Type::STRUCT;
InlinedVector<grpc_error*, 1> error_list =
ParseMetadataStruct(json, &result->struct_value);
if (!error_list.empty()) {
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
// string is not static in this case.
char* context = context_func();
char* msg;
gpr_asprintf(&msg, "errors parsing struct for %s", context);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(context);
gpr_free(msg);
for (size_t i = 0; i < error_list.size(); ++i) {
error = grpc_error_add_child(error, error_list[i]);
GRPC_ERROR_UNREF(error_list[i]);
}
}
break;
}
default:
break;
}
return error;
}
} // namespace grpc_core

@ -0,0 +1,99 @@
//
// Copyright 2019 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_BOOTSTRAP_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_BOOTSTRAP_H
#include <grpc/support/port_platform.h>
#include <vector>
#include <grpc/impl/codegen/slice.h>
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
namespace grpc_core {
class XdsBootstrap {
public:
struct MetadataValue {
enum class Type { MD_NULL, DOUBLE, STRING, BOOL, STRUCT, LIST };
Type type = Type::MD_NULL;
// TODO(roth): Once we can use C++17, these can be in a std::variant.
double double_value;
const char* string_value;
bool bool_value;
Map<const char*, MetadataValue, StringLess> struct_value;
std::vector<MetadataValue> list_value;
};
struct Node {
const char* id = nullptr;
const char* cluster = nullptr;
const char* locality_region = nullptr;
const char* locality_zone = nullptr;
const char* locality_subzone = nullptr;
Map<const char*, MetadataValue, StringLess> metadata;
};
struct ChannelCreds {
const char* type = nullptr;
grpc_json* config = nullptr;
};
// If *error is not GRPC_ERROR_NONE after returning, then there was an
// error reading the file.
static UniquePtr<XdsBootstrap> ReadFromFile(grpc_error** error);
// Do not instantiate directly -- use ReadFromFile() above instead.
XdsBootstrap(grpc_slice contents, grpc_error** error);
~XdsBootstrap();
const char* server_uri() const { return server_uri_; }
const InlinedVector<ChannelCreds, 1>& channel_creds() const {
return channel_creds_;
}
const Node* node() const { return node_.get(); }
private:
grpc_error* ParseXdsServer(grpc_json* json);
grpc_error* ParseChannelCredsArray(grpc_json* json);
grpc_error* ParseChannelCreds(grpc_json* json, size_t idx);
grpc_error* ParseNode(grpc_json* json);
grpc_error* ParseLocality(grpc_json* json);
InlinedVector<grpc_error*, 1> ParseMetadataStruct(
grpc_json* json, Map<const char*, MetadataValue, StringLess>* result);
InlinedVector<grpc_error*, 1> ParseMetadataList(
grpc_json* json, std::vector<MetadataValue>* result);
grpc_error* ParseMetadataValue(grpc_json* json, size_t idx,
MetadataValue* result);
grpc_slice contents_;
grpc_json* tree_ = nullptr;
const char* server_uri_ = nullptr;
InlinedVector<ChannelCreds, 1> channel_creds_;
UniquePtr<Node> node_;
};
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_XDS_XDS_BOOTSTRAP_H */

@ -28,9 +28,10 @@ grpc_channel_args* ModifyXdsChannelArgs(grpc_channel_args* args) {
return args;
}
grpc_channel* CreateXdsChannel(const char* target_uri,
grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
const grpc_channel_args& args) {
return grpc_insecure_channel_create(target_uri, &args, nullptr);
if (!bootstrap.channel_creds().empty()) return nullptr;
return grpc_insecure_channel_create(bootstrap.server_uri(), &args, nullptr);
}
} // namespace grpc_core

@ -23,6 +23,8 @@
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
namespace grpc_core {
/// Makes any necessary modifications to \a args for use in the xds
@ -33,7 +35,7 @@ namespace grpc_core {
/// Caller takes ownership of the returned args.
grpc_channel_args* ModifyXdsChannelArgs(grpc_channel_args* args);
grpc_channel* CreateXdsChannel(const char* target_uri,
grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
const grpc_channel_args& args);
} // namespace grpc_core

@ -32,6 +32,7 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/sockaddr_utils.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/target_authority_table.h"
#include "src/core/lib/slice/slice_internal.h"
@ -62,19 +63,35 @@ grpc_channel_args* ModifyXdsChannelArgs(grpc_channel_args* args) {
return result;
}
grpc_channel* CreateXdsChannel(const char* target_uri,
grpc_channel* CreateXdsChannel(const XdsBootstrap& bootstrap,
const grpc_channel_args& args) {
grpc_channel_credentials* creds =
grpc_channel_credentials_find_in_args(&args);
grpc_channel_credentials* creds = nullptr;
RefCountedPtr<grpc_channel_credentials> creds_to_unref;
if (!bootstrap.channel_creds().empty()) {
for (size_t i = 0; i < bootstrap.channel_creds().size(); ++i) {
if (strcmp(bootstrap.channel_creds()[i].type, "google_default") == 0) {
creds = grpc_google_default_credentials_create();
break;
} else if (strcmp(bootstrap.channel_creds()[i].type, "fake") == 0) {
creds = grpc_fake_transport_security_credentials_create();
break;
}
}
if (creds == nullptr) return nullptr;
creds_to_unref.reset(creds);
} else {
creds = grpc_channel_credentials_find_in_args(&args);
if (creds == nullptr) {
// Built with security but parent channel is insecure.
return grpc_insecure_channel_create(target_uri, &args, nullptr);
return grpc_insecure_channel_create(bootstrap.server_uri(), &args,
nullptr);
}
}
const char* arg_to_remove = GRPC_ARG_CHANNEL_CREDENTIALS;
grpc_channel_args* new_args =
grpc_channel_args_copy_and_remove(&args, &arg_to_remove, 1);
grpc_channel* channel =
grpc_secure_channel_create(creds, target_uri, new_args, nullptr);
grpc_channel* channel = grpc_secure_channel_create(
creds, bootstrap.server_uri(), new_args, nullptr);
grpc_channel_args_destroy(new_args);
return channel;
}

@ -68,22 +68,15 @@ namespace grpc_core {
TraceFlag grpc_xds_client_trace(false, "xds_client");
// Contains a channel to the xds server and all the data related to the
// channel. Holds a ref to the xds client object.
// TODO(roth): This is separate from the XdsClient object because it was
// originally designed to be able to swap itself out in case the
// balancer name changed. Now that the balancer name is going to be
// coming from the bootstrap file, we don't really need this level of
// indirection unless we decide to support watching the bootstrap file
// for changes. At some point, if we decide that we're never going to
// need to do that, then we can eliminate this class and move its
// contents directly into the XdsClient class.
class XdsClient::ChannelState : public InternallyRefCounted<ChannelState> {
public:
//
// Internal class declarations
//
// An xds call wrapper that can restart a call upon failure. Holds a ref to
// the xds channel. The template parameter is the kind of wrapped xds call.
template <typename T>
class RetryableCall : public InternallyRefCounted<RetryableCall<T>> {
class XdsClient::ChannelState::RetryableCall
: public InternallyRefCounted<RetryableCall<T>> {
public:
explicit RetryableCall(RefCountedPtr<ChannelState> chand);
@ -94,12 +87,14 @@ class XdsClient::ChannelState : public InternallyRefCounted<ChannelState> {
T* calld() const { return calld_.get(); }
ChannelState* chand() const { return chand_.get(); }
bool IsCurrentCallOnChannel() const;
private:
void StartNewCallLocked();
void StartRetryTimerLocked();
static void OnRetryTimerLocked(void* arg, grpc_error* error);
// The wrapped call that talks to the xds server. It's instantiated
// The wrapped xds call that talks to the xds server. It's instantiated
// every time we start a new call. It's null during call retry backoff.
OrphanablePtr<T> calld_;
// The owning xds channel.
@ -115,7 +110,8 @@ class XdsClient::ChannelState : public InternallyRefCounted<ChannelState> {
};
// Contains an ADS call to the xds server.
class AdsCallState : public InternallyRefCounted<AdsCallState> {
class XdsClient::ChannelState::AdsCallState
: public InternallyRefCounted<AdsCallState> {
public:
// The ctor and dtor should not be used directly.
explicit AdsCallState(RefCountedPtr<RetryableCall<AdsCallState>> parent);
@ -159,7 +155,8 @@ class XdsClient::ChannelState : public InternallyRefCounted<ChannelState> {
};
// Contains an LRS call to the xds server.
class LrsCallState : public InternallyRefCounted<LrsCallState> {
class XdsClient::ChannelState::LrsCallState
: public InternallyRefCounted<LrsCallState> {
public:
// The ctor and dtor should not be used directly.
explicit LrsCallState(RefCountedPtr<RetryableCall<LrsCallState>> parent);
@ -248,44 +245,6 @@ class XdsClient::ChannelState : public InternallyRefCounted<ChannelState> {
OrphanablePtr<Reporter> reporter_;
};
ChannelState(RefCountedPtr<XdsClient> xds_client, const char* balancer_name,
const grpc_channel_args& args);
~ChannelState();
void Orphan() override;
grpc_channel* channel() const { return channel_; }
XdsClient* xds_client() const { return xds_client_.get(); }
AdsCallState* ads_calld() const { return ads_calld_->calld(); }
LrsCallState* lrs_calld() const { return lrs_calld_->calld(); }
void MaybeStartAdsCall();
void StopAdsCall();
void MaybeStartLrsCall();
void StopLrsCall();
bool HasActiveAdsCall() const { return ads_calld_->calld() != nullptr; }
void StartConnectivityWatchLocked();
void CancelConnectivityWatchLocked();
private:
class StateWatcher;
// The owning xds client.
RefCountedPtr<XdsClient> xds_client_;
// The channel and its status.
grpc_channel* channel_;
bool shutting_down_ = false;
StateWatcher* watcher_ = nullptr;
// The retryable XDS calls.
OrphanablePtr<RetryableCall<AdsCallState>> ads_calld_;
OrphanablePtr<RetryableCall<LrsCallState>> lrs_calld_;
};
//
// XdsClient::ChannelState::StateWatcher
//
@ -374,12 +333,11 @@ grpc_channel_args* BuildXdsChannelArgs(const grpc_channel_args& args) {
} // namespace
XdsClient::ChannelState::ChannelState(RefCountedPtr<XdsClient> xds_client,
const char* balancer_name,
const grpc_channel_args& args)
: InternallyRefCounted<ChannelState>(&grpc_xds_client_trace),
xds_client_(std::move(xds_client)) {
grpc_channel_args* new_args = BuildXdsChannelArgs(args);
channel_ = CreateXdsChannel(balancer_name, *new_args);
channel_ = CreateXdsChannel(*xds_client_->bootstrap_, *new_args);
grpc_channel_args_destroy(new_args);
GPR_ASSERT(channel_ != nullptr);
StartConnectivityWatchLocked();
@ -401,6 +359,20 @@ void XdsClient::ChannelState::Orphan() {
Unref(DEBUG_LOCATION, "ChannelState+orphaned");
}
XdsClient::ChannelState::AdsCallState* XdsClient::ChannelState::ads_calld()
const {
return ads_calld_->calld();
}
XdsClient::ChannelState::LrsCallState* XdsClient::ChannelState::lrs_calld()
const {
return lrs_calld_->calld();
}
bool XdsClient::ChannelState::HasActiveAdsCall() const {
return ads_calld_->calld() != nullptr;
}
void XdsClient::ChannelState::MaybeStartAdsCall() {
if (ads_calld_ != nullptr) return;
ads_calld_.reset(New<RetryableCall<AdsCallState>>(
@ -547,8 +519,9 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
nullptr, GRPC_MILLIS_INF_FUTURE, nullptr);
GPR_ASSERT(call_ != nullptr);
// Init the request payload.
grpc_slice request_payload_slice =
XdsEdsRequestCreateAndEncode(xds_client()->server_name_.get());
grpc_slice request_payload_slice = XdsEdsRequestCreateAndEncode(
xds_client()->server_name_.get(), xds_client()->bootstrap_->node(),
xds_client()->build_version_.get());
send_message_payload_ =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_slice_unref_internal(request_payload_slice);
@ -923,8 +896,9 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
nullptr, GRPC_MILLIS_INF_FUTURE, nullptr);
GPR_ASSERT(call_ != nullptr);
// Init the request payload.
grpc_slice request_payload_slice =
XdsLrsRequestCreateAndEncode(xds_client()->server_name_.get());
grpc_slice request_payload_slice = XdsLrsRequestCreateAndEncode(
xds_client()->server_name_.get(), xds_client()->bootstrap_->node(),
xds_client()->build_version_.get());
send_message_payload_ =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_slice_unref_internal(request_payload_slice);
@ -1177,19 +1151,48 @@ bool XdsClient::ChannelState::LrsCallState::IsCurrentCallOnChannel() const {
// XdsClient
//
namespace {
UniquePtr<char> GenerateBuildVersionString() {
char* build_version_str;
gpr_asprintf(&build_version_str, "gRPC C-core %s %s", grpc_version_string(),
GPR_PLATFORM_STRING);
return UniquePtr<char>(build_version_str);
}
} // namespace
XdsClient::XdsClient(grpc_combiner* combiner,
grpc_pollset_set* interested_parties,
const char* balancer_name, StringView server_name,
StringView server_name,
UniquePtr<ServiceConfigWatcherInterface> watcher,
const grpc_channel_args& channel_args)
: combiner_(GRPC_COMBINER_REF(combiner, "xds_client")),
const grpc_channel_args& channel_args, grpc_error** error)
: build_version_(GenerateBuildVersionString()),
combiner_(GRPC_COMBINER_REF(combiner, "xds_client")),
interested_parties_(interested_parties),
bootstrap_(XdsBootstrap::ReadFromFile(error)),
server_name_(server_name.dup()),
service_config_watcher_(std::move(watcher)),
chand_(MakeOrphanable<ChannelState>(
Ref(DEBUG_LOCATION, "XdsClient+ChannelState"), balancer_name,
channel_args)) {
// TODO(roth): Start LDS call.
service_config_watcher_(std::move(watcher)) {
if (*error != GRPC_ERROR_NONE) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
gpr_log(GPR_INFO, "[xds_client %p: failed to read bootstrap file: %s",
this, grpc_error_string(*error));
}
return;
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
gpr_log(GPR_INFO, "[xds_client %p: creating channel to %s", this,
bootstrap_->server_uri());
}
chand_ = MakeOrphanable<ChannelState>(
Ref(DEBUG_LOCATION, "XdsClient+ChannelState"), channel_args);
if (service_config_watcher_ != nullptr) {
// TODO(juanlishen): Start LDS call and do not return service config
// until we get the first LDS response.
GRPC_CLOSURE_INIT(&service_config_notify_, NotifyOnServiceConfig,
Ref().release(), grpc_combiner_scheduler(combiner_));
GRPC_CLOSURE_SCHED(&service_config_notify_, GRPC_ERROR_NONE);
}
}
XdsClient::~XdsClient() { GRPC_COMBINER_UNREF(combiner_, "xds_client"); }
@ -1202,12 +1205,12 @@ void XdsClient::Orphan() {
void XdsClient::WatchClusterData(StringView cluster,
UniquePtr<ClusterWatcherInterface> watcher) {
// TODO(roth): Implement.
// TODO(juanlishen): Implement.
}
void XdsClient::CancelClusterDataWatch(StringView cluster,
ClusterWatcherInterface* watcher) {
// TODO(roth): Implement.
// TODO(juanlishen): Implement.
}
void XdsClient::WatchEndpointData(StringView cluster,
@ -1228,7 +1231,9 @@ void XdsClient::CancelEndpointDataWatch(StringView cluster,
if (it != cluster_state_.endpoint_watchers.end()) {
cluster_state_.endpoint_watchers.erase(it);
}
if (cluster_state_.endpoint_watchers.empty()) chand_->StopAdsCall();
if (chand_ != nullptr && cluster_state_.endpoint_watchers.empty()) {
chand_->StopAdsCall();
}
}
void XdsClient::AddClientStats(StringView cluster,
@ -1246,7 +1251,9 @@ void XdsClient::RemoveClientStats(StringView cluster,
if (it != cluster_state_.client_stats.end()) {
cluster_state_.client_stats.erase(it);
}
if (cluster_state_.client_stats.empty()) chand_->StopLrsCall();
if (chand_ != nullptr && cluster_state_.client_stats.empty()) {
chand_->StopLrsCall();
}
}
void XdsClient::ResetBackoff() {
@ -1256,9 +1263,6 @@ void XdsClient::ResetBackoff() {
}
void XdsClient::NotifyOnError(grpc_error* error) {
// TODO(roth): Once we implement the full LDS flow, it will not be
// necessary to check for the service config watcher being non-null,
// because that will always be true.
if (service_config_watcher_ != nullptr) {
service_config_watcher_->OnError(GRPC_ERROR_REF(error));
}
@ -1271,6 +1275,27 @@ void XdsClient::NotifyOnError(grpc_error* error) {
GRPC_ERROR_UNREF(error);
}
void XdsClient::NotifyOnServiceConfig(void* arg, grpc_error* error) {
XdsClient* self = static_cast<XdsClient*>(arg);
// TODO(roth): When we add support for WeightedClusters, select the
// LB policy based on that functionality.
static const char* json =
"{\n"
" \"loadBalancingConfig\":[\n"
" { \"xds_experimental\":{} }\n"
" ]\n"
"}";
RefCountedPtr<ServiceConfig> service_config =
ServiceConfig::Create(json, &error);
if (error != GRPC_ERROR_NONE) {
self->service_config_watcher_->OnError(error);
} else {
self->service_config_watcher_->OnServiceConfigChanged(
std::move(service_config));
}
self->Unref();
}
void* XdsClient::ChannelArgCopy(void* p) {
XdsClient* xds_client = static_cast<XdsClient*>(p);
xds_client->Ref().release();

@ -21,6 +21,7 @@
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/xds/xds_api.h"
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
#include "src/core/ext/filters/client_channel/xds/xds_client_stats.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/memory.h"
@ -68,10 +69,12 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
virtual void OnError(grpc_error* error) = 0;
};
// If *error is not GRPC_ERROR_NONE after construction, then there was
// an error initializing the client.
XdsClient(grpc_combiner* combiner, grpc_pollset_set* interested_parties,
const char* balancer_name, StringView server_name,
StringView server_name,
UniquePtr<ServiceConfigWatcherInterface> watcher,
const grpc_channel_args& channel_args);
const grpc_channel_args& channel_args, grpc_error** error);
~XdsClient();
void Orphan() override;
@ -109,7 +112,61 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
const grpc_channel_args& args);
private:
class ChannelState;
// Contains a channel to the xds server and all the data related to the
// channel. Holds a ref to the xds client object.
// TODO(roth): This is separate from the XdsClient object because it was
// originally designed to be able to swap itself out in case the
// balancer name changed. Now that the balancer name is going to be
// coming from the bootstrap file, we don't really need this level of
// indirection unless we decide to support watching the bootstrap file
// for changes. At some point, if we decide that we're never going to
// need to do that, then we can eliminate this class and move its
// contents directly into the XdsClient class.
class ChannelState : public InternallyRefCounted<ChannelState> {
public:
template <typename T>
class RetryableCall;
class AdsCallState;
class LrsCallState;
ChannelState(RefCountedPtr<XdsClient> xds_client,
const grpc_channel_args& args);
~ChannelState();
void Orphan() override;
grpc_channel* channel() const { return channel_; }
XdsClient* xds_client() const { return xds_client_.get(); }
AdsCallState* ads_calld() const;
LrsCallState* lrs_calld() const;
void MaybeStartAdsCall();
void StopAdsCall();
void MaybeStartLrsCall();
void StopLrsCall();
bool HasActiveAdsCall() const;
void StartConnectivityWatchLocked();
void CancelConnectivityWatchLocked();
private:
class StateWatcher;
// The owning xds client.
RefCountedPtr<XdsClient> xds_client_;
// The channel and its status.
grpc_channel* channel_;
bool shutting_down_ = false;
StateWatcher* watcher_ = nullptr;
// The retryable XDS calls.
OrphanablePtr<RetryableCall<AdsCallState>> ads_calld_;
OrphanablePtr<RetryableCall<LrsCallState>> lrs_calld_;
};
struct ClusterState {
Map<ClusterWatcherInterface*, UniquePtr<ClusterWatcherInterface>>
@ -124,6 +181,10 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
// Sends an error notification to all watchers.
void NotifyOnError(grpc_error* error);
// TODO(juanlishen): Once we implement LDS support, this can be a
// normal method instead of a closure callback.
static void NotifyOnServiceConfig(void* arg, grpc_error* error);
// Channel arg vtable functions.
static void* ChannelArgCopy(void* p);
static void ChannelArgDestroy(void* p);
@ -131,11 +192,18 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
static const grpc_arg_pointer_vtable kXdsClientVtable;
UniquePtr<char> build_version_;
grpc_combiner* combiner_;
grpc_pollset_set* interested_parties_;
UniquePtr<XdsBootstrap> bootstrap_;
UniquePtr<char> server_name_;
UniquePtr<ServiceConfigWatcherInterface> service_config_watcher_;
// TODO(juanlishen): Once we implement LDS support, this will no
// longer be needed.
grpc_closure service_config_notify_;
// The channel for communicating with the xds server.
OrphanablePtr<ChannelState> chand_;

@ -152,7 +152,7 @@ class TransportFlowControlBase {
virtual bool flow_control_enabled() const { abort(); }
// Called to check if the transport needs to send a WINDOW_UPDATE frame
virtual uint32_t MaybeSendUpdate(bool writing_anyway) { abort(); }
virtual uint32_t MaybeSendUpdate(bool /* writing_anyway */) { abort(); }
// Using the protected members, returns and Action to be taken by the
// tranport.
@ -165,14 +165,14 @@ class TransportFlowControlBase {
// Called to do bookkeeping when a stream owned by this transport sends
// data on the wire
virtual void StreamSentData(int64_t size) { abort(); }
virtual void StreamSentData(int64_t /* size */) { abort(); }
// Called to do bookkeeping when a stream owned by this transport receives
// data from the wire. Also does error checking for frame size.
virtual grpc_error* RecvData(int64_t incoming_frame_size) { abort(); }
virtual grpc_error* RecvData(int64_t /* incoming_frame_size */) { abort(); }
// Called to do bookkeeping when we receive a WINDOW_UPDATE frame.
virtual void RecvUpdate(uint32_t size) { abort(); }
virtual void RecvUpdate(uint32_t /* size */) { abort(); }
// Returns the BdpEstimator held by this object. Caller is responsible for
// checking for nullptr. TODO(ncteisen): consider fully encapsulating all
@ -207,14 +207,14 @@ class TransportFlowControlDisabled final : public TransportFlowControlBase {
bool flow_control_enabled() const override { return false; }
// Never do anything.
uint32_t MaybeSendUpdate(bool writing_anyway) override { return 0; }
uint32_t MaybeSendUpdate(bool /* writing_anyway */) override { return 0; }
FlowControlAction MakeAction() override { return FlowControlAction(); }
FlowControlAction PeriodicUpdate() override { return FlowControlAction(); }
void StreamSentData(int64_t size) override {}
grpc_error* RecvData(int64_t incoming_frame_size) override {
void StreamSentData(int64_t /* size */) override {}
grpc_error* RecvData(int64_t /* incoming_frame_size */) override {
return GRPC_ERROR_NONE;
}
void RecvUpdate(uint32_t size) override {}
void RecvUpdate(uint32_t /* size */) override {}
};
// Implementation of flow control that abides to HTTP/2 spec and attempts
@ -347,29 +347,31 @@ class StreamFlowControlBase {
virtual ~StreamFlowControlBase() {}
// Updates an action using the protected members.
virtual FlowControlAction UpdateAction(FlowControlAction action) { abort(); }
virtual FlowControlAction UpdateAction(FlowControlAction /* action */) {
abort();
}
// Using the protected members, returns an Action for this stream to be
// taken by the tranport.
virtual FlowControlAction MakeAction() { abort(); }
// Bookkeeping for when data is sent on this stream.
virtual void SentData(int64_t outgoing_frame_size) { abort(); }
virtual void SentData(int64_t /* outgoing_frame_size */) { abort(); }
// Bookkeeping and error checking for when data is received by this stream.
virtual grpc_error* RecvData(int64_t incoming_frame_size) { abort(); }
virtual grpc_error* RecvData(int64_t /* incoming_frame_size */) { abort(); }
// Called to check if this stream needs to send a WINDOW_UPDATE frame.
virtual uint32_t MaybeSendUpdate() { abort(); }
// Bookkeeping for receiving a WINDOW_UPDATE from for this stream.
virtual void RecvUpdate(uint32_t size) { abort(); }
virtual void RecvUpdate(uint32_t /* size */) { abort(); }
// Bookkeeping for when a call pulls bytes out of the transport. At this
// point we consider the data 'used' and can thus let out peer know we are
// ready for more data.
virtual void IncomingByteStreamUpdate(size_t max_size_hint,
size_t have_already) {
virtual void IncomingByteStreamUpdate(size_t /* max_size_hint */,
size_t /* have_already */) {
abort();
}
@ -399,14 +401,14 @@ class StreamFlowControlDisabled : public StreamFlowControlBase {
return action;
}
FlowControlAction MakeAction() override { return FlowControlAction(); }
void SentData(int64_t outgoing_frame_size) override {}
grpc_error* RecvData(int64_t incoming_frame_size) override {
void SentData(int64_t /* outgoing_frame_size */) override {}
grpc_error* RecvData(int64_t /* incoming_frame_size */) override {
return GRPC_ERROR_NONE;
}
uint32_t MaybeSendUpdate() override { return 0; }
void RecvUpdate(uint32_t size) override {}
void IncomingByteStreamUpdate(size_t max_size_hint,
size_t have_already) override {}
void RecvUpdate(uint32_t /* size */) override {}
void IncomingByteStreamUpdate(size_t /* max_size_hint */,
size_t /* have_already */) override {}
};
// Implementation of flow control that abides to HTTP/2 spec and attempts

@ -110,7 +110,7 @@ class Allocator {
std::allocator<void>::const_pointer hint = nullptr) {
return static_cast<pointer>(gpr_malloc(n * sizeof(T)));
}
void deallocate(T* p, std::size_t n) { gpr_free(p); }
void deallocate(T* p, std::size_t /* n */) { gpr_free(p); }
size_t max_size() const {
return std::numeric_limits<size_type>::max() / sizeof(value_type);
}

@ -225,7 +225,7 @@ class ExecCtx {
virtual bool CheckReadyToFinish() { return false; }
/** Disallow delete on ExecCtx. */
static void operator delete(void* p) { abort(); }
static void operator delete(void* /* p */) { abort(); }
private:
/** Set exec_ctx_ to exec_ctx. */

@ -62,7 +62,7 @@ class ThreadPoolInterface {
// NULL closure.
class ThreadPoolWorker {
public:
ThreadPoolWorker(const char* thd_name, ThreadPoolInterface* pool,
ThreadPoolWorker(const char* thd_name, ThreadPoolInterface* /*pool*/,
MPMCQueueInterface* queue, Thread::Options& options,
int index)
: queue_(queue), thd_name_(thd_name), index_(index) {

@ -38,7 +38,7 @@ typedef struct grpc_udp_server grpc_udp_server;
* Its implementation should do the real IO work, e.g. read packet and write. */
class GrpcUdpHandler {
public:
GrpcUdpHandler(grpc_fd* emfd, void* user_data) {}
GrpcUdpHandler(grpc_fd* /* emfd */, void* /* user_data */) {}
virtual ~GrpcUdpHandler() {}
// Interfaces to be implemented by subclasses to do the actual setup/tear down

@ -67,7 +67,7 @@ grpc_json* grpc_json_parse_string(char* input);
* If indent is 0, then newlines will be suppressed as well, and the
* output will be condensed at its maximum.
*/
char* grpc_json_dump_to_string(grpc_json* json, int indent);
char* grpc_json_dump_to_string(const grpc_json* json, int indent);
/* Use these to create or delete a grpc_json object.
* Deletion is recursive. We will not attempt to free any of the strings

@ -311,7 +311,7 @@ grpc_json* grpc_json_parse_string(char* input) {
return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
}
static void json_dump_recursive(grpc_json_writer* writer, grpc_json* json,
static void json_dump_recursive(grpc_json_writer* writer, const grpc_json* json,
int in_object) {
while (json) {
if (in_object) grpc_json_writer_object_key(writer, json->key);
@ -351,7 +351,7 @@ static grpc_json_writer_vtable writer_vtable = {
json_writer_output_char, json_writer_output_string,
json_writer_output_string_with_len};
char* grpc_json_dump_to_string(grpc_json* json, int indent) {
char* grpc_json_dump_to_string(const grpc_json* json, int indent) {
grpc_json_writer writer;
json_writer_userdata state;

@ -1267,6 +1267,7 @@ static void continue_receiving_slices(batch_control* bctl) {
*call->receiving_buffer = nullptr;
call->receiving_message = 0;
finish_batch_step(bctl);
GRPC_ERROR_UNREF(error);
return;
}
} else {

@ -293,7 +293,7 @@ struct grpc_transport_stream_op_batch_payload {
struct {
grpc_metadata_batch* recv_trailing_metadata = nullptr;
grpc_transport_stream_stats* collect_stats = nullptr;
/** Should be enqueued when initial metadata is ready to be processed. */
/** Should be enqueued when trailing metadata is ready to be processed. */
grpc_closure* recv_trailing_metadata_ready = nullptr;
} recv_trailing_metadata;

@ -262,11 +262,9 @@ std::shared_ptr<ChannelCredentials> AltsCredentials(
grpc::GrpcLibraryCodegen init; // To call grpc_init().
grpc_alts_credentials_options* c_options =
grpc_alts_credentials_client_options_create();
for (auto service_account = options.target_service_accounts.begin();
service_account != options.target_service_accounts.end();
service_account++) {
for (const auto& service_account : options.target_service_accounts) {
grpc_alts_credentials_client_options_add_target_service_account(
c_options, service_account->c_str());
c_options, service_account.c_str());
}
grpc_channel_credentials* c_creds = grpc_alts_credentials_create(c_options);
grpc_alts_credentials_options_destroy(c_options);
@ -384,7 +382,7 @@ std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
namespace grpc {
namespace {
void DeleteWrapper(void* wrapper, grpc_error* ignored) {
void DeleteWrapper(void* wrapper, grpc_error* /*ignored*/) {
MetadataCredentialsPluginWrapper* w =
static_cast<MetadataCredentialsPluginWrapper*>(wrapper);
delete w;
@ -439,9 +437,9 @@ int MetadataCredentialsPluginWrapper::GetMetadata(
namespace {
void UnrefMetadata(const std::vector<grpc_metadata>& md) {
for (auto it = md.begin(); it != md.end(); ++it) {
grpc_slice_unref(it->key);
grpc_slice_unref(it->value);
for (const auto& metadatum : md) {
grpc_slice_unref(metadatum.key);
grpc_slice_unref(metadatum.value);
}
}
@ -461,10 +459,10 @@ void MetadataCredentialsPluginWrapper::InvokePlugin(
Status status = plugin_->GetMetadata(context.service_url, context.method_name,
cpp_channel_auth_context, &metadata);
std::vector<grpc_metadata> md;
for (auto it = metadata.begin(); it != metadata.end(); ++it) {
for (auto& metadatum : metadata) {
grpc_metadata md_entry;
md_entry.key = SliceFromCopiedString(it->first);
md_entry.value = SliceFromCopiedString(it->second);
md_entry.key = SliceFromCopiedString(metadatum.first);
md_entry.value = SliceFromCopiedString(metadatum.second);
md_entry.flags = 0;
md.push_back(md_entry);
}

@ -39,26 +39,26 @@ ChannelArguments::ChannelArguments(const ChannelArguments& other)
args_.reserve(other.args_.size());
auto list_it_dst = strings_.begin();
auto list_it_src = other.strings_.begin();
for (auto a = other.args_.begin(); a != other.args_.end(); ++a) {
for (const auto& a : other.args_) {
grpc_arg ap;
ap.type = a->type;
GPR_ASSERT(list_it_src->c_str() == a->key);
ap.type = a.type;
GPR_ASSERT(list_it_src->c_str() == a.key);
ap.key = const_cast<char*>(list_it_dst->c_str());
++list_it_src;
++list_it_dst;
switch (a->type) {
switch (a.type) {
case GRPC_ARG_INTEGER:
ap.value.integer = a->value.integer;
ap.value.integer = a.value.integer;
break;
case GRPC_ARG_STRING:
GPR_ASSERT(list_it_src->c_str() == a->value.string);
GPR_ASSERT(list_it_src->c_str() == a.value.string);
ap.value.string = const_cast<char*>(list_it_dst->c_str());
++list_it_src;
++list_it_dst;
break;
case GRPC_ARG_POINTER:
ap.value.pointer = a->value.pointer;
ap.value.pointer.p = a->value.pointer.vtable->copy(ap.value.pointer.p);
ap.value.pointer = a.value.pointer;
ap.value.pointer.p = a.value.pointer.vtable->copy(ap.value.pointer.p);
break;
}
args_.push_back(ap);
@ -67,9 +67,9 @@ ChannelArguments::ChannelArguments(const ChannelArguments& other)
ChannelArguments::~ChannelArguments() {
grpc_core::ExecCtx exec_ctx;
for (auto it = args_.begin(); it != args_.end(); ++it) {
if (it->type == GRPC_ARG_POINTER) {
it->value.pointer.vtable->destroy(it->value.pointer.p);
for (auto& arg : args_) {
if (arg.type == GRPC_ARG_POINTER) {
arg.value.pointer.vtable->destroy(arg.value.pointer.p);
}
}
}
@ -95,12 +95,12 @@ void ChannelArguments::SetSocketMutator(grpc_socket_mutator* mutator) {
grpc_arg mutator_arg = grpc_socket_mutator_to_arg(mutator);
bool replaced = false;
grpc_core::ExecCtx exec_ctx;
for (auto it = args_.begin(); it != args_.end(); ++it) {
if (it->type == mutator_arg.type &&
grpc::string(it->key) == grpc::string(mutator_arg.key)) {
for (auto& arg : args_) {
if (arg.type == mutator_arg.type &&
grpc::string(arg.key) == grpc::string(mutator_arg.key)) {
GPR_ASSERT(!replaced);
it->value.pointer.vtable->destroy(it->value.pointer.p);
it->value.pointer = mutator_arg.value.pointer;
arg.value.pointer.vtable->destroy(arg.value.pointer.p);
arg.value.pointer = mutator_arg.value.pointer;
replaced = true;
}
}
@ -123,14 +123,13 @@ void ChannelArguments::SetUserAgentPrefix(
}
bool replaced = false;
auto strings_it = strings_.begin();
for (auto it = args_.begin(); it != args_.end(); ++it) {
const grpc_arg& arg = *it;
for (auto& arg : args_) {
++strings_it;
if (arg.type == GRPC_ARG_STRING) {
if (grpc::string(arg.key) == GRPC_ARG_PRIMARY_USER_AGENT_STRING) {
GPR_ASSERT(arg.value.string == strings_it->c_str());
*(strings_it) = user_agent_prefix + " " + arg.value.string;
it->value.string = const_cast<char*>(strings_it->c_str());
arg.value.string = const_cast<char*>(strings_it->c_str());
replaced = true;
break;
}

@ -236,13 +236,13 @@ class ChannelData {
// TODO(roth): Come up with a more C++-like API for the channel element.
/// Initializes the channel data.
virtual grpc_error* Init(grpc_channel_element* elem,
grpc_channel_element_args* args) {
virtual grpc_error* Init(grpc_channel_element* /*elem*/,
grpc_channel_element_args* /*args*/) {
return GRPC_ERROR_NONE;
}
// Called before destruction.
virtual void Destroy(grpc_channel_element* elem) {}
virtual void Destroy(grpc_channel_element* /*elem*/) {}
virtual void StartTransportOp(grpc_channel_element* elem, TransportOp* op);
@ -259,15 +259,15 @@ class CallData {
// TODO(roth): Come up with a more C++-like API for the call element.
/// Initializes the call data.
virtual grpc_error* Init(grpc_call_element* elem,
const grpc_call_element_args* args) {
virtual grpc_error* Init(grpc_call_element* /*elem*/,
const grpc_call_element_args* /*args*/) {
return GRPC_ERROR_NONE;
}
// Called before destruction.
virtual void Destroy(grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) {}
virtual void Destroy(grpc_call_element* /*elem*/,
const grpc_call_final_info* /*final_info*/,
grpc_closure* /*then_call_closure*/) {}
/// Starts a new stream operation.
virtual void StartTransportStreamOpBatch(grpc_call_element* elem,

@ -123,6 +123,9 @@ void CoreCodegen::grpc_call_unref(grpc_call* call) { ::grpc_call_unref(call); }
void* CoreCodegen::grpc_call_arena_alloc(grpc_call* call, size_t length) {
return ::grpc_call_arena_alloc(call, length);
}
const char* CoreCodegen::grpc_call_error_to_string(grpc_call_error error) {
return ::grpc_call_error_to_string(error);
}
int CoreCodegen::grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
grpc_byte_buffer* buffer) {

@ -106,15 +106,13 @@ void TlsCredentialReloadArg::set_key_materials_config(
}
::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1>
c_pem_key_cert_pair_list;
for (auto key_cert_pair =
key_materials_config->pem_key_cert_pair_list().begin();
key_cert_pair != key_materials_config->pem_key_cert_pair_list().end();
key_cert_pair++) {
for (const auto& key_cert_pair :
key_materials_config->pem_key_cert_pair_list()) {
grpc_ssl_pem_key_cert_pair* ssl_pair =
(grpc_ssl_pem_key_cert_pair*)gpr_malloc(
sizeof(grpc_ssl_pem_key_cert_pair));
ssl_pair->private_key = gpr_strdup(key_cert_pair->private_key.c_str());
ssl_pair->cert_chain = gpr_strdup(key_cert_pair->cert_chain.c_str());
ssl_pair->private_key = gpr_strdup(key_cert_pair.private_key.c_str());
ssl_pair->cert_chain = gpr_strdup(key_cert_pair.cert_chain.c_str());
::grpc_core::PemKeyCertPair c_pem_key_cert_pair =
::grpc_core::PemKeyCertPair(ssl_pair);
c_pem_key_cert_pair_list.emplace_back(std::move(c_pem_key_cert_pair));

@ -36,14 +36,12 @@ grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig(
grpc_tls_key_materials_config_create();
::grpc_core::InlinedVector<::grpc_core::PemKeyCertPair, 1>
c_pem_key_cert_pair_list;
for (auto key_cert_pair = config->pem_key_cert_pair_list().begin();
key_cert_pair != config->pem_key_cert_pair_list().end();
key_cert_pair++) {
for (const auto& key_cert_pair : config->pem_key_cert_pair_list()) {
grpc_ssl_pem_key_cert_pair* ssl_pair =
(grpc_ssl_pem_key_cert_pair*)gpr_malloc(
sizeof(grpc_ssl_pem_key_cert_pair));
ssl_pair->private_key = gpr_strdup(key_cert_pair->private_key.c_str());
ssl_pair->cert_chain = gpr_strdup(key_cert_pair->cert_chain.c_str());
ssl_pair->private_key = gpr_strdup(key_cert_pair.private_key.c_str());
ssl_pair->cert_chain = gpr_strdup(key_cert_pair.cert_chain.c_str());
::grpc_core::PemKeyCertPair c_pem_key_cert_pair =
::grpc_core::PemKeyCertPair(ssl_pair);
c_pem_key_cert_pair_list.push_back(::std::move(c_pem_key_cert_pair));
@ -59,7 +57,7 @@ grpc_tls_key_materials_config* ConvertToCKeyMaterialsConfig(
/** The C schedule and cancel functions for the credential reload config.
* They populate a C credential reload arg with the result of a C++ credential
* reload schedule/cancel API. **/
int TlsCredentialReloadConfigCSchedule(void* config_user_data,
int TlsCredentialReloadConfigCSchedule(void* /*config_user_data*/,
grpc_tls_credential_reload_arg* arg) {
if (arg == nullptr || arg->config == nullptr ||
arg->config->context() == nullptr) {
@ -73,7 +71,7 @@ int TlsCredentialReloadConfigCSchedule(void* config_user_data,
return schedule_result;
}
void TlsCredentialReloadConfigCCancel(void* config_user_data,
void TlsCredentialReloadConfigCCancel(void* /*config_user_data*/,
grpc_tls_credential_reload_arg* arg) {
if (arg == nullptr || arg->config == nullptr ||
arg->config->context() == nullptr) {
@ -103,7 +101,7 @@ void TlsCredentialReloadArgDestroyContext(void* context) {
* config. They populate a C server authorization check arg with the result
* of a C++ server authorization check schedule/cancel API. **/
int TlsServerAuthorizationCheckConfigCSchedule(
void* config_user_data, grpc_tls_server_authorization_check_arg* arg) {
void* /*config_user_data*/, grpc_tls_server_authorization_check_arg* arg) {
if (arg == nullptr || arg->config == nullptr ||
arg->config->context() == nullptr) {
gpr_log(GPR_ERROR,
@ -119,7 +117,7 @@ int TlsServerAuthorizationCheckConfigCSchedule(
}
void TlsServerAuthorizationCheckConfigCCancel(
void* config_user_data, grpc_tls_server_authorization_check_arg* arg) {
void* /*config_user_data*/, grpc_tls_server_authorization_check_arg* arg) {
if (arg == nullptr || arg->config == nullptr ||
arg->config->context() == nullptr) {
gpr_log(GPR_ERROR,

@ -97,20 +97,20 @@ void ProtoServerReflection::FillErrorResponse(const Status& status,
error_response->set_error_message(status.error_message());
}
Status ProtoServerReflection::ListService(ServerContext* context,
Status ProtoServerReflection::ListService(ServerContext* /*context*/,
ListServiceResponse* response) {
if (services_ == nullptr) {
return Status(StatusCode::NOT_FOUND, "Services not found.");
}
for (auto it = services_->begin(); it != services_->end(); ++it) {
for (const auto& value : *services_) {
ServiceResponse* service_response = response->add_service();
service_response->set_name(*it);
service_response->set_name(value);
}
return Status::OK;
}
Status ProtoServerReflection::GetFileByName(
ServerContext* context, const grpc::string& filename,
ServerContext* /*context*/, const grpc::string& filename,
ServerReflectionResponse* response) {
if (descriptor_pool_ == nullptr) {
return Status::CANCELLED;
@ -127,7 +127,7 @@ Status ProtoServerReflection::GetFileByName(
}
Status ProtoServerReflection::GetFileContainingSymbol(
ServerContext* context, const grpc::string& symbol,
ServerContext* /*context*/, const grpc::string& symbol,
ServerReflectionResponse* response) {
if (descriptor_pool_ == nullptr) {
return Status::CANCELLED;
@ -144,7 +144,7 @@ Status ProtoServerReflection::GetFileContainingSymbol(
}
Status ProtoServerReflection::GetFileContainingExtension(
ServerContext* context, const ExtensionRequest* request,
ServerContext* /*context*/, const ExtensionRequest* request,
ServerReflectionResponse* response) {
if (descriptor_pool_ == nullptr) {
return Status::CANCELLED;
@ -168,7 +168,7 @@ Status ProtoServerReflection::GetFileContainingExtension(
}
Status ProtoServerReflection::GetAllExtensionNumbers(
ServerContext* context, const grpc::string& type,
ServerContext* /*context*/, const grpc::string& type,
ExtensionNumberResponse* response) {
if (descriptor_pool_ == nullptr) {
return Status::CANCELLED;
@ -182,8 +182,8 @@ Status ProtoServerReflection::GetAllExtensionNumbers(
std::vector<const protobuf::FieldDescriptor*> extensions;
descriptor_pool_->FindAllExtensions(desc, &extensions);
for (auto it = extensions.begin(); it != extensions.end(); it++) {
response->add_extension_number((*it)->number());
for (const auto& value : extensions) {
response->add_extension_number(value->number());
}
response->set_base_type_name(type);
return Status::OK;

@ -41,8 +41,8 @@ void ProtoServerReflectionPlugin::Finish(grpc::ServerInitializer* si) {
reflection_service_->SetServiceList(si->GetServiceList());
}
void ProtoServerReflectionPlugin::ChangeArguments(const grpc::string& name,
void* value) {}
void ProtoServerReflectionPlugin::ChangeArguments(const grpc::string& /*name*/,
void* /*value*/) {}
bool ProtoServerReflectionPlugin::has_sync_methods() const {
if (reflection_service_) {

@ -32,7 +32,8 @@ grpc::protobuf::util::Status ParseJson(const char* json_str,
}
Status ChannelzService::GetTopChannels(
ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request,
ServerContext* /*unused*/,
const channelz::v1::GetTopChannelsRequest* request,
channelz::v1::GetTopChannelsResponse* response) {
char* json_str = grpc_channelz_get_top_channels(request->start_channel_id());
if (json_str == nullptr) {
@ -48,7 +49,7 @@ Status ChannelzService::GetTopChannels(
}
Status ChannelzService::GetServers(
ServerContext* unused, const channelz::v1::GetServersRequest* request,
ServerContext* /*unused*/, const channelz::v1::GetServersRequest* request,
channelz::v1::GetServersResponse* response) {
char* json_str = grpc_channelz_get_servers(request->start_server_id());
if (json_str == nullptr) {
@ -63,7 +64,7 @@ Status ChannelzService::GetServers(
return Status::OK;
}
Status ChannelzService::GetServer(ServerContext* unused,
Status ChannelzService::GetServer(ServerContext* /*unused*/,
const channelz::v1::GetServerRequest* request,
channelz::v1::GetServerResponse* response) {
char* json_str = grpc_channelz_get_server(request->server_id());
@ -80,7 +81,8 @@ Status ChannelzService::GetServer(ServerContext* unused,
}
Status ChannelzService::GetServerSockets(
ServerContext* unused, const channelz::v1::GetServerSocketsRequest* request,
ServerContext* /*unused*/,
const channelz::v1::GetServerSocketsRequest* request,
channelz::v1::GetServerSocketsResponse* response) {
char* json_str = grpc_channelz_get_server_sockets(
request->server_id(), request->start_socket_id(), request->max_results());
@ -97,7 +99,7 @@ Status ChannelzService::GetServerSockets(
}
Status ChannelzService::GetChannel(
ServerContext* unused, const channelz::v1::GetChannelRequest* request,
ServerContext* /*unused*/, const channelz::v1::GetChannelRequest* request,
channelz::v1::GetChannelResponse* response) {
char* json_str = grpc_channelz_get_channel(request->channel_id());
if (json_str == nullptr) {
@ -112,7 +114,8 @@ Status ChannelzService::GetChannel(
}
Status ChannelzService::GetSubchannel(
ServerContext* unused, const channelz::v1::GetSubchannelRequest* request,
ServerContext* /*unused*/,
const channelz::v1::GetSubchannelRequest* request,
channelz::v1::GetSubchannelResponse* response) {
char* json_str = grpc_channelz_get_subchannel(request->subchannel_id());
if (json_str == nullptr) {
@ -127,7 +130,7 @@ Status ChannelzService::GetSubchannel(
return Status::OK;
}
Status ChannelzService::GetSocket(ServerContext* unused,
Status ChannelzService::GetSocket(ServerContext* /*unused*/,
const channelz::v1::GetSocketRequest* request,
channelz::v1::GetSocketResponse* response) {
char* json_str = grpc_channelz_get_socket(request->socket_id());

@ -39,9 +39,10 @@ class ChannelzServicePlugin : public ::grpc::ServerBuilderPlugin {
si->RegisterService(channelz_service_);
}
void Finish(grpc::ServerInitializer* si) override {}
void Finish(grpc::ServerInitializer* /*si*/) override {}
void ChangeArguments(const grpc::string& name, void* value) override {}
void ChangeArguments(const grpc::string& /*name*/, void* /*value*/) override {
}
bool has_sync_methods() const override {
if (channelz_service_) {

@ -120,8 +120,8 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface {
HealthCheckServiceImpl* service);
// Not used for Check.
void SendHealth(std::shared_ptr<CallHandler> self,
ServingStatus status) override {}
void SendHealth(std::shared_ptr<CallHandler> /*self*/,
ServingStatus /*status*/) override {}
private:
// Called when we receive a call.

@ -69,20 +69,18 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor(
&response_metadata);
std::vector<grpc_metadata> consumed_md;
for (auto it = consumed_metadata.begin(); it != consumed_metadata.end();
++it) {
for (const auto& consumed : consumed_metadata) {
grpc_metadata md_entry;
md_entry.key = SliceReferencingString(it->first);
md_entry.value = SliceReferencingString(it->second);
md_entry.key = SliceReferencingString(consumed.first);
md_entry.value = SliceReferencingString(consumed.second);
md_entry.flags = 0;
consumed_md.push_back(md_entry);
}
std::vector<grpc_metadata> response_md;
for (auto it = response_metadata.begin(); it != response_metadata.end();
++it) {
for (const auto& response : response_metadata) {
grpc_metadata md_entry;
md_entry.key = SliceReferencingString(it->first);
md_entry.value = SliceReferencingString(it->second);
md_entry.key = SliceReferencingString(response.first);
md_entry.value = SliceReferencingString(response.second);
md_entry.flags = 0;
response_md.push_back(md_entry);
}
@ -113,10 +111,9 @@ void SecureServerCredentials::SetAuthMetadataProcessor(
std::shared_ptr<ServerCredentials> SslServerCredentials(
const grpc::SslServerCredentialsOptions& options) {
std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
for (auto key_cert_pair = options.pem_key_cert_pairs.begin();
key_cert_pair != options.pem_key_cert_pairs.end(); key_cert_pair++) {
grpc_ssl_pem_key_cert_pair p = {key_cert_pair->private_key.c_str(),
key_cert_pair->cert_chain.c_str()};
for (const auto& key_cert_pair : options.pem_key_cert_pairs) {
grpc_ssl_pem_key_cert_pair p = {key_cert_pair.private_key.c_str(),
key_cert_pair.cert_chain.c_str()};
pem_key_cert_pairs.push_back(p);
}
grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create_ex(
@ -134,7 +131,7 @@ std::shared_ptr<ServerCredentials> SslServerCredentials(
namespace experimental {
std::shared_ptr<ServerCredentials> AltsServerCredentials(
const AltsServerCredentialsOptions& options) {
const AltsServerCredentialsOptions& /* options */) {
grpc_alts_credentials_options* c_options =
grpc_alts_credentials_server_options_create();
grpc_server_credentials* c_creds =

@ -48,10 +48,8 @@ ServerBuilder::ServerBuilder()
sync_server_settings_(SyncServerSettings()),
resource_quota_(nullptr) {
gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
for (auto it = g_plugin_factory_list->begin();
it != g_plugin_factory_list->end(); it++) {
auto& factory = *it;
plugins_.emplace_back(factory());
for (const auto& value : *g_plugin_factory_list) {
plugins_.emplace_back(value());
}
// all compression algorithms enabled by default.
@ -205,14 +203,14 @@ ServerBuilder& ServerBuilder::AddListeningPort(
std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
grpc::ChannelArguments args;
for (auto option = options_.begin(); option != options_.end(); ++option) {
(*option)->UpdateArguments(&args);
(*option)->UpdatePlugins(&plugins_);
for (const auto& option : options_) {
option->UpdateArguments(&args);
option->UpdatePlugins(&plugins_);
}
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin)->UpdateServerBuilder(this);
(*plugin)->UpdateChannelArguments(&args);
for (const auto& plugin : plugins_) {
plugin->UpdateServerBuilder(this);
plugin->UpdateChannelArguments(&args);
}
if (max_receive_message_size_ >= -1) {
@ -243,16 +241,16 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
// == Determine if the server has any syncrhonous methods ==
bool has_sync_methods = false;
for (auto it = services_.begin(); it != services_.end(); ++it) {
if ((*it)->service->has_synchronous_methods()) {
for (const auto& value : services_) {
if (value->service->has_synchronous_methods()) {
has_sync_methods = true;
break;
}
}
if (!has_sync_methods) {
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
if ((*plugin)->has_sync_methods()) {
for (const auto& value : plugins_) {
if (value->has_sync_methods()) {
has_sync_methods = true;
break;
}
@ -271,8 +269,8 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
std::vector<std::unique_ptr<ServerCompletionQueue>>>());
bool has_frequently_polled_cqs = false;
for (auto it = cqs_.begin(); it != cqs_.end(); ++it) {
if ((*it)->IsFrequentlyPolled()) {
for (const auto& cq : cqs_) {
if (cq->IsFrequentlyPolled()) {
has_frequently_polled_cqs = true;
break;
}
@ -280,8 +278,8 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
// == Determine if the server has any callback methods ==
bool has_callback_methods = false;
for (auto it = services_.begin(); it != services_.end(); ++it) {
if ((*it)->service->has_callback_methods()) {
for (const auto& service : services_) {
if (service->service->has_callback_methods()) {
has_callback_methods = true;
has_frequently_polled_cqs = true;
break;
@ -331,8 +329,8 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
// server
// 2. cqs_: Completion queues added via AddCompletionQueue() call
for (auto it = sync_server_cqs->begin(); it != sync_server_cqs->end(); ++it) {
grpc_server_register_completion_queue(server->server_, (*it)->cq(),
for (const auto& value : *sync_server_cqs) {
grpc_server_register_completion_queue(server->server_, value->cq(),
nullptr);
has_frequently_polled_cqs = true;
}
@ -347,8 +345,8 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
// calling Next() or AsyncNext()) and hence are not safe to be used for
// listening to incoming channels. Such completion queues must be registered
// as non-listening queues
for (auto it = cqs_.begin(); it != cqs_.end(); ++it) {
grpc_server_register_completion_queue(server->server_, (*it)->cq(),
for (const auto& value : cqs_) {
grpc_server_register_completion_queue(server->server_, value->cq(),
nullptr);
}
@ -358,15 +356,14 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
return nullptr;
}
for (auto service = services_.begin(); service != services_.end();
service++) {
if (!server->RegisterService((*service)->host.get(), (*service)->service)) {
for (const auto& value : services_) {
if (!server->RegisterService(value->host.get(), value->service)) {
return nullptr;
}
}
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin)->InitServer(initializer);
for (const auto& value : plugins_) {
value->InitServer(initializer);
}
if (generic_service_) {
@ -374,8 +371,8 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
} else if (callback_generic_service_) {
server->RegisterCallbackGenericService(callback_generic_service_);
} else {
for (auto it = services_.begin(); it != services_.end(); ++it) {
if ((*it)->service->has_generic_methods()) {
for (const auto& value : services_) {
if (value->service->has_generic_methods()) {
gpr_log(GPR_ERROR,
"Some methods were marked generic but there is no "
"generic service registered.");
@ -385,23 +382,23 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
}
bool added_port = false;
for (auto port = ports_.begin(); port != ports_.end(); port++) {
int r = server->AddListeningPort(port->addr, port->creds.get());
for (auto& port : ports_) {
int r = server->AddListeningPort(port.addr, port.creds.get());
if (!r) {
if (added_port) server->Shutdown();
return nullptr;
}
added_port = true;
if (port->selected_port != nullptr) {
*port->selected_port = r;
if (port.selected_port != nullptr) {
*port.selected_port = r;
}
}
auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0];
server->Start(cqs_data, cqs_.size());
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin)->Finish(initializer);
for (const auto& value : plugins_) {
value->Finish(initializer);
}
return server;

@ -75,8 +75,8 @@ namespace {
class DefaultGlobalCallbacks final : public Server::GlobalCallbacks {
public:
~DefaultGlobalCallbacks() override {}
void PreSynchronousRequest(ServerContext* context) override {}
void PostSynchronousRequest(ServerContext* context) override {}
void PreSynchronousRequest(ServerContext* /*context*/) override {}
void PostSynchronousRequest(ServerContext* /*context*/) override {}
};
std::shared_ptr<Server::GlobalCallbacks> g_callbacks = nullptr;
@ -90,12 +90,12 @@ void InitGlobalCallbacks() {
class ShutdownTag : public internal::CompletionQueueTag {
public:
bool FinalizeResult(void** tag, bool* status) { return false; }
bool FinalizeResult(void** /*tag*/, bool* /*status*/) { return false; }
};
class DummyTag : public internal::CompletionQueueTag {
public:
bool FinalizeResult(void** tag, bool* status) { return true; }
bool FinalizeResult(void** /*tag*/, bool* /*status*/) { return true; }
};
class UnimplementedAsyncRequestContext {
@ -187,7 +187,7 @@ void ServerInterface::BaseAsyncRequest::
grpc_cq_begin_op(notification_cq_->cq(), this);
grpc_cq_end_op(
notification_cq_->cq(), this, GRPC_ERROR_NONE,
[](void* arg, grpc_cq_completion* completion) { delete completion; },
[](void* /*arg*/, grpc_cq_completion* completion) { delete completion; },
nullptr, new grpc_cq_completion());
}
@ -204,11 +204,13 @@ ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest(
void ServerInterface::RegisteredAsyncRequest::IssueRequest(
void* registered_method, grpc_byte_buffer** payload,
ServerCompletionQueue* notification_cq) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_registered_call(
// The following call_start_batch is internally-generated so no need for an
// explanatory log on failure.
GPR_ASSERT(grpc_server_request_registered_call(
server_->server(), registered_method, &call_,
&context_->deadline_,
context_->client_metadata_.arr(), payload,
call_cq_->cq(), notification_cq->cq(), this));
&context_->deadline_, context_->client_metadata_.arr(),
payload, call_cq_->cq(), notification_cq->cq(),
this) == GRPC_CALL_OK);
}
ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
@ -220,10 +222,12 @@ ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
grpc_call_details_init(&call_details_);
GPR_ASSERT(notification_cq);
GPR_ASSERT(call_cq);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
server->server(), &call_, &call_details_,
context->client_metadata_.arr(), call_cq->cq(),
notification_cq->cq(), this));
// The following call_start_batch is internally-generated so no need for an
// explanatory log on failure.
GPR_ASSERT(grpc_server_request_call(server->server(), &call_, &call_details_,
context->client_metadata_.arr(),
call_cq->cq(), notification_cq->cq(),
this) == GRPC_CALL_OK);
}
bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag,
@ -391,7 +395,7 @@ class Server::SyncRequest final : public grpc::internal::CompletionQueueTag {
}
}
bool FinalizeResult(void** tag, bool* status) override {
bool FinalizeResult(void** /*tag*/, bool* status) override {
if (!*status) {
grpc_completion_queue_destroy(cq_);
cq_ = nullptr;
@ -571,12 +575,11 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
bool Request() override {
if (method_tag_) {
if (GRPC_CALL_OK !=
grpc_server_request_registered_call(
if (grpc_server_request_registered_call(
server_->c_server(), method_tag_, &call_, &deadline_,
&request_metadata_,
has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(),
cq_->cq(), static_cast<void*>(&tag_))) {
cq_->cq(), static_cast<void*>(&tag_)) != GRPC_CALL_OK) {
return false;
}
} else {
@ -782,13 +785,13 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase {
template <>
bool Server::CallbackRequest<grpc::ServerContext>::FinalizeResult(
void** tag, bool* status) {
void** /*tag*/, bool* /*status*/) {
return false;
}
template <>
bool Server::CallbackRequest<grpc::GenericServerContext>::FinalizeResult(
void** tag, bool* status) {
void** /*tag*/, bool* status) {
if (*status) {
// TODO(yangg) remove the copy here
ctx_.method_ = grpc::StringFromCopiedSlice(call_details_->method);
@ -914,9 +917,9 @@ class Server::SyncRequestThreadManager : public grpc::ThreadManager {
void Start() {
if (!sync_requests_.empty()) {
for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) {
(*m)->SetupRequest();
(*m)->Request(server_->c_server(), server_cq_->cq());
for (const auto& value : sync_requests_) {
value->SetupRequest();
value->Request(server_->c_server(), server_cq_->cq());
}
Initialize(); // ThreadManager's Initialize()
@ -1014,8 +1017,8 @@ Server::~Server() {
Shutdown();
} else if (!started_) {
// Shutdown the completion queues
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->Shutdown();
for (const auto& value : sync_req_mgrs_) {
value->Shutdown();
}
}
}
@ -1083,16 +1086,14 @@ bool Server::RegisterService(const grpc::string* host, grpc::Service* service) {
const char* method_name = nullptr;
for (auto it = service->methods_.begin(); it != service->methods_.end();
++it) {
if (it->get() == nullptr) { // Handled by generic service if any.
for (const auto& method : service->methods_) {
if (method.get() == nullptr) { // Handled by generic service if any.
continue;
}
grpc::internal::RpcServiceMethod* method = it->get();
void* method_registration_tag = grpc_server_register_method(
server_, method->name(), host ? host->c_str() : nullptr,
PayloadHandlingForMethod(method), 0);
PayloadHandlingForMethod(method.get()), 0);
if (method_registration_tag == nullptr) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
method->name());
@ -1103,8 +1104,8 @@ bool Server::RegisterService(const grpc::string* host, grpc::Service* service) {
method->set_server_tag(method_registration_tag);
} else if (method->api_type() ==
grpc::internal::RpcServiceMethod::ApiType::SYNC) {
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->AddSyncMethod(method, method_registration_tag);
for (const auto& value : sync_req_mgrs_) {
value->AddSyncMethod(method.get(), method_registration_tag);
}
} else {
// a callback method. Register at least some callback requests
@ -1113,8 +1114,8 @@ bool Server::RegisterService(const grpc::string* host, grpc::Service* service) {
// TODO(vjpai): Register these dynamically based on need
for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) {
callback_reqs_to_start_.push_back(
new CallbackRequest<grpc::ServerContext>(this, method_index, method,
method_registration_tag));
new CallbackRequest<grpc::ServerContext>(
this, method_index, method.get(), method_registration_tag));
}
// Enqueue it so that it will be Request'ed later after all request
// matchers are created at core server startup
@ -1213,8 +1214,8 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) {
grpc_server_start(server_);
if (!has_async_generic_service_ && !has_callback_generic_service_) {
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->AddUnknownSyncMethod();
for (const auto& value : sync_req_mgrs_) {
value->AddUnknownSyncMethod();
}
for (size_t i = 0; i < num_cqs; i++) {
@ -1235,8 +1236,8 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) {
new grpc::internal::ResourceExhaustedHandler);
}
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->Start();
for (const auto& value : sync_req_mgrs_) {
value->Start();
}
for (auto* cbreq : callback_reqs_to_start_) {
@ -1287,13 +1288,13 @@ void Server::ShutdownInternal(gpr_timespec deadline) {
// Shutdown all ThreadManagers. This will try to gracefully stop all the
// threads in the ThreadManagers (once they process any inflight requests)
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->Shutdown(); // ThreadManager's Shutdown()
for (const auto& value : sync_req_mgrs_) {
value->Shutdown(); // ThreadManager's Shutdown()
}
// Wait for threads in all ThreadManagers to terminate
for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
(*it)->Wait();
for (const auto& value : sync_req_mgrs_) {
value->Wait();
}
// Wait for all outstanding callback requests to complete

@ -17,7 +17,6 @@
*/
#include <grpcpp/impl/codegen/server_context_impl.h>
#include <grpcpp/support/server_callback.h>
#include <algorithm>
#include <mutex>
@ -30,6 +29,7 @@
#include <grpc/support/log.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/codegen/completion_queue_impl.h>
#include <grpcpp/support/server_callback.h>
#include <grpcpp/support/time.h>
#include "src/core/lib/gprpp/ref_counted.h"
@ -73,7 +73,7 @@ class ServerContext::CompletionOp final
// This should always be arena allocated in the call, so override delete.
// But this class is not trivially destructible, so must actually call delete
// before allowing the arena to be freed
static void operator delete(void* ptr, std::size_t size) {
static void operator delete(void* /*ptr*/, std::size_t size) {
assert(size == sizeof(CompletionOp));
}
@ -123,7 +123,7 @@ class ServerContext::CompletionOp final
// RPC. This should set hijacking state for each of the ops.
void SetHijackingState() override {
/* Servers don't allow hijacking */
GPR_CODEGEN_ASSERT(false);
GPR_ASSERT(false);
}
/* Should be called after interceptors are done running */
@ -139,9 +139,8 @@ class ServerContext::CompletionOp final
return;
}
/* Start a dummy op so that we can return the tag */
GPR_CODEGEN_ASSERT(
GRPC_CALL_OK ==
grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_, nullptr));
GPR_ASSERT(grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_,
nullptr) == GRPC_CALL_OK);
}
private:
@ -181,8 +180,10 @@ void ServerContext::CompletionOp::FillOps(::grpc::internal::Call* call) {
interceptor_methods_.SetCall(&call_);
interceptor_methods_.SetReverse();
interceptor_methods_.SetCallOpSetInterface(this);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), &ops, 1,
core_cq_tag_, nullptr));
// The following call_start_batch is internally-generated so no need for an
// explanatory log on failure.
GPR_ASSERT(grpc_call_start_batch(call->call(), &ops, 1, core_cq_tag_,
nullptr) == GRPC_CALL_OK);
/* No interceptors to run here */
}

@ -34,9 +34,13 @@ ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
thd_ = grpc_core::Thread(
"grpcpp_sync_server",
[](void* th) { static_cast<ThreadManager::WorkerThread*>(th)->Run(); },
this);
this, &created_);
if (!created_) {
gpr_log(GPR_ERROR, "Could not create grpc_sync_server worker-thread");
} else {
thd_.Start();
}
}
void ThreadManager::WorkerThread::Run() {
thd_mgr_->MainWorkLoop();
@ -177,7 +181,12 @@ void ThreadManager::MainWorkLoop() {
}
// Drop lock before spawning thread to avoid contention
lock.Unlock();
new WorkerThread(this);
WorkerThread* w = new WorkerThread(this);
if (!w->created()) {
num_pollers_--;
num_threads_--;
resource_exhausted = true;
}
} else if (num_pollers_ > 0) {
// There is still at least some thread polling, so we can go on
// even though we are below the number of pollers that we would

@ -124,6 +124,8 @@ class ThreadManager {
WorkerThread(ThreadManager* thd_mgr);
~WorkerThread();
bool created() const { return created_; }
private:
// Calls thd_mgr_->MainWorkLoop() and once that completes, calls
// thd_mgr_>MarkAsCompleted(this) to mark the thread as completed
@ -131,6 +133,7 @@ class ThreadManager {
ThreadManager* const thd_mgr_;
grpc_core::Thread thd_;
bool created_;
};
// The main function in ThreadManager

@ -39,6 +39,8 @@ namespace Grpc.Core
/// <summary>
/// Creates a new <c>RpcException</c> associated with given status and message.
/// NOTE: the exception message is not sent to the remote peer. Use <c>status.Details</c> to pass error
/// details to the peer.
/// </summary>
/// <param name="status">Resulting status of a call.</param>
/// <param name="message">The exception message.</param>
@ -57,6 +59,8 @@ namespace Grpc.Core
/// <summary>
/// Creates a new <c>RpcException</c> associated with given status, message and trailing response metadata.
/// NOTE: the exception message is not sent to the remote peer. Use <c>status.Details</c> to pass error
/// details to the peer.
/// </summary>
/// <param name="status">Resulting status of a call.</param>
/// <param name="trailers">Response trailing metadata.</param>

@ -41,15 +41,24 @@ Or to only print out individual `docker run` commands
$ ./src/php/bin/run_all_docker_images.sh --cmds
```
## `grpc-ext`
## Build and Run Specified Image
### `grpc-ext`
This image builds the full `grpc` PECL extension (effectively the current
release candidate), installs it against the current PHP version, and runs the
unit tests.
Build `grpc-ext` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/grpc-ext -f ./src/php/docker/grpc-ext/Dockerfile .
```
## `grpc-src`
Run image:
```sh
$ docker run -it --rm grpc-php/grpc-ext
```
### `grpc-src`
This image builds the `grpc` PECL extension in a 'thin' way, only containing
the gRPC extension source files. The gRPC C Core library is expected to be
@ -60,14 +69,34 @@ This also allows us to compile our `grpc` extension with some additional
configure options, like `--enable-tests`, which allows some additional unit
tests to be run.
Build `grpc-src` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/grpc-src -f ./src/php/docker/grpc-src/Dockerfile .
```
Run image:
```sh
$ docker run -it --rm grpc-php/grpc-src
```
## `alpine`
### `alpine`
This image builds the `grpc` extension against the current PHP version in an
Alpine-Linux base image.
Build `alpine` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/alpine -f ./src/php/docker/alpine/Dockerfile .
```
Run image:
```sh
$ docker run -it --rm grpc-php/alpine
```
## `php-src`
### `php-src`
Instead of using a general purpose base docker image provided by PHP, here we
compile PHP itself from
@ -75,28 +104,79 @@ compile PHP itself from
`configure` options, like `--enable-debug`. Then we proceed to build the full
`grpc` PECL extension and run the unit tests.
Build `php-src` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/php-src -f ./src/php/docker/php-src/Dockerfile .
```
Run image:
```sh
$ docker run -it --rm grpc-php/php-src
```
## `php-zts`
### `php-zts`
This image builds the `grpc` extension against the current PHP version with ZTS
enabled.
Build `php-zts` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/php-zts -f ./src/php/docker/php-zts/Dockerfile .
```
## `php-future`
Run image:
```sh
$ docker run -it --rm grpc-php/php-zts
```
### `php-future`
This image builds the `grpc` extension against the next future PHP version
currently in alpha, beta or release candidate stage.
Build `php-future` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/php-future -f ./src/php/docker/php-future/Dockerfile .
```
Run image:
```sh
$ docker run -it --rm grpc-php/php-future
```
## `php5`
### `php5`
This image builds the `grpc` extension against a PHP 5 base image with ZTS
enabled.
NOTE: PHP 5.x has reached the end-of-life state and is no longer supported.
Build `php5` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/php5 -f ./src/php/docker/php5/Dockerfile .
```
Run image:
```sh
$ docker run -it --rm grpc-php/php5
```
## `fork-support`
### `fork-support`
This image tests `pcntl_fork()` support and makes sure scripts using
`pcntl_fork()` don't hang or crash.
Build `grpc-ext` docker image:
```sh
$ cd grpc
$ docker build -t grpc-php/fork-support -f ./src/php/docker/fork-support/Dockerfile .
```
Run image:
```sh
$ docker run -it --rm grpc-php/fork-support
```

@ -10,8 +10,6 @@ pyx_library(
"_cygrpc/_hooks.pyx.pxi",
"_cygrpc/aio/call.pxd.pxi",
"_cygrpc/aio/call.pyx.pxi",
"_cygrpc/aio/rpc_error.pxd.pxi",
"_cygrpc/aio/rpc_error.pyx.pxi",
"_cygrpc/aio/callbackcontext.pxd.pxi",
"_cygrpc/aio/channel.pxd.pxi",
"_cygrpc/aio/channel.pyx.pxi",

@ -13,15 +13,15 @@
# limitations under the License.
cimport cpython
import grpc
_EMPTY_FLAGS = 0
_EMPTY_METADATA = None
_EMPTY_METADATA = ()
_OP_ARRAY_LENGTH = 6
cdef class _AioCall:
def __cinit__(self, AioChannel channel):
self._channel = channel
self._functor.functor_run = _AioCall.functor_run
@ -59,7 +59,7 @@ cdef class _AioCall:
else:
call._waiter_call.set_result(None)
async def unary_unary(self, method, request, timeout):
async def unary_unary(self, method, request):
cdef grpc_call * call
cdef grpc_slice method_slice
cdef grpc_op * ops
@ -72,7 +72,7 @@ cdef class _AioCall:
cdef Operation receive_status_on_client_operation
cdef grpc_call_error call_status
cdef gpr_timespec deadline = _timespec_from_time(timeout)
method_slice = grpc_slice_from_copied_buffer(
<const char *> method,
@ -86,7 +86,7 @@ cdef class _AioCall:
self._cq,
method_slice,
NULL,
deadline,
_timespec_from_time(None),
NULL
)
@ -146,12 +146,4 @@ cdef class _AioCall:
grpc_call_unref(call)
gpr_free(ops)
if receive_status_on_client_operation.code() == grpc._cygrpc.StatusCode.ok:
return receive_message_operation.message()
raise grpc.experimental.aio.AioRpcError(
receive_initial_metadata_operation.initial_metadata(),
receive_status_on_client_operation.code(),
receive_status_on_client_operation.details(),
receive_status_on_client_operation.trailing_metadata(),
)

@ -25,6 +25,6 @@ cdef class AioChannel:
def close(self):
grpc_channel_destroy(self.channel)
async def unary_unary(self, method, request, timeout):
async def unary_unary(self, method, request):
call = _AioCall(self)
return await call.unary_unary(method, request, timeout)
return await call.unary_unary(method, request)

@ -1,27 +0,0 @@
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Exceptions for the aio version of the RPC calls."""
cdef class _AioRpcError(Exception):
cdef readonly:
tuple _initial_metadata
int _code
str _details
tuple _trailing_metadata
cpdef tuple initial_metadata(self)
cpdef int code(self)
cpdef str details(self)
cpdef tuple trailing_metadata(self)

@ -1,35 +0,0 @@
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Exceptions for the aio version of the RPC calls."""
cdef class _AioRpcError(Exception):
def __cinit__(self, tuple initial_metadata, int code, str details, tuple trailing_metadata):
self._initial_metadata = initial_metadata
self._code = code
self._details = details
self._trailing_metadata = trailing_metadata
cpdef tuple initial_metadata(self):
return self._initial_metadata
cpdef int code(self):
return self._code
cpdef str details(self):
return self._details
cpdef tuple trailing_metadata(self):
return self._trailing_metadata

@ -63,7 +63,6 @@ include "_cygrpc/aio/iomgr/resolver.pyx.pxi"
include "_cygrpc/aio/grpc_aio.pyx.pxi"
include "_cygrpc/aio/call.pyx.pxi"
include "_cygrpc/aio/channel.pyx.pxi"
include "_cygrpc/aio/rpc_error.pyx.pxi"
#

@ -14,11 +14,8 @@
"""gRPC's Asynchronous Python API."""
import abc
import types
import six
import grpc
from grpc._cython import cygrpc
from grpc._cython.cygrpc import init_grpc_aio
@ -77,7 +74,6 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
@abc.abstractmethod
async def __call__(self,
request,
*,
timeout=None,
metadata=None,
credentials=None,
@ -125,25 +121,3 @@ def insecure_channel(target, options=None, compression=None):
from grpc.experimental.aio import _channel # pylint: disable=cyclic-import
return _channel.Channel(target, ()
if options is None else options, None, compression)
class _AioRpcError:
"""Private implementation of AioRpcError"""
class AioRpcError:
"""An RpcError to be used by the asynchronous API.
Parent classes: (cygrpc._AioRpcError, RpcError)
"""
# Dynamically registered as subclass of _AioRpcError and RpcError, because the former one is
# only available after the cython code has been compiled.
_class_built = _AioRpcError
def __new__(cls, *args, **kwargs):
if cls._class_built is _AioRpcError:
cls._class_built = types.new_class(
"AioRpcError", (cygrpc._AioRpcError, grpc.RpcError))
cls._class_built.__doc__ = cls.__doc__
return cls._class_built(*args, **kwargs)

@ -12,42 +12,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Invocation-side implementation of gRPC Asyncio Python."""
import asyncio
from typing import Callable, Optional
from grpc import _common
from grpc._cython import cygrpc
from grpc.experimental import aio
SerializingFunction = Callable[[str], bytes]
DeserializingFunction = Callable[[bytes], str]
class UnaryUnaryMultiCallable(aio.UnaryUnaryMultiCallable):
def __init__(self, channel: cygrpc.AioChannel, method: bytes,
request_serializer: SerializingFunction,
response_deserializer: DeserializingFunction) -> None:
def __init__(self, channel, method, request_serializer,
response_deserializer):
self._channel = channel
self._method = method
self._request_serializer = request_serializer
self._response_deserializer = response_deserializer
self._loop = asyncio.get_event_loop()
def _timeout_to_deadline(self, timeout: int) -> Optional[int]:
if timeout is None:
return None
return self._loop.time() + timeout
async def __call__(self,
request,
*,
timeout=None,
metadata=None,
credentials=None,
wait_for_ready=None,
compression=None):
if timeout:
raise NotImplementedError("TODO: timeout not implemented yet")
if metadata:
raise NotImplementedError("TODO: metadata not implemented yet")
@ -61,11 +51,9 @@ class UnaryUnaryMultiCallable(aio.UnaryUnaryMultiCallable):
if compression:
raise NotImplementedError("TODO: compression not implemented yet")
serialized_request = _common.serialize(request,
self._request_serializer)
timeout = self._timeout_to_deadline(timeout)
response = await self._channel.unary_unary(self._method,
serialized_request, timeout)
response = await self._channel.unary_unary(
self._method, _common.serialize(request, self._request_serializer))
return _common.deserialize(response, self._response_deserializer)

@ -387,6 +387,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
'src/core/ext/filters/client_channel/xds/xds_bootstrap.cc',
'src/core/ext/filters/client_channel/xds/xds_channel_secure.cc',
'src/core/ext/filters/client_channel/xds/xds_client.cc',
'src/core/ext/filters/client_channel/xds/xds_client_stats.cc',

@ -53,6 +53,8 @@ CLASSIFIERS = [
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'License :: OSI Approved :: Apache Software License',
]

@ -52,6 +52,8 @@ CLASSIFIERS = [
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'License :: OSI Approved :: Apache Software License',
]

@ -53,6 +53,8 @@ CLASSIFIERS = [
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'License :: OSI Approved :: Apache Software License',
]

@ -53,6 +53,7 @@ CLASSIFIERS = [
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'License :: OSI Approved :: Apache Software License',
]

@ -1,6 +1,5 @@
[
"_sanity._sanity_test.AioSanityTest",
"unit.channel_test.TestChannel",
"unit.init_test.TestAioRpcError",
"unit.init_test.TestInsecureChannel"
]

@ -15,12 +15,9 @@
import logging
import unittest
import grpc
from grpc.experimental import aio
from tests_aio.unit import test_base
from src.proto.grpc.testing import messages_pb2
from tests.unit.framework.common import test_constants
class TestChannel(test_base.AioTestBase):
@ -55,36 +52,6 @@ class TestChannel(test_base.AioTestBase):
self.loop.run_until_complete(coro())
def test_unary_call_times_out(self):
async def coro():
async with aio.insecure_channel(self.server_target) as channel:
empty_call_with_sleep = channel.unary_unary(
"/grpc.testing.TestService/EmptyCall",
request_serializer=messages_pb2.SimpleRequest.
SerializeToString,
response_deserializer=messages_pb2.SimpleResponse.
FromString,
)
timeout = test_constants.SHORT_TIMEOUT / 2
# TODO: Update once the async server is ready, change the synchronization mechanism by removing the
# sleep(<timeout>) as both components (client & server) will be on the same process.
with self.assertRaises(grpc.RpcError) as exception_context:
await empty_call_with_sleep(
messages_pb2.SimpleRequest(), timeout=timeout)
status_code, details = grpc.StatusCode.DEADLINE_EXCEEDED.value
self.assertEqual(exception_context.exception.code(),
status_code)
self.assertEqual(exception_context.exception.details(),
details.title())
self.assertIsNotNone(
exception_context.exception.initial_metadata())
self.assertIsNotNone(
exception_context.exception.trailing_metadata())
self.loop.run_until_complete(coro())
if __name__ == '__main__':
logging.basicConfig()

@ -15,50 +15,10 @@
import logging
import unittest
import grpc
from grpc.experimental import aio
from tests_aio.unit import test_base
class TestAioRpcError(unittest.TestCase):
_TEST_INITIAL_METADATA = ("initial metadata",)
_TEST_TRAILING_METADATA = ("trailing metadata",)
def test_attributes(self):
aio_rpc_error = aio.AioRpcError(self._TEST_INITIAL_METADATA, 0,
"details", self._TEST_TRAILING_METADATA)
self.assertEqual(aio_rpc_error.initial_metadata(),
self._TEST_INITIAL_METADATA)
self.assertEqual(aio_rpc_error.code(), 0)
self.assertEqual(aio_rpc_error.details(), "details")
self.assertEqual(aio_rpc_error.trailing_metadata(),
self._TEST_TRAILING_METADATA)
def test_class_hierarchy(self):
aio_rpc_error = aio.AioRpcError(self._TEST_INITIAL_METADATA, 0,
"details", self._TEST_TRAILING_METADATA)
self.assertIsInstance(aio_rpc_error, grpc.RpcError)
def test_class_attributes(self):
aio_rpc_error = aio.AioRpcError(self._TEST_INITIAL_METADATA, 0,
"details", self._TEST_TRAILING_METADATA)
self.assertEqual(aio_rpc_error.__class__.__name__, "AioRpcError")
self.assertEqual(aio_rpc_error.__class__.__doc__,
aio.AioRpcError.__doc__)
def test_class_singleton(self):
first_aio_rpc_error = aio.AioRpcError(self._TEST_INITIAL_METADATA, 0,
"details",
self._TEST_TRAILING_METADATA)
second_aio_rpc_error = aio.AioRpcError(self._TEST_INITIAL_METADATA, 0,
"details",
self._TEST_TRAILING_METADATA)
self.assertIs(first_aio_rpc_error.__class__,
second_aio_rpc_error.__class__)
class TestInsecureChannel(test_base.AioTestBase):
def test_insecure_channel(self):

@ -20,7 +20,6 @@ from time import sleep
import grpc
from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import test_pb2_grpc
from tests.unit.framework.common import test_constants
# TODO (https://github.com/grpc/grpc/issues/19762)
@ -30,10 +29,6 @@ class TestServiceServicer(test_pb2_grpc.TestServiceServicer):
def UnaryCall(self, request, context):
return messages_pb2.SimpleResponse()
def EmptyCall(self, request, context):
while True:
sleep(test_constants.LONG_TIMEOUT)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Synchronous gRPC server.')

@ -604,7 +604,7 @@
"gRPC"
"high performance general RPC framework"
"<%text>${gRPC_CORE_VERSION}</%text>"
"gpr"
"gpr openssl"
"-lgrpc -laddress_sorting -lcares -lz"
""
"grpc.pc")

@ -2,7 +2,7 @@
# Bazel installation
# Must be in sync with tools/bazel
ENV BAZEL_VERSION 1.0.0
ENV BAZEL_VERSION 0.29.1
# The correct bazel version is already preinstalled, no need to use //tools/bazel wrapper.
ENV DISABLE_BAZEL_WRAPPER 1

@ -57,7 +57,7 @@ static void thd_func(void* arg) {
}
/* Sets the done_write event */
static void set_done_write(void* arg, grpc_error* error) {
static void set_done_write(void* arg, grpc_error* /*error*/) {
gpr_event* done_write = static_cast<gpr_event*>(arg);
gpr_event_set(done_write, (void*)1);
}
@ -70,7 +70,7 @@ static void server_setup_transport(void* ts, grpc_transport* transport) {
}
/* Sets the read_done event */
static void set_read_done(void* arg, grpc_error* error) {
static void set_read_done(void* arg, grpc_error* /*error*/) {
gpr_event* read_done = static_cast<gpr_event*>(arg);
gpr_event_set(read_done, (void*)1);
}
@ -252,7 +252,7 @@ void grpc_run_bad_client_test(
}
bool client_connection_preface_validator(grpc_slice_buffer* incoming,
void* arg) {
void* /*arg*/) {
if (incoming->count < 1) {
return false;
}
@ -278,7 +278,7 @@ grpc_bad_client_arg connection_preface_arg = {
client_connection_preface_validator, nullptr,
CONNECTION_PREFACE_FROM_CLIENT, sizeof(CONNECTION_PREFACE_FROM_CLIENT) - 1};
bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* arg) {
bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* /*arg*/) {
// Get last frame from incoming slice buffer.
grpc_slice_buffer last_frame_buffer;
grpc_slice_buffer_init(&last_frame_buffer);
@ -311,7 +311,7 @@ static void* tag(intptr_t t) { return (void*)t; }
void server_verifier_request_call(grpc_server* server,
grpc_completion_queue* cq,
void* registered_method) {
void* /*registered_method*/) {
grpc_call_error error;
grpc_call* s;
grpc_call_details call_details;

@ -75,7 +75,7 @@
namespace {
void verifier(grpc_server* server, grpc_completion_queue* cq,
void* registered_method) {
void* /*registered_method*/) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(
cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)

@ -30,7 +30,7 @@
"\x00\x00\x00\x04\x00\x00\x00\x00\x00" /* settings frame */
static void verifier(grpc_server* server, grpc_completion_queue* cq,
void* registered_method) {
void* /*registered_method*/) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(
cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)

@ -20,7 +20,7 @@
#include "test/core/bad_client/bad_client.h"
static void verifier(grpc_server* server, grpc_completion_queue* cq,
void* registered_method) {
void* /*registered_method*/) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(
cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)

@ -52,7 +52,7 @@
static void* tag(intptr_t t) { return (void*)t; }
static void verifier(grpc_server* server, grpc_completion_queue* cq,
void* registered_method) {
void* /*registered_method*/) {
grpc_call_error error;
grpc_call* s;
grpc_call_details call_details;

@ -24,7 +24,7 @@
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
static void verifier(grpc_server* server, grpc_completion_queue* cq,
void* registered_method) {
void* /*registered_method*/) {
while (grpc_server_has_open_connections(server)) {
GPR_ASSERT(grpc_completion_queue_next(
cq, grpc_timeout_milliseconds_to_deadline(20), nullptr)

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

Loading…
Cancel
Save