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

reviewable/pr15343/r22
ncteisen 7 years ago
commit 68d4f50f77
  1. 42
      BUILD
  2. 45
      CMakeLists.txt
  3. 47
      Makefile
  4. 3
      bazel/grpc_build_system.bzl
  5. 41
      bazel/grpc_deps.bzl
  6. 27
      build.yaml
  7. 5
      config.m4
  8. 8
      config.w32
  9. 3
      gRPC-Core.podspec
  10. 3
      grpc.gemspec
  11. 7
      grpc.gyp
  12. 31
      include/grpc/grpc_security.h
  13. 41
      include/grpcpp/opencensus.h
  14. 3
      package.xml
  15. 835
      src/core/ext/filters/client_channel/client_channel.cc
  16. 311
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
  17. 36
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  18. 292
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  19. 28
      src/core/ext/filters/deadline/deadline_filter.cc
  20. 10
      src/core/ext/filters/deadline/deadline_filter.h
  21. 19
      src/core/ext/filters/http/client/http_client_filter.cc
  22. 35
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  23. 19
      src/core/ext/transport/cronet/transport/cronet_transport.cc
  24. 52
      src/core/ext/transport/inproc/inproc_transport.cc
  25. 9
      src/core/lib/channel/connected_channel.cc
  26. 2
      src/core/lib/gprpp/inlined_vector.h
  27. 80
      src/core/lib/iomgr/call_combiner.h
  28. 5
      src/core/lib/iomgr/closure.h
  29. 3
      src/core/lib/security/credentials/google_default/google_default_credentials.cc
  30. 20
      src/core/lib/security/credentials/ssl/ssl_credentials.cc
  31. 33
      src/core/lib/security/security_connector/security_connector.cc
  32. 1
      src/core/lib/security/security_connector/security_connector.h
  33. 74
      src/core/lib/surface/call.cc
  34. 29
      src/core/lib/transport/transport.cc
  35. 22
      src/core/lib/transport/transport.h
  36. 7
      src/core/lib/transport/transport_op_string.cc
  37. 3
      src/cpp/client/secure_credentials.cc
  38. 19
      src/cpp/ext/filters/census/channel_filter.cc
  39. 27
      src/cpp/ext/filters/census/channel_filter.h
  40. 163
      src/cpp/ext/filters/census/client_filter.cc
  41. 104
      src/cpp/ext/filters/census/client_filter.h
  42. 132
      src/cpp/ext/filters/census/context.cc
  43. 126
      src/cpp/ext/filters/census/context.h
  44. 0
      src/cpp/ext/filters/census/grpc_context.cc
  45. 130
      src/cpp/ext/filters/census/grpc_plugin.cc
  46. 111
      src/cpp/ext/filters/census/grpc_plugin.h
  47. 129
      src/cpp/ext/filters/census/measures.cc
  48. 46
      src/cpp/ext/filters/census/measures.h
  49. 39
      src/cpp/ext/filters/census/rpc_encoding.cc
  50. 284
      src/cpp/ext/filters/census/rpc_encoding.h
  51. 198
      src/cpp/ext/filters/census/server_filter.cc
  52. 101
      src/cpp/ext/filters/census/server_filter.h
  53. 491
      src/cpp/ext/filters/census/views.cc
  54. 1
      src/csharp/Grpc.Core/Interceptors/CallInvokerExtensions.cs
  55. 1
      src/csharp/Grpc.Core/Interceptors/ChannelExtensions.cs
  56. 1
      src/csharp/Grpc.Core/Interceptors/ClientInterceptorContext.cs
  57. 1
      src/csharp/Grpc.Core/Interceptors/Interceptor.cs
  58. 3
      src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs
  59. 2
      src/csharp/Grpc.Core/Server.cs
  60. 5
      src/csharp/ext/grpc_csharp_ext.c
  61. 4
      src/objective-c/GRPCClient/private/GRPCHost.m
  62. 2
      src/php/ext/grpc/channel_credentials.c
  63. 3
      src/proto/census/census.options
  64. 307
      src/proto/census/census.proto
  65. 0
      src/proto/census/trace_context.options
  66. 29
      src/proto/census/trace_context.proto
  67. 4
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
  68. 7
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  69. 3
      src/python/grpcio/grpc_core_dependencies.py
  70. 54
      src/ruby/end2end/package_with_underscore_checker.rb
  71. 0
      src/ruby/end2end/protos/package_with_underscore/data.proto
  72. 0
      src/ruby/end2end/protos/package_with_underscore/service.proto
  73. 6
      src/ruby/ext/grpc/rb_channel_credentials.c
  74. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  75. 2
      src/ruby/spec/call_credentials_spec.rb
  76. 2
      src/ruby/spec/call_spec.rb
  77. 2
      src/ruby/spec/channel_credentials_spec.rb
  78. 2
      src/ruby/spec/channel_spec.rb
  79. 2
      src/ruby/spec/client_auth_spec.rb
  80. 2
      src/ruby/spec/client_server_spec.rb
  81. 2
      src/ruby/spec/compression_options_spec.rb
  82. 2
      src/ruby/spec/error_sanity_spec.rb
  83. 2
      src/ruby/spec/generic/client_stub_spec.rb
  84. 2
      src/ruby/spec/generic/rpc_desc_spec.rb
  85. 2
      src/ruby/spec/generic/rpc_server_pool_spec.rb
  86. 2
      src/ruby/spec/generic/service_spec.rb
  87. 2
      src/ruby/spec/google_rpc_status_utils_spec.rb
  88. 1
      src/ruby/spec/pb/duplicate/codegen_spec.rb
  89. 2
      src/ruby/spec/pb/health/checker_spec.rb
  90. 51
      src/ruby/spec/pb/package_with_underscore/checker_spec.rb
  91. 2
      src/ruby/spec/server_credentials_spec.rb
  92. 2
      src/ruby/spec/server_spec.rb
  93. 1
      src/ruby/spec/spec_helper.rb
  94. 2
      src/ruby/spec/support/services.rb
  95. 2
      src/ruby/spec/time_consts_spec.rb
  96. 1
      templates/grpc.gyp.template
  97. 1
      templates/tools/dockerfile/apt_get_basic.include
  98. 2
      templates/tools/dockerfile/python_deps.include
  99. 2
      test/core/bad_ssl/bad_ssl_test.cc
  100. 1
      test/core/channel/BUILD
  101. Some files were not shown because too many files have changed in this diff Show More

42
BUILD

@ -485,10 +485,7 @@ grpc_cc_library(
grpc_cc_library(
name = "census",
srcs = [
"src/core/ext/census/grpc_context.cc",
],
external_deps = [
"nanopb",
"src/cpp/ext/filters/census/grpc_context.cc",
],
language = "c++",
public_hdrs = [
@ -1335,6 +1332,7 @@ grpc_cc_library(
name = "grpc_resolver_dns_ares",
srcs = [
"src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc",
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc",
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc",
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc",
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc",
@ -1991,4 +1989,40 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_opencensus_plugin",
srcs = [
"src/cpp/ext/filters/census/client_filter.cc",
"src/cpp/ext/filters/census/server_filter.cc",
"src/cpp/ext/filters/census/channel_filter.cc",
"src/cpp/ext/filters/census/context.cc",
"src/cpp/ext/filters/census/grpc_context.cc",
"src/cpp/ext/filters/census/grpc_plugin.cc",
"src/cpp/ext/filters/census/measures.cc",
"src/cpp/ext/filters/census/rpc_encoding.cc",
"src/cpp/ext/filters/census/views.cc",
],
hdrs = [
"include/grpcpp/opencensus.h",
"src/cpp/ext/filters/census/client_filter.h",
"src/cpp/ext/filters/census/server_filter.h",
"src/cpp/ext/filters/census/channel_filter.h",
"src/cpp/ext/filters/census/context.h",
"src/cpp/ext/filters/census/grpc_plugin.h",
"src/cpp/ext/filters/census/measures.h",
"src/cpp/ext/filters/census/rpc_encoding.h",
],
language = "c++",
external_deps = [
"absl-base",
"absl-time",
"opencensus-trace",
"opencensus-stats",
],
deps = [
":census",
":grpc++",
],
)
grpc_generate_one_off_targets()

@ -309,6 +309,9 @@ endif()
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c handshake_server_with_readahead_handshaker)
endif()
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c handshake_verify_peer_options)
endif()
add_dependencies(buildtests_c histogram_test)
add_dependencies(buildtests_c hpack_parser_test)
add_dependencies(buildtests_c hpack_table_test)
@ -1215,6 +1218,7 @@ add_library(grpc
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/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
@ -1222,7 +1226,7 @@ add_library(grpc
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
src/core/ext/census/grpc_context.cc
src/cpp/ext/filters/census/grpc_context.cc
src/core/ext/filters/max_age/max_age_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
src/core/ext/filters/http/client_authority_filter.cc
@ -2509,6 +2513,7 @@ add_library(grpc_unsecure
src/core/ext/transport/inproc/inproc_plugin.cc
src/core/ext/transport/inproc/inproc_transport.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
@ -2528,7 +2533,7 @@ add_library(grpc_unsecure
third_party/nanopb/pb_encode.c
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/census/grpc_context.cc
src/cpp/ext/filters/census/grpc_context.cc
src/core/ext/filters/max_age/max_age_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
src/core/ext/filters/http/client_authority_filter.cc
@ -3312,10 +3317,7 @@ add_library(grpc++_cronet
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc
src/core/ext/transport/chttp2/server/chttp2_server.cc
src/core/ext/census/grpc_context.cc
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
third_party/nanopb/pb_encode.c
src/cpp/ext/filters/census/grpc_context.cc
)
if(WIN32 AND MSVC)
@ -7498,6 +7500,37 @@ target_link_libraries(handshake_server_with_readahead_handshaker
gpr
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX)
add_executable(handshake_verify_peer_options
test/core/handshake/verify_peer_options.cc
)
target_include_directories(handshake_verify_peer_options
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
)
target_link_libraries(handshake_verify_peer_options
${_gRPC_SSL_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)

@ -1012,6 +1012,7 @@ grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
handshake_client: $(BINDIR)/$(CONFIG)/handshake_client
handshake_server: $(BINDIR)/$(CONFIG)/handshake_server
handshake_server_with_readahead_handshaker: $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker
handshake_verify_peer_options: $(BINDIR)/$(CONFIG)/handshake_verify_peer_options
histogram_test: $(BINDIR)/$(CONFIG)/histogram_test
hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
@ -1455,6 +1456,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/handshake_client \
$(BINDIR)/$(CONFIG)/handshake_server \
$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker \
$(BINDIR)/$(CONFIG)/handshake_verify_peer_options \
$(BINDIR)/$(CONFIG)/histogram_test \
$(BINDIR)/$(CONFIG)/hpack_parser_test \
$(BINDIR)/$(CONFIG)/hpack_table_test \
@ -2012,6 +2014,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/handshake_server || ( echo test handshake_server failed ; exit 1 )
$(E) "[RUN] Testing handshake_server_with_readahead_handshaker"
$(Q) $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker || ( echo test handshake_server_with_readahead_handshaker failed ; exit 1 )
$(E) "[RUN] Testing handshake_verify_peer_options"
$(Q) $(BINDIR)/$(CONFIG)/handshake_verify_peer_options || ( echo test handshake_verify_peer_options failed ; exit 1 )
$(E) "[RUN] Testing histogram_test"
$(Q) $(BINDIR)/$(CONFIG)/histogram_test || ( echo test histogram_test failed ; exit 1 )
$(E) "[RUN] Testing hpack_parser_test"
@ -3594,6 +3598,7 @@ LIBGRPC_SRC = \
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/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \
@ -3601,7 +3606,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
src/core/ext/census/grpc_context.cc \
src/cpp/ext/filters/census/grpc_context.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
src/core/ext/filters/http/client_authority_filter.cc \
@ -4854,6 +4859,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/transport/inproc/inproc_plugin.cc \
src/core/ext/transport/inproc/inproc_transport.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \
@ -4873,7 +4879,7 @@ LIBGRPC_UNSECURE_SRC = \
third_party/nanopb/pb_encode.c \
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/census/grpc_context.cc \
src/cpp/ext/filters/census/grpc_context.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
src/core/ext/filters/http/client_authority_filter.cc \
@ -5645,10 +5651,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc \
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc \
src/core/ext/transport/chttp2/server/chttp2_server.cc \
src/core/ext/census/grpc_context.cc \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
src/cpp/ext/filters/census/grpc_context.cc \
PUBLIC_HEADERS_CXX += \
include/grpc++/alarm.h \
@ -12483,6 +12486,38 @@ endif
endif
HANDSHAKE_VERIFY_PEER_OPTIONS_SRC = \
test/core/handshake/verify_peer_options.cc \
HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_VERIFY_PEER_OPTIONS_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/handshake_verify_peer_options: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/handshake_verify_peer_options: $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/handshake_verify_peer_options
endif
$(OBJDIR)/$(CONFIG)/test/core/handshake/verify_peer_options.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_handshake_verify_peer_options: $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS:.o=.dep)
endif
endif
HISTOGRAM_TEST_SRC = \
test/core/util/histogram_test.cc \

@ -60,7 +60,7 @@ def _maybe_update_cc_library_hdrs(hdrs):
def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
external_deps = [], deps = [], standalone = False,
language = "C++", testonly = False, visibility = None,
alwayslink = 0):
alwayslink = 0, data = []):
copts = []
if language.upper() == "C":
copts = if_not_windows(["-std=c99"])
@ -85,6 +85,7 @@ def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
"include"
],
alwayslink = alwayslink,
data = data,
)
def grpc_proto_plugin(name, srcs = [], deps = []):

@ -8,6 +8,16 @@ def grpc_deps():
actual = "@com_github_nanopb_nanopb//:nanopb",
)
native.bind(
name = "absl-base",
actual = "@com_google_absl//absl/base",
)
native.bind(
name = "absl-time",
actual = "@com_google_absl//absl/time:time",
)
native.bind(
name = "libssl",
actual = "@boringssl//:ssl",
@ -73,6 +83,21 @@ def grpc_deps():
actual = "@com_github_grpc_grpc//:grpc++_codegen_proto",
)
native.bind(
name = "opencensus-trace",
actual = "@io_opencensus_cpp//opencensus/trace:trace"
)
native.bind(
name = "opencensus-stats",
actual = "@io_opencensus_cpp//opencensus/stats:stats"
)
native.bind(
name = "opencensus-stats-test",
actual = "@io_opencensus_cpp//opencensus/stats:test_utils"
)
if "boringssl" not in native.existing_rules():
native.http_archive(
name = "boringssl",
@ -122,8 +147,8 @@ def grpc_deps():
native.new_http_archive(
name = "com_github_google_benchmark",
build_file = "@com_github_grpc_grpc//third_party:benchmark.BUILD",
strip_prefix = "benchmark-5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8",
url = "https://github.com/google/benchmark/archive/5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8.tar.gz",
strip_prefix = "benchmark-9913418d323e64a0111ca0da81388260c2bbe1e9",
url = "https://github.com/google/benchmark/archive/9913418d323e64a0111ca0da81388260c2bbe1e9.tar.gz",
)
if "com_github_cares_cares" not in native.existing_rules():
@ -137,8 +162,8 @@ def grpc_deps():
if "com_google_absl" not in native.existing_rules():
native.http_archive(
name = "com_google_absl",
strip_prefix = "abseil-cpp-cc4bed2d74f7c8717e31f9579214ab52a9c9c610",
url = "https://github.com/abseil/abseil-cpp/archive/cc4bed2d74f7c8717e31f9579214ab52a9c9c610.tar.gz",
strip_prefix = "abseil-cpp-cd95e71df6eaf8f2a282b1da556c2cf1c9b09207",
url = "https://github.com/abseil/abseil-cpp/archive/cd95e71df6eaf8f2a282b1da556c2cf1c9b09207.tar.gz",
)
if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules():
@ -152,6 +177,14 @@ def grpc_deps():
sha256 = "1c4a532b396c698e6467a1548554571cb85fa091e472b05e398ebc836c315d77",
)
if "io_opencensus_cpp" not in native.existing_rules():
native.http_archive(
name = "io_opencensus_cpp",
strip_prefix = "opencensus-cpp-fdf0f308b1631bb4a942e32ba5d22536a6170274",
url = "https://github.com/census-instrumentation/opencensus-cpp/archive/fdf0f308b1631bb4a942e32ba5d22536a6170274.tar.gz",
)
# TODO: move some dependencies from "grpc_deps" here?
def grpc_test_only_deps():
"""Internal, not intended for use by packages that are consuming grpc.

@ -100,10 +100,9 @@ filegroups:
public_headers:
- include/grpc/census.h
src:
- src/core/ext/census/grpc_context.cc
- src/cpp/ext/filters/census/grpc_context.cc
uses:
- grpc_base
- nanopb
- name: cmdline
headers:
- test/core/util/cmdline.h
@ -727,6 +726,7 @@ filegroups:
- src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
src:
- src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
- src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
- src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
- src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
- src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
@ -2794,6 +2794,21 @@ targets:
platforms:
- linux
secure: true
- name: handshake_verify_peer_options
build: test
language: c
src:
- test/core/handshake/verify_peer_options.cc
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
exclude_iomgrs:
- uv
platforms:
- linux
secure: true
- name: histogram_test
build: test
language: c
@ -5512,7 +5527,7 @@ configs:
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
LSAN_OPTIONS: suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
asan-noleaks:
CC: clang
CPPFLAGS: -O0 -fsanitize-coverage=edge,trace-pc-guard -fsanitize=address -fno-omit-frame-pointer
@ -5536,7 +5551,7 @@ configs:
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
LSAN_OPTIONS: suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
basicprof:
CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
DEFINES: NDEBUG
@ -5610,7 +5625,7 @@ configs:
LDXX: clang++
compile_the_world: true
test_environ:
TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
TSAN_OPTIONS: suppressions=test/core/util/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
ubsan:
CC: clang
CPPFLAGS: -O0 -fsanitize-coverage=edge,trace-pc-guard -fsanitize=undefined -fno-omit-frame-pointer
@ -5622,7 +5637,7 @@ configs:
LDXX: clang++
compile_the_world: true
test_environ:
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=test/core/util/ubsan_suppressions.txt
defaults:
ares:
CFLAGS: -Wno-sign-conversion $(if $(subst Darwin,,$(SYSTEM)),,-Wno-shorten-64-to-32)

@ -371,6 +371,7 @@ if test "$PHP_GRPC" != "no"; then
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/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \
@ -378,7 +379,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
src/core/ext/census/grpc_context.cc \
src/cpp/ext/filters/census/grpc_context.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
src/core/ext/filters/http/client_authority_filter.cc \
@ -649,7 +650,6 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1)
@ -712,6 +712,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/handshaker)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/zero_copy_frame_protector)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/ssl/session_cache)
PHP_ADD_BUILD_DIR($ext_builddir/src/cpp/ext/filters/census)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/address_sorting)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1)

@ -347,6 +347,7 @@ if (PHP_GRPC != "no") {
"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\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_fallback.cc " +
@ -354,7 +355,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr\\sockaddr_resolver.cc " +
"src\\core\\ext\\filters\\load_reporting\\server_load_reporting_filter.cc " +
"src\\core\\ext\\filters\\load_reporting\\server_load_reporting_plugin.cc " +
"src\\core\\ext\\census\\grpc_context.cc " +
"src\\cpp\\ext\\filters\\census\\grpc_context.cc " +
"src\\core\\ext\\filters\\max_age\\max_age_filter.cc " +
"src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
"src\\core\\ext\\filters\\http\\client_authority_filter.cc " +
@ -653,7 +654,6 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\boringssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\census");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy");
@ -729,6 +729,10 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\zero_copy_frame_protector");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\ssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\ssl\\session_cache");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp\\ext\\filters");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp\\ext\\filters\\census");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext\\grpc");

@ -787,6 +787,7 @@ Pod::Spec.new do |s|
'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/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc',
@ -794,7 +795,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
'src/core/ext/census/grpc_context.cc',
'src/cpp/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
'src/core/ext/filters/http/client_authority_filter.cc',

@ -727,6 +727,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc )
@ -734,7 +735,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc )
s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_filter.cc )
s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc )
s.files += %w( src/core/ext/census/grpc_context.cc )
s.files += %w( src/cpp/ext/filters/census/grpc_context.cc )
s.files += %w( src/core/ext/filters/max_age/max_age_filter.cc )
s.files += %w( src/core/ext/filters/message_size/message_size_filter.cc )
s.files += %w( src/core/ext/filters/http/client_authority_filter.cc )

@ -77,6 +77,7 @@
'.',
'../..',
'include',
'../../third_party/nanopb',
],
'defines': [
'GRPC_ARES=0',
@ -537,6 +538,7 @@
'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/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc',
@ -544,7 +546,7 @@
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
'src/core/ext/census/grpc_context.cc',
'src/cpp/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
'src/core/ext/filters/http/client_authority_filter.cc',
@ -1250,6 +1252,7 @@
'src/core/ext/transport/inproc/inproc_plugin.cc',
'src/core/ext/transport/inproc/inproc_transport.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc',
@ -1269,7 +1272,7 @@
'third_party/nanopb/pb_encode.c',
'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/census/grpc_context.cc',
'src/cpp/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
'src/core/ext/filters/http/client_authority_filter.cc',

@ -163,6 +163,26 @@ typedef struct {
const char* cert_chain;
} grpc_ssl_pem_key_cert_pair;
/** Object that holds additional peer-verification options on a secure
channel. */
typedef struct {
/** If non-NULL this callback will be invoked with the expected
target_name, the peer's certificate (in PEM format), and whatever
userdata pointer is set below. If a non-zero value is returned by this
callback then it is treated as a verification failure. Invocation of
the callback is blocking, so any implementation should be light-weight.
*/
int (*verify_peer_callback)(const char* target_name, const char* peer_pem,
void* userdata);
/** Arbitrary userdata that will be passed as the last argument to
verify_peer_callback. */
void* verify_peer_callback_userdata;
/** A destruct callback that will be invoked when the channel is being
cleaned up. The userdata argument will be passed to it. The intent is
to perform any cleanup associated with that userdata. */
void (*verify_peer_destruct)(void* userdata);
} verify_peer_options;
/** Creates an SSL credentials object.
- pem_root_certs is the NULL-terminated string containing the PEM encoding
of the server root certificates. If this parameter is NULL, the
@ -173,10 +193,17 @@ typedef struct {
disk (in the grpc install directory).
- pem_key_cert_pair is a pointer on the object containing client's private
key and certificate chain. This parameter can be NULL if the client does
not have such a key/cert pair. */
not have such a key/cert pair.
- verify_options is an optional verify_peer_options object which holds
additional options controlling how peer certificates are verified. For
example, you can supply a callback which receives the peer's certificate
with which you can do additional verification. Can be NULL, in which
case verification will retain default behavior. Any settings in
verify_options are copied during this call, so the verify_options
object can be released afterwards. */
GRPCAPI grpc_channel_credentials* grpc_ssl_credentials_create(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
void* reserved);
const verify_peer_options* verify_options, void* reserved);
/** --- grpc_call_credentials object.

@ -0,0 +1,41 @@
/*
*
* Copyright 2018 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 GRPCPP_OPENCENSUS_H
#define GRPCPP_OPENCENSUS_H
namespace grpc {
// These symbols in this file will not be included in the binary unless
// grpc_opencensus_plugin build target was added as a dependency. At the moment
// it is only setup to be built with Bazel.
// Registers the OpenCensus plugin with gRPC, so that it will be used for future
// RPCs. This must be called before any views are created.
void RegisterOpenCensusPlugin();
// RPC stats definitions, defined by
// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md
// Registers the cumulative gRPC views so that they will be exported by any
// registered stats exporter. For on-task stats, construct a View using the
// ViewDescriptors below.
void RegisterOpenCensusViewsForExport();
} // namespace grpc
#endif // GRPCPP_OPENCENSUS_H

@ -732,6 +732,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc" role="src" />
@ -739,7 +740,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_context.cc" role="src" />
<file baseinstalldir="/" name="src/cpp/ext/filters/census/grpc_context.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.cc" role="src" />

File diff suppressed because it is too large Load Diff

@ -0,0 +1,311 @@
/*
*
* Copyright 2016 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/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER)
#include <ares.h>
#include <string.h>
#include <sys/ioctl.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
typedef struct fd_node {
/** the owner of this fd node */
grpc_ares_ev_driver* ev_driver;
/** a closure wrapping on_readable_locked, which should be
invoked when the grpc_fd in this node becomes readable. */
grpc_closure read_closure;
/** a closure wrapping on_writable_locked, which should be
invoked when the grpc_fd in this node becomes writable. */
grpc_closure write_closure;
/** next fd node in the list */
struct fd_node* next;
/** wrapped fd that's polled by grpc's poller for the current platform */
grpc_core::GrpcPolledFd* grpc_polled_fd;
/** if the readable closure has been registered */
bool readable_registered;
/** if the writable closure has been registered */
bool writable_registered;
/** if the fd has been shutdown yet from grpc iomgr perspective */
bool already_shutdown;
} fd_node;
struct grpc_ares_ev_driver {
/** the ares_channel owned by this event driver */
ares_channel channel;
/** pollset set for driving the IO events of the channel */
grpc_pollset_set* pollset_set;
/** refcount of the event driver */
gpr_refcount refs;
/** combiner to synchronize c-ares and I/O callbacks on */
grpc_combiner* combiner;
/** a list of grpc_fd that this event driver is currently using. */
fd_node* fds;
/** is this event driver currently working? */
bool working;
/** is this event driver being shut down */
bool shutting_down;
};
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
static grpc_ares_ev_driver* grpc_ares_ev_driver_ref(
grpc_ares_ev_driver* ev_driver) {
gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
gpr_ref(&ev_driver->refs);
return ev_driver;
}
static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
if (gpr_unref(&ev_driver->refs)) {
gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
GPR_ASSERT(ev_driver->fds == nullptr);
GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
ares_destroy(ev_driver->channel);
gpr_free(ev_driver);
}
}
static void fd_node_destroy_locked(fd_node* fdn) {
gpr_log(GPR_DEBUG, "delete fd: %s", fdn->grpc_polled_fd->GetName());
GPR_ASSERT(!fdn->readable_registered);
GPR_ASSERT(!fdn->writable_registered);
GPR_ASSERT(fdn->already_shutdown);
grpc_core::Delete(fdn->grpc_polled_fd);
gpr_free(fdn);
}
static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) {
if (!fdn->already_shutdown) {
fdn->already_shutdown = true;
fdn->grpc_polled_fd->ShutdownLocked(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(reason));
}
}
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
grpc_combiner* combiner) {
*ev_driver = static_cast<grpc_ares_ev_driver*>(
gpr_malloc(sizeof(grpc_ares_ev_driver)));
ares_options opts;
memset(&opts, 0, sizeof(opts));
opts.flags |= ARES_FLAG_STAYOPEN;
int status = ares_init_options(&(*ev_driver)->channel, &opts, ARES_OPT_FLAGS);
grpc_core::ConfigureAresChannelLocked(&(*ev_driver)->channel);
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create_locked");
if (status != ARES_SUCCESS) {
char* err_msg;
gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s",
ares_strerror(status));
grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg);
gpr_free(err_msg);
gpr_free(*ev_driver);
return err;
}
(*ev_driver)->combiner = GRPC_COMBINER_REF(combiner, "ares event driver");
gpr_ref_init(&(*ev_driver)->refs, 1);
(*ev_driver)->pollset_set = pollset_set;
(*ev_driver)->fds = nullptr;
(*ev_driver)->working = false;
(*ev_driver)->shutting_down = false;
return GRPC_ERROR_NONE;
}
void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver) {
// We mark the event driver as being shut down. If the event driver
// is working, grpc_ares_notify_on_event_locked will shut down the
// fds; if it's not working, there are no fds to shut down.
ev_driver->shutting_down = true;
grpc_ares_ev_driver_unref(ev_driver);
}
void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) {
ev_driver->shutting_down = true;
fd_node* fn = ev_driver->fds;
while (fn != nullptr) {
fd_node_shutdown_locked(fn, "grpc_ares_ev_driver_shutdown");
fn = fn->next;
}
}
// Search fd in the fd_node list head. This is an O(n) search, the max possible
// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) {
fd_node dummy_head;
dummy_head.next = *head;
fd_node* node = &dummy_head;
while (node->next != nullptr) {
if (node->next->grpc_polled_fd->GetWrappedAresSocketLocked() == as) {
fd_node* ret = node->next;
node->next = node->next->next;
*head = dummy_head.next;
return ret;
}
node = node->next;
}
return nullptr;
}
static void on_readable_locked(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
fdn->readable_registered = false;
gpr_log(GPR_DEBUG, "readable on %s", fdn->grpc_polled_fd->GetName());
if (error == GRPC_ERROR_NONE) {
do {
ares_process_fd(ev_driver->channel, as, ARES_SOCKET_BAD);
} while (fdn->grpc_polled_fd->IsFdStillReadableLocked());
} else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled
// by the following ares_cancel() and the on_done callbacks will be invoked
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
// ev_driver will be cleaned up in the follwing
// grpc_ares_notify_on_event_locked().
ares_cancel(ev_driver->channel);
}
grpc_ares_notify_on_event_locked(ev_driver);
grpc_ares_ev_driver_unref(ev_driver);
}
static void on_writable_locked(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
fdn->writable_registered = false;
gpr_log(GPR_DEBUG, "writable on %s", fdn->grpc_polled_fd->GetName());
if (error == GRPC_ERROR_NONE) {
ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, as);
} else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled
// by the following ares_cancel() and the on_done callbacks will be invoked
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
// ev_driver will be cleaned up in the follwing
// grpc_ares_notify_on_event_locked().
ares_cancel(ev_driver->channel);
}
grpc_ares_notify_on_event_locked(ev_driver);
grpc_ares_ev_driver_unref(ev_driver);
}
ares_channel* grpc_ares_ev_driver_get_channel_locked(
grpc_ares_ev_driver* ev_driver) {
return &ev_driver->channel;
}
// Get the file descriptors used by the ev_driver's ares channel, register
// driver_closure with these filedescriptors.
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) {
fd_node* new_list = nullptr;
if (!ev_driver->shutting_down) {
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
int socks_bitmask =
ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM);
for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
if (ARES_GETSOCK_READABLE(socks_bitmask, i) ||
ARES_GETSOCK_WRITABLE(socks_bitmask, i)) {
fd_node* fdn = pop_fd_node_locked(&ev_driver->fds, socks[i]);
// Create a new fd_node if sock[i] is not in the fd_node list.
if (fdn == nullptr) {
fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node)));
fdn->grpc_polled_fd = grpc_core::NewGrpcPolledFdLocked(
socks[i], ev_driver->pollset_set);
gpr_log(GPR_DEBUG, "new fd: %s", fdn->grpc_polled_fd->GetName());
fdn->ev_driver = ev_driver;
fdn->readable_registered = false;
fdn->writable_registered = false;
fdn->already_shutdown = false;
GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_locked, fdn,
grpc_combiner_scheduler(ev_driver->combiner));
GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_locked, fdn,
grpc_combiner_scheduler(ev_driver->combiner));
}
fdn->next = new_list;
new_list = fdn;
// Register read_closure if the socket is readable and read_closure has
// not been registered with this socket.
if (ARES_GETSOCK_READABLE(socks_bitmask, i) &&
!fdn->readable_registered) {
grpc_ares_ev_driver_ref(ev_driver);
gpr_log(GPR_DEBUG, "notify read on: %s",
fdn->grpc_polled_fd->GetName());
fdn->grpc_polled_fd->RegisterForOnReadableLocked(&fdn->read_closure);
fdn->readable_registered = true;
}
// Register write_closure if the socket is writable and write_closure
// has not been registered with this socket.
if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) &&
!fdn->writable_registered) {
gpr_log(GPR_DEBUG, "notify write on: %s",
fdn->grpc_polled_fd->GetName());
grpc_ares_ev_driver_ref(ev_driver);
fdn->grpc_polled_fd->RegisterForOnWriteableLocked(
&fdn->write_closure);
fdn->writable_registered = true;
}
}
}
}
// Any remaining fds in ev_driver->fds were not returned by ares_getsock() and
// are therefore no longer in use, so they can be shut down and removed from
// the list.
while (ev_driver->fds != nullptr) {
fd_node* cur = ev_driver->fds;
ev_driver->fds = ev_driver->fds->next;
fd_node_shutdown_locked(cur, "c-ares fd shutdown");
if (!cur->readable_registered && !cur->writable_registered) {
fd_node_destroy_locked(cur);
} else {
cur->next = new_list;
new_list = cur;
}
}
ev_driver->fds = new_list;
// If the ev driver has no working fd, all the tasks are done.
if (new_list == nullptr) {
ev_driver->working = false;
gpr_log(GPR_DEBUG, "ev driver stop working");
}
}
void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) {
if (!ev_driver->working) {
ev_driver->working = true;
grpc_ares_notify_on_event_locked(ev_driver);
}
}
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */

@ -22,6 +22,7 @@
#include <grpc/support/port_platform.h>
#include <ares.h>
#include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/iomgr/pollset_set.h"
typedef struct grpc_ares_ev_driver grpc_ares_ev_driver;
@ -51,5 +52,40 @@ void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver);
/* Shutdown all the grpc_fds used by \a ev_driver */
void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver);
namespace grpc_core {
/* A wrapped fd that integrates with the grpc iomgr of the current platform.
* A GrpcPolledFd knows how to create grpc platform-specific iomgr endpoints
* from "ares_socket_t" sockets, and then sign up for readability/writeability
* with that poller, and do shutdown and destruction. */
class GrpcPolledFd {
public:
virtual ~GrpcPolledFd() {}
/* Called when c-ares library is interested and there's no pending callback */
virtual void RegisterForOnReadableLocked(grpc_closure* read_closure)
GRPC_ABSTRACT;
/* Called when c-ares library is interested and there's no pending callback */
virtual void RegisterForOnWriteableLocked(grpc_closure* write_closure)
GRPC_ABSTRACT;
/* Indicates if there is data left even after just being read from */
virtual bool IsFdStillReadableLocked() GRPC_ABSTRACT;
/* Called once and only once. Must cause cancellation of any pending
* read/write callbacks. */
virtual void ShutdownLocked(grpc_error* error) GRPC_ABSTRACT;
/* Get the underlying ares_socket_t that this was created from */
virtual ares_socket_t GetWrappedAresSocketLocked() GRPC_ABSTRACT;
/* A unique name, for logging */
virtual const char* GetName() GRPC_ABSTRACT;
GRPC_ABSTRACT_BASE_CLASS
};
/* Creates a new wrapped fd for the current platform */
GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
grpc_pollset_set* driver_pollset_set);
void ConfigureAresChannelLocked(ares_channel* channel);
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H \
*/

@ -36,286 +36,60 @@
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
typedef struct fd_node {
/** the owner of this fd node */
grpc_ares_ev_driver* ev_driver;
/** a closure wrapping on_readable_locked, which should be
invoked when the grpc_fd in this node becomes readable. */
grpc_closure read_closure;
/** a closure wrapping on_writable_locked, which should be
invoked when the grpc_fd in this node becomes writable. */
grpc_closure write_closure;
/** next fd node in the list */
struct fd_node* next;
namespace grpc_core {
/** the grpc_fd owned by this fd node */
grpc_fd* fd;
/** if the readable closure has been registered */
bool readable_registered;
/** if the writable closure has been registered */
bool writable_registered;
/** if the fd has been shutdown yet from grpc iomgr perspective */
bool already_shutdown;
} fd_node;
struct grpc_ares_ev_driver {
/** the ares_channel owned by this event driver */
ares_channel channel;
/** pollset set for driving the IO events of the channel */
grpc_pollset_set* pollset_set;
/** refcount of the event driver */
gpr_refcount refs;
/** combiner to synchronize c-ares and I/O callbacks on */
grpc_combiner* combiner;
/** a list of grpc_fd that this event driver is currently using. */
fd_node* fds;
/** is this event driver currently working? */
bool working;
/** is this event driver being shut down */
bool shutting_down;
};
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
static grpc_ares_ev_driver* grpc_ares_ev_driver_ref(
grpc_ares_ev_driver* ev_driver) {
gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
gpr_ref(&ev_driver->refs);
return ev_driver;
}
static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
if (gpr_unref(&ev_driver->refs)) {
gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
GPR_ASSERT(ev_driver->fds == nullptr);
GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
ares_destroy(ev_driver->channel);
gpr_free(ev_driver);
class GrpcPolledFdPosix : public GrpcPolledFd {
public:
GrpcPolledFdPosix(ares_socket_t as, grpc_pollset_set* driver_pollset_set)
: as_(as) {
gpr_asprintf(&name_, "c-ares fd: %d", (int)as);
fd_ = grpc_fd_create((int)as, name_, false);
grpc_pollset_set_add_fd(driver_pollset_set, fd_);
}
}
static void fd_node_destroy_locked(fd_node* fdn) {
gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->fd));
GPR_ASSERT(!fdn->readable_registered);
GPR_ASSERT(!fdn->writable_registered);
GPR_ASSERT(fdn->already_shutdown);
~GrpcPolledFdPosix() {
gpr_free(name_);
/* c-ares library will close the fd inside grpc_fd. This fd may be picked up
immediately by another thread, and should not be closed by the following
grpc_fd_orphan. */
int dummy_release_fd;
grpc_fd_orphan(fdn->fd, nullptr, &dummy_release_fd, "c-ares query finished");
gpr_free(fdn);
}
static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) {
if (!fdn->already_shutdown) {
fdn->already_shutdown = true;
grpc_fd_shutdown(fdn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING(reason));
grpc_fd_orphan(fd_, nullptr, &dummy_release_fd, "c-ares query finished");
}
}
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
grpc_combiner* combiner) {
*ev_driver = static_cast<grpc_ares_ev_driver*>(
gpr_malloc(sizeof(grpc_ares_ev_driver)));
ares_options opts;
memset(&opts, 0, sizeof(opts));
opts.flags |= ARES_FLAG_STAYOPEN;
int status = ares_init_options(&(*ev_driver)->channel, &opts, ARES_OPT_FLAGS);
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create_locked");
if (status != ARES_SUCCESS) {
char* err_msg;
gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s",
ares_strerror(status));
grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg);
gpr_free(err_msg);
gpr_free(*ev_driver);
return err;
void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
grpc_fd_notify_on_read(fd_, read_closure);
}
(*ev_driver)->combiner = GRPC_COMBINER_REF(combiner, "ares event driver");
gpr_ref_init(&(*ev_driver)->refs, 1);
(*ev_driver)->pollset_set = pollset_set;
(*ev_driver)->fds = nullptr;
(*ev_driver)->working = false;
(*ev_driver)->shutting_down = false;
return GRPC_ERROR_NONE;
}
void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver) {
// We mark the event driver as being shut down. If the event driver
// is working, grpc_ares_notify_on_event_locked will shut down the
// fds; if it's not working, there are no fds to shut down.
ev_driver->shutting_down = true;
grpc_ares_ev_driver_unref(ev_driver);
}
void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) {
ev_driver->shutting_down = true;
fd_node* fn = ev_driver->fds;
while (fn != nullptr) {
fd_node_shutdown_locked(fn, "grpc_ares_ev_driver_shutdown");
fn = fn->next;
void RegisterForOnWriteableLocked(grpc_closure* write_closure) override {
grpc_fd_notify_on_write(fd_, write_closure);
}
}
// Search fd in the fd_node list head. This is an O(n) search, the max possible
// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
static fd_node* pop_fd_node_locked(fd_node** head, int fd) {
fd_node dummy_head;
dummy_head.next = *head;
fd_node* node = &dummy_head;
while (node->next != nullptr) {
if (grpc_fd_wrapped_fd(node->next->fd) == fd) {
fd_node* ret = node->next;
node->next = node->next->next;
*head = dummy_head.next;
return ret;
bool IsFdStillReadableLocked() override {
size_t bytes_available = 0;
return ioctl(grpc_fd_wrapped_fd(fd_), FIONREAD, &bytes_available) == 0 &&
bytes_available > 0;
}
node = node->next;
void ShutdownLocked(grpc_error* error) override {
grpc_fd_shutdown(fd_, error);
}
return nullptr;
}
/* Check if \a fd is still readable */
static bool grpc_ares_is_fd_still_readable_locked(
grpc_ares_ev_driver* ev_driver, int fd) {
size_t bytes_available = 0;
return ioctl(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0;
}
ares_socket_t GetWrappedAresSocketLocked() override { return as_; }
static void on_readable_locked(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
const int fd = grpc_fd_wrapped_fd(fdn->fd);
fdn->readable_registered = false;
gpr_log(GPR_DEBUG, "readable on %d", fd);
if (error == GRPC_ERROR_NONE) {
do {
ares_process_fd(ev_driver->channel, fd, ARES_SOCKET_BAD);
} while (grpc_ares_is_fd_still_readable_locked(ev_driver, fd));
} else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled
// by the following ares_cancel() and the on_done callbacks will be invoked
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
// ev_driver will be cleaned up in the follwing
// grpc_ares_notify_on_event_locked().
ares_cancel(ev_driver->channel);
}
grpc_ares_notify_on_event_locked(ev_driver);
grpc_ares_ev_driver_unref(ev_driver);
}
const char* GetName() override { return name_; }
static void on_writable_locked(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
const int fd = grpc_fd_wrapped_fd(fdn->fd);
fdn->writable_registered = false;
gpr_log(GPR_DEBUG, "writable on %d", fd);
if (error == GRPC_ERROR_NONE) {
ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, fd);
} else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled
// by the following ares_cancel() and the on_done callbacks will be invoked
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
// ev_driver will be cleaned up in the follwing
// grpc_ares_notify_on_event_locked().
ares_cancel(ev_driver->channel);
}
grpc_ares_notify_on_event_locked(ev_driver);
grpc_ares_ev_driver_unref(ev_driver);
}
char* name_;
ares_socket_t as_;
grpc_fd* fd_;
};
ares_channel* grpc_ares_ev_driver_get_channel_locked(
grpc_ares_ev_driver* ev_driver) {
return &ev_driver->channel;
GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
grpc_pollset_set* driver_pollset_set) {
return grpc_core::New<GrpcPolledFdPosix>(as, driver_pollset_set);
}
// Get the file descriptors used by the ev_driver's ares channel, register
// driver_closure with these filedescriptors.
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) {
fd_node* new_list = nullptr;
if (!ev_driver->shutting_down) {
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
int socks_bitmask =
ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM);
for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
if (ARES_GETSOCK_READABLE(socks_bitmask, i) ||
ARES_GETSOCK_WRITABLE(socks_bitmask, i)) {
fd_node* fdn = pop_fd_node_locked(&ev_driver->fds, socks[i]);
// Create a new fd_node if sock[i] is not in the fd_node list.
if (fdn == nullptr) {
char* fd_name;
gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i);
fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node)));
gpr_log(GPR_DEBUG, "new fd: %d", socks[i]);
fdn->fd = grpc_fd_create(socks[i], fd_name, false);
fdn->ev_driver = ev_driver;
fdn->readable_registered = false;
fdn->writable_registered = false;
fdn->already_shutdown = false;
GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_locked, fdn,
grpc_combiner_scheduler(ev_driver->combiner));
GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_locked, fdn,
grpc_combiner_scheduler(ev_driver->combiner));
grpc_pollset_set_add_fd(ev_driver->pollset_set, fdn->fd);
gpr_free(fd_name);
}
fdn->next = new_list;
new_list = fdn;
// Register read_closure if the socket is readable and read_closure has
// not been registered with this socket.
if (ARES_GETSOCK_READABLE(socks_bitmask, i) &&
!fdn->readable_registered) {
grpc_ares_ev_driver_ref(ev_driver);
gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->fd));
grpc_fd_notify_on_read(fdn->fd, &fdn->read_closure);
fdn->readable_registered = true;
}
// Register write_closure if the socket is writable and write_closure
// has not been registered with this socket.
if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) &&
!fdn->writable_registered) {
gpr_log(GPR_DEBUG, "notify write on: %d",
grpc_fd_wrapped_fd(fdn->fd));
grpc_ares_ev_driver_ref(ev_driver);
grpc_fd_notify_on_write(fdn->fd, &fdn->write_closure);
fdn->writable_registered = true;
}
}
}
}
// Any remaining fds in ev_driver->fds were not returned by ares_getsock() and
// are therefore no longer in use, so they can be shut down and removed from
// the list.
while (ev_driver->fds != nullptr) {
fd_node* cur = ev_driver->fds;
ev_driver->fds = ev_driver->fds->next;
fd_node_shutdown_locked(cur, "c-ares fd shutdown");
if (!cur->readable_registered && !cur->writable_registered) {
fd_node_destroy_locked(cur);
} else {
cur->next = new_list;
new_list = cur;
}
}
ev_driver->fds = new_list;
// If the ev driver has no working fd, all the tasks are done.
if (new_list == nullptr) {
ev_driver->working = false;
gpr_log(GPR_DEBUG, "ev driver stop working");
}
}
void ConfigureAresChannelLocked(ares_channel* channel) {}
void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) {
if (!ev_driver->working) {
ev_driver->working = true;
grpc_ares_notify_on_event_locked(ev_driver);
}
}
} // namespace grpc_core
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */

@ -128,21 +128,25 @@ static void cancel_timer_if_needed(grpc_deadline_state* deadline_state) {
}
}
// Callback run when the call is complete.
static void on_complete(void* arg, grpc_error* error) {
// Callback run when we receive trailing metadata.
static void recv_trailing_metadata_ready(void* arg, grpc_error* error) {
grpc_deadline_state* deadline_state = static_cast<grpc_deadline_state*>(arg);
cancel_timer_if_needed(deadline_state);
// Invoke the next callback.
GRPC_CLOSURE_RUN(deadline_state->next_on_complete, GRPC_ERROR_REF(error));
// Invoke the original callback.
GRPC_CLOSURE_RUN(deadline_state->original_recv_trailing_metadata_ready,
GRPC_ERROR_REF(error));
}
// Inject our own on_complete callback into op.
static void inject_on_complete_cb(grpc_deadline_state* deadline_state,
grpc_transport_stream_op_batch* op) {
deadline_state->next_on_complete = op->on_complete;
GRPC_CLOSURE_INIT(&deadline_state->on_complete, on_complete, deadline_state,
// Inject our own recv_trailing_metadata_ready callback into op.
static void inject_recv_trailing_metadata_ready(
grpc_deadline_state* deadline_state, grpc_transport_stream_op_batch* op) {
deadline_state->original_recv_trailing_metadata_ready =
op->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
GRPC_CLOSURE_INIT(&deadline_state->recv_trailing_metadata_ready,
recv_trailing_metadata_ready, deadline_state,
grpc_schedule_on_exec_ctx);
op->on_complete = &deadline_state->on_complete;
op->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
&deadline_state->recv_trailing_metadata_ready;
}
// Callback and associated state for starting the timer after call stack
@ -226,7 +230,7 @@ void grpc_deadline_state_client_start_transport_stream_op_batch(
// Make sure we know when the call is complete, so that we can cancel
// the timer.
if (op->recv_trailing_metadata) {
inject_on_complete_cb(deadline_state, op);
inject_recv_trailing_metadata_ready(deadline_state, op);
}
}
}
@ -322,7 +326,7 @@ static void server_start_transport_stream_op_batch(
// the client never sends trailing metadata, because this is the
// hook that tells us when the call is complete on the server side.
if (op->recv_trailing_metadata) {
inject_on_complete_cb(&calld->base.deadline_state, op);
inject_recv_trailing_metadata_ready(&calld->base.deadline_state, op);
}
}
// Chain to next filter.

@ -37,12 +37,12 @@ typedef struct grpc_deadline_state {
grpc_deadline_timer_state timer_state;
grpc_timer timer;
grpc_closure timer_callback;
// Closure to invoke when the call is complete.
// Closure to invoke when we receive trailing metadata.
// We use this to cancel the timer.
grpc_closure on_complete;
// The original on_complete closure, which we chain to after our own
// closure is invoked.
grpc_closure* next_on_complete;
grpc_closure recv_trailing_metadata_ready;
// The original recv_trailing_metadata_ready closure, which we chain to
// after our own closure is invoked.
grpc_closure* original_recv_trailing_metadata_ready;
} grpc_deadline_state;
//

@ -55,8 +55,8 @@ struct call_data {
grpc_closure recv_initial_metadata_ready;
// State for handling recv_trailing_metadata ops.
grpc_metadata_batch* recv_trailing_metadata;
grpc_closure* original_recv_trailing_metadata_on_complete;
grpc_closure recv_trailing_metadata_on_complete;
grpc_closure* original_recv_trailing_metadata_ready;
grpc_closure recv_trailing_metadata_ready;
// State for handling send_message ops.
grpc_transport_stream_op_batch* send_message_batch;
size_t send_message_bytes_read;
@ -153,8 +153,7 @@ static void recv_initial_metadata_ready(void* user_data, grpc_error* error) {
GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, error);
}
static void recv_trailing_metadata_on_complete(void* user_data,
grpc_error* error) {
static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (error == GRPC_ERROR_NONE) {
@ -163,7 +162,7 @@ static void recv_trailing_metadata_on_complete(void* user_data,
} else {
GRPC_ERROR_REF(error);
}
GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_on_complete, error);
GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error);
}
static void send_message_on_complete(void* arg, grpc_error* error) {
@ -312,8 +311,10 @@ static void hc_start_transport_stream_op_batch(
/* substitute our callback for the higher callback */
calld->recv_trailing_metadata =
batch->payload->recv_trailing_metadata.recv_trailing_metadata;
calld->original_recv_trailing_metadata_on_complete = batch->on_complete;
batch->on_complete = &calld->recv_trailing_metadata_on_complete;
calld->original_recv_trailing_metadata_ready =
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
&calld->recv_trailing_metadata_ready;
}
grpc_error* error = GRPC_ERROR_NONE;
@ -420,8 +421,8 @@ static grpc_error* init_call_elem(grpc_call_element* elem,
GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready,
recv_initial_metadata_ready, elem,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_on_complete,
recv_trailing_metadata_on_complete, elem,
GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready,
recv_trailing_metadata_ready, elem,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete,
elem, grpc_schedule_on_exec_ctx);

@ -1149,12 +1149,10 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
}
}
/* Flag that this closure barrier wants stats to be updated before finishing */
#define CLOSURE_BARRIER_STATS_BIT (1 << 0)
/* Flag that this closure barrier may be covering a write in a pollset, and so
we should not complete this closure until we can prove that the write got
scheduled */
#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1)
#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 0)
/* First bit of the reference count, stored in the high order bits (with the low
bits being used for flags defined above) */
#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
@ -1206,10 +1204,6 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
grpc_error_add_child(closure->error_data.error, error);
}
if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
grpc_transport_move_stats(&s->stats, s->collecting_stats);
s->collecting_stats = nullptr;
}
if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) ||
!(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) {
GRPC_CLOSURE_RUN(closure, closure->error_data.error);
@ -1351,9 +1345,14 @@ static void perform_stream_op_locked(void* stream_op,
}
grpc_closure* on_complete = op->on_complete;
// TODO(roth): This is a hack needed because we use data inside of the
// closure itself to do the barrier calculation (i.e., to ensure that
// we don't schedule the closure until all ops in the batch have been
// completed). This can go away once we move to a new C++ closure API
// that provides the ability to create a barrier closure.
if (on_complete == nullptr) {
on_complete =
GRPC_CLOSURE_CREATE(do_nothing, nullptr, grpc_schedule_on_exec_ctx);
on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing,
nullptr, grpc_schedule_on_exec_ctx);
}
/* use final_data as a barrier until enqueue time; the inital counter is
@ -1361,12 +1360,6 @@ static void perform_stream_op_locked(void* stream_op,
on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
on_complete->error_data.error = GRPC_ERROR_NONE;
if (op->collect_stats) {
GPR_ASSERT(s->collecting_stats == nullptr);
s->collecting_stats = op_payload->collect_stats.collect_stats;
on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
}
if (op->cancel_stream) {
GRPC_STATS_INC_HTTP2_OP_CANCEL();
grpc_chttp2_cancel_stream(t, s, op_payload->cancel_stream.cancel_error);
@ -1600,8 +1593,11 @@ static void perform_stream_op_locked(void* stream_op,
if (op->recv_trailing_metadata) {
GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA();
GPR_ASSERT(s->collecting_stats == nullptr);
s->collecting_stats = op_payload->recv_trailing_metadata.collect_stats;
GPR_ASSERT(s->recv_trailing_metadata_finished == nullptr);
s->recv_trailing_metadata_finished = add_closure_barrier(on_complete);
s->recv_trailing_metadata_finished =
op_payload->recv_trailing_metadata.recv_trailing_metadata_ready;
s->recv_trailing_metadata =
op_payload->recv_trailing_metadata.recv_trailing_metadata;
s->final_metadata_requested = true;
@ -1960,11 +1956,12 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
}
if (s->read_closed && s->frame_storage.length == 0 && !pending_data &&
s->recv_trailing_metadata_finished != nullptr) {
grpc_transport_move_stats(&s->stats, s->collecting_stats);
s->collecting_stats = nullptr;
grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
s->recv_trailing_metadata);
grpc_chttp2_complete_closure_step(
t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
"recv_trailing_metadata_finished");
null_then_run_closure(&s->recv_trailing_metadata_finished,
GRPC_ERROR_NONE);
}
}
}

@ -925,6 +925,10 @@ static bool op_can_be_run(grpc_transport_stream_op_batch* curr_op,
result = false;
}
/* Check if every op that was asked for is done. */
/* TODO(muxi): We should not consider the recv ops here, since they
* have their own callbacks. We should invoke a batch's on_complete
* as soon as all of the batch's send ops are complete, even if
* there are still recv ops pending. */
else if (curr_op->send_initial_metadata &&
!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) {
CRONET_LOG(GPR_DEBUG, "Because");
@ -1280,12 +1284,20 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
op_can_be_run(stream_op, s, &oas->state,
OP_RECV_TRAILING_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
if (oas->s->state.rs.trailing_metadata_valid) {
grpc_error* error = GRPC_ERROR_NONE;
if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
error = GRPC_ERROR_REF(stream_state->cancel_error);
} else if (stream_state->state_op_done[OP_FAILED]) {
error = make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable.");
} else if (oas->s->state.rs.trailing_metadata_valid) {
grpc_chttp2_incoming_metadata_buffer_publish(
&oas->s->state.rs.trailing_metadata,
stream_op->payload->recv_trailing_metadata.recv_trailing_metadata);
stream_state->rs.trailing_metadata_valid = false;
}
GRPC_CLOSURE_SCHED(
stream_op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
error);
stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_op->cancel_stream &&
@ -1398,6 +1410,11 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready,
GRPC_ERROR_CANCELLED);
}
if (op->recv_trailing_metadata) {
GRPC_CLOSURE_SCHED(
op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
GRPC_ERROR_CANCELLED);
}
GRPC_CLOSURE_SCHED(op->on_complete, GRPC_ERROR_CANCELLED);
return;
}

@ -120,7 +120,6 @@ typedef struct inproc_stream {
struct inproc_stream* stream_list_next;
} inproc_stream;
static grpc_closure do_nothing_closure;
static bool cancel_stream_locked(inproc_stream* s, grpc_error* error);
static void op_state_machine(void* arg, grpc_error* error);
@ -373,6 +372,10 @@ static void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error,
const char* msg) {
int is_sm = static_cast<int>(op == s->send_message_op);
int is_stm = static_cast<int>(op == s->send_trailing_md_op);
// TODO(vjpai): We should not consider the recv ops here, since they
// have their own callbacks. We should invoke a batch's on_complete
// as soon as all of the batch's send ops are complete, even if there
// are still recv ops pending.
int is_rim = static_cast<int>(op == s->recv_initial_md_op);
int is_rm = static_cast<int>(op == s->recv_message_op);
int is_rtm = static_cast<int>(op == s->recv_trailing_md_op);
@ -496,6 +499,11 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
s->send_trailing_md_op = nullptr;
}
if (s->recv_trailing_md_op) {
INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-metadata-ready %p",
s, error);
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata
.recv_trailing_metadata_ready,
GRPC_ERROR_REF(error));
INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-md-on-complete %p",
s, error);
complete_if_batch_end_locked(
@ -638,6 +646,12 @@ static void op_state_machine(void* arg, grpc_error* error) {
}
s->trailing_md_sent = true;
if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-metadata-ready", s);
GRPC_CLOSURE_SCHED(
s->recv_trailing_md_op->payload->recv_trailing_metadata
.recv_trailing_metadata_ready,
GRPC_ERROR_NONE);
INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-md-on-complete", s);
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
@ -711,6 +725,12 @@ static void op_state_machine(void* arg, grpc_error* error) {
}
if (s->recv_trailing_md_op && s->t->is_client && other &&
other->send_message_op) {
INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-metadata-ready %p", s,
GRPC_ERROR_NONE);
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata
.recv_trailing_metadata_ready,
GRPC_ERROR_NONE);
maybe_schedule_op_closure_locked(other, GRPC_ERROR_NONE);
}
if (s->to_read_trailing_md_filled) {
@ -766,6 +786,10 @@ static void op_state_machine(void* arg, grpc_error* error) {
INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-md-on-complete %p",
s, new_err);
GRPC_CLOSURE_SCHED(
s->recv_trailing_md_op->payload->recv_trailing_metadata
.recv_trailing_metadata_ready,
GRPC_ERROR_REF(new_err));
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
GRPC_ERROR_REF(new_err));
s->recv_trailing_md_op = nullptr;
@ -859,6 +883,9 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
// couldn't complete that because we hadn't yet sent out trailing
// md, now's the chance
if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata
.recv_trailing_metadata_ready,
GRPC_ERROR_REF(s->cancel_self_error));
complete_if_batch_end_locked(
s, s->cancel_self_error, s->recv_trailing_md_op,
"cancel_stream scheduling trailing-md-on-complete");
@ -873,6 +900,8 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
return ret;
}
static void do_nothing(void* arg, grpc_error* error) {}
static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
grpc_transport_stream_op_batch* op) {
INPROC_LOG(GPR_INFO, "perform_stream_op %p %p %p", gt, gs, op);
@ -892,8 +921,14 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
}
grpc_error* error = GRPC_ERROR_NONE;
grpc_closure* on_complete = op->on_complete;
// TODO(roth): This is a hack needed because we use data inside of the
// closure itself to do the barrier calculation (i.e., to ensure that
// we don't schedule the closure until all ops in the batch have been
// completed). This can go away once we move to a new C++ closure API
// that provides the ability to create a barrier closure.
if (on_complete == nullptr) {
on_complete = &do_nothing_closure;
on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing,
nullptr, grpc_schedule_on_exec_ctx);
}
if (op->cancel_stream) {
@ -1026,6 +1061,15 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready,
GRPC_ERROR_REF(error));
}
if (op->recv_trailing_metadata) {
INPROC_LOG(
GPR_INFO,
"perform_stream_op error %p scheduling trailing-metadata-ready %p",
s, error);
GRPC_CLOSURE_SCHED(
op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
GRPC_ERROR_REF(error));
}
}
INPROC_LOG(GPR_INFO, "perform_stream_op %p scheduling on_complete %p", s,
error);
@ -1129,12 +1173,8 @@ static grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; }
/*******************************************************************************
* GLOBAL INIT AND DESTROY
*/
static void do_nothing(void* arg, grpc_error* error) {}
void grpc_inproc_transport_init(void) {
grpc_core::ExecCtx exec_ctx;
GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, nullptr,
grpc_schedule_on_exec_ctx);
g_empty_slice = grpc_slice_from_static_buffer(nullptr, 0);
grpc_slice key_tmp = grpc_slice_from_static_string(":path");

@ -51,6 +51,7 @@ typedef struct connected_channel_call_data {
callback_state on_complete[6]; // Max number of pending batches.
callback_state recv_initial_metadata_ready;
callback_state recv_message_ready;
callback_state recv_trailing_metadata_ready;
} call_data;
static void run_in_call_combiner(void* arg, grpc_error* error) {
@ -111,6 +112,12 @@ static void con_start_transport_stream_op_batch(
intercept_callback(calld, state, false, "recv_message_ready",
&batch->payload->recv_message.recv_message_ready);
}
if (batch->recv_trailing_metadata) {
callback_state* state = &calld->recv_trailing_metadata_ready;
intercept_callback(
calld, state, false, "recv_trailing_metadata_ready",
&batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready);
}
if (batch->cancel_stream) {
// There can be more than one cancellation batch in flight at any
// given time, so we can't just pick out a fixed index into
@ -121,7 +128,7 @@ static void con_start_transport_stream_op_batch(
static_cast<callback_state*>(gpr_malloc(sizeof(*state)));
intercept_callback(calld, state, true, "on_complete (cancel_stream)",
&batch->on_complete);
} else {
} else if (batch->on_complete != nullptr) {
callback_state* state = get_state_for_batch(calld, batch);
intercept_callback(calld, state, false, "on_complete", &batch->on_complete);
}

@ -99,6 +99,8 @@ class InlinedVector {
void push_back(T&& value) { emplace_back(std::move(value)); }
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
size_t capacity() const { return capacity_; }
void clear() {

@ -26,6 +26,7 @@
#include <grpc/support/atm.h>
#include "src/core/lib/gpr/mpscq.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/iomgr/closure.h"
// A simple, lock-free mechanism for serializing activity related to a
@ -109,4 +110,83 @@ void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner,
void grpc_call_combiner_cancel(grpc_call_combiner* call_combiner,
grpc_error* error);
namespace grpc_core {
// Helper for running a list of closures in a call combiner.
//
// Each callback running in the call combiner will eventually be
// returned to the surface, at which point the surface will yield the
// call combiner. So when we are running in the call combiner and have
// more than one callback to return to the surface, we need to re-enter
// the call combiner for all but one of those callbacks.
class CallCombinerClosureList {
public:
CallCombinerClosureList() {}
// Adds a closure to the list. The closure must eventually result in
// the call combiner being yielded.
void Add(grpc_closure* closure, grpc_error* error, const char* reason) {
closures_.emplace_back(closure, error, reason);
}
// Runs all closures in the call combiner and yields the call combiner.
//
// All but one of the closures in the list will be scheduled via
// GRPC_CALL_COMBINER_START(), and the remaining closure will be
// scheduled via GRPC_CLOSURE_SCHED(), which will eventually result in
// yielding the call combiner. If the list is empty, then the call
// combiner will be yielded immediately.
void RunClosures(grpc_call_combiner* call_combiner) {
if (closures_.empty()) {
GRPC_CALL_COMBINER_STOP(call_combiner, "no closures to schedule");
return;
}
for (size_t i = 1; i < closures_.size(); ++i) {
auto& closure = closures_[i];
GRPC_CALL_COMBINER_START(call_combiner, closure.closure, closure.error,
closure.reason);
}
if (grpc_call_combiner_trace.enabled()) {
gpr_log(GPR_INFO,
"CallCombinerClosureList executing closure while already "
"holding call_combiner %p: closure=%p error=%s reason=%s",
call_combiner, closures_[0].closure,
grpc_error_string(closures_[0].error), closures_[0].reason);
}
// This will release the call combiner.
GRPC_CLOSURE_SCHED(closures_[0].closure, closures_[0].error);
closures_.clear();
}
// Runs all closures in the call combiner, but does NOT yield the call
// combiner. All closures will be scheduled via GRPC_CALL_COMBINER_START().
void RunClosuresWithoutYielding(grpc_call_combiner* call_combiner) {
for (size_t i = 0; i < closures_.size(); ++i) {
auto& closure = closures_[i];
GRPC_CALL_COMBINER_START(call_combiner, closure.closure, closure.error,
closure.reason);
}
closures_.clear();
}
size_t size() const { return closures_.size(); }
private:
struct CallCombinerClosure {
grpc_closure* closure;
grpc_error* error;
const char* reason;
CallCombinerClosure(grpc_closure* closure, grpc_error* error,
const char* reason)
: closure(closure), error(error), reason(reason) {}
};
// There are generally a maximum of 6 closures to run in the call
// combiner, one for each pending op.
InlinedVector<CallCombinerClosure, 6> closures_;
};
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_IOMGR_CALL_COMBINER_H */

@ -283,9 +283,10 @@ inline void grpc_closure_sched(grpc_closure* c, grpc_error* error) {
if (c->scheduled) {
gpr_log(GPR_ERROR,
"Closure already scheduled. (closure: %p, created: [%s:%d], "
"previously scheduled at: [%s: %d] run?: %s",
"previously scheduled at: [%s: %d], newly scheduled at [%s: %d], "
"run?: %s",
c, c->file_created, c->line_created, c->file_initiated,
c->line_initiated, c->run ? "true" : "false");
c->line_initiated, file, line, c->run ? "true" : "false");
abort();
}
c->scheduled = true;

@ -231,7 +231,8 @@ end:
creds->base.vtable = &google_default_credentials_vtable;
creds->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT;
gpr_ref_init(&creds->base.refcount, 1);
creds->ssl_creds = grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
creds->ssl_creds =
grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
GPR_ASSERT(creds->ssl_creds != nullptr);
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();

@ -48,6 +48,10 @@ static void ssl_destruct(grpc_channel_credentials* creds) {
grpc_ssl_credentials* c = reinterpret_cast<grpc_ssl_credentials*>(creds);
gpr_free(c->config.pem_root_certs);
grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1);
if (c->config.verify_options.verify_peer_destruct != nullptr) {
c->config.verify_options.verify_peer_destruct(
c->config.verify_options.verify_peer_callback_userdata);
}
}
static grpc_security_status ssl_create_security_connector(
@ -87,6 +91,7 @@ static grpc_channel_credentials_vtable ssl_vtable = {
static void ssl_build_config(const char* pem_root_certs,
grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
const verify_peer_options* verify_options,
grpc_ssl_config* config) {
if (pem_root_certs != nullptr) {
config->pem_root_certs = gpr_strdup(pem_root_certs);
@ -101,23 +106,32 @@ static void ssl_build_config(const char* pem_root_certs,
config->pem_key_cert_pair->private_key =
gpr_strdup(pem_key_cert_pair->private_key);
}
if (verify_options != nullptr) {
memcpy(&config->verify_options, verify_options,
sizeof(verify_peer_options));
} else {
// Otherwise set all options to default values
memset(&config->verify_options, 0, sizeof(verify_peer_options));
}
}
grpc_channel_credentials* grpc_ssl_credentials_create(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
void* reserved) {
const verify_peer_options* verify_options, void* reserved) {
grpc_ssl_credentials* c = static_cast<grpc_ssl_credentials*>(
gpr_zalloc(sizeof(grpc_ssl_credentials)));
GRPC_API_TRACE(
"grpc_ssl_credentials_create(pem_root_certs=%s, "
"pem_key_cert_pair=%p, "
"verify_options=%p, "
"reserved=%p)",
3, (pem_root_certs, pem_key_cert_pair, reserved));
4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved));
GPR_ASSERT(reserved == nullptr);
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
gpr_ref_init(&c->base.refcount, 1);
ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
ssl_build_config(pem_root_certs, pem_key_cert_pair, verify_options,
&c->config);
return &c->base;
}

@ -620,6 +620,7 @@ typedef struct {
tsi_ssl_client_handshaker_factory* client_handshaker_factory;
char* target_name;
char* overridden_target_name;
const verify_peer_options* verify_options;
} grpc_ssl_channel_security_connector;
typedef struct {
@ -878,11 +879,34 @@ static void ssl_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_closure* on_peer_checked) {
grpc_ssl_channel_security_connector* c =
reinterpret_cast<grpc_ssl_channel_security_connector*>(sc);
grpc_error* error = ssl_check_peer(sc,
c->overridden_target_name != nullptr
const char* target_name = c->overridden_target_name != nullptr
? c->overridden_target_name
: c->target_name,
&peer, auth_context);
: c->target_name;
grpc_error* error = ssl_check_peer(sc, target_name, &peer, auth_context);
if (error == GRPC_ERROR_NONE &&
c->verify_options->verify_peer_callback != nullptr) {
const tsi_peer_property* p =
tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
if (p == nullptr) {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Cannot check peer: missing pem cert property.");
} else {
char* peer_pem = static_cast<char*>(gpr_malloc(p->value.length + 1));
memcpy(peer_pem, p->value.data, p->value.length);
peer_pem[p->value.length] = '\0';
int callback_status = c->verify_options->verify_peer_callback(
target_name, peer_pem,
c->verify_options->verify_peer_callback_userdata);
gpr_free(peer_pem);
if (callback_status) {
char* msg;
gpr_asprintf(&msg, "Verify peer callback returned a failure (%d)",
callback_status);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
}
}
}
GRPC_CLOSURE_SCHED(on_peer_checked, error);
tsi_peer_destruct(&peer);
}
@ -1047,6 +1071,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
if (overridden_target_name != nullptr) {
c->overridden_target_name = gpr_strdup(overridden_target_name);
}
c->verify_options = &config->verify_options;
has_key_cert_pair = config->pem_key_cert_pair != nullptr &&
config->pem_key_cert_pair->private_key != nullptr &&

@ -193,6 +193,7 @@ grpc_server_security_connector* grpc_fake_server_security_connector_create(
typedef struct {
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
char* pem_root_certs;
verify_peer_options verify_options;
} grpc_ssl_config;
/* Creates an SSL channel_security_connector.

@ -233,6 +233,7 @@ struct grpc_call {
grpc_closure receiving_slice_ready;
grpc_closure receiving_stream_ready;
grpc_closure receiving_initial_metadata_ready;
grpc_closure receiving_trailing_metadata_ready;
uint32_t test_only_last_message_flags;
grpc_closure release_call;
@ -270,8 +271,17 @@ struct grpc_call {
grpc_core::TraceFlag grpc_call_error_trace(false, "call_error");
grpc_core::TraceFlag grpc_compression_trace(false, "compression");
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack*)((call) + 1))
#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call*)(call_stack)) - 1)
/* Given a size, round up to the next multiple of sizeof(void*) */
#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
(((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
#define CALL_STACK_FROM_CALL(call) \
(grpc_call_stack*)((char*)(call) + \
ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
#define CALL_FROM_CALL_STACK(call_stack) \
(grpc_call*)(((char*)(call_stack)) - \
ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
#define CALL_ELEM_FROM_CALL(call, idx) \
grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
#define CALL_FROM_TOP_ELEM(top_elem) \
@ -342,8 +352,9 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args,
size_t initial_size = grpc_channel_get_call_size_estimate(args->channel);
GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size);
gpr_arena* arena = gpr_arena_create(initial_size);
call = static_cast<grpc_call*>(gpr_arena_alloc(
arena, sizeof(grpc_call) + channel_stack->call_stack_size));
call = static_cast<grpc_call*>(
gpr_arena_alloc(arena, ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) +
channel_stack->call_stack_size));
gpr_ref_init(&call->ext_ref, 1);
call->arena = arena;
grpc_call_combiner_init(&call->call_combiner);
@ -1211,7 +1222,6 @@ static void post_batch_completion(batch_control* bctl) {
if (bctl->op.send_initial_metadata) {
grpc_metadata_batch_destroy(
&call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
}
if (bctl->op.send_message) {
@ -1219,14 +1229,9 @@ static void post_batch_completion(batch_control* bctl) {
}
if (bctl->op.send_trailing_metadata) {
grpc_metadata_batch_destroy(
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
}
if (bctl->op.recv_trailing_metadata) {
grpc_metadata_batch* md =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
recv_trailing_filter(call, md);
/* propagate cancellation to any interested children */
gpr_atm_rel_store(&call->received_final_op_atm, 1);
parent_call* pc = get_parent_call(call);
@ -1248,7 +1253,6 @@ static void post_batch_completion(batch_control* bctl) {
}
gpr_mu_unlock(&pc->child_list_mu);
}
if (call->is_client) {
get_final_status(call, set_status_value_directly,
call->final_op.client.status,
@ -1258,7 +1262,6 @@ static void post_batch_completion(batch_control* bctl) {
get_final_status(call, set_cancelled_value,
call->final_op.server.cancelled, nullptr, nullptr);
}
grpc_core::channelz::ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(call->channel);
if (*call->final_op.client.status != GRPC_STATUS_OK) {
@ -1266,7 +1269,6 @@ static void post_batch_completion(batch_control* bctl) {
} else {
channelz_channel->RecordCallSucceeded();
}
GRPC_ERROR_UNREF(error);
error = GRPC_ERROR_NONE;
}
@ -1548,6 +1550,17 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) {
finish_batch_step(bctl);
}
static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) {
batch_control* bctl = static_cast<batch_control*>(bctlp);
grpc_call* call = bctl->call;
GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready");
add_batch_error(bctl, GRPC_ERROR_REF(error), false);
grpc_metadata_batch* md =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
recv_trailing_filter(call, md);
finish_batch_step(bctl);
}
static void finish_batch(void* bctlp, grpc_error* error) {
batch_control* bctl = static_cast<batch_control*>(bctlp);
grpc_call* call = bctl->call;
@ -1568,7 +1581,8 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
size_t i;
const grpc_op* op;
batch_control* bctl;
int num_completion_callbacks_needed = 1;
bool has_send_ops = false;
int num_recv_ops = 0;
grpc_call_error error = GRPC_CALL_OK;
grpc_transport_stream_op_batch* stream_op;
grpc_transport_stream_op_batch_payload* stream_op_payload;
@ -1674,6 +1688,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
stream_op_payload->send_initial_metadata.peer_string =
&call->peer_string;
}
has_send_ops = true;
break;
}
case GRPC_OP_SEND_MESSAGE: {
@ -1703,6 +1718,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
&op->data.send_message.send_message->data.raw.slice_buffer, flags);
stream_op_payload->send_message.send_message.reset(
call->sending_stream.get());
has_send_ops = true;
break;
}
case GRPC_OP_SEND_CLOSE_FROM_CLIENT: {
@ -1723,6 +1739,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
call->sent_final_op = true;
stream_op_payload->send_trailing_metadata.send_trailing_metadata =
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
has_send_ops = true;
break;
}
case GRPC_OP_SEND_STATUS_FROM_SERVER: {
@ -1787,6 +1804,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
}
stream_op_payload->send_trailing_metadata.send_trailing_metadata =
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
has_send_ops = true;
break;
}
case GRPC_OP_RECV_INITIAL_METADATA: {
@ -1814,7 +1832,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
stream_op_payload->recv_initial_metadata.peer_string =
&call->peer_string;
}
num_completion_callbacks_needed++;
++num_recv_ops;
break;
}
case GRPC_OP_RECV_MESSAGE: {
@ -1836,7 +1854,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
grpc_schedule_on_exec_ctx);
stream_op_payload->recv_message.recv_message_ready =
&call->receiving_stream_ready;
num_completion_callbacks_needed++;
++num_recv_ops;
break;
}
case GRPC_OP_RECV_STATUS_ON_CLIENT: {
@ -1862,11 +1880,16 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
call->final_op.client.error_string =
op->data.recv_status_on_client.error_string;
stream_op->recv_trailing_metadata = true;
stream_op->collect_stats = true;
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
stream_op_payload->collect_stats.collect_stats =
stream_op_payload->recv_trailing_metadata.collect_stats =
&call->final_info.stats.transport_stream_stats;
GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready,
receiving_trailing_metadata_ready, bctl,
grpc_schedule_on_exec_ctx);
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata_ready =
&call->receiving_trailing_metadata_ready;
++num_recv_ops;
break;
}
case GRPC_OP_RECV_CLOSE_ON_SERVER: {
@ -1887,11 +1910,16 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
call->final_op.server.cancelled =
op->data.recv_close_on_server.cancelled;
stream_op->recv_trailing_metadata = true;
stream_op->collect_stats = true;
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
stream_op_payload->collect_stats.collect_stats =
stream_op_payload->recv_trailing_metadata.collect_stats =
&call->final_info.stats.transport_stream_stats;
GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready,
receiving_trailing_metadata_ready, bctl,
grpc_schedule_on_exec_ctx);
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata_ready =
&call->receiving_trailing_metadata_ready;
++num_recv_ops;
break;
}
}
@ -1901,13 +1929,15 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
if (!is_notify_tag_closure) {
GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
}
gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
gpr_ref_init(&bctl->steps_to_complete, (has_send_ops ? 1 : 0) + num_recv_ops);
if (has_send_ops) {
GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl,
grpc_schedule_on_exec_ctx);
stream_op->on_complete = &bctl->finish_batch;
gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
}
gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
execute_batch(call, stream_op, &bctl->start_batch);
done:

@ -212,21 +212,32 @@ void grpc_transport_stream_op_batch_finish_with_failure(
if (batch->send_message) {
batch->payload->send_message.send_message.reset();
}
if (batch->recv_message) {
GRPC_CALL_COMBINER_START(
call_combiner, batch->payload->recv_message.recv_message_ready,
GRPC_ERROR_REF(error), "failing recv_message_ready");
if (batch->cancel_stream) {
GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error);
}
// Construct a list of closures to execute.
grpc_core::CallCombinerClosureList closures;
if (batch->recv_initial_metadata) {
GRPC_CALL_COMBINER_START(
call_combiner,
closures.Add(
batch->payload->recv_initial_metadata.recv_initial_metadata_ready,
GRPC_ERROR_REF(error), "failing recv_initial_metadata_ready");
}
GRPC_CLOSURE_SCHED(batch->on_complete, error);
if (batch->cancel_stream) {
GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error);
if (batch->recv_message) {
closures.Add(batch->payload->recv_message.recv_message_ready,
GRPC_ERROR_REF(error), "failing recv_message_ready");
}
if (batch->recv_trailing_metadata) {
closures.Add(
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
GRPC_ERROR_REF(error), "failing recv_trailing_metadata_ready");
}
if (batch->on_complete != nullptr) {
closures.Add(batch->on_complete, GRPC_ERROR_REF(error),
"failing on_complete");
}
// Execute closures.
closures.RunClosures(call_combiner);
GRPC_ERROR_UNREF(error);
}
typedef struct {

@ -122,9 +122,15 @@ typedef struct grpc_transport_stream_op_batch_payload
/* Transport stream op: a set of operations to perform on a transport
against a single stream */
typedef struct grpc_transport_stream_op_batch {
/** Should be enqueued when all requested operations (excluding recv_message
and recv_initial_metadata which have their own closures) in a given batch
have been completed. */
/** Should be scheduled when all of the non-recv operations in the batch
are complete.
The recv ops (recv_initial_metadata, recv_message, and
recv_trailing_metadata) each have their own callbacks. If a batch
contains both recv ops and non-recv ops, on_complete should be
scheduled as soon as the non-recv ops are complete, regardless of
whether or not the recv ops are complete. If a batch contains
only recv ops, on_complete can be null. */
grpc_closure* on_complete;
/** Values for the stream op (fields set are determined by flags above) */
@ -149,9 +155,6 @@ typedef struct grpc_transport_stream_op_batch {
*/
bool recv_trailing_metadata : 1;
/** Collect any stats into provided buffer, zero internal stat counters */
bool collect_stats : 1;
/** Cancel this stream with the provided error */
bool cancel_stream : 1;
@ -219,11 +222,10 @@ struct grpc_transport_stream_op_batch_payload {
struct {
grpc_metadata_batch* recv_trailing_metadata;
} recv_trailing_metadata;
struct {
grpc_transport_stream_stats* collect_stats;
} collect_stats;
/** Should be enqueued when initial metadata is ready to be processed. */
grpc_closure* recv_trailing_metadata_ready;
} recv_trailing_metadata;
/** Forcefully close this stream.
The HTTP2 semantics should be:

@ -120,13 +120,6 @@ char* grpc_transport_stream_op_batch_string(
gpr_strvec_add(&b, tmp);
}
if (op->collect_stats) {
gpr_strvec_add(&b, gpr_strdup(" "));
gpr_asprintf(&tmp, "COLLECT_STATS:%p",
op->payload->collect_stats.collect_stats);
gpr_strvec_add(&b, tmp);
}
out = gpr_strvec_flatten(&b, nullptr);
gpr_strvec_destroy(&b);

@ -83,7 +83,8 @@ std::shared_ptr<ChannelCredentials> SslCredentials(
grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr,
nullptr);
return WrapChannelCredentials(c_creds);
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2015 gRPC authors.
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,16 +16,15 @@
*
*/
#include "test/core/statistics/census_log_tests.h"
#include <grpc/support/port_platform.h>
#include <stdlib.h>
#include "src/cpp/ext/filters/census/channel_filter.h"
#include <grpc/support/time.h>
#include "test/core/util/test_config.h"
namespace grpc {
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_small_log();
return 0;
grpc_error* CensusChannelData::Init(grpc_channel_element* elem,
grpc_channel_element_args* args) {
return GRPC_ERROR_NONE;
}
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2015 gRPC authors.
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,16 +16,21 @@
*
*/
#include "test/core/statistics/census_log_tests.h"
#ifndef GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H
#include <stdlib.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/time.h>
#include "test/core/util/test_config.h"
#include "src/cpp/ext/filters/census/context.h"
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_multiple_writers_circular_log();
return 0;
}
namespace grpc {
class CensusChannelData : public ChannelData {
public:
grpc_error* Init(grpc_channel_element* elem,
grpc_channel_element_args* args) override;
};
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H */

@ -0,0 +1,163 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/client_filter.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "opencensus/stats/stats.h"
#include "src/core/lib/surface/call.h"
#include "src/cpp/ext/filters/census/grpc_plugin.h"
#include "src/cpp/ext/filters/census/measures.h"
namespace grpc {
constexpr uint32_t CensusClientCallData::kMaxTraceContextLen;
constexpr uint32_t CensusClientCallData::kMaxTagsLen;
namespace {
void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) {
if (b->idx.named.grpc_server_stats_bin != nullptr) {
ServerStatsDeserialize(
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(
GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md))),
GRPC_SLICE_LENGTH(GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md)),
elapsed_time);
grpc_metadata_batch_remove(b, b->idx.named.grpc_server_stats_bin);
}
}
} // namespace
void CensusClientCallData::OnDoneRecvTrailingMetadataCb(void* user_data,
grpc_error* error) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
CensusClientCallData* calld =
reinterpret_cast<CensusClientCallData*>(elem->call_data);
GPR_ASSERT(calld != nullptr);
if (error == GRPC_ERROR_NONE) {
GPR_ASSERT(calld->recv_trailing_metadata_ != nullptr);
FilterTrailingMetadata(calld->recv_trailing_metadata_,
&calld->elapsed_time_);
}
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_trailing_metadata_,
GRPC_ERROR_REF(error));
}
void CensusClientCallData::OnDoneRecvMessageCb(void* user_data,
grpc_error* error) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
CensusClientCallData* calld =
reinterpret_cast<CensusClientCallData*>(elem->call_data);
CensusChannelData* channeld =
reinterpret_cast<CensusChannelData*>(elem->channel_data);
GPR_ASSERT(calld != nullptr);
GPR_ASSERT(channeld != nullptr);
// Stream messages are no longer valid after receiving trailing metadata.
if ((*calld->recv_message_) != nullptr) {
calld->recv_message_count_++;
}
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error));
}
void CensusClientCallData::StartTransportStreamOpBatch(
grpc_call_element* elem, TransportStreamOpBatch* op) {
if (op->send_initial_metadata() != nullptr) {
census_context* ctxt = op->get_census_context();
GenerateClientContext(
qualified_method_, &context_,
(ctxt == nullptr) ? nullptr : reinterpret_cast<CensusContext*>(ctxt));
size_t tracing_len = TraceContextSerialize(context_.Context(), tracing_buf_,
kMaxTraceContextLen);
if (tracing_len > 0) {
GRPC_LOG_IF_ERROR(
"census grpc_filter",
grpc_metadata_batch_add_tail(
op->send_initial_metadata()->batch(), &tracing_bin_,
grpc_mdelem_from_slices(
GRPC_MDSTR_GRPC_TRACE_BIN,
grpc_slice_from_copied_buffer(tracing_buf_, tracing_len))));
}
grpc_slice tags = grpc_empty_slice();
// TODO: Add in tagging serialization.
size_t encoded_tags_len = StatsContextSerialize(kMaxTagsLen, &tags);
if (encoded_tags_len > 0) {
GRPC_LOG_IF_ERROR(
"census grpc_filter",
grpc_metadata_batch_add_tail(
op->send_initial_metadata()->batch(), &stats_bin_,
grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_TAGS_BIN, tags)));
}
}
if (op->send_message() != nullptr) {
++sent_message_count_;
}
if (op->recv_message() != nullptr) {
recv_message_ = op->op()->payload->recv_message.recv_message;
initial_on_done_recv_message_ =
op->op()->payload->recv_message.recv_message_ready;
op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_;
}
if (op->recv_trailing_metadata() != nullptr) {
recv_trailing_metadata_ = op->recv_trailing_metadata()->batch();
initial_on_done_recv_trailing_metadata_ = op->on_complete();
op->set_on_complete(&on_done_recv_trailing_metadata_);
}
// Call next op.
grpc_call_next_op(elem, op->op());
}
grpc_error* CensusClientCallData::Init(grpc_call_element* elem,
const grpc_call_element_args* args) {
path_ = grpc_slice_ref_internal(args->path);
start_time_ = absl::Now();
method_ = GetMethod(&path_);
qualified_method_ = absl::StrCat("Sent.", method_);
GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&on_done_recv_trailing_metadata_,
OnDoneRecvTrailingMetadataCb, elem,
grpc_schedule_on_exec_ctx);
return GRPC_ERROR_NONE;
}
void CensusClientCallData::Destroy(grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) {
const uint64_t request_size = GetOutgoingDataSize(final_info);
const uint64_t response_size = GetIncomingDataSize(final_info);
double latency_ms = absl::ToDoubleMilliseconds(absl::Now() - start_time_);
::opencensus::stats::Record(
{{RpcClientSentBytesPerRpc(), static_cast<double>(request_size)},
{RpcClientReceivedBytesPerRpc(), static_cast<double>(response_size)},
{RpcClientRoundtripLatency(), latency_ms},
{RpcClientServerLatency(),
ToDoubleMilliseconds(absl::Nanoseconds(elapsed_time_))},
{RpcClientSentMessagesPerRpc(), sent_message_count_},
{RpcClientReceivedMessagesPerRpc(), recv_message_count_}},
{{ClientMethodTagKey(), method_},
{ClientStatusTagKey(), StatusCodeToString(final_info->final_status)}});
grpc_slice_unref_internal(path_);
context_.EndSpan();
}
} // namespace grpc

@ -0,0 +1,104 @@
/*
*
* Copyright 2018 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H
#include <grpc/support/port_platform.h>
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "src/cpp/ext/filters/census/channel_filter.h"
#include "src/cpp/ext/filters/census/context.h"
namespace grpc {
// A CallData class will be created for every grpc call within a channel. It is
// used to store data and methods specific to that call. CensusClientCallData is
// thread-compatible, however typically only 1 thread should be interacting with
// a call at a time.
class CensusClientCallData : public CallData {
public:
// Maximum size of trace context is sent on the wire.
static constexpr uint32_t kMaxTraceContextLen = 64;
// Maximum size of tags that are sent on the wire.
static constexpr uint32_t kMaxTagsLen = 2048;
CensusClientCallData()
: recv_trailing_metadata_(nullptr),
initial_on_done_recv_trailing_metadata_(nullptr),
initial_on_done_recv_message_(nullptr),
elapsed_time_(0),
recv_message_(nullptr),
recv_message_count_(0),
sent_message_count_(0) {
memset(&stats_bin_, 0, sizeof(grpc_linked_mdelem));
memset(&tracing_bin_, 0, sizeof(grpc_linked_mdelem));
memset(&path_, 0, sizeof(grpc_slice));
memset(&on_done_recv_trailing_metadata_, 0, sizeof(grpc_closure));
memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
}
grpc_error* Init(grpc_call_element* elem,
const grpc_call_element_args* args) override;
void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) override;
void StartTransportStreamOpBatch(grpc_call_element* elem,
TransportStreamOpBatch* op) override;
static void OnDoneRecvTrailingMetadataCb(void* user_data, grpc_error* error);
static void OnDoneSendInitialMetadataCb(void* user_data, grpc_error* error);
static void OnDoneRecvMessageCb(void* user_data, grpc_error* error);
private:
CensusContext context_;
// Metadata elements for tracing and census stats data.
grpc_linked_mdelem stats_bin_;
grpc_linked_mdelem tracing_bin_;
// Client method.
absl::string_view method_;
std::string qualified_method_;
grpc_slice path_;
// The recv trailing metadata callbacks.
grpc_metadata_batch* recv_trailing_metadata_;
grpc_closure* initial_on_done_recv_trailing_metadata_;
grpc_closure on_done_recv_trailing_metadata_;
// recv message
grpc_closure* initial_on_done_recv_message_;
grpc_closure on_done_recv_message_;
// Start time (for measuring latency).
absl::Time start_time_;
// Server elapsed time in nanoseconds.
uint64_t elapsed_time_;
// The received message--may be null.
grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_;
// Number of messages in this RPC.
uint64_t recv_message_count_;
uint64_t sent_message_count_;
// Buffer needed for grpc_slice to reference when adding trace context
// metatdata to outgoing message.
char tracing_buf_[kMaxTraceContextLen];
};
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H */

@ -0,0 +1,132 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/context.h"
namespace grpc {
using ::opencensus::trace::Span;
using ::opencensus::trace::SpanContext;
void GenerateServerContext(absl::string_view tracing, absl::string_view stats,
absl::string_view primary_role,
absl::string_view method, CensusContext* context) {
GrpcTraceContext trace_ctxt;
TraceContextEncoding::Decode(tracing, &trace_ctxt);
SpanContext parent_ctx = trace_ctxt.ToSpanContext();
new (context) CensusContext(method, parent_ctx);
}
void GenerateClientContext(absl::string_view method, CensusContext* ctxt,
CensusContext* parent_ctxt) {
if (parent_ctxt != nullptr) {
SpanContext span_ctxt = parent_ctxt->Context();
Span span = parent_ctxt->Span();
if (span_ctxt.IsValid()) {
new (ctxt) CensusContext(method, &span);
return;
}
}
new (ctxt) CensusContext(method);
}
size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context,
char* tracing_buf, size_t tracing_buf_size) {
GrpcTraceContext trace_ctxt(context);
return TraceContextEncoding::Encode(trace_ctxt, tracing_buf,
tracing_buf_size);
}
size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags) {
// TODO: Add implementation. Waiting on stats tagging to be added.
return 0;
}
size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf,
size_t buf_size) {
return RpcServerStatsEncoding::Encode(server_elapsed_time, buf, buf_size);
}
size_t ServerStatsDeserialize(const char* buf, size_t buf_size,
uint64_t* server_elapsed_time) {
return RpcServerStatsEncoding::Decode(absl::string_view(buf, buf_size),
server_elapsed_time);
}
uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info) {
return final_info->stats.transport_stream_stats.incoming.data_bytes;
}
uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info) {
return final_info->stats.transport_stream_stats.outgoing.data_bytes;
}
SpanContext SpanContextFromCensusContext(const census_context* ctxt) {
return reinterpret_cast<const CensusContext*>(ctxt)->Context();
}
Span SpanFromCensusContext(const census_context* ctxt) {
return reinterpret_cast<const CensusContext*>(ctxt)->Span();
}
absl::string_view StatusCodeToString(grpc_status_code code) {
switch (code) {
case GRPC_STATUS_OK:
return "OK";
case GRPC_STATUS_CANCELLED:
return "CANCELLED";
case GRPC_STATUS_UNKNOWN:
return "UNKNOWN";
case GRPC_STATUS_INVALID_ARGUMENT:
return "INVALID_ARGUMENT";
case GRPC_STATUS_DEADLINE_EXCEEDED:
return "DEADLINE_EXCEEDED";
case GRPC_STATUS_NOT_FOUND:
return "NOT_FOUND";
case GRPC_STATUS_ALREADY_EXISTS:
return "ALREADY_EXISTS";
case GRPC_STATUS_PERMISSION_DENIED:
return "PERMISSION_DENIED";
case GRPC_STATUS_UNAUTHENTICATED:
return "UNAUTHENTICATED";
case GRPC_STATUS_RESOURCE_EXHAUSTED:
return "RESOURCE_EXHAUSTED";
case GRPC_STATUS_FAILED_PRECONDITION:
return "FAILED_PRECONDITION";
case GRPC_STATUS_ABORTED:
return "ABORTED";
case GRPC_STATUS_OUT_OF_RANGE:
return "OUT_OF_RANGE";
case GRPC_STATUS_UNIMPLEMENTED:
return "UNIMPLEMENTED";
case GRPC_STATUS_INTERNAL:
return "INTERNAL";
case GRPC_STATUS_UNAVAILABLE:
return "UNAVAILABLE";
case GRPC_STATUS_DATA_LOSS:
return "DATA_LOSS";
default:
// gRPC wants users of this enum to include a default branch so that
// adding values is not a breaking change.
return "UNKNOWN_STATUS";
}
}
} // namespace grpc

@ -0,0 +1,126 @@
/*
*
* Copyright 2018 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H
#include <grpc/support/port_platform.h>
#include <grpc/status.h>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "opencensus/trace/span.h"
#include "opencensus/trace/span_context.h"
#include "opencensus/trace/trace_params.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/cpp/common/channel_filter.h"
#include "src/cpp/ext/filters/census/rpc_encoding.h"
// This is needed because grpc has hardcoded CensusContext with a
// forward declaration of 'struct census_context;'
struct census_context;
namespace grpc {
// Thread compatible.
class CensusContext {
public:
CensusContext() : span_(::opencensus::trace::Span::BlankSpan()) {}
explicit CensusContext(absl::string_view name)
: span_(::opencensus::trace::Span::StartSpan(name)) {}
CensusContext(absl::string_view name, const ::opencensus::trace::Span* parent)
: span_(::opencensus::trace::Span::StartSpan(name, parent)) {}
CensusContext(absl::string_view name,
const ::opencensus::trace::SpanContext& parent_ctxt)
: span_(::opencensus::trace::Span::StartSpanWithRemoteParent(
name, parent_ctxt)) {}
::opencensus::trace::SpanContext Context() const { return span_.context(); }
::opencensus::trace::Span Span() const { return span_; }
void EndSpan() { span_.End(); }
private:
::opencensus::trace::Span span_;
};
// Serializes the outgoing trace context. Field IDs are 1 byte followed by
// field data. A 1 byte version ID is always encoded first.
size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context,
char* tracing_buf, size_t tracing_buf_size);
// Serializes the outgoing stats context. Field IDs are 1 byte followed by
// field data. A 1 byte version ID is always encoded first. Tags are directly
// serialized into the given grpc_slice.
size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags);
// Serialize outgoing server stats. Returns the number of bytes serialized.
size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf,
size_t buf_size);
// Deserialize incoming server stats. Returns the number of bytes deserialized.
size_t ServerStatsDeserialize(const char* buf, size_t buf_size,
uint64_t* server_elapsed_time);
// Deserialize the incoming SpanContext and generate a new server context based
// on that. This new span will never be a root span. This should only be called
// with a blank CensusContext as it overwrites it.
void GenerateServerContext(absl::string_view tracing, absl::string_view stats,
absl::string_view primary_role,
absl::string_view method, CensusContext* context);
// Creates a new client context that is by default a new root context.
// If the current context is the default context then the newly created
// span automatically becomes a root span. This should only be called with a
// blank CensusContext as it overwrites it.
void GenerateClientContext(absl::string_view method, CensusContext* ctxt,
CensusContext* parent_ctx);
// Returns the incoming data size from the grpc call final info.
uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info);
// Returns the outgoing data size from the grpc call final info.
uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info);
// These helper functions return the SpanContext and Span, respectively
// associated with the census_context* stored by grpc. The user will need to
// call this for manual propagation of tracing data.
::opencensus::trace::SpanContext SpanContextFromCensusContext(
const census_context* ctxt);
::opencensus::trace::Span SpanFromCensusContext(const census_context* ctxt);
// Returns a string representation of the StatusCode enum.
absl::string_view StatusCodeToString(grpc_status_code code);
inline absl::string_view GetMethod(const grpc_slice* path) {
if (GRPC_SLICE_IS_EMPTY(*path)) {
return "";
}
// Check for leading '/' and trim it if present.
return absl::StripPrefix(absl::string_view(reinterpret_cast<const char*>(
GRPC_SLICE_START_PTR(*path)),
GRPC_SLICE_LENGTH(*path)),
"/");
}
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H */

@ -0,0 +1,130 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/grpc_plugin.h"
#include <grpcpp/server_context.h>
#include "opencensus/trace/span.h"
#include "src/cpp/ext/filters/census/channel_filter.h"
#include "src/cpp/ext/filters/census/client_filter.h"
#include "src/cpp/ext/filters/census/measures.h"
#include "src/cpp/ext/filters/census/server_filter.h"
namespace grpc {
void RegisterOpenCensusPlugin() {
RegisterChannelFilter<CensusChannelData, CensusClientCallData>(
"opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */,
nullptr /* condition function */);
RegisterChannelFilter<CensusChannelData, CensusServerCallData>(
"opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */,
nullptr /* condition function */);
// Access measures to ensure they are initialized. Otherwise, creating a view
// before the first RPC would cause an error.
RpcClientSentBytesPerRpc();
RpcClientReceivedBytesPerRpc();
RpcClientRoundtripLatency();
RpcClientServerLatency();
RpcClientSentMessagesPerRpc();
RpcClientReceivedMessagesPerRpc();
RpcServerSentBytesPerRpc();
RpcServerReceivedBytesPerRpc();
RpcServerServerLatency();
RpcServerSentMessagesPerRpc();
RpcServerReceivedMessagesPerRpc();
}
::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context) {
return reinterpret_cast<const CensusContext*>(context->census_context())
->Span();
}
// These measure definitions should be kept in sync across opencensus
// implementations--see
// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
::opencensus::stats::TagKey ClientMethodTagKey() {
static const auto method_tag_key =
::opencensus::stats::TagKey::Register("grpc_client_method");
return method_tag_key;
}
::opencensus::stats::TagKey ClientStatusTagKey() {
static const auto status_tag_key =
::opencensus::stats::TagKey::Register("grpc_client_status");
return status_tag_key;
}
::opencensus::stats::TagKey ServerMethodTagKey() {
static const auto method_tag_key =
::opencensus::stats::TagKey::Register("grpc_server_method");
return method_tag_key;
}
::opencensus::stats::TagKey ServerStatusTagKey() {
static const auto status_tag_key =
::opencensus::stats::TagKey::Register("grpc_server_status");
return status_tag_key;
}
// Client
ABSL_CONST_INIT const absl::string_view
kRpcClientSentMessagesPerRpcMeasureName =
"grpc.io/client/sent_messages_per_rpc";
ABSL_CONST_INIT const absl::string_view kRpcClientSentBytesPerRpcMeasureName =
"grpc.io/client/sent_bytes_per_rpc";
ABSL_CONST_INIT const absl::string_view
kRpcClientReceivedMessagesPerRpcMeasureName =
"grpc.io/client/received_messages_per_rpc";
ABSL_CONST_INIT const absl::string_view
kRpcClientReceivedBytesPerRpcMeasureName =
"grpc.io/client/received_bytes_per_rpc";
ABSL_CONST_INIT const absl::string_view kRpcClientRoundtripLatencyMeasureName =
"grpc.io/client/roundtrip_latency";
ABSL_CONST_INIT const absl::string_view kRpcClientServerLatencyMeasureName =
"grpc.io/client/server_latency";
// Server
ABSL_CONST_INIT const absl::string_view
kRpcServerSentMessagesPerRpcMeasureName =
"grpc.io/server/sent_messages_per_rpc";
ABSL_CONST_INIT const absl::string_view kRpcServerSentBytesPerRpcMeasureName =
"grpc.io/server/sent_bytes_per_rpc";
ABSL_CONST_INIT const absl::string_view
kRpcServerReceivedMessagesPerRpcMeasureName =
"grpc.io/server/received_messages_per_rpc";
ABSL_CONST_INIT const absl::string_view
kRpcServerReceivedBytesPerRpcMeasureName =
"grpc.io/server/received_bytes_per_rpc";
ABSL_CONST_INIT const absl::string_view kRpcServerServerLatencyMeasureName =
"grpc.io/server/server_latency";
} // namespace grpc

@ -0,0 +1,111 @@
/*
*
* Copyright 2018 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H
#include <grpc/support/port_platform.h>
#include "absl/strings/string_view.h"
#include "include/grpcpp/opencensus.h"
#include "opencensus/stats/stats.h"
#include "opencensus/trace/span.h"
namespace grpc {
class ServerContext;
// Returns the tracing Span for the current RPC.
::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context);
// The tag keys set when recording RPC stats.
::opencensus::stats::TagKey ClientMethodTagKey();
::opencensus::stats::TagKey ClientStatusTagKey();
::opencensus::stats::TagKey ServerMethodTagKey();
::opencensus::stats::TagKey ServerStatusTagKey();
// Names of measures used by the plugin--users can create views on these
// measures but should not record data for them.
extern const absl::string_view kRpcClientSentMessagesPerRpcMeasureName;
extern const absl::string_view kRpcClientSentBytesPerRpcMeasureName;
extern const absl::string_view kRpcClientReceivedMessagesPerRpcMeasureName;
extern const absl::string_view kRpcClientReceivedBytesPerRpcMeasureName;
extern const absl::string_view kRpcClientRoundtripLatencyMeasureName;
extern const absl::string_view kRpcClientServerLatencyMeasureName;
extern const absl::string_view kRpcServerSentMessagesPerRpcMeasureName;
extern const absl::string_view kRpcServerSentBytesPerRpcMeasureName;
extern const absl::string_view kRpcServerReceivedMessagesPerRpcMeasureName;
extern const absl::string_view kRpcServerReceivedBytesPerRpcMeasureName;
extern const absl::string_view kRpcServerServerLatencyMeasureName;
// Canonical gRPC view definitions.
const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor&
ClientReceivedMessagesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor&
ClientReceivedBytesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyCumulative();
const ::opencensus::stats::ViewDescriptor& ClientServerLatencyCumulative();
const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsCumulative();
const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor&
ServerReceivedBytesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor& ServerServerLatencyCumulative();
const ::opencensus::stats::ViewDescriptor& ServerStartedCountCumulative();
const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsCumulative();
const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor&
ServerReceivedMessagesPerRpcCumulative();
const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyMinute();
const ::opencensus::stats::ViewDescriptor& ClientServerLatencyMinute();
const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsMinute();
const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcMinute();
const ::opencensus::stats::ViewDescriptor& ServerServerLatencyMinute();
const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsMinute();
const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyHour();
const ::opencensus::stats::ViewDescriptor& ClientServerLatencyHour();
const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsHour();
const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcHour();
const ::opencensus::stats::ViewDescriptor& ServerServerLatencyHour();
const ::opencensus::stats::ViewDescriptor& ServerStartedCountHour();
const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsHour();
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H */

@ -0,0 +1,129 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/measures.h"
#include "opencensus/stats/stats.h"
#include "src/cpp/ext/filters/census/grpc_plugin.h"
namespace grpc {
using ::opencensus::stats::MeasureDouble;
using ::opencensus::stats::MeasureInt64;
// These measure definitions should be kept in sync across opencensus
// implementations--see
// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
namespace {
// Unit constants
constexpr char kUnitBytes[] = "By";
constexpr char kUnitMilliseconds[] = "ms";
constexpr char kCount[] = "1";
} // namespace
// Client
MeasureDouble RpcClientSentBytesPerRpc() {
static const auto measure = MeasureDouble::Register(
kRpcClientSentBytesPerRpcMeasureName,
"Total bytes sent across all request messages per RPC", kUnitBytes);
return measure;
}
MeasureDouble RpcClientReceivedBytesPerRpc() {
static const auto measure = MeasureDouble::Register(
kRpcClientReceivedBytesPerRpcMeasureName,
"Total bytes received across all response messages per RPC", kUnitBytes);
return measure;
}
MeasureDouble RpcClientRoundtripLatency() {
static const auto measure = MeasureDouble::Register(
kRpcClientRoundtripLatencyMeasureName,
"Time between first byte of request sent to last byte of response "
"received, or terminal error",
kUnitMilliseconds);
return measure;
}
MeasureDouble RpcClientServerLatency() {
static const auto measure = MeasureDouble::Register(
kRpcClientServerLatencyMeasureName,
"Time between first byte of request received to last byte of response "
"sent, or terminal error (propagated from the server)",
kUnitMilliseconds);
return measure;
}
MeasureInt64 RpcClientSentMessagesPerRpc() {
static const auto measure =
MeasureInt64::Register(kRpcClientSentMessagesPerRpcMeasureName,
"Number of messages sent per RPC", kCount);
return measure;
}
MeasureInt64 RpcClientReceivedMessagesPerRpc() {
static const auto measure =
MeasureInt64::Register(kRpcClientReceivedMessagesPerRpcMeasureName,
"Number of messages received per RPC", kCount);
return measure;
}
// Server
MeasureDouble RpcServerSentBytesPerRpc() {
static const auto measure = MeasureDouble::Register(
kRpcServerSentBytesPerRpcMeasureName,
"Total bytes sent across all messages per RPC", kUnitBytes);
return measure;
}
MeasureDouble RpcServerReceivedBytesPerRpc() {
static const auto measure = MeasureDouble::Register(
kRpcServerReceivedBytesPerRpcMeasureName,
"Total bytes received across all messages per RPC", kUnitBytes);
return measure;
}
MeasureDouble RpcServerServerLatency() {
static const auto measure = MeasureDouble::Register(
kRpcServerServerLatencyMeasureName,
"Time between first byte of request received to last byte of response "
"sent, or terminal error",
kUnitMilliseconds);
return measure;
}
MeasureInt64 RpcServerSentMessagesPerRpc() {
static const auto measure =
MeasureInt64::Register(kRpcServerSentMessagesPerRpcMeasureName,
"Number of messages sent per RPC", kCount);
return measure;
}
MeasureInt64 RpcServerReceivedMessagesPerRpc() {
static const auto measure =
MeasureInt64::Register(kRpcServerReceivedMessagesPerRpcMeasureName,
"Number of messages received per RPC", kCount);
return measure;
}
} // namespace grpc

@ -0,0 +1,46 @@
/*
*
* Copyright 2018 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H
#include <grpc/support/port_platform.h>
#include "opencensus/stats/stats.h"
#include "src/cpp/ext/filters/census/grpc_plugin.h"
namespace grpc {
::opencensus::stats::MeasureInt64 RpcClientSentMessagesPerRpc();
::opencensus::stats::MeasureDouble RpcClientSentBytesPerRpc();
::opencensus::stats::MeasureInt64 RpcClientReceivedMessagesPerRpc();
::opencensus::stats::MeasureDouble RpcClientReceivedBytesPerRpc();
::opencensus::stats::MeasureDouble RpcClientRoundtripLatency();
::opencensus::stats::MeasureDouble RpcClientServerLatency();
::opencensus::stats::MeasureInt64 RpcClientCompletedRpcs();
::opencensus::stats::MeasureInt64 RpcServerSentMessagesPerRpc();
::opencensus::stats::MeasureDouble RpcServerSentBytesPerRpc();
::opencensus::stats::MeasureInt64 RpcServerReceivedMessagesPerRpc();
::opencensus::stats::MeasureDouble RpcServerReceivedBytesPerRpc();
::opencensus::stats::MeasureDouble RpcServerServerLatency();
::opencensus::stats::MeasureInt64 RpcServerCompletedRpcs();
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H */

@ -0,0 +1,39 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/rpc_encoding.h"
namespace grpc {
constexpr size_t TraceContextEncoding::kGrpcTraceContextSize;
constexpr size_t TraceContextEncoding::kEncodeDecodeFailure;
constexpr size_t TraceContextEncoding::kVersionIdSize;
constexpr size_t TraceContextEncoding::kFieldIdSize;
constexpr size_t TraceContextEncoding::kVersionIdOffset;
constexpr size_t TraceContextEncoding::kVersionId;
constexpr size_t RpcServerStatsEncoding::kRpcServerStatsSize;
constexpr size_t RpcServerStatsEncoding::kEncodeDecodeFailure;
constexpr size_t RpcServerStatsEncoding::kVersionIdSize;
constexpr size_t RpcServerStatsEncoding::kFieldIdSize;
constexpr size_t RpcServerStatsEncoding::kVersionIdOffset;
constexpr size_t RpcServerStatsEncoding::kVersionId;
} // namespace grpc

@ -0,0 +1,284 @@
/*
*
* Copyright 2018 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H
#include <grpc/support/port_platform.h>
#include <string.h>
#include "absl/base/internal/endian.h"
#include "absl/strings/string_view.h"
#include "opencensus/trace/span_context.h"
#include "opencensus/trace/span_id.h"
#include "opencensus/trace/trace_id.h"
namespace grpc {
// TODO: Rename to GrpcTraceContextV0.
struct GrpcTraceContext {
GrpcTraceContext() {}
explicit GrpcTraceContext(const ::opencensus::trace::SpanContext& ctx) {
ctx.trace_id().CopyTo(trace_id);
ctx.span_id().CopyTo(span_id);
ctx.trace_options().CopyTo(trace_options);
}
::opencensus::trace::SpanContext ToSpanContext() const {
return ::opencensus::trace::SpanContext(
::opencensus::trace::TraceId(trace_id),
::opencensus::trace::SpanId(span_id),
::opencensus::trace::TraceOptions(trace_options));
}
// TODO: For performance:
// uint8_t version;
// uint8_t trace_id_field_id;
uint8_t trace_id[::opencensus::trace::TraceId::kSize];
// uint8_t span_id_field_id;
uint8_t span_id[::opencensus::trace::SpanId::kSize];
// uint8_t trace_options_field_id;
uint8_t trace_options[::opencensus::trace::TraceOptions::kSize];
};
// TraceContextEncoding encapsulates the logic for encoding and decoding of
// trace contexts.
class TraceContextEncoding {
public:
// Size of encoded GrpcTraceContext. (16 + 8 + 1 + 4)
static constexpr size_t kGrpcTraceContextSize = 29;
// Error value.
static constexpr size_t kEncodeDecodeFailure = 0;
// Deserializes a GrpcTraceContext from the incoming buffer. Returns the
// number of bytes deserialized from the buffer. If the incoming buffer is
// empty or the encoding version is not supported it will return 0 bytes,
// currently only version 0 is supported. If an unknown field ID is
// encountered it will return immediately without parsing the rest of the
// buffer. Inlined for performance reasons.
static size_t Decode(absl::string_view buf, GrpcTraceContext* tc) {
if (buf.empty()) {
return kEncodeDecodeFailure;
}
uint8_t version = buf[kVersionIdOffset];
// TODO: Support other versions later. Only support version 0 for
// now.
if (version != kVersionId) {
return kEncodeDecodeFailure;
}
size_t pos = kVersionIdSize;
while (pos < buf.size()) {
size_t bytes_read =
ParseField(absl::string_view(&buf[pos], buf.size() - pos), tc);
if (bytes_read == 0) {
break;
} else {
pos += bytes_read;
}
}
return pos;
}
// Serializes a GrpcTraceContext into the provided buffer. Returns the number
// of bytes serialized into the buffer. If the buffer is not of sufficient
// size (it must be at least kGrpcTraceContextSize bytes) it will drop
// everything and return 0 bytes serialized. Inlined for performance reasons.
static size_t Encode(const GrpcTraceContext& tc, char* buf, size_t buf_size) {
if (buf_size < kGrpcTraceContextSize) {
return kEncodeDecodeFailure;
}
buf[kVersionIdOffset] = kVersionId;
buf[kTraceIdOffset] = kTraceIdField;
memcpy(&buf[kTraceIdOffset + 1], tc.trace_id,
opencensus::trace::TraceId::kSize);
buf[kSpanIdOffset] = kSpanIdField;
memcpy(&buf[kSpanIdOffset + 1], tc.span_id,
opencensus::trace::SpanId::kSize);
buf[kTraceOptionsOffset] = kTraceOptionsField;
memcpy(&buf[kTraceOptionsOffset + 1], tc.trace_options,
opencensus::trace::TraceOptions::kSize);
return kGrpcTraceContextSize;
}
private:
// Parses the next field from the incoming buffer and stores the parsed value
// in a GrpcTraceContext struct. If it does not recognize the field ID it
// will return 0, otherwise it returns the number of bytes read.
static size_t ParseField(absl::string_view buf, GrpcTraceContext* tc) {
// TODO: Add support for multi-byte field IDs.
if (buf.empty()) {
return 0;
}
// Field ID is always the first byte in a field.
uint32_t field_id = buf[0];
size_t bytes_read = kFieldIdSize;
switch (field_id) {
case kTraceIdField:
bytes_read += kTraceIdSize;
if (bytes_read > buf.size()) {
return 0;
}
memcpy(tc->trace_id, &buf[kFieldIdSize],
opencensus::trace::TraceId::kSize);
break;
case kSpanIdField:
bytes_read += kSpanIdSize;
if (bytes_read > buf.size()) {
return 0;
}
memcpy(tc->span_id, &buf[kFieldIdSize],
opencensus::trace::SpanId::kSize);
break;
case kTraceOptionsField:
bytes_read += kTraceOptionsSize;
if (bytes_read > buf.size()) {
return 0;
}
memcpy(tc->trace_options, &buf[kFieldIdSize],
opencensus::trace::TraceOptions::kSize);
break;
default: // Invalid field ID
return 0;
}
return bytes_read;
}
// Size of Version ID.
static constexpr size_t kVersionIdSize = 1;
// Size of Field ID.
static constexpr size_t kFieldIdSize = 1;
// Offset and value for currently supported version ID.
static constexpr size_t kVersionIdOffset = 0;
static constexpr size_t kVersionId = 0;
// Fixed Field ID values:
enum FieldIdValue {
kTraceIdField = 0,
kSpanIdField = 1,
kTraceOptionsField = 2,
};
// Field data sizes in bytes
enum FieldSize {
kTraceIdSize = 16,
kSpanIdSize = 8,
kTraceOptionsSize = 1,
};
// Fixed size offsets for field ID start positions during encoding. Field
// data immediately follows.
enum FieldIdOffset {
kTraceIdOffset = kVersionIdSize,
kSpanIdOffset = kTraceIdOffset + kFieldIdSize + kTraceIdSize,
kTraceOptionsOffset = kSpanIdOffset + kFieldIdSize + kSpanIdSize,
};
TraceContextEncoding() = delete;
TraceContextEncoding(const TraceContextEncoding&) = delete;
TraceContextEncoding(TraceContextEncoding&&) = delete;
TraceContextEncoding operator=(const TraceContextEncoding&) = delete;
TraceContextEncoding operator=(TraceContextEncoding&&) = delete;
};
// TODO: This may not be needed. Check to see if opencensus requires
// a trailing server response.
// RpcServerStatsEncoding encapsulates the logic for encoding and decoding of
// rpc server stats messages. Rpc server stats consists of a uint64_t time
// value (server latency in nanoseconds).
class RpcServerStatsEncoding {
public:
// Size of encoded RPC server stats.
static constexpr size_t kRpcServerStatsSize = 10;
// Error value.
static constexpr size_t kEncodeDecodeFailure = 0;
// Deserializes rpc server stats from the incoming 'buf' into *time. Returns
// number of bytes decoded. If the buffer is of insufficient size (it must be
// at least kRpcServerStatsSize bytes) or the encoding version or field ID are
// unrecognized, *time will be set to 0 and it will return
// kEncodeDecodeFailure. Inlined for performance reasons.
static size_t Decode(absl::string_view buf, uint64_t* time) {
if (buf.size() < kRpcServerStatsSize) {
*time = 0;
return kEncodeDecodeFailure;
}
uint8_t version = buf[kVersionIdOffset];
uint32_t fieldID = buf[kServerElapsedTimeOffset];
if (version != kVersionId || fieldID != kServerElapsedTimeField) {
*time = 0;
return kEncodeDecodeFailure;
}
*time = absl::little_endian::Load64(
&buf[kServerElapsedTimeOffset + kFieldIdSize]);
return kRpcServerStatsSize;
}
// Serializes rpc server stats into the provided buffer. It returns the
// number of bytes written to the buffer. If the buffer is smaller than
// kRpcServerStatsSize bytes it will return kEncodeDecodeFailure. Inlined for
// performance reasons.
static size_t Encode(uint64_t time, char* buf, size_t buf_size) {
if (buf_size < kRpcServerStatsSize) {
return kEncodeDecodeFailure;
}
buf[kVersionIdOffset] = kVersionId;
buf[kServerElapsedTimeOffset] = kServerElapsedTimeField;
absl::little_endian::Store64(&buf[kServerElapsedTimeOffset + kFieldIdSize],
time);
return kRpcServerStatsSize;
}
private:
// Size of Version ID.
static constexpr size_t kVersionIdSize = 1;
// Size of Field ID.
static constexpr size_t kFieldIdSize = 1;
// Offset and value for currently supported version ID.
static constexpr size_t kVersionIdOffset = 0;
static constexpr size_t kVersionId = 0;
enum FieldIdValue {
kServerElapsedTimeField = 0,
};
enum FieldSize {
kServerElapsedTimeSize = 8,
};
enum FieldIdOffset {
kServerElapsedTimeOffset = kVersionIdSize,
};
RpcServerStatsEncoding() = delete;
RpcServerStatsEncoding(const RpcServerStatsEncoding&) = delete;
RpcServerStatsEncoding(RpcServerStatsEncoding&&) = delete;
RpcServerStatsEncoding operator=(const RpcServerStatsEncoding&) = delete;
RpcServerStatsEncoding operator=(RpcServerStatsEncoding&&) = delete;
};
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H */

@ -0,0 +1,198 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/server_filter.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "opencensus/stats/stats.h"
#include "src/core/lib/surface/call.h"
#include "src/cpp/ext/filters/census/grpc_plugin.h"
#include "src/cpp/ext/filters/census/measures.h"
namespace grpc {
constexpr uint32_t CensusServerCallData::kMaxServerStatsLen;
namespace {
// server metadata elements
struct ServerMetadataElements {
grpc_slice path;
grpc_slice tracing_slice;
grpc_slice census_proto;
};
void FilterInitialMetadata(grpc_metadata_batch* b,
ServerMetadataElements* sml) {
if (b->idx.named.path != nullptr) {
sml->path = grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.path->md));
}
if (b->idx.named.grpc_trace_bin != nullptr) {
sml->tracing_slice =
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_trace_bin->md));
grpc_metadata_batch_remove(b, b->idx.named.grpc_trace_bin);
}
if (b->idx.named.grpc_tags_bin != nullptr) {
sml->census_proto =
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_tags_bin->md));
grpc_metadata_batch_remove(b, b->idx.named.grpc_tags_bin);
}
}
} // namespace
void CensusServerCallData::OnDoneRecvMessageCb(void* user_data,
grpc_error* error) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
CensusServerCallData* calld =
reinterpret_cast<CensusServerCallData*>(elem->call_data);
CensusChannelData* channeld =
reinterpret_cast<CensusChannelData*>(elem->channel_data);
GPR_ASSERT(calld != nullptr);
GPR_ASSERT(channeld != nullptr);
// Stream messages are no longer valid after receiving trailing metadata.
if ((*calld->recv_message_) != nullptr) {
++calld->recv_message_count_;
}
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error));
}
void CensusServerCallData::OnDoneRecvInitialMetadataCb(void* user_data,
grpc_error* error) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
CensusServerCallData* calld =
reinterpret_cast<CensusServerCallData*>(elem->call_data);
GPR_ASSERT(calld != nullptr);
if (error == GRPC_ERROR_NONE) {
grpc_metadata_batch* initial_metadata = calld->recv_initial_metadata_;
GPR_ASSERT(initial_metadata != nullptr);
ServerMetadataElements sml;
sml.path = grpc_empty_slice();
sml.tracing_slice = grpc_empty_slice();
sml.census_proto = grpc_empty_slice();
FilterInitialMetadata(initial_metadata, &sml);
calld->path_ = grpc_slice_ref_internal(sml.path);
calld->method_ = GetMethod(&calld->path_);
calld->qualified_method_ = StrCat("Recv.", calld->method_);
const char* tracing_str =
GRPC_SLICE_IS_EMPTY(sml.tracing_slice)
? ""
: reinterpret_cast<const char*>(
GRPC_SLICE_START_PTR(sml.tracing_slice));
size_t tracing_str_len = GRPC_SLICE_IS_EMPTY(sml.tracing_slice)
? 0
: GRPC_SLICE_LENGTH(sml.tracing_slice);
const char* census_str = GRPC_SLICE_IS_EMPTY(sml.census_proto)
? ""
: reinterpret_cast<const char*>(
GRPC_SLICE_START_PTR(sml.census_proto));
size_t census_str_len = GRPC_SLICE_IS_EMPTY(sml.census_proto)
? 0
: GRPC_SLICE_LENGTH(sml.census_proto);
GenerateServerContext(absl::string_view(tracing_str, tracing_str_len),
absl::string_view(census_str, census_str_len),
/*primary_role*/ "", calld->qualified_method_,
&calld->context_);
grpc_slice_unref_internal(sml.tracing_slice);
grpc_slice_unref_internal(sml.census_proto);
grpc_slice_unref_internal(sml.path);
grpc_census_call_set_context(
calld->gc_, reinterpret_cast<census_context*>(&calld->context_));
}
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_initial_metadata_,
GRPC_ERROR_REF(error));
}
void CensusServerCallData::StartTransportStreamOpBatch(
grpc_call_element* elem, TransportStreamOpBatch* op) {
if (op->recv_initial_metadata() != nullptr) {
// substitute our callback for the op callback
recv_initial_metadata_ = op->recv_initial_metadata()->batch();
initial_on_done_recv_initial_metadata_ = op->recv_initial_metadata_ready();
op->set_recv_initial_metadata_ready(&on_done_recv_initial_metadata_);
}
if (op->send_message() != nullptr) {
++sent_message_count_;
}
if (op->recv_message() != nullptr) {
recv_message_ = op->op()->payload->recv_message.recv_message;
initial_on_done_recv_message_ =
op->op()->payload->recv_message.recv_message_ready;
op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_;
}
// We need to record the time when the trailing metadata was sent to mark the
// completeness of the request.
if (op->send_trailing_metadata() != nullptr) {
elapsed_time_ = absl::Now() - start_time_;
size_t len = ServerStatsSerialize(absl::ToInt64Nanoseconds(elapsed_time_),
stats_buf_, kMaxServerStatsLen);
if (len > 0) {
GRPC_LOG_IF_ERROR(
"census grpc_filter",
grpc_metadata_batch_add_tail(
op->send_trailing_metadata()->batch(), &census_bin_,
grpc_mdelem_from_slices(
GRPC_MDSTR_GRPC_SERVER_STATS_BIN,
grpc_slice_from_copied_buffer(stats_buf_, len))));
}
}
// Call next op.
grpc_call_next_op(elem, op->op());
}
grpc_error* CensusServerCallData::Init(grpc_call_element* elem,
const grpc_call_element_args* args) {
start_time_ = absl::Now();
gc_ =
grpc_call_from_top_element(grpc_call_stack_element(args->call_stack, 0));
GRPC_CLOSURE_INIT(&on_done_recv_initial_metadata_,
OnDoneRecvInitialMetadataCb, elem,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem,
grpc_schedule_on_exec_ctx);
auth_context_ = grpc_call_auth_context(gc_);
return GRPC_ERROR_NONE;
}
void CensusServerCallData::Destroy(grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) {
const uint64_t request_size = GetOutgoingDataSize(final_info);
const uint64_t response_size = GetIncomingDataSize(final_info);
double elapsed_time_ms = absl::ToDoubleMilliseconds(elapsed_time_);
grpc_auth_context_release(auth_context_);
::opencensus::stats::Record(
{{RpcServerSentBytesPerRpc(), static_cast<double>(response_size)},
{RpcServerReceivedBytesPerRpc(), static_cast<double>(request_size)},
{RpcServerServerLatency(), elapsed_time_ms},
{RpcServerSentMessagesPerRpc(), sent_message_count_},
{RpcServerReceivedMessagesPerRpc(), recv_message_count_}},
{{ServerMethodTagKey(), method_},
{ServerStatusTagKey(), StatusCodeToString(final_info->final_status)}});
grpc_slice_unref_internal(path_);
context_.EndSpan();
}
} // namespace grpc

@ -0,0 +1,101 @@
/*
*
* Copyright 2018 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H
#include <grpc/support/port_platform.h>
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "include/grpc/grpc_security.h"
#include "src/cpp/ext/filters/census/channel_filter.h"
#include "src/cpp/ext/filters/census/context.h"
namespace grpc {
// A CallData class will be created for every grpc call within a channel. It is
// used to store data and methods specific to that call. CensusServerCallData is
// thread-compatible, however typically only 1 thread should be interacting with
// a call at a time.
class CensusServerCallData : public CallData {
public:
// Maximum size of server stats that are sent on the wire.
static constexpr uint32_t kMaxServerStatsLen = 16;
CensusServerCallData()
: gc_(nullptr),
auth_context_(nullptr),
recv_initial_metadata_(nullptr),
initial_on_done_recv_initial_metadata_(nullptr),
initial_on_done_recv_message_(nullptr),
recv_message_(nullptr),
recv_message_count_(0),
sent_message_count_(0) {
memset(&census_bin_, 0, sizeof(grpc_linked_mdelem));
memset(&path_, 0, sizeof(grpc_slice));
memset(&on_done_recv_initial_metadata_, 0, sizeof(grpc_closure));
memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
}
grpc_error* Init(grpc_call_element* elem,
const grpc_call_element_args* args) override;
void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) override;
void StartTransportStreamOpBatch(grpc_call_element* elem,
TransportStreamOpBatch* op) override;
static void OnDoneRecvInitialMetadataCb(void* user_data, grpc_error* error);
static void OnDoneRecvMessageCb(void* user_data, grpc_error* error);
private:
CensusContext context_;
// server method
absl::string_view method_;
std::string qualified_method_;
grpc_slice path_;
// Pointer to the grpc_call element
grpc_call* gc_;
// Authorization context for the call.
grpc_auth_context* auth_context_;
// Metadata element for census stats.
grpc_linked_mdelem census_bin_;
// recv callback
grpc_metadata_batch* recv_initial_metadata_;
grpc_closure* initial_on_done_recv_initial_metadata_;
grpc_closure on_done_recv_initial_metadata_;
// recv message
grpc_closure* initial_on_done_recv_message_;
grpc_closure on_done_recv_message_;
absl::Time start_time_;
absl::Duration elapsed_time_;
grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_;
uint64_t recv_message_count_;
uint64_t sent_message_count_;
// Buffer needed for grpc_slice to reference it when adding metatdata to
// response.
char stats_buf_[kMaxServerStatsLen];
};
} // namespace grpc
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H */

@ -0,0 +1,491 @@
/*
*
* Copyright 2018 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/cpp/ext/filters/census/grpc_plugin.h"
#include "absl/time/time.h"
#include "opencensus/stats/internal/aggregation_window.h"
#include "opencensus/stats/internal/set_aggregation_window.h"
#include "opencensus/stats/stats.h"
namespace grpc {
using ::opencensus::stats::Aggregation;
using ::opencensus::stats::AggregationWindow;
using ::opencensus::stats::BucketBoundaries;
using ::opencensus::stats::ViewDescriptor;
// These measure definitions should be kept in sync across opencensus
// implementations.
namespace {
Aggregation BytesDistributionAggregation() {
return Aggregation::Distribution(BucketBoundaries::Explicit(
{0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216,
67108864, 268435456, 1073741824, 4294967296}));
}
Aggregation MillisDistributionAggregation() {
return Aggregation::Distribution(BucketBoundaries::Explicit(
{0, 0.01, 0.05, 0.1, 0.3, 0.6, 0.8, 1, 2, 3, 4,
5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50,
65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650,
800, 1000, 2000, 5000, 10000, 20000, 50000, 100000}));
}
Aggregation CountDistributionAggregation() {
return Aggregation::Distribution(BucketBoundaries::Exponential(17, 1.0, 2.0));
}
ViewDescriptor MinuteDescriptor() {
auto descriptor = ViewDescriptor();
SetAggregationWindow(AggregationWindow::Interval(absl::Minutes(1)),
&descriptor);
return descriptor;
}
ViewDescriptor HourDescriptor() {
auto descriptor = ViewDescriptor();
SetAggregationWindow(AggregationWindow::Interval(absl::Hours(1)),
&descriptor);
return descriptor;
}
} // namespace
void RegisterOpenCensusViewsForExport() {
ClientSentMessagesPerRpcCumulative().RegisterForExport();
ClientSentBytesPerRpcCumulative().RegisterForExport();
ClientReceivedMessagesPerRpcCumulative().RegisterForExport();
ClientReceivedBytesPerRpcCumulative().RegisterForExport();
ClientRoundtripLatencyCumulative().RegisterForExport();
ClientServerLatencyCumulative().RegisterForExport();
ServerSentMessagesPerRpcCumulative().RegisterForExport();
ServerSentBytesPerRpcCumulative().RegisterForExport();
ServerReceivedMessagesPerRpcCumulative().RegisterForExport();
ServerReceivedBytesPerRpcCumulative().RegisterForExport();
ServerServerLatencyCumulative().RegisterForExport();
}
// client cumulative
const ViewDescriptor& ClientSentBytesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/sent_bytes_per_rpc/cumulative")
.set_measure(kRpcClientSentBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientReceivedBytesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/received_bytes_per_rpc/cumulative")
.set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientRoundtripLatencyCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/roundtrip_latency/cumulative")
.set_measure(kRpcClientRoundtripLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientServerLatencyCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/server_latency/cumulative")
.set_measure(kRpcClientServerLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientCompletedRpcsCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/completed_rpcs/cumulative")
.set_measure(kRpcClientRoundtripLatencyMeasureName)
.set_aggregation(Aggregation::Count())
.add_column(ClientMethodTagKey())
.add_column(ClientStatusTagKey());
return descriptor;
}
const ViewDescriptor& ClientSentMessagesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/received_messages_per_rpc/cumulative")
.set_measure(kRpcClientSentMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientReceivedMessagesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/client/sent_messages_per_rpc/cumulative")
.set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
// server cumulative
const ViewDescriptor& ServerSentBytesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/server/received_bytes_per_rpc/cumulative")
.set_measure(kRpcServerSentBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerReceivedBytesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/server/sent_bytes_per_rpc/cumulative")
.set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerServerLatencyCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/server/elapsed_time/cumulative")
.set_measure(kRpcServerServerLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerCompletedRpcsCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/server/completed_rpcs/cumulative")
.set_measure(kRpcServerServerLatencyMeasureName)
.set_aggregation(Aggregation::Count())
.add_column(ServerMethodTagKey())
.add_column(ServerStatusTagKey());
return descriptor;
}
const ViewDescriptor& ServerSentMessagesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/server/received_messages_per_rpc/cumulative")
.set_measure(kRpcServerSentMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerReceivedMessagesPerRpcCumulative() {
const static ViewDescriptor descriptor =
ViewDescriptor()
.set_name("grpc.io/server/sent_messages_per_rpc/cumulative")
.set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
// client minute
const ViewDescriptor& ClientSentBytesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/sent_bytes_per_rpc/minute")
.set_measure(kRpcClientSentBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientReceivedBytesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/received_bytes_per_rpc/minute")
.set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientRoundtripLatencyMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/roundtrip_latency/minute")
.set_measure(kRpcClientRoundtripLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientServerLatencyMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/server_latency/minute")
.set_measure(kRpcClientServerLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientCompletedRpcsMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/completed_rpcs/minute")
.set_measure(kRpcClientRoundtripLatencyMeasureName)
.set_aggregation(Aggregation::Count())
.add_column(ClientMethodTagKey())
.add_column(ClientStatusTagKey());
return descriptor;
}
const ViewDescriptor& ClientSentMessagesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/sent_messages_per_rpc/minute")
.set_measure(kRpcClientSentMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientReceivedMessagesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/client/received_messages_per_rpc/minute")
.set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
// server minute
const ViewDescriptor& ServerSentBytesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/server/sent_bytes_per_rpc/minute")
.set_measure(kRpcServerSentBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerReceivedBytesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/server/received_bytes_per_rpc/minute")
.set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerServerLatencyMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/server/server_latency/minute")
.set_measure(kRpcServerServerLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerCompletedRpcsMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/server/completed_rpcs/minute")
.set_measure(kRpcServerServerLatencyMeasureName)
.set_aggregation(Aggregation::Count())
.add_column(ServerMethodTagKey())
.add_column(ServerStatusTagKey());
return descriptor;
}
const ViewDescriptor& ServerSentMessagesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/server/sent_messages_per_rpc/minute")
.set_measure(kRpcServerSentMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerReceivedMessagesPerRpcMinute() {
const static ViewDescriptor descriptor =
MinuteDescriptor()
.set_name("grpc.io/server/received_messages_per_rpc/minute")
.set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
// client hour
const ViewDescriptor& ClientSentBytesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/sent_bytes_per_rpc/hour")
.set_measure(kRpcClientSentBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientReceivedBytesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/received_bytes_per_rpc/hour")
.set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientRoundtripLatencyHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/roundtrip_latency/hour")
.set_measure(kRpcClientRoundtripLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientServerLatencyHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/server_latency/hour")
.set_measure(kRpcClientServerLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientCompletedRpcsHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/completed_rpcs/hour")
.set_measure(kRpcClientRoundtripLatencyMeasureName)
.set_aggregation(Aggregation::Count())
.add_column(ClientMethodTagKey())
.add_column(ClientStatusTagKey());
return descriptor;
}
const ViewDescriptor& ClientSentMessagesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/sent_messages_per_rpc/hour")
.set_measure(kRpcClientSentMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
const ViewDescriptor& ClientReceivedMessagesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/client/received_messages_per_rpc/hour")
.set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ClientMethodTagKey());
return descriptor;
}
// server hour
const ViewDescriptor& ServerSentBytesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/server/sent_bytes_per_rpc/hour")
.set_measure(kRpcServerSentBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerReceivedBytesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/server/received_bytes_per_rpc/hour")
.set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
.set_aggregation(BytesDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerServerLatencyHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/server/server_latency/hour")
.set_measure(kRpcServerServerLatencyMeasureName)
.set_aggregation(MillisDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerCompletedRpcsHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/server/completed_rpcs/hour")
.set_measure(kRpcServerServerLatencyMeasureName)
.set_aggregation(Aggregation::Count())
.add_column(ServerMethodTagKey())
.add_column(ServerStatusTagKey());
return descriptor;
}
const ViewDescriptor& ServerSentMessagesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/server/sent_messages_per_rpc/hour")
.set_measure(kRpcServerSentMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
const ViewDescriptor& ServerReceivedMessagesPerRpcHour() {
const static ViewDescriptor descriptor =
HourDescriptor()
.set_name("grpc.io/server/received_messages_per_rpc/hour")
.set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
.set_aggregation(CountDistributionAggregation())
.add_column(ServerMethodTagKey());
return descriptor;
}
} // namespace grpc

@ -24,7 +24,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Extends the CallInvoker class to provide the interceptor facility on the client side.
/// This is an EXPERIMENTAL API.
/// </summary>
public static class CallInvokerExtensions
{

@ -22,7 +22,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Provides extension methods to make it easy to register interceptors on Channel objects.
/// This is an EXPERIMENTAL API.
/// </summary>
public static class ChannelExtensions
{

@ -25,7 +25,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Carries along the context associated with intercepted invocations on the client side.
/// This is an EXPERIMENTAL API.
/// </summary>
public struct ClientInterceptorContext<TRequest, TResponse>
where TRequest : class

@ -25,7 +25,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Serves as the base class for gRPC interceptors.
/// This is an EXPERIMENTAL API.
/// </summary>
public abstract class Interceptor
{

@ -24,14 +24,12 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Extends the ServerServiceDefinition class to add methods used to register interceptors on the server side.
/// This is an EXPERIMENTAL API.
/// </summary>
public static class ServerServiceDefinitionExtensions
{
/// <summary>
/// Returns a <see cref="Grpc.Core.ServerServiceDefinition" /> instance that
/// intercepts incoming calls to the underlying service handler through the given interceptor.
/// This is an EXPERIMENTAL API.
/// </summary>
/// <param name="serverServiceDefinition">The <see cref="Grpc.Core.ServerServiceDefinition" /> instance to register interceptors on.</param>
/// <param name="interceptor">The interceptor to intercept the incoming invocations with.</param>
@ -52,7 +50,6 @@ namespace Grpc.Core.Interceptors
/// <summary>
/// Returns a <see cref="Grpc.Core.ServerServiceDefinition" /> instance that
/// intercepts incoming calls to the underlying service handler through the given interceptors.
/// This is an EXPERIMENTAL API.
/// </summary>
/// <param name="serverServiceDefinition">The <see cref="Grpc.Core.ServerServiceDefinition" /> instance to register interceptors on.</param>
/// <param name="interceptors">

@ -29,7 +29,7 @@ using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// gRPC server. A single server can server arbitrary number of services and can listen on more than one ports.
/// gRPC server. A single server can serve an arbitrary number of services and can listen on more than one port.
/// </summary>
public class Server
{

@ -935,11 +935,12 @@ grpcsharp_ssl_credentials_create(const char* pem_root_certs,
if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
key_cert_pair.cert_chain = key_cert_pair_cert_chain;
key_cert_pair.private_key = key_cert_pair_private_key;
return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL);
return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL,
NULL);
} else {
GPR_ASSERT(!key_cert_pair_cert_chain);
GPR_ASSERT(!key_cert_pair_private_key);
return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL, NULL);
}
}

@ -183,14 +183,14 @@ static NSMutableDictionary *kHostCache;
grpc_channel_credentials *creds;
if (pemPrivateKey == nil && pemCertChain == nil) {
creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL);
creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL);
} else {
grpc_ssl_pem_key_cert_pair key_cert_pair;
NSData *privateKeyASCII = [self nullTerminatedDataWithString:pemPrivateKey];
NSData *certChainASCII = [self nullTerminatedDataWithString:pemCertChain];
key_cert_pair.private_key = privateKeyASCII.bytes;
key_cert_pair.cert_chain = certChainASCII.bytes;
creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL);
creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL, NULL);
}
@synchronized(self) {

@ -158,7 +158,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
grpc_channel_credentials *creds = grpc_ssl_credentials_create(
pem_root_certs,
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, hashstr, false
TSRMLS_CC);
efree(hashkey);

@ -1,3 +0,0 @@
google.census.Tag.key max_size:255
google.census.Tag.value max_size:255
google.census.View.tag_key max_count:15

@ -1,307 +0,0 @@
// Copyright 2016 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.
syntax = "proto3";
package google.census;
// All the census protos.
//
// Nomenclature note: capitalized names below (like Resource) are protos.
//
// Census lets you define a Resource - something which can be measured, like the
// latency of an RPC, the number of CPU cycles spent on an operation, or
// anything else you care to measure. You can record individual instances of
// measurements (a double value) for every Resource of interest. These
// individual measurements are aggregated together into an Aggregation. There
// are two Aggregation types available: Distribution (describes the
// distribution of all measurements, possibly with a histogram) and
// IntervalStats (the count and mean of measurements across specified time
// periods). An Aggregation is described by an AggregationDescriptor.
//
// You can define how your stats are broken down by Tag values and which
// Aggregations to use through a View. The corresponding combination of
// Resource/View/Aggregation which is available to census clients is called a
// Metric.
// The following two types are copied from
// google/protobuf/{duration,timestamp}.proto. Ideally, we would be able to
// import them, but this causes compilation issues on C-based systems
// (e.g. https://koti.kapsi.fi/jpa/nanopb/), which cannot process the C++
// headers generated from the standard protobuf distribution. See the relevant
// proto files for full documentation of these types.
message Duration {
// Signed seconds of the span of time. Must be from -315,576,000,000
// to +315,576,000,000 inclusive.
int64 seconds = 1;
// Signed fractions of a second at nanosecond resolution of the span
// of time. Durations less than one second are represented with a 0
// `seconds` field and a positive or negative `nanos` field. For durations
// of one second or more, a non-zero value for the `nanos` field must be
// of the same sign as the `seconds` field. Must be from -999,999,999
// to +999,999,999 inclusive.
int32 nanos = 2;
}
message Timestamp {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
int64 seconds = 1;
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
int32 nanos = 2;
}
// Describes a Resource.
message Resource {
// name of resource, e.g. rpc_latency, cpu. Must be unique.
string name = 1;
// More detailed description of the resource, used in documentation.
string description = 2;
// Fundamental units of measurement supported by Census
// TODO(aveitch): expand this to include other S.I. units?
enum BasicUnit {
UNKNOWN = 0;
BITS = 1;
BYTES = 2;
SECS = 3;
CORES = 4;
MAX_UNITS = 5;
}
// MeasurementUnit lets you build compound units of the form
// 10^n * (A * B * ...) / (X * Y * ...),
// where the elements in the numerator and denominator are all BasicUnits. A
// MeasurementUnit must have at least one BasicUnit in its numerator.
//
// To specify multiplication in the numerator or denominator, simply specify
// multiple numerator or denominator fields. For example:
//
// - byte-seconds (i.e. bytes * seconds):
// numerator: BYTES
// numerator: SECS
//
// - events/sec^2 (i.e. rate of change of events/sec):
// numerator: COUNT
// denominator: SECS
// denominator: SECS
//
// To specify multiples (in power of 10) of units, specify a non-zero prefix
// value, for example:
//
// - MB/s (i.e. megabytes / s):
// prefix: 6
// numerator: BYTES
// denominator: SECS
//
// - nanoseconds
// prefix: -9
// numerator: SECS
message MeasurementUnit {
int32 prefix = 1;
repeated BasicUnit numerator = 2;
repeated BasicUnit denominator = 3;
}
// The units in which Resource values are measured.
MeasurementUnit unit = 3;
}
// An Aggregation summarizes a series of individual Resource measurements, an
// AggregationDescriptor describes an Aggregation.
message AggregationDescriptor {
enum AggregationType {
// Unspecified. Should not be used.
UNKNOWN = 0;
// A count of measurements made.
COUNT = 1;
// A Distribution.
DISTRIBUTION = 2;
// Counts over fixed time intervals.
INTERVAL = 3;
}
// The type of Aggregation.
AggregationType type = 1;
// At most one set of options. It is illegal to specifiy an option for
// COUNT Aggregations. interval_boundaries must be set for INTERVAL types.
// bucket_boundaries are optional for DISTRIBUTION types.
oneof options {
// Defines histogram bucket boundaries for Distributions.
BucketBoundaries bucket_boundaries = 2;
// Defines the time windows to record for IntervalStats.
IntervalBoundaries interval_boundaries = 3;
}
// A Distribution may optionally contain a histogram of the values in the
// population. The bucket boundaries for that histogram are described by
// `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The
// boundaries for bucket index i are:
//
// [-infinity, bounds[i]) for i == 0
// [bounds[i-1], bounds[i]) for 0 < i < N-2
// [bounds[i-1], +infinity) for i == N-1
//
// i.e. an underflow bucket (number 0), zero or more finite buckets (1
// through N - 2, and an overflow bucket (N - 1), with inclusive lower
// bounds and exclusive upper bounds.
//
// There must be at least one element in `bounds`. If `bounds` has only one
// element, there are no finite buckets, and that single element is the
// common boundary of the overflow and underflow buckets.
message BucketBoundaries {
// The values must be monotonically increasing.
repeated double bounds = 1;
}
// For Interval stats, describe the size of each window.
message IntervalBoundaries {
// For each time window, specify a duration in seconds.
repeated double window_size = 1;
}
}
// Distribution contains summary statistics for a population of values and,
// optionally, a histogram representing the distribution of those values across
// a specified set of histogram buckets, as defined in
// Aggregation.bucket_options.
//
// The summary statistics are the count, mean, minimum, and the maximum of the
// set of population of values.
//
// Although it is not forbidden, it is generally a bad idea to include
// non-finite values (infinities or NaNs) in the population of values, as this
// will render the `mean` field meaningless.
message Distribution {
// The number of values in the population. Must be non-negative.
int64 count = 1;
// The arithmetic mean of the values in the population. If `count` is zero
// then this field must be zero.
double mean = 2;
// Describes a range of population values.
message Range {
// The minimum of the population values.
double min = 1;
// The maximum of the population values.
double max = 2;
}
// The range of the population values. If `count` is zero, this field will not
// be defined.
Range range = 3;
// A Distribution may optionally contain a histogram of the values in the
// population. The histogram is given in `bucket_count` as counts of values
// that fall into one of a sequence of non-overlapping buckets, as described
// by `AggregationDescriptor.options.bucket_boundaries`.
// The sum of the values in `bucket_counts` must equal the value in `count`.
//
// Bucket counts are given in order under the numbering scheme described
// above (the underflow bucket has number 0; the finite buckets, if any,
// have numbers 1 through N-2; the overflow bucket has number N-1).
//
// The size of `bucket_count` must be no greater than N as defined in
// `bucket_boundaries`.
//
// Any suffix of trailing zero bucket_count fields may be omitted.
repeated int64 bucket_count = 4;
}
// Record summary stats over various time windows.
message IntervalStats {
// Summary statistic over a single time window.
message Window {
// The window duration. Must be positive.
Duration window_size = 1;
// The number of measurements in this window.
int64 count = 2;
// The arithmetic mean of all measurements in the window.
double mean = 3;
}
// Full set of windows for this aggregation.
repeated Window window = 1;
}
// A Tag: key-value pair.
message Tag {
string key = 1;
string value = 2;
}
// A View specifies an Aggregation and a set of tag keys. The Aggregation will
// be broken down by the unique set of matching tag values for each measurement.
message View {
// Name of view. Must be unique.
string name = 1;
// More detailed description, for documentation purposes.
string description = 2;
// Name of Resource to be broken down for this view.
string resource_name = 3;
// Aggregation type to associate with this View.
AggregationDescriptor aggregation = 4;
// Tag keys to match with a given Resource measurement. If no keys are
// specified, then all stats are recorded. Keys must be unique.
repeated string tag_key = 5;
}
// An Aggregation summarizes a series of individual Resource measurements.
message Aggregation {
// Name of this aggregation.
string name = 1;
// More detailed description, for documentation purposes.
string description = 2;
// The data for this Aggregation.
oneof data {
uint64 count = 3;
Distribution distribution = 4;
IntervalStats interval_stats = 5;
}
// Tags associated with this Aggregation.
repeated Tag tag = 6;
}
// A Metric represents all the Aggregations for a particular view.
message Metric {
// View associated with this Metric.
string view_name = 1;
// Aggregations - each will have a unique set of tag values for the tag_keys
// associated with the corresponding View.
repeated Aggregation aggregation = 2;
// Start and end timestamps over which the metric was accumulated. These
// values are not relevant/defined for IntervalStats aggregations, which are
// always accumulated over a fixed time period.
Timestamp start = 3;
Timestamp end = 4;
}

@ -1,29 +0,0 @@
// Copyright 2016 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.
syntax = "proto3";
package google.trace;
// Tracing information that is propagated with RPC's.
message TraceContext {
// A TraceId uniquely represents a single Trace. It is a 128-bit nonce.
// The 128-bit ID is split into 2 64-bit chunks. (REQUIRED)
fixed64 trace_id_hi = 1;
fixed64 trace_id_lo = 2;
// ID of parent (client) span. (REQUIRED)
fixed64 span_id = 3;
// Span option flags. First bit is true if this trace is sampled. (OPTIONAL)
fixed32 span_options = 4;
}

@ -142,12 +142,12 @@ cdef class SSLChannelCredentials(ChannelCredentials):
c_pem_root_certificates = self._pem_root_certificates
if self._private_key is None and self._certificate_chain is None:
return grpc_ssl_credentials_create(
c_pem_root_certificates, NULL, NULL)
c_pem_root_certificates, NULL, NULL, NULL)
else:
c_pem_key_certificate_pair.private_key = self._private_key
c_pem_key_certificate_pair.certificate_chain = self._certificate_chain
return grpc_ssl_credentials_create(
c_pem_root_certificates, &c_pem_key_certificate_pair, NULL)
c_pem_root_certificates, &c_pem_key_certificate_pair, NULL, NULL)
cdef class CompositeChannelCredentials(ChannelCredentials):

@ -453,11 +453,14 @@ cdef extern from "grpc/grpc_security.h":
# We don't care about the internals (and in fact don't know them)
pass
ctypedef struct grpc_ssl_session_cache:
# We don't care about the internals (and in fact don't know them)
pass
ctypedef struct verify_peer_options:
# We don't care about the internals (and in fact don't know them)
pass
ctypedef void (*grpc_ssl_roots_override_callback)(char **pem_root_certs)
grpc_ssl_session_cache *grpc_ssl_session_cache_create_lru(size_t capacity)
@ -469,7 +472,7 @@ cdef extern from "grpc/grpc_security.h":
grpc_channel_credentials *grpc_google_default_credentials_create() nogil
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
void *reserved) nogil
verify_peer_options *verify_options, void *reserved) nogil
grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *creds1, grpc_call_credentials *creds2,
void *reserved) nogil

@ -346,6 +346,7 @@ CORE_SOURCE_FILES = [
'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/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc',
@ -353,7 +354,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
'src/core/ext/census/grpc_context.cc',
'src/cpp/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
'src/core/ext/filters/http/client_authority_filter.cc',

@ -0,0 +1,54 @@
# Copyright 2018 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.
require 'open3'
require 'tmpdir'
def main
root_dir = File.join(File.dirname(__FILE__), '..', '..', '..')
pb_dir = File.join(root_dir, 'src', 'ruby', 'end2end', 'protos')
fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG']
bins_sub_dir = ENV['CONFIG']
bins_dir = File.join(root_dir, 'bins', bins_sub_dir)
plugin = File.join(bins_dir, 'grpc_ruby_plugin')
protoc = File.join(bins_dir, 'protobuf', 'protoc')
got = nil
Dir.mktmpdir do |tmp_dir|
gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb')
pid = spawn(
protoc,
"--proto_path=#{pb_dir}",
'package_with_underscore/service.proto',
"--grpc_out=#{tmp_dir}",
"--plugin=protoc-gen-grpc=#{plugin}"
)
Process.waitpid2(pid)
File.open(gen_out) { |f| got = f.read }
end
correct_modularized_rpc = 'rpc :TestOne, ' \
'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \
'Grpc::Testing::PackageWithUnderscore::Data::Response'
return if got.include?(correct_modularized_rpc)
fail 'generated file does not match with correct_modularized_rpc'
end
main

@ -159,12 +159,12 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv,
pem_root_certs_cstr = RSTRING_PTR(pem_root_certs);
}
if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL);
creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL, NULL);
} else {
key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
creds =
grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair, NULL);
creds = grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair,
NULL, NULL);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");

@ -311,7 +311,7 @@ extern grpc_google_default_credentials_create_type grpc_google_default_credentia
typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
extern grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
#define grpc_set_ssl_roots_override_callback grpc_set_ssl_roots_override_callback_import
typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, void* reserved);
typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const verify_peer_options* verify_options, void* reserved);
extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
#define grpc_ssl_credentials_create grpc_ssl_credentials_create_import
typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
describe GRPC::Core::CallCredentials do
CallCredentials = GRPC::Core::CallCredentials

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
include GRPC::Core::StatusCodes

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
describe GRPC::Core::ChannelCredentials do
ChannelCredentials = GRPC::Core::ChannelCredentials

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
def create_channel_creds
test_root = File.join(File.dirname(__FILE__), 'testdata')

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
include GRPC::Core

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
describe GRPC::Core::CompressionOptions do
# Note these constants should be updated

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
StatusCodes = GRPC::Core::StatusCodes

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
Thread.abort_on_exception = true

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
require 'grpc/generic/rpc_desc'
describe GRPC::RpcDesc do

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
Thread.abort_on_exception = true

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
require 'grpc/generic/rpc_desc'
require 'grpc/generic/service'

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
require_relative '../lib/grpc/google_rpc_status_utils'
require_relative '../pb/src/proto/grpc/testing/messages_pb'
require_relative '../pb/src/proto/grpc/testing/messages_pb'

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'spec_helper'
require 'open3'
require 'tmpdir'

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
require 'grpc/health/v1/health_pb'
require 'grpc/health/checker'
require 'open3'

@ -1,51 +0,0 @@
# Copyright 2016 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.
require 'open3'
require 'tmpdir'
describe 'Package with underscore protobuf code generation' do
it 'should have the same content as created by code generation' do
root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..')
pb_dir = File.join(root_dir, 'src', 'ruby', 'spec', 'pb')
fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG']
bins_sub_dir = ENV['CONFIG']
bins_dir = File.join(root_dir, 'bins', bins_sub_dir)
plugin = File.join(bins_dir, 'grpc_ruby_plugin')
protoc = File.join(bins_dir, 'protobuf', 'protoc')
got = nil
Dir.mktmpdir do |tmp_dir|
gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb')
pid = spawn(
protoc,
'-I.',
'package_with_underscore/service.proto',
"--grpc_out=#{tmp_dir}",
"--plugin=protoc-gen-grpc=#{plugin}",
chdir: pb_dir)
Process.waitpid2(pid)
File.open(gen_out) { |f| got = f.read }
end
correct_modularized_rpc = 'rpc :TestOne, ' \
'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \
'Grpc::Testing::PackageWithUnderscore::Data::Response'
expect(got).to include(correct_modularized_rpc)
end
end

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')

@ -31,6 +31,7 @@ end if ENV['COVERAGE_NAME']
require 'rspec'
require 'logging'
require 'rspec/logging_helper'
require 'grpc'
require_relative 'support/services'
require_relative 'support/helpers'

@ -13,7 +13,7 @@
# limitations under the License.
# Test stubs for various scenarios
require 'grpc'
require 'spec_helper'
# A test message
class EchoMsg

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require 'grpc'
require 'spec_helper'
TimeConsts = GRPC::Core::TimeConsts

@ -70,6 +70,7 @@
'.',
'../..',
'include',
'../../third_party/nanopb',
],
'defines': [
'GRPC_ARES=0',

@ -23,6 +23,7 @@ RUN apt-get update && apt-get install -y ${'\\'}
strace ${'\\'}
python-dev ${'\\'}
python-setuptools ${'\\'}
python-yaml ${'\\'}
telnet ${'\\'}
unzip ${'\\'}
wget ${'\\'}

@ -11,4 +11,4 @@ RUN apt-get update && apt-get install -y ${'\\'}
# Install Python packages from PyPI
RUN pip install --upgrade pip==10.0.1
RUN pip install virtualenv
RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0 pyyaml==3.12
RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0

@ -37,7 +37,7 @@ static void* tag(intptr_t t) { return (void*)t; }
static void run_test(const char* target, size_t nops) {
grpc_channel_credentials* ssl_creds =
grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_channel* channel;
grpc_call* c;

@ -122,6 +122,7 @@ grpc_cc_test(
language = "C++",
deps = [
"//:grpc",
"//test/core/util:gpr_test_util",
],
external_deps = [
"gtest",

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

Loading…
Cancel
Save