Browse Source

Merge branch 'master' into aio-graduate

Lidi Zheng 5 years ago
parent
commit
6326422b05
100 changed files with 2673 additions and 3539 deletions
  1. 1 1
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 1 1
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 1 1
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 1 1
      .github/ISSUE_TEMPLATE/question.md
  5. 1 1
      .github/pull_request_template.md
  6. 1 1
      .gitmodules
  7. 24 4
      BUILD
  8. 0 4
      BUILD.gn
  9. 5 10
      CMakeLists.txt
  10. 7 1379
      Makefile
  11. 4 4
      bazel/grpc_deps.bzl
  12. 8 11
      build_autogenerated.yaml
  13. 2 0
      config.m4
  14. 2 0
      config.w32
  15. 7 0
      doc/python/sphinx/grpc.rst
  16. 5 2
      doc/ssl-performance.md
  17. 3 2
      doc/status_ordering.md
  18. 1 1
      examples/csharp/Helloworld/GreeterClient/Program.cs
  19. 1 1
      examples/csharp/Helloworld/GreeterServer/Program.cs
  20. 1 1
      examples/csharp/HelloworldLegacyCsproj/GreeterClient/Program.cs
  21. 1 1
      examples/csharp/HelloworldLegacyCsproj/GreeterServer/Program.cs
  22. 2 2
      examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs
  23. 3 3
      examples/csharp/HelloworldXamarin/Droid/MainActivity.cs
  24. 3 3
      examples/csharp/HelloworldXamarin/iOS/ViewController.cs
  25. 1 1
      examples/csharp/RouteGuide/RouteGuideClient/Program.cs
  26. 1 1
      examples/csharp/RouteGuide/RouteGuideServer/Program.cs
  27. 1 1
      examples/csharp/Xds/GreeterClient/Program.cs
  28. 1 1
      examples/csharp/Xds/GreeterServer/Program.cs
  29. 4 4
      examples/csharp/Xds/README.md
  30. 40 0
      examples/python/no_codegen/greeter_client.py
  31. 40 0
      examples/python/no_codegen/greeter_server.py
  32. 38 0
      examples/python/no_codegen/helloworld.proto
  33. 0 4
      gRPC-C++.podspec
  34. 2 1
      gRPC-Core.podspec
  35. 2 0
      grpc.gemspec
  36. 3 0
      grpc.gyp
  37. 22 0
      include/grpc/impl/codegen/README.md
  38. 91 2
      include/grpcpp/channel.h
  39. 0 130
      include/grpcpp/channel_impl.h
  40. 0 24
      include/grpcpp/completion_queue_impl.h
  41. 6 8
      include/grpcpp/generic/generic_stub.h
  42. 21 0
      include/grpcpp/impl/codegen/README.md
  43. 2 3
      include/grpcpp/impl/codegen/async_generic_service.h
  44. 15 18
      include/grpcpp/impl/codegen/async_stream_impl.h
  45. 7 7
      include/grpcpp/impl/codegen/async_unary_call_impl.h
  46. 6 9
      include/grpcpp/impl/codegen/call.h
  47. 5 5
      include/grpcpp/impl/codegen/call_op_set.h
  48. 9 10
      include/grpcpp/impl/codegen/channel_interface.h
  49. 18 22
      include/grpcpp/impl/codegen/client_callback_impl.h
  50. 501 4
      include/grpcpp/impl/codegen/client_context.h
  51. 0 517
      include/grpcpp/impl/codegen/client_context_impl.h
  52. 6 10
      include/grpcpp/impl/codegen/client_interceptor.h
  53. 4 7
      include/grpcpp/impl/codegen/client_unary_call.h
  54. 423 3
      include/grpcpp/impl/codegen/completion_queue.h
  55. 0 454
      include/grpcpp/impl/codegen/completion_queue_impl.h
  56. 4 4
      include/grpcpp/impl/codegen/delegating_channel.h
  57. 5 8
      include/grpcpp/impl/codegen/intercepted_channel.h
  58. 4 4
      include/grpcpp/impl/codegen/server_context_impl.h
  59. 28 32
      include/grpcpp/impl/codegen/server_interface.h
  60. 9 9
      include/grpcpp/impl/codegen/service_type.h
  61. 14 15
      include/grpcpp/impl/codegen/sync_stream_impl.h
  62. 2 2
      include/grpcpp/server_builder.h
  63. 24 22
      include/grpcpp/server_impl.h
  64. 2 0
      package.xml
  65. 13 1
      src/boringssl/boringssl_prefix_symbols.h
  66. 1 1
      src/compiler/BUILD
  67. 1 1
      src/compiler/ruby_generator_string-inl.h
  68. 47 8
      src/core/ext/filters/client_channel/client_channel.cc
  69. 2 1
      src/core/ext/filters/client_channel/health/health_check_client.cc
  70. 1 0
      src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
  71. 375 13
      src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
  72. 19 0
      src/core/ext/filters/client_channel/subchannel.cc
  73. 7 0
      src/core/ext/filters/client_channel/subchannel.h
  74. 5 4
      src/core/ext/transport/chttp2/client/chttp2_connector.cc
  75. 55 93
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  76. 1 28
      src/core/ext/transport/chttp2/transport/parsing.cc
  77. 7 8
      src/core/ext/transport/inproc/inproc_transport.cc
  78. 43 0
      src/core/ext/upb-generated/third_party/istio/security/proto/providers/google/meshca.upb.c
  79. 103 0
      src/core/ext/upb-generated/third_party/istio/security/proto/providers/google/meshca.upb.h
  80. 231 87
      src/core/ext/xds/xds_api.cc
  81. 23 25
      src/core/ext/xds/xds_api.h
  82. 19 347
      src/core/ext/xds/xds_client.cc
  83. 12 39
      src/core/ext/xds/xds_client.h
  84. 98 0
      src/core/lib/security/authorization/evaluate_args.cc
  85. 54 0
      src/core/lib/security/authorization/evaluate_args.h
  86. 4 8
      src/core/lib/security/authorization/mock_cel/activation.h
  87. 4 8
      src/core/lib/security/authorization/mock_cel/cel_value.h
  88. 28 20
      src/core/lib/surface/channel.cc
  89. 9 2
      src/core/lib/surface/channel.h
  90. 7 0
      src/core/lib/transport/transport.h
  91. 23 21
      src/core/lib/uri/uri_parser.cc
  92. 3 1
      src/core/lib/uri/uri_parser.h
  93. 3 9
      src/core/tsi/ssl_transport_security.cc
  94. 3 8
      src/cpp/client/channel_cc.cc
  95. 9 9
      src/cpp/client/client_context.cc
  96. 1 4
      src/cpp/client/secure_credentials.h
  97. 3 3
      src/cpp/common/completion_queue_cc.cc
  98. 2 2
      src/cpp/server/async_generic_service.cc
  99. 9 10
      src/cpp/server/server_builder.cc
  100. 2 2
      src/cpp/server/server_context.cc

+ 1 - 1
.github/ISSUE_TEMPLATE/bug_report.md

@@ -2,7 +2,7 @@
 name: Report a bug
 name: Report a bug
 about: Create a report to help us improve
 about: Create a report to help us improve
 labels: kind/bug, priority/P2
 labels: kind/bug, priority/P2
-assignees: nicolasnoble
+assignees: veblush
 
 
 ---
 ---
 
 

+ 1 - 1
.github/ISSUE_TEMPLATE/cleanup_request.md

@@ -2,7 +2,7 @@
 name: Request a cleanup
 name: Request a cleanup
 about: Suggest a cleanup in our repository
 about: Suggest a cleanup in our repository
 labels: kind/internal cleanup, priority/P2
 labels: kind/internal cleanup, priority/P2
-assignees: nicolasnoble
+assignees: veblush
 
 
 ---
 ---
 
 

+ 1 - 1
.github/ISSUE_TEMPLATE/feature_request.md

@@ -2,7 +2,7 @@
 name: Request a feature
 name: Request a feature
 about: Suggest an idea for this project
 about: Suggest an idea for this project
 labels: kind/enhancement, priority/P2
 labels: kind/enhancement, priority/P2
-assignees: nicolasnoble
+assignees: veblush
 
 
 ---
 ---
 
 

+ 1 - 1
.github/ISSUE_TEMPLATE/question.md

@@ -2,7 +2,7 @@
 name: Ask a question
 name: Ask a question
 about: Ask a question
 about: Ask a question
 labels: kind/question, priority/P3
 labels: kind/question, priority/P3
-assignees: nicolasnoble
+assignees: veblush
 
 
 ---
 ---
 
 

+ 1 - 1
.github/pull_request_template.md

@@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
 
 
 -->
 -->
 
 
-@nicolasnoble
+@veblush

+ 1 - 1
.gitmodules

@@ -22,7 +22,7 @@
 	url = https://github.com/google/boringssl.git
 	url = https://github.com/google/boringssl.git
 [submodule "third_party/re2"]
 [submodule "third_party/re2"]
 	path = third_party/re2
 	path = third_party/re2
-	url = git://github.com/google/re2.git
+	url = https://github.com/google/re2.git
 [submodule "third_party/cares/cares"]
 [submodule "third_party/cares/cares"]
 	path = third_party/cares/cares
 	path = third_party/cares/cares
 	url = https://github.com/c-ares/c-ares.git
 	url = https://github.com/c-ares/c-ares.git

+ 24 - 4
BUILD

@@ -220,10 +220,8 @@ GRPCXX_PUBLIC_HDRS = [
     "include/grpcpp/alarm.h",
     "include/grpcpp/alarm.h",
     "include/grpcpp/alarm_impl.h",
     "include/grpcpp/alarm_impl.h",
     "include/grpcpp/channel.h",
     "include/grpcpp/channel.h",
-    "include/grpcpp/channel_impl.h",
     "include/grpcpp/client_context.h",
     "include/grpcpp/client_context.h",
     "include/grpcpp/completion_queue.h",
     "include/grpcpp/completion_queue.h",
-    "include/grpcpp/completion_queue_impl.h",
     "include/grpcpp/create_channel.h",
     "include/grpcpp/create_channel.h",
     "include/grpcpp/create_channel_posix.h",
     "include/grpcpp/create_channel_posix.h",
     "include/grpcpp/ext/health_check_service_server_builder_option.h",
     "include/grpcpp/ext/health_check_service_server_builder_option.h",
@@ -954,6 +952,7 @@ grpc_cc_library(
         "madler_zlib",
         "madler_zlib",
         "absl/container:inlined_vector",
         "absl/container:inlined_vector",
         "absl/status",
         "absl/status",
+        "absl/strings",
         "absl/types:optional",
         "absl/types:optional",
     ],
     ],
     language = "c++",
     language = "c++",
@@ -1857,9 +1856,11 @@ grpc_cc_library(
     name = "grpc_authorization_engine",
     name = "grpc_authorization_engine",
     srcs = [
     srcs = [
         "src/core/lib/security/authorization/authorization_engine.cc",
         "src/core/lib/security/authorization/authorization_engine.cc",
+        "src/core/lib/security/authorization/evaluate_args.cc",
     ],
     ],
     hdrs = [
     hdrs = [
         "src/core/lib/security/authorization/authorization_engine.h",
         "src/core/lib/security/authorization/authorization_engine.h",
+        "src/core/lib/security/authorization/evaluate_args.h",
         "src/core/lib/security/authorization/mock_cel/activation.h",
         "src/core/lib/security/authorization/mock_cel/activation.h",
         "src/core/lib/security/authorization/mock_cel/cel_value.h",
         "src/core/lib/security/authorization/mock_cel/cel_value.h",
     ],
     ],
@@ -1868,6 +1869,7 @@ grpc_cc_library(
         "envoy_ads_upb",
         "envoy_ads_upb",
         "google_api_upb",
         "google_api_upb",
         "grpc_base",
         "grpc_base",
+        "grpc_secure",
     ],
     ],
 )
 )
 
 
@@ -2256,11 +2258,9 @@ grpc_cc_library(
         "include/grpcpp/impl/codegen/client_callback.h",
         "include/grpcpp/impl/codegen/client_callback.h",
         "include/grpcpp/impl/codegen/client_callback_impl.h",
         "include/grpcpp/impl/codegen/client_callback_impl.h",
         "include/grpcpp/impl/codegen/client_context.h",
         "include/grpcpp/impl/codegen/client_context.h",
-        "include/grpcpp/impl/codegen/client_context_impl.h",
         "include/grpcpp/impl/codegen/client_interceptor.h",
         "include/grpcpp/impl/codegen/client_interceptor.h",
         "include/grpcpp/impl/codegen/client_unary_call.h",
         "include/grpcpp/impl/codegen/client_unary_call.h",
         "include/grpcpp/impl/codegen/completion_queue.h",
         "include/grpcpp/impl/codegen/completion_queue.h",
-        "include/grpcpp/impl/codegen/completion_queue_impl.h",
         "include/grpcpp/impl/codegen/completion_queue_tag.h",
         "include/grpcpp/impl/codegen/completion_queue_tag.h",
         "include/grpcpp/impl/codegen/config.h",
         "include/grpcpp/impl/codegen/config.h",
         "include/grpcpp/impl/codegen/core_codegen_interface.h",
         "include/grpcpp/impl/codegen/core_codegen_interface.h",
@@ -2833,6 +2833,26 @@ grpc_cc_library(
     ],
     ],
 )
 )
 
 
+# Once upb code-gen issue is resolved, replace meshca_upb with this.
+# meshca_upb_proto_library(
+#     name = "meshca_upb",
+#     deps = ["//third_party/istio/security/proto/providers/google:meshca_proto"],
+# )
+
+grpc_cc_library(
+    name = "meshca_upb",
+    srcs = [
+        "src/core/ext/upb-generated/third_party/istio/security/proto/providers/google/meshca.upb.c",
+    ],
+    hdrs = [
+        "src/core/ext/upb-generated/third_party/istio/security/proto/providers/google/meshca.upb.h",
+    ],
+    language = "c++",
+    deps = [
+        "google_api_upb",
+    ],
+)
+
 # Once upb code-gen issue is resolved, replace alts_upb with this.
 # Once upb code-gen issue is resolved, replace alts_upb with this.
 # grpc_upb_proto_library(
 # grpc_upb_proto_library(
 #     name = "alts_upb",
 #     name = "alts_upb",

+ 0 - 4
BUILD.gn

@@ -1100,10 +1100,8 @@ config("grpc_config") {
         "include/grpcpp/alarm.h",
         "include/grpcpp/alarm.h",
         "include/grpcpp/alarm_impl.h",
         "include/grpcpp/alarm_impl.h",
         "include/grpcpp/channel.h",
         "include/grpcpp/channel.h",
-        "include/grpcpp/channel_impl.h",
         "include/grpcpp/client_context.h",
         "include/grpcpp/client_context.h",
         "include/grpcpp/completion_queue.h",
         "include/grpcpp/completion_queue.h",
-        "include/grpcpp/completion_queue_impl.h",
         "include/grpcpp/create_channel.h",
         "include/grpcpp/create_channel.h",
         "include/grpcpp/create_channel_posix.h",
         "include/grpcpp/create_channel_posix.h",
         "include/grpcpp/ext/health_check_service_server_builder_option.h",
         "include/grpcpp/ext/health_check_service_server_builder_option.h",
@@ -1129,11 +1127,9 @@ config("grpc_config") {
         "include/grpcpp/impl/codegen/client_callback.h",
         "include/grpcpp/impl/codegen/client_callback.h",
         "include/grpcpp/impl/codegen/client_callback_impl.h",
         "include/grpcpp/impl/codegen/client_callback_impl.h",
         "include/grpcpp/impl/codegen/client_context.h",
         "include/grpcpp/impl/codegen/client_context.h",
-        "include/grpcpp/impl/codegen/client_context_impl.h",
         "include/grpcpp/impl/codegen/client_interceptor.h",
         "include/grpcpp/impl/codegen/client_interceptor.h",
         "include/grpcpp/impl/codegen/client_unary_call.h",
         "include/grpcpp/impl/codegen/client_unary_call.h",
         "include/grpcpp/impl/codegen/completion_queue.h",
         "include/grpcpp/impl/codegen/completion_queue.h",
-        "include/grpcpp/impl/codegen/completion_queue_impl.h",
         "include/grpcpp/impl/codegen/completion_queue_tag.h",
         "include/grpcpp/impl/codegen/completion_queue_tag.h",
         "include/grpcpp/impl/codegen/config.h",
         "include/grpcpp/impl/codegen/config.h",
         "include/grpcpp/impl/codegen/config_protobuf.h",
         "include/grpcpp/impl/codegen/config_protobuf.h",

+ 5 - 10
CMakeLists.txt

@@ -1050,6 +1050,7 @@ add_library(end2end_nosec_tests
   test/core/end2end/tests/retry_throttled.cc
   test/core/end2end/tests/retry_throttled.cc
   test/core/end2end/tests/retry_too_many_attempts.cc
   test/core/end2end/tests/retry_too_many_attempts.cc
   test/core/end2end/tests/server_finishes_request.cc
   test/core/end2end/tests/server_finishes_request.cc
+  test/core/end2end/tests/server_streaming.cc
   test/core/end2end/tests/shutdown_finishes_calls.cc
   test/core/end2end/tests/shutdown_finishes_calls.cc
   test/core/end2end/tests/shutdown_finishes_tags.cc
   test/core/end2end/tests/shutdown_finishes_tags.cc
   test/core/end2end/tests/simple_cacheable_request.cc
   test/core/end2end/tests/simple_cacheable_request.cc
@@ -1183,6 +1184,7 @@ add_library(end2end_tests
   test/core/end2end/tests/retry_throttled.cc
   test/core/end2end/tests/retry_throttled.cc
   test/core/end2end/tests/retry_too_many_attempts.cc
   test/core/end2end/tests/retry_too_many_attempts.cc
   test/core/end2end/tests/server_finishes_request.cc
   test/core/end2end/tests/server_finishes_request.cc
+  test/core/end2end/tests/server_streaming.cc
   test/core/end2end/tests/shutdown_finishes_calls.cc
   test/core/end2end/tests/shutdown_finishes_calls.cc
   test/core/end2end/tests/shutdown_finishes_tags.cc
   test/core/end2end/tests/shutdown_finishes_tags.cc
   test/core/end2end/tests/simple_cacheable_request.cc
   test/core/end2end/tests/simple_cacheable_request.cc
@@ -2744,10 +2746,8 @@ foreach(_hdr
   include/grpcpp/alarm.h
   include/grpcpp/alarm.h
   include/grpcpp/alarm_impl.h
   include/grpcpp/alarm_impl.h
   include/grpcpp/channel.h
   include/grpcpp/channel.h
-  include/grpcpp/channel_impl.h
   include/grpcpp/client_context.h
   include/grpcpp/client_context.h
   include/grpcpp/completion_queue.h
   include/grpcpp/completion_queue.h
-  include/grpcpp/completion_queue_impl.h
   include/grpcpp/create_channel.h
   include/grpcpp/create_channel.h
   include/grpcpp/create_channel_posix.h
   include/grpcpp/create_channel_posix.h
   include/grpcpp/ext/health_check_service_server_builder_option.h
   include/grpcpp/ext/health_check_service_server_builder_option.h
@@ -2773,11 +2773,9 @@ foreach(_hdr
   include/grpcpp/impl/codegen/client_callback.h
   include/grpcpp/impl/codegen/client_callback.h
   include/grpcpp/impl/codegen/client_callback_impl.h
   include/grpcpp/impl/codegen/client_callback_impl.h
   include/grpcpp/impl/codegen/client_context.h
   include/grpcpp/impl/codegen/client_context.h
-  include/grpcpp/impl/codegen/client_context_impl.h
   include/grpcpp/impl/codegen/client_interceptor.h
   include/grpcpp/impl/codegen/client_interceptor.h
   include/grpcpp/impl/codegen/client_unary_call.h
   include/grpcpp/impl/codegen/client_unary_call.h
   include/grpcpp/impl/codegen/completion_queue.h
   include/grpcpp/impl/codegen/completion_queue.h
-  include/grpcpp/impl/codegen/completion_queue_impl.h
   include/grpcpp/impl/codegen/completion_queue_tag.h
   include/grpcpp/impl/codegen/completion_queue_tag.h
   include/grpcpp/impl/codegen/config.h
   include/grpcpp/impl/codegen/config.h
   include/grpcpp/impl/codegen/config_protobuf.h
   include/grpcpp/impl/codegen/config_protobuf.h
@@ -3433,10 +3431,8 @@ foreach(_hdr
   include/grpcpp/alarm.h
   include/grpcpp/alarm.h
   include/grpcpp/alarm_impl.h
   include/grpcpp/alarm_impl.h
   include/grpcpp/channel.h
   include/grpcpp/channel.h
-  include/grpcpp/channel_impl.h
   include/grpcpp/client_context.h
   include/grpcpp/client_context.h
   include/grpcpp/completion_queue.h
   include/grpcpp/completion_queue.h
-  include/grpcpp/completion_queue_impl.h
   include/grpcpp/create_channel.h
   include/grpcpp/create_channel.h
   include/grpcpp/create_channel_posix.h
   include/grpcpp/create_channel_posix.h
   include/grpcpp/ext/health_check_service_server_builder_option.h
   include/grpcpp/ext/health_check_service_server_builder_option.h
@@ -3462,11 +3458,9 @@ foreach(_hdr
   include/grpcpp/impl/codegen/client_callback.h
   include/grpcpp/impl/codegen/client_callback.h
   include/grpcpp/impl/codegen/client_callback_impl.h
   include/grpcpp/impl/codegen/client_callback_impl.h
   include/grpcpp/impl/codegen/client_context.h
   include/grpcpp/impl/codegen/client_context.h
-  include/grpcpp/impl/codegen/client_context_impl.h
   include/grpcpp/impl/codegen/client_interceptor.h
   include/grpcpp/impl/codegen/client_interceptor.h
   include/grpcpp/impl/codegen/client_unary_call.h
   include/grpcpp/impl/codegen/client_unary_call.h
   include/grpcpp/impl/codegen/completion_queue.h
   include/grpcpp/impl/codegen/completion_queue.h
-  include/grpcpp/impl/codegen/completion_queue_impl.h
   include/grpcpp/impl/codegen/completion_queue_tag.h
   include/grpcpp/impl/codegen/completion_queue_tag.h
   include/grpcpp/impl/codegen/config.h
   include/grpcpp/impl/codegen/config.h
   include/grpcpp/impl/codegen/config_protobuf.h
   include/grpcpp/impl/codegen/config_protobuf.h
@@ -7998,7 +7992,7 @@ endif()
 if(gRPC_BUILD_TESTS)
 if(gRPC_BUILD_TESTS)
 
 
 add_executable(uri_parser_test
 add_executable(uri_parser_test
-  test/core/client_channel/uri_parser_test.cc
+  test/core/uri/uri_parser_test.cc
 )
 )
 
 
 target_include_directories(uri_parser_test
 target_include_directories(uri_parser_test
@@ -8417,6 +8411,7 @@ if(gRPC_BUILD_TESTS)
 
 
 add_executable(authorization_engine_test
 add_executable(authorization_engine_test
   src/core/lib/security/authorization/authorization_engine.cc
   src/core/lib/security/authorization/authorization_engine.cc
+  src/core/lib/security/authorization/evaluate_args.cc
   test/core/security/authorization_engine_test.cc
   test/core/security/authorization_engine_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
@@ -15524,7 +15519,7 @@ endif()
 if(gRPC_BUILD_TESTS)
 if(gRPC_BUILD_TESTS)
 
 
 add_executable(uri_fuzzer_test_one_entry
 add_executable(uri_fuzzer_test_one_entry
-  test/core/client_channel/uri_fuzzer_test.cc
+  test/core/uri/uri_fuzzer_test.cc
   test/core/util/one_corpus_entry_fuzzer.cc
   test/core/util/one_corpus_entry_fuzzer.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googletest/src/gtest-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc
   third_party/googletest/googlemock/src/gmock-all.cc

File diff suppressed because it is too large
+ 7 - 1379
Makefile


+ 4 - 4
bazel/grpc_deps.bzl

@@ -136,11 +136,11 @@ def grpc_deps():
             name = "boringssl",
             name = "boringssl",
             # Use github mirror instead of https://boringssl.googlesource.com/boringssl
             # Use github mirror instead of https://boringssl.googlesource.com/boringssl
             # to obtain a boringssl archive with consistent sha256
             # to obtain a boringssl archive with consistent sha256
-            sha256 = "5bbb2bbddf5e4e5fefd02501f930436f3f45402152d7ea9f8f27916d5cf70157",
-            strip_prefix = "boringssl-e8a935e323510419e0b37638716f6df4dcbbe6f6",
+            sha256 = "81333e496d7b74a60aa6fa622c028ba382a0a6b9c815cc6ccb221042383b9a9b",
+            strip_prefix = "boringssl-412844d75b14b9090b58423fd5f5ed8c2fd80212",
             urls = [
             urls = [
-                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/e8a935e323510419e0b37638716f6df4dcbbe6f6.tar.gz",
-                "https://github.com/google/boringssl/archive/e8a935e323510419e0b37638716f6df4dcbbe6f6.tar.gz",
+                "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/412844d75b14b9090b58423fd5f5ed8c2fd80212.tar.gz",
+                "https://github.com/google/boringssl/archive/412844d75b14b9090b58423fd5f5ed8c2fd80212.tar.gz",
             ],
             ],
         )
         )
 
 

+ 8 - 11
build_autogenerated.yaml

@@ -100,6 +100,7 @@ libs:
   - test/core/end2end/tests/retry_throttled.cc
   - test/core/end2end/tests/retry_throttled.cc
   - test/core/end2end/tests/retry_too_many_attempts.cc
   - test/core/end2end/tests/retry_too_many_attempts.cc
   - test/core/end2end/tests/server_finishes_request.cc
   - test/core/end2end/tests/server_finishes_request.cc
+  - test/core/end2end/tests/server_streaming.cc
   - test/core/end2end/tests/shutdown_finishes_calls.cc
   - test/core/end2end/tests/shutdown_finishes_calls.cc
   - test/core/end2end/tests/shutdown_finishes_tags.cc
   - test/core/end2end/tests/shutdown_finishes_tags.cc
   - test/core/end2end/tests/simple_cacheable_request.cc
   - test/core/end2end/tests/simple_cacheable_request.cc
@@ -209,6 +210,7 @@ libs:
   - test/core/end2end/tests/retry_throttled.cc
   - test/core/end2end/tests/retry_throttled.cc
   - test/core/end2end/tests/retry_too_many_attempts.cc
   - test/core/end2end/tests/retry_too_many_attempts.cc
   - test/core/end2end/tests/server_finishes_request.cc
   - test/core/end2end/tests/server_finishes_request.cc
+  - test/core/end2end/tests/server_streaming.cc
   - test/core/end2end/tests/shutdown_finishes_calls.cc
   - test/core/end2end/tests/shutdown_finishes_calls.cc
   - test/core/end2end/tests/shutdown_finishes_tags.cc
   - test/core/end2end/tests/shutdown_finishes_tags.cc
   - test/core/end2end/tests/simple_cacheable_request.cc
   - test/core/end2end/tests/simple_cacheable_request.cc
@@ -2087,10 +2089,8 @@ libs:
   - include/grpcpp/alarm.h
   - include/grpcpp/alarm.h
   - include/grpcpp/alarm_impl.h
   - include/grpcpp/alarm_impl.h
   - include/grpcpp/channel.h
   - include/grpcpp/channel.h
-  - include/grpcpp/channel_impl.h
   - include/grpcpp/client_context.h
   - include/grpcpp/client_context.h
   - include/grpcpp/completion_queue.h
   - include/grpcpp/completion_queue.h
-  - include/grpcpp/completion_queue_impl.h
   - include/grpcpp/create_channel.h
   - include/grpcpp/create_channel.h
   - include/grpcpp/create_channel_posix.h
   - include/grpcpp/create_channel_posix.h
   - include/grpcpp/ext/health_check_service_server_builder_option.h
   - include/grpcpp/ext/health_check_service_server_builder_option.h
@@ -2116,11 +2116,9 @@ libs:
   - include/grpcpp/impl/codegen/client_callback.h
   - include/grpcpp/impl/codegen/client_callback.h
   - include/grpcpp/impl/codegen/client_callback_impl.h
   - include/grpcpp/impl/codegen/client_callback_impl.h
   - include/grpcpp/impl/codegen/client_context.h
   - include/grpcpp/impl/codegen/client_context.h
-  - include/grpcpp/impl/codegen/client_context_impl.h
   - include/grpcpp/impl/codegen/client_interceptor.h
   - include/grpcpp/impl/codegen/client_interceptor.h
   - include/grpcpp/impl/codegen/client_unary_call.h
   - include/grpcpp/impl/codegen/client_unary_call.h
   - include/grpcpp/impl/codegen/completion_queue.h
   - include/grpcpp/impl/codegen/completion_queue.h
-  - include/grpcpp/impl/codegen/completion_queue_impl.h
   - include/grpcpp/impl/codegen/completion_queue_tag.h
   - include/grpcpp/impl/codegen/completion_queue_tag.h
   - include/grpcpp/impl/codegen/config.h
   - include/grpcpp/impl/codegen/config.h
   - include/grpcpp/impl/codegen/config_protobuf.h
   - include/grpcpp/impl/codegen/config_protobuf.h
@@ -2468,10 +2466,8 @@ libs:
   - include/grpcpp/alarm.h
   - include/grpcpp/alarm.h
   - include/grpcpp/alarm_impl.h
   - include/grpcpp/alarm_impl.h
   - include/grpcpp/channel.h
   - include/grpcpp/channel.h
-  - include/grpcpp/channel_impl.h
   - include/grpcpp/client_context.h
   - include/grpcpp/client_context.h
   - include/grpcpp/completion_queue.h
   - include/grpcpp/completion_queue.h
-  - include/grpcpp/completion_queue_impl.h
   - include/grpcpp/create_channel.h
   - include/grpcpp/create_channel.h
   - include/grpcpp/create_channel_posix.h
   - include/grpcpp/create_channel_posix.h
   - include/grpcpp/ext/health_check_service_server_builder_option.h
   - include/grpcpp/ext/health_check_service_server_builder_option.h
@@ -2497,11 +2493,9 @@ libs:
   - include/grpcpp/impl/codegen/client_callback.h
   - include/grpcpp/impl/codegen/client_callback.h
   - include/grpcpp/impl/codegen/client_callback_impl.h
   - include/grpcpp/impl/codegen/client_callback_impl.h
   - include/grpcpp/impl/codegen/client_context.h
   - include/grpcpp/impl/codegen/client_context.h
-  - include/grpcpp/impl/codegen/client_context_impl.h
   - include/grpcpp/impl/codegen/client_interceptor.h
   - include/grpcpp/impl/codegen/client_interceptor.h
   - include/grpcpp/impl/codegen/client_unary_call.h
   - include/grpcpp/impl/codegen/client_unary_call.h
   - include/grpcpp/impl/codegen/completion_queue.h
   - include/grpcpp/impl/codegen/completion_queue.h
-  - include/grpcpp/impl/codegen/completion_queue_impl.h
   - include/grpcpp/impl/codegen/completion_queue_tag.h
   - include/grpcpp/impl/codegen/completion_queue_tag.h
   - include/grpcpp/impl/codegen/config.h
   - include/grpcpp/impl/codegen/config.h
   - include/grpcpp/impl/codegen/config_protobuf.h
   - include/grpcpp/impl/codegen/config_protobuf.h
@@ -4582,7 +4576,7 @@ targets:
   language: c
   language: c
   headers: []
   headers: []
   src:
   src:
-  - test/core/client_channel/uri_parser_test.cc
+  - test/core/uri/uri_parser_test.cc
   deps:
   deps:
   - grpc_test_util
   - grpc_test_util
   - grpc
   - grpc
@@ -4777,10 +4771,12 @@ targets:
   language: c++
   language: c++
   headers:
   headers:
   - src/core/lib/security/authorization/authorization_engine.h
   - src/core/lib/security/authorization/authorization_engine.h
+  - src/core/lib/security/authorization/evaluate_args.h
   - src/core/lib/security/authorization/mock_cel/activation.h
   - src/core/lib/security/authorization/mock_cel/activation.h
   - src/core/lib/security/authorization/mock_cel/cel_value.h
   - src/core/lib/security/authorization/mock_cel/cel_value.h
   src:
   src:
   - src/core/lib/security/authorization/authorization_engine.cc
   - src/core/lib/security/authorization/authorization_engine.cc
+  - src/core/lib/security/authorization/evaluate_args.cc
   - test/core/security/authorization_engine_test.cc
   - test/core/security/authorization_engine_test.cc
   deps:
   deps:
   - grpc_test_util
   - grpc_test_util
@@ -7228,6 +7224,7 @@ targets:
 - name: stranded_event_test
 - name: stranded_event_test
   gtest: true
   gtest: true
   build: test
   build: test
+  run: false
   language: c++
   language: c++
   headers:
   headers:
   - test/core/end2end/cq_verifier.h
   - test/core/end2end/cq_verifier.h
@@ -7453,7 +7450,7 @@ targets:
   language: c++
   language: c++
   headers: []
   headers: []
   src:
   src:
-  - test/core/client_channel/uri_fuzzer_test.cc
+  - test/core/uri/uri_fuzzer_test.cc
   - test/core/util/fuzzer_corpus_test.cc
   - test/core/util/fuzzer_corpus_test.cc
   deps:
   deps:
   - grpc_test_util
   - grpc_test_util
@@ -7463,7 +7460,7 @@ targets:
   - address_sorting
   - address_sorting
   - upb
   - upb
   corpus_dirs:
   corpus_dirs:
-  - test/core/client_channel/uri_corpus
+  - test/core/uri/uri_corpus
   maxlen: 128
   maxlen: 128
 - name: window_overflow_bad_client_test
 - name: window_overflow_bad_client_test
   gtest: true
   gtest: true

+ 2 - 0
config.m4

@@ -691,6 +691,7 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c \
     third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c \
     third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c \
     third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c \
+    third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c \
     third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c \
     third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c \
     third_party/boringssl-with-bazel/src/crypto/lhash/lhash.c \
     third_party/boringssl-with-bazel/src/crypto/lhash/lhash.c \
     third_party/boringssl-with-bazel/src/crypto/mem.c \
     third_party/boringssl-with-bazel/src/crypto/mem.c \
@@ -1035,6 +1036,7 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/evp)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/evp)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/fipsmodule)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/fipsmodule)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/hkdf)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/hkdf)
+  PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/hpke)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/hrss)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/hrss)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/lhash)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/lhash)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/obj)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl-with-bazel/src/crypto/obj)

+ 2 - 0
config.w32

@@ -659,6 +659,7 @@ if (PHP_GRPC != "no") {
     "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\fips_shared_support.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\fips_shared_support.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\is_fips.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\is_fips.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\hkdf\\hkdf.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\hkdf\\hkdf.c " +
+    "third_party\\boringssl-with-bazel\\src\\crypto\\hpke\\hpke.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\hrss\\hrss.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\hrss\\hrss.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\lhash\\lhash.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\lhash\\lhash.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\mem.c " +
     "third_party\\boringssl-with-bazel\\src\\crypto\\mem.c " +
@@ -1088,6 +1089,7 @@ if (PHP_GRPC != "no") {
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\evp");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\evp");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\hkdf");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\hkdf");
+  FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\hpke");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\hrss");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\hrss");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\lhash");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\lhash");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\obj");
   FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl-with-bazel\\src\\crypto\\obj");

+ 7 - 0
doc/python/sphinx/grpc.rst

@@ -187,3 +187,10 @@ Compression
 ^^^^^^^^^^^
 ^^^^^^^^^^^
 
 
 .. autoclass:: Compression
 .. autoclass:: Compression
+
+Runtime Protobuf Parsing
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. autofunction:: protos
+.. autofunction:: services
+.. autofunction:: protos_and_services

+ 5 - 2
doc/ssl-performance.md

@@ -36,6 +36,9 @@ Electron | n/a | all | :heavy_check_mark:
 ObjC | Yes | iOS | :x:
 ObjC | Yes | iOS | :x:
 PHP | Yes | all | Same as the `Makefile` case from above
 PHP | Yes | all | Same as the `Makefile` case from above
 PHP | No | all | :x:
 PHP | No | all | :x:
-Python | n/a | all | :x:
+Python | n/a | Linux, 64bit | :heavy_check_mark:
+Python | n/a | Linux, 32bit | :x:
+Python | n/a | MacOS, 64bit | :heavy_check_mark:
+Python | n/a | MacOS, 32bit | :x:
+Python | n/a | Windows | :x:
 Ruby | No | all | :x:
 Ruby | No | all | :x:
-

+ 3 - 2
doc/status_ordering.md

@@ -3,11 +3,12 @@ Ordering Status and Reads in the gRPC API
 
 
 Rules for implementors:
 Rules for implementors:
 1. Reads and Writes Must not succeed after Status has been delivered.
 1. Reads and Writes Must not succeed after Status has been delivered.
-2. OK Status is only delivered after all buffered messages are read.
+2. Status is only delivered after all buffered messages are read.
 3. Reads May continue to succeed after a failing write.
 3. Reads May continue to succeed after a failing write.
    However, once a write fails, all subsequent writes Must fail,
    However, once a write fails, all subsequent writes Must fail,
    and similarly, once a read fails, all subsequent reads Must fail.
    and similarly, once a read fails, all subsequent reads Must fail.
-4. When an error status is known to the library, if the user asks for status,
+4. A non-OK status received from the server is not considered an error status.
+5. When an error status is known to the library, if the user asks for status,
    the library Should discard messages received in the library but not delivered
    the library Should discard messages received in the library but not delivered
    to the user and then deliver the status. If the user does not ask for status
    to the user and then deliver the status. If the user does not ask for status
    but continues reading, the library Should deliver buffered messages before
    but continues reading, the library Should deliver buffered messages before

+ 1 - 1
examples/csharp/Helloworld/GreeterClient/Program.cs

@@ -22,7 +22,7 @@ namespace GreeterClient
     {
     {
         public static void Main(string[] args)
         public static void Main(string[] args)
         {
         {
-            Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
+            Channel channel = new Channel("127.0.0.1:30051", ChannelCredentials.Insecure);
 
 
             var client = new Greeter.GreeterClient(channel);
             var client = new Greeter.GreeterClient(channel);
             String user = "you";
             String user = "you";

+ 1 - 1
examples/csharp/Helloworld/GreeterServer/Program.cs

@@ -30,7 +30,7 @@ namespace GreeterServer
 
 
     class Program
     class Program
     {
     {
-        const int Port = 50051;
+        const int Port = 30051;
 
 
         public static void Main(string[] args)
         public static void Main(string[] args)
         {
         {

+ 1 - 1
examples/csharp/HelloworldLegacyCsproj/GreeterClient/Program.cs

@@ -22,7 +22,7 @@ namespace GreeterClient
     {
     {
         public static void Main(string[] args)
         public static void Main(string[] args)
         {
         {
-            Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
+            Channel channel = new Channel("127.0.0.1:30051", ChannelCredentials.Insecure);
 
 
             var client = new Greeter.GreeterClient(channel);
             var client = new Greeter.GreeterClient(channel);
             String user = "you";
             String user = "you";

+ 1 - 1
examples/csharp/HelloworldLegacyCsproj/GreeterServer/Program.cs

@@ -30,7 +30,7 @@ namespace GreeterServer
 
 
     class Program
     class Program
     {
     {
-        const int Port = 50051;
+        const int Port = 30051;
 
 
         public static void Main(string[] args)
         public static void Main(string[] args)
         {
         {

+ 2 - 2
examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs

@@ -48,7 +48,7 @@ class HelloWorldTest
 
 
   public static HelloReply Greet(string greeting)
   public static HelloReply Greet(string greeting)
   {
   {
-    const int Port = 50051;
+    const int Port = 30051;
 
 
     Server server = new Server
     Server server = new Server
     {
     {
@@ -57,7 +57,7 @@ class HelloWorldTest
     };
     };
     server.Start();
     server.Start();
 
 
-    Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
+    Channel channel = new Channel("127.0.0.1:30051", ChannelCredentials.Insecure);
 
 
     var client = new Greeter.GreeterClient(channel);
     var client = new Greeter.GreeterClient(channel);
 
 

+ 3 - 3
examples/csharp/HelloworldXamarin/Droid/MainActivity.cs

@@ -28,7 +28,7 @@ namespace HelloworldXamarin.Droid
     [Activity(Label = "HelloworldXamarin", MainLauncher = true, Icon = "@mipmap/icon")]
     [Activity(Label = "HelloworldXamarin", MainLauncher = true, Icon = "@mipmap/icon")]
     public class MainActivity : Activity
     public class MainActivity : Activity
     {
     {
-        const int Port = 50051;
+        const int Port = 30051;
         int count = 1;
         int count = 1;
 
 
         protected override void OnCreate(Bundle savedInstanceState)
         protected override void OnCreate(Bundle savedInstanceState)
@@ -55,8 +55,8 @@ namespace HelloworldXamarin.Droid
             server.Start();
             server.Start();
 
 
             // use loopback on host machine: https://developer.android.com/studio/run/emulator-networking
             // use loopback on host machine: https://developer.android.com/studio/run/emulator-networking
-            //10.0.2.2:50051
-            Channel channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
+            //10.0.2.2:30051
+            Channel channel = new Channel("localhost:30051", ChannelCredentials.Insecure);
 
 
             var client = new Greeter.GreeterClient(channel);
             var client = new Greeter.GreeterClient(channel);
             string user = "Xamarin " + count;
             string user = "Xamarin " + count;

+ 3 - 3
examples/csharp/HelloworldXamarin/iOS/ViewController.cs

@@ -28,7 +28,7 @@ namespace HelloworldXamarin.iOS
 {
 {
     public partial class ViewController : UIViewController
     public partial class ViewController : UIViewController
     {
     {
-        const int Port = 50051;
+        const int Port = 30051;
         int count = 1;
         int count = 1;
 
 
         public ViewController(IntPtr handle) : base(handle)
         public ViewController(IntPtr handle) : base(handle)
@@ -42,7 +42,7 @@ namespace HelloworldXamarin.iOS
             // Perform any additional setup after loading the view, typically from a nib.
             // Perform any additional setup after loading the view, typically from a nib.
             Button.AccessibilityIdentifier = "myButton";
             Button.AccessibilityIdentifier = "myButton";
             Button.TouchUpInside += delegate
             Button.TouchUpInside += delegate
-            {
+            {
                 var title = SayHello();
                 var title = SayHello();
                 Button.SetTitle(title, UIControlState.Normal);
                 Button.SetTitle(title, UIControlState.Normal);
             };
             };
@@ -63,7 +63,7 @@ namespace HelloworldXamarin.iOS
             };
             };
             server.Start();
             server.Start();
 
 
-            Channel channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
+            Channel channel = new Channel("localhost:30051", ChannelCredentials.Insecure);
 
 
             var client = new Greeter.GreeterClient(channel);
             var client = new Greeter.GreeterClient(channel);
             string user = "Xamarin " + count;
             string user = "Xamarin " + count;

+ 1 - 1
examples/csharp/RouteGuide/RouteGuideClient/Program.cs

@@ -215,7 +215,7 @@ namespace Routeguide
 
 
         static void Main(string[] args)
         static void Main(string[] args)
         {
         {
-            var channel = new Channel("127.0.0.1:50052", ChannelCredentials.Insecure);
+            var channel = new Channel("127.0.0.1:30052", ChannelCredentials.Insecure);
             var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel));
             var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel));
 
 
             // Looking for a valid feature
             // Looking for a valid feature

+ 1 - 1
examples/csharp/RouteGuide/RouteGuideServer/Program.cs

@@ -25,7 +25,7 @@ namespace Routeguide
     {
     {
         static void Main(string[] args)
         static void Main(string[] args)
         {
         {
-            const int Port = 50052;
+            const int Port = 30052;
 
 
             var features = RouteGuideUtil.LoadFeatures();
             var features = RouteGuideUtil.LoadFeatures();
 
 

+ 1 - 1
examples/csharp/Xds/GreeterClient/Program.cs

@@ -23,7 +23,7 @@ namespace GreeterClient
     {
     {
         private class Options
         private class Options
         {
         {
-            [Option("server", Default = "localhost:50051", HelpText = "The address of the server")]
+            [Option("server", Default = "localhost:30051", HelpText = "The address of the server")]
             public string Server { get; set; }
             public string Server { get; set; }
         }
         }
 
 

+ 1 - 1
examples/csharp/Xds/GreeterServer/Program.cs

@@ -46,7 +46,7 @@ namespace GreeterServer
     {
     {
         class Options
         class Options
         {
         {
-            [Option("port", Default = 50051, HelpText = "The port to listen on.")]
+            [Option("port", Default = 30051, HelpText = "The port to listen on.")]
             public int Port { get; set; }
             public int Port { get; set; }
 
 
             [Option("hostname", Required = false, HelpText = "The name clients will see in responses. If not specified, machine's hostname will obtain automatically.")]
             [Option("hostname", Required = false, HelpText = "The name clients will see in responses. If not specified, machine's hostname will obtain automatically.")]

+ 4 - 4
examples/csharp/Xds/README.md

@@ -67,7 +67,7 @@ you to manually test the service.
 Exercise your server's application-layer service:
 Exercise your server's application-layer service:
 
 
 ```sh
 ```sh
-> grpcurl --plaintext -d '{"name": "you"}' localhost:50051
+> grpcurl --plaintext -d '{"name": "you"}' localhost:30051
 {
 {
   "message": "Hello you from jtatt.muc.corp.google.com!"
   "message": "Hello you from jtatt.muc.corp.google.com!"
 }
 }
@@ -76,7 +76,7 @@ Exercise your server's application-layer service:
 Make sure that all of your server's services are available via reflection:
 Make sure that all of your server's services are available via reflection:
 
 
 ```sh
 ```sh
-> grpcurl --plaintext localhost:50051 list
+> grpcurl --plaintext localhost:30051 list
 grpc.health.v1.Health
 grpc.health.v1.Health
 grpc.reflection.v1alpha.ServerReflection
 grpc.reflection.v1alpha.ServerReflection
 helloworld.Greeter
 helloworld.Greeter
@@ -85,13 +85,13 @@ helloworld.Greeter
 Make sure that your services are reporting healthy:
 Make sure that your services are reporting healthy:
 
 
 ```sh
 ```sh
-> grpcurl --plaintext -d '{"service": "helloworld.Greeter"}' localhost:50051
+> grpcurl --plaintext -d '{"service": "helloworld.Greeter"}' localhost:30051
 grpc.health.v1.Health/Check
 grpc.health.v1.Health/Check
 {
 {
   "status": "SERVING"
   "status": "SERVING"
 }
 }
 
 
-> grpcurl --plaintext -d '{"service": ""}' localhost:50051
+> grpcurl --plaintext -d '{"service": ""}' localhost:30051
 grpc.health.v1.Health/Check
 grpc.health.v1.Health/Check
 {
 {
   "status": "SERVING"
   "status": "SERVING"

+ 40 - 0
examples/python/no_codegen/greeter_client.py

@@ -0,0 +1,40 @@
+# Copyright 2020 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Hello World without using protoc.
+
+This example parses message and service schemas directly from a
+.proto file on the filesystem.
+
+Several APIs used in this example are in an experimental state.
+"""
+
+from __future__ import print_function
+import logging
+
+import grpc
+import grpc.experimental
+
+# NOTE: The path to the .proto file must be reachable from an entry
+# on sys.path. Use sys.path.insert or set the $PYTHONPATH variable to
+# import from files located elsewhere on the filesystem.
+
+protos = grpc.protos("helloworld.proto")
+services = grpc.services("helloworld.proto")
+
+logging.basicConfig()
+
+response = services.Greeter.SayHello(protos.HelloRequest(name='you'),
+                                     'localhost:50051',
+                                     insecure=True)
+print("Greeter client received: " + response.message)

+ 40 - 0
examples/python/no_codegen/greeter_server.py

@@ -0,0 +1,40 @@
+# Copyright 2020 The gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""The Python implementation of the GRPC helloworld.Greeter server."""
+
+from concurrent import futures
+import logging
+
+import grpc
+
+protos, services = grpc.protos_and_services("helloworld.proto")
+
+
+class Greeter(services.GreeterServicer):
+
+    def SayHello(self, request, context):
+        return protos.HelloReply(message='Hello, %s!' % request.name)
+
+
+def serve():
+    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+    services.add_GreeterServicer_to_server(Greeter(), server)
+    server.add_insecure_port('[::]:50051')
+    server.start()
+    server.wait_for_termination()
+
+
+if __name__ == '__main__':
+    logging.basicConfig()
+    serve()

+ 38 - 0
examples/python/no_codegen/helloworld.proto

@@ -0,0 +1,38 @@
+// Copyright 2020 The gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "io.grpc.examples.helloworld";
+option java_outer_classname = "HelloWorldProto";
+option objc_class_prefix = "HLW";
+
+package helloworld;
+
+// The greeting service definition.
+service Greeter {
+  // Sends a greeting
+  rpc SayHello (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+  string name = 1;
+}
+
+// The response message containing the greetings
+message HelloReply {
+  string message = 1;
+}

+ 0 - 4
gRPC-C++.podspec

@@ -79,10 +79,8 @@ Pod::Spec.new do |s|
     ss.source_files = 'include/grpcpp/alarm.h',
     ss.source_files = 'include/grpcpp/alarm.h',
                       'include/grpcpp/alarm_impl.h',
                       'include/grpcpp/alarm_impl.h',
                       'include/grpcpp/channel.h',
                       'include/grpcpp/channel.h',
-                      'include/grpcpp/channel_impl.h',
                       'include/grpcpp/client_context.h',
                       'include/grpcpp/client_context.h',
                       'include/grpcpp/completion_queue.h',
                       'include/grpcpp/completion_queue.h',
-                      'include/grpcpp/completion_queue_impl.h',
                       'include/grpcpp/create_channel.h',
                       'include/grpcpp/create_channel.h',
                       'include/grpcpp/create_channel_posix.h',
                       'include/grpcpp/create_channel_posix.h',
                       'include/grpcpp/ext/health_check_service_server_builder_option.h',
                       'include/grpcpp/ext/health_check_service_server_builder_option.h',
@@ -108,11 +106,9 @@ Pod::Spec.new do |s|
                       'include/grpcpp/impl/codegen/client_callback.h',
                       'include/grpcpp/impl/codegen/client_callback.h',
                       'include/grpcpp/impl/codegen/client_callback_impl.h',
                       'include/grpcpp/impl/codegen/client_callback_impl.h',
                       'include/grpcpp/impl/codegen/client_context.h',
                       'include/grpcpp/impl/codegen/client_context.h',
-                      'include/grpcpp/impl/codegen/client_context_impl.h',
                       'include/grpcpp/impl/codegen/client_interceptor.h',
                       'include/grpcpp/impl/codegen/client_interceptor.h',
                       'include/grpcpp/impl/codegen/client_unary_call.h',
                       'include/grpcpp/impl/codegen/client_unary_call.h',
                       'include/grpcpp/impl/codegen/completion_queue.h',
                       'include/grpcpp/impl/codegen/completion_queue.h',
-                      'include/grpcpp/impl/codegen/completion_queue_impl.h',
                       'include/grpcpp/impl/codegen/completion_queue_tag.h',
                       'include/grpcpp/impl/codegen/completion_queue_tag.h',
                       'include/grpcpp/impl/codegen/config.h',
                       'include/grpcpp/impl/codegen/config.h',
                       'include/grpcpp/impl/codegen/core_codegen.h',
                       'include/grpcpp/impl/codegen/core_codegen.h',

+ 2 - 1
gRPC-Core.podspec

@@ -172,7 +172,7 @@ Pod::Spec.new do |s|
     ss.header_mappings_dir = '.'
     ss.header_mappings_dir = '.'
     ss.libraries = 'z'
     ss.libraries = 'z'
     ss.dependency "#{s.name}/Interface", version
     ss.dependency "#{s.name}/Interface", version
-    ss.dependency 'BoringSSL-GRPC', '0.0.11'
+    ss.dependency 'BoringSSL-GRPC', '0.0.12'
     abseil_version = '1.20200225.0'
     abseil_version = '1.20200225.0'
     ss.dependency 'abseil/base/base', abseil_version
     ss.dependency 'abseil/base/base', abseil_version
     ss.dependency 'abseil/container/inlined_vector', abseil_version
     ss.dependency 'abseil/container/inlined_vector', abseil_version
@@ -1654,6 +1654,7 @@ Pod::Spec.new do |s|
                       'test/core/end2end/tests/retry_throttled.cc',
                       'test/core/end2end/tests/retry_throttled.cc',
                       'test/core/end2end/tests/retry_too_many_attempts.cc',
                       'test/core/end2end/tests/retry_too_many_attempts.cc',
                       'test/core/end2end/tests/server_finishes_request.cc',
                       'test/core/end2end/tests/server_finishes_request.cc',
+                      'test/core/end2end/tests/server_streaming.cc',
                       'test/core/end2end/tests/shutdown_finishes_calls.cc',
                       'test/core/end2end/tests/shutdown_finishes_calls.cc',
                       'test/core/end2end/tests/shutdown_finishes_tags.cc',
                       'test/core/end2end/tests/shutdown_finishes_tags.cc',
                       'test/core/end2end/tests/simple_cacheable_request.cc',
                       'test/core/end2end/tests/simple_cacheable_request.cc',

+ 2 - 0
grpc.gemspec

@@ -1388,6 +1388,8 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/kdf.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/kdf.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c )
+  s.files += %w( third_party/boringssl-with-bazel/src/crypto/hpke/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/hrss/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/hrss/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/internal.h )
   s.files += %w( third_party/boringssl-with-bazel/src/crypto/internal.h )

+ 3 - 0
grpc.gyp

@@ -252,6 +252,7 @@
         'test/core/end2end/tests/retry_throttled.cc',
         'test/core/end2end/tests/retry_throttled.cc',
         'test/core/end2end/tests/retry_too_many_attempts.cc',
         'test/core/end2end/tests/retry_too_many_attempts.cc',
         'test/core/end2end/tests/server_finishes_request.cc',
         'test/core/end2end/tests/server_finishes_request.cc',
+        'test/core/end2end/tests/server_streaming.cc',
         'test/core/end2end/tests/shutdown_finishes_calls.cc',
         'test/core/end2end/tests/shutdown_finishes_calls.cc',
         'test/core/end2end/tests/shutdown_finishes_tags.cc',
         'test/core/end2end/tests/shutdown_finishes_tags.cc',
         'test/core/end2end/tests/simple_cacheable_request.cc',
         'test/core/end2end/tests/simple_cacheable_request.cc',
@@ -354,6 +355,7 @@
         'test/core/end2end/tests/retry_throttled.cc',
         'test/core/end2end/tests/retry_throttled.cc',
         'test/core/end2end/tests/retry_too_many_attempts.cc',
         'test/core/end2end/tests/retry_too_many_attempts.cc',
         'test/core/end2end/tests/server_finishes_request.cc',
         'test/core/end2end/tests/server_finishes_request.cc',
+        'test/core/end2end/tests/server_streaming.cc',
         'test/core/end2end/tests/shutdown_finishes_calls.cc',
         'test/core/end2end/tests/shutdown_finishes_calls.cc',
         'test/core/end2end/tests/shutdown_finishes_tags.cc',
         'test/core/end2end/tests/shutdown_finishes_tags.cc',
         'test/core/end2end/tests/simple_cacheable_request.cc',
         'test/core/end2end/tests/simple_cacheable_request.cc',
@@ -1674,6 +1676,7 @@
         'third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c',
         'third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c',
         'third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c',
         'third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c',
         'third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c',
         'third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c',
+        'third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c',
         'third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c',
         'third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c',
         'third_party/boringssl-with-bazel/src/crypto/lhash/lhash.c',
         'third_party/boringssl-with-bazel/src/crypto/lhash/lhash.c',
         'third_party/boringssl-with-bazel/src/crypto/mem.c',
         'third_party/boringssl-with-bazel/src/crypto/mem.c',

+ 22 - 0
include/grpc/impl/codegen/README.md

@@ -0,0 +1,22 @@
+# Welcome to `include/grpc/impl/codegen`
+
+## Why is this directory here?
+
+This directory exists so that generated C++ code can include selected files upon
+which it depends without having to depend on the entire gRPC C++ library. This
+directory thus exists to support `include/grpcpp/impl/codegen`. This constraint
+is particularly relevant for users of bazel, particularly if they use the
+multi-lingual `proto_library` target type. Generated code that uses this target
+only depends on the gRPC C++ targets associated with these header files, not the
+entire gRPC C++ codebase since that would make the build time of these types of
+targets excessively large (particularly when they are not even C++ specific).
+
+## What should user code do?
+
+User code should *not* include anything from this directory. Only generated code
+and gRPC library code should include contents from this directory. C++ user code
+should instead include contents from the main `grpcpp` directory or its
+accessible subcomponents like `grpcpp/support`. It is possible that we may
+remove this directory altogether if the motivations for its existence are no
+longer strong enough (e.g., if the gRPC C++ library no longer has a need for an
+`impl/codegen` directory of its own).

+ 91 - 2
include/grpcpp/channel.h

@@ -19,11 +19,29 @@
 #ifndef GRPCPP_CHANNEL_H
 #ifndef GRPCPP_CHANNEL_H
 #define GRPCPP_CHANNEL_H
 #define GRPCPP_CHANNEL_H
 
 
-#include <grpcpp/channel_impl.h>
+#include <memory>
+
+#include <grpc/grpc.h>
+#include <grpcpp/impl/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/client_interceptor.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/impl/codegen/sync.h>
+
+struct grpc_channel;
 
 
 namespace grpc {
 namespace grpc {
+namespace testing {
+class ChannelTestPeer;
+}  // namespace testing
 
 
-typedef ::grpc_impl::Channel Channel;
+std::shared_ptr<Channel> CreateChannelInternal(
+    const std::string& host, grpc_channel* c_channel,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators);
 
 
 namespace experimental {
 namespace experimental {
 /// Resets the channel's connection backoff.
 /// Resets the channel's connection backoff.
@@ -32,6 +50,77 @@ namespace experimental {
 void ChannelResetConnectionBackoff(Channel* channel);
 void ChannelResetConnectionBackoff(Channel* channel);
 }  // namespace experimental
 }  // namespace experimental
 
 
+/// Channels represent a connection to an endpoint. Created by \a CreateChannel.
+class Channel final : public ::grpc::ChannelInterface,
+                      public ::grpc::internal::CallHook,
+                      public std::enable_shared_from_this<Channel>,
+                      private ::grpc::GrpcLibraryCodegen {
+ public:
+  ~Channel();
+
+  /// Get the current channel state. If the channel is in IDLE and
+  /// \a try_to_connect is set to true, try to connect.
+  grpc_connectivity_state GetState(bool try_to_connect) override;
+
+  /// Returns the LB policy name, or the empty string if not yet available.
+  std::string GetLoadBalancingPolicyName() const;
+
+  /// Returns the service config in JSON form, or the empty string if
+  /// not available.
+  std::string GetServiceConfigJSON() const;
+
+ private:
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::BlockingUnaryCallImpl;
+  friend class ::grpc::testing::ChannelTestPeer;
+  friend void experimental::ChannelResetConnectionBackoff(Channel* channel);
+  friend std::shared_ptr<Channel> grpc::CreateChannelInternal(
+      const std::string& host, grpc_channel* c_channel,
+      std::vector<std::unique_ptr<
+          ::grpc::experimental::ClientInterceptorFactoryInterface>>
+          interceptor_creators);
+  friend class ::grpc::internal::InterceptedChannel;
+  Channel(const std::string& host, grpc_channel* c_channel,
+          std::vector<std::unique_ptr<
+              ::grpc::experimental::ClientInterceptorFactoryInterface>>
+              interceptor_creators);
+
+  ::grpc::internal::Call CreateCall(const ::grpc::internal::RpcMethod& method,
+                                    ::grpc::ClientContext* context,
+                                    ::grpc::CompletionQueue* cq) override;
+  void PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops,
+                        ::grpc::internal::Call* call) override;
+  void* RegisterMethod(const char* method) override;
+
+  void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
+                               gpr_timespec deadline,
+                               ::grpc::CompletionQueue* cq, void* tag) override;
+  bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
+                              gpr_timespec deadline) override;
+
+  ::grpc::CompletionQueue* CallbackCQ() override;
+
+  ::grpc::internal::Call CreateCallInternal(
+      const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context,
+      ::grpc::CompletionQueue* cq, size_t interceptor_pos) override;
+
+  const std::string host_;
+  grpc_channel* const c_channel_;  // owned
+
+  // mu_ protects callback_cq_ (the per-channel callbackable completion queue)
+  grpc::internal::Mutex mu_;
+
+  // callback_cq_ references the callbackable completion queue associated
+  // with this channel (if any). It is set on the first call to CallbackCQ().
+  // It is _not owned_ by the channel; ownership belongs with its internal
+  // shutdown callback tag (invoked when the CQ is fully shutdown).
+  ::grpc::CompletionQueue* callback_cq_ = nullptr;
+
+  std::vector<
+      std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>>
+      interceptor_creators_;
+};
+
 }  // namespace grpc
 }  // namespace grpc
 
 
 #endif  // GRPCPP_CHANNEL_H
 #endif  // GRPCPP_CHANNEL_H

+ 0 - 130
include/grpcpp/channel_impl.h

@@ -1,130 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPCPP_CHANNEL_IMPL_H
-#define GRPCPP_CHANNEL_IMPL_H
-
-#include <memory>
-
-#include <grpc/grpc.h>
-#include <grpcpp/impl/call.h>
-#include <grpcpp/impl/codegen/channel_interface.h>
-#include <grpcpp/impl/codegen/client_interceptor.h>
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
-#include <grpcpp/impl/codegen/config.h>
-#include <grpcpp/impl/codegen/grpc_library.h>
-#include <grpcpp/impl/codegen/sync.h>
-
-struct grpc_channel;
-
-namespace grpc {
-namespace testing {
-class ChannelTestPeer;
-}  // namespace testing
-
-std::shared_ptr<::grpc_impl::Channel> CreateChannelInternal(
-    const std::string& host, grpc_channel* c_channel,
-    std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
-        interceptor_creators);
-}  // namespace grpc
-namespace grpc_impl {
-
-namespace experimental {
-/// Resets the channel's connection backoff.
-/// TODO(roth): Once we see whether this proves useful, either create a gRFC
-/// and change this to be a method of the Channel class, or remove it.
-void ChannelResetConnectionBackoff(Channel* channel);
-}  // namespace experimental
-
-/// Channels represent a connection to an endpoint. Created by \a CreateChannel.
-class Channel final : public ::grpc::ChannelInterface,
-                      public ::grpc::internal::CallHook,
-                      public std::enable_shared_from_this<Channel>,
-                      private ::grpc::GrpcLibraryCodegen {
- public:
-  ~Channel();
-
-  /// Get the current channel state. If the channel is in IDLE and
-  /// \a try_to_connect is set to true, try to connect.
-  grpc_connectivity_state GetState(bool try_to_connect) override;
-
-  /// Returns the LB policy name, or the empty string if not yet available.
-  std::string GetLoadBalancingPolicyName() const;
-
-  /// Returns the service config in JSON form, or the empty string if
-  /// not available.
-  std::string GetServiceConfigJSON() const;
-
- private:
-  template <class InputMessage, class OutputMessage>
-  friend class ::grpc::internal::BlockingUnaryCallImpl;
-  friend class ::grpc::testing::ChannelTestPeer;
-  friend void experimental::ChannelResetConnectionBackoff(Channel* channel);
-  friend std::shared_ptr<Channel> grpc::CreateChannelInternal(
-      const std::string& host, grpc_channel* c_channel,
-      std::vector<std::unique_ptr<
-          ::grpc::experimental::ClientInterceptorFactoryInterface>>
-          interceptor_creators);
-  friend class ::grpc::internal::InterceptedChannel;
-  Channel(const std::string& host, grpc_channel* c_channel,
-          std::vector<std::unique_ptr<
-              ::grpc::experimental::ClientInterceptorFactoryInterface>>
-              interceptor_creators);
-
-  ::grpc::internal::Call CreateCall(const ::grpc::internal::RpcMethod& method,
-                                    ::grpc_impl::ClientContext* context,
-                                    ::grpc_impl::CompletionQueue* cq) override;
-  void PerformOpsOnCall(::grpc::internal::CallOpSetInterface* ops,
-                        ::grpc::internal::Call* call) override;
-  void* RegisterMethod(const char* method) override;
-
-  void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
-                               gpr_timespec deadline,
-                               ::grpc_impl::CompletionQueue* cq,
-                               void* tag) override;
-  bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
-                              gpr_timespec deadline) override;
-
-  ::grpc_impl::CompletionQueue* CallbackCQ() override;
-
-  ::grpc::internal::Call CreateCallInternal(
-      const ::grpc::internal::RpcMethod& method,
-      ::grpc_impl::ClientContext* context, ::grpc_impl::CompletionQueue* cq,
-      size_t interceptor_pos) override;
-
-  const std::string host_;
-  grpc_channel* const c_channel_;  // owned
-
-  // mu_ protects callback_cq_ (the per-channel callbackable completion queue)
-  grpc::internal::Mutex mu_;
-
-  // callback_cq_ references the callbackable completion queue associated
-  // with this channel (if any). It is set on the first call to CallbackCQ().
-  // It is _not owned_ by the channel; ownership belongs with its internal
-  // shutdown callback tag (invoked when the CQ is fully shutdown).
-  ::grpc_impl::CompletionQueue* callback_cq_ = nullptr;
-
-  std::vector<
-      std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>>
-      interceptor_creators_;
-};
-
-}  // namespace grpc_impl
-
-#endif  // GRPCPP_CHANNEL_IMPL_H

+ 0 - 24
include/grpcpp/completion_queue_impl.h

@@ -1,24 +0,0 @@
-/*
- *
- * Copyright 2019 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPCPP_COMPLETION_QUEUE_IMPL_H
-#define GRPCPP_COMPLETION_QUEUE_IMPL_H
-
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
-
-#endif  // GRPCPP_COMPLETION_QUEUE_IMPL_H

+ 6 - 8
include/grpcpp/generic/generic_stub.h

@@ -29,11 +29,10 @@
 #include <grpcpp/support/client_callback_impl.h>
 #include <grpcpp/support/client_callback_impl.h>
 #include <grpcpp/support/status.h>
 #include <grpcpp/support/status.h>
 
 
-namespace grpc_impl {
-class CompletionQueue;
-}  // namespace grpc_impl
 namespace grpc {
 namespace grpc {
 
 
+class CompletionQueue;
+
 typedef ::grpc_impl::ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
 typedef ::grpc_impl::ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
     GenericClientAsyncReaderWriter;
     GenericClientAsyncReaderWriter;
 typedef ::grpc_impl::ClientAsyncResponseReader<ByteBuffer>
 typedef ::grpc_impl::ClientAsyncResponseReader<ByteBuffer>
@@ -55,7 +54,7 @@ class TemplatedGenericStub final {
   std::unique_ptr<
   std::unique_ptr<
       ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>
       ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>
   PrepareCall(ClientContext* context, const std::string& method,
   PrepareCall(ClientContext* context, const std::string& method,
-              ::grpc_impl::CompletionQueue* cq) {
+              ::grpc::CompletionQueue* cq) {
     return CallInternal(channel_.get(), context, method, cq, false, nullptr);
     return CallInternal(channel_.get(), context, method, cq, false, nullptr);
   }
   }
 
 
@@ -65,8 +64,7 @@ class TemplatedGenericStub final {
   /// succeeded (i.e. the call won't proceed if the return value is nullptr).
   /// succeeded (i.e. the call won't proceed if the return value is nullptr).
   std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<ResponseType>>
   std::unique_ptr<::grpc_impl::ClientAsyncResponseReader<ResponseType>>
   PrepareUnaryCall(ClientContext* context, const std::string& method,
   PrepareUnaryCall(ClientContext* context, const std::string& method,
-                   const RequestType& request,
-                   ::grpc_impl::CompletionQueue* cq) {
+                   const RequestType& request, ::grpc::CompletionQueue* cq) {
     return std::unique_ptr<
     return std::unique_ptr<
         ::grpc_impl::ClientAsyncResponseReader<ResponseType>>(
         ::grpc_impl::ClientAsyncResponseReader<ResponseType>>(
         grpc_impl::internal::ClientAsyncResponseReaderFactory<
         grpc_impl::internal::ClientAsyncResponseReaderFactory<
@@ -86,7 +84,7 @@ class TemplatedGenericStub final {
   std::unique_ptr<
   std::unique_ptr<
       ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>
       ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>
   Call(ClientContext* context, const std::string& method,
   Call(ClientContext* context, const std::string& method,
-       ::grpc_impl::CompletionQueue* cq, void* tag) {
+       ::grpc::CompletionQueue* cq, void* tag) {
     return CallInternal(channel_.get(), context, method, cq, true, tag);
     return CallInternal(channel_.get(), context, method, cq, true, tag);
   }
   }
 
 
@@ -205,7 +203,7 @@ class TemplatedGenericStub final {
   std::unique_ptr<
   std::unique_ptr<
       ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>
       ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>
   CallInternal(grpc::ChannelInterface* channel, ClientContext* context,
   CallInternal(grpc::ChannelInterface* channel, ClientContext* context,
-               const std::string& method, ::grpc_impl::CompletionQueue* cq,
+               const std::string& method, ::grpc::CompletionQueue* cq,
                bool start, void* tag) {
                bool start, void* tag) {
     return std::unique_ptr<
     return std::unique_ptr<
         ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>(
         ::grpc_impl::ClientAsyncReaderWriter<RequestType, ResponseType>>(

+ 21 - 0
include/grpcpp/impl/codegen/README.md

@@ -0,0 +1,21 @@
+# Welcome to `include/grpcpp/impl/codegen`
+
+## Why is this directory here?
+
+This directory exists so that generated code can include selected files upon
+which it depends without having to depend on the entire gRPC C++ library. This
+is particularly relevant for users of bazel, particularly if they use the
+multi-lingual `proto_library` target type. Generated code that uses this target
+only depends on the gRPC C++ targets associated with these header files, not the
+entire gRPC C++ codebase since that would make the build time of these types of
+targets excessively large (particularly when they are not even C++ specific).
+
+## What should user code do?
+
+User code should *not* include anything from this directory. Only generated code
+and gRPC library code should include contents from this directory. User code
+should instead include contents from the main `grpcpp` directory or its
+accessible subcomponents like `grpcpp/support`. It is possible that we may
+remove this directory altogether if the motivations for its existence are no
+longer strong enough (e.g., if most users migrate away from the `proto_library`
+target type or if the additional overhead of depending on gRPC C++ is not high).

+ 2 - 3
include/grpcpp/impl/codegen/async_generic_service.h

@@ -80,9 +80,8 @@ class AsyncGenericService final {
 
 
   void RequestCall(GenericServerContext* ctx,
   void RequestCall(GenericServerContext* ctx,
                    GenericServerAsyncReaderWriter* reader_writer,
                    GenericServerAsyncReaderWriter* reader_writer,
-                   ::grpc_impl::CompletionQueue* call_cq,
-                   ::grpc_impl::ServerCompletionQueue* notification_cq,
-                   void* tag);
+                   ::grpc::CompletionQueue* call_cq,
+                   ::grpc::ServerCompletionQueue* notification_cq, void* tag);
 
 
  private:
  private:
   friend class grpc_impl::Server;
   friend class grpc_impl::Server;

+ 15 - 18
include/grpcpp/impl/codegen/async_stream_impl.h

@@ -178,9 +178,9 @@ class ClientAsyncReaderFactory {
   /// used to send to the server when starting the call.
   /// used to send to the server when starting the call.
   template <class W>
   template <class W>
   static ClientAsyncReader<R>* Create(::grpc::ChannelInterface* channel,
   static ClientAsyncReader<R>* Create(::grpc::ChannelInterface* channel,
-                                      ::grpc_impl::CompletionQueue* cq,
+                                      ::grpc::CompletionQueue* cq,
                                       const ::grpc::internal::RpcMethod& method,
                                       const ::grpc::internal::RpcMethod& method,
-                                      ::grpc_impl::ClientContext* context,
+                                      ::grpc::ClientContext* context,
                                       const W& request, bool start, void* tag) {
                                       const W& request, bool start, void* tag) {
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
@@ -259,9 +259,8 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
  private:
  private:
   friend class internal::ClientAsyncReaderFactory<R>;
   friend class internal::ClientAsyncReaderFactory<R>;
   template <class W>
   template <class W>
-  ClientAsyncReader(::grpc::internal::Call call,
-                    ::grpc_impl::ClientContext* context, const W& request,
-                    bool start, void* tag)
+  ClientAsyncReader(::grpc::internal::Call call, ::grpc::ClientContext* context,
+                    const W& request, bool start, void* tag)
       : context_(context), call_(call), started_(start) {
       : context_(context), call_(call), started_(start) {
     // TODO(ctiller): don't assert
     // TODO(ctiller): don't assert
     GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
     GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
@@ -280,7 +279,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
     call_.PerformOps(&init_ops_);
     call_.PerformOps(&init_ops_);
   }
   }
 
 
-  ::grpc_impl::ClientContext* context_;
+  ::grpc::ClientContext* context_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
   bool started_;
   bool started_;
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
@@ -327,9 +326,9 @@ class ClientAsyncWriterFactory {
   /// method of this instance.
   /// method of this instance.
   template <class R>
   template <class R>
   static ClientAsyncWriter<W>* Create(::grpc::ChannelInterface* channel,
   static ClientAsyncWriter<W>* Create(::grpc::ChannelInterface* channel,
-                                      ::grpc_impl::CompletionQueue* cq,
+                                      ::grpc::CompletionQueue* cq,
                                       const ::grpc::internal::RpcMethod& method,
                                       const ::grpc::internal::RpcMethod& method,
-                                      ::grpc_impl::ClientContext* context,
+                                      ::grpc::ClientContext* context,
                                       R* response, bool start, void* tag) {
                                       R* response, bool start, void* tag) {
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
@@ -426,9 +425,8 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
  private:
  private:
   friend class internal::ClientAsyncWriterFactory<W>;
   friend class internal::ClientAsyncWriterFactory<W>;
   template <class R>
   template <class R>
-  ClientAsyncWriter(::grpc::internal::Call call,
-                    ::grpc_impl::ClientContext* context, R* response,
-                    bool start, void* tag)
+  ClientAsyncWriter(::grpc::internal::Call call, ::grpc::ClientContext* context,
+                    R* response, bool start, void* tag)
       : context_(context), call_(call), started_(start) {
       : context_(context), call_(call), started_(start) {
     finish_ops_.RecvMessage(response);
     finish_ops_.RecvMessage(response);
     finish_ops_.AllowNoMessage();
     finish_ops_.AllowNoMessage();
@@ -450,7 +448,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* context_;
+  ::grpc::ClientContext* context_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
   bool started_;
   bool started_;
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
@@ -493,9 +491,9 @@ class ClientAsyncReaderWriterFactory {
   /// Note that \a context will be used to fill in custom initial metadata
   /// Note that \a context will be used to fill in custom initial metadata
   /// used to send to the server when starting the call.
   /// used to send to the server when starting the call.
   static ClientAsyncReaderWriter<W, R>* Create(
   static ClientAsyncReaderWriter<W, R>* Create(
-      ::grpc::ChannelInterface* channel, ::grpc_impl::CompletionQueue* cq,
-      const ::grpc::internal::RpcMethod& method,
-      ::grpc_impl::ClientContext* context, bool start, void* tag) {
+      ::grpc::ChannelInterface* channel, ::grpc::CompletionQueue* cq,
+      const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context,
+      bool start, void* tag) {
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
 
 
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
@@ -601,8 +599,7 @@ class ClientAsyncReaderWriter final
  private:
  private:
   friend class internal::ClientAsyncReaderWriterFactory<W, R>;
   friend class internal::ClientAsyncReaderWriterFactory<W, R>;
   ClientAsyncReaderWriter(::grpc::internal::Call call,
   ClientAsyncReaderWriter(::grpc::internal::Call call,
-                          ::grpc_impl::ClientContext* context, bool start,
-                          void* tag)
+                          ::grpc::ClientContext* context, bool start, void* tag)
       : context_(context), call_(call), started_(start) {
       : context_(context), call_(call), started_(start) {
     if (start) {
     if (start) {
       StartCallInternal(tag);
       StartCallInternal(tag);
@@ -622,7 +619,7 @@ class ClientAsyncReaderWriter final
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* context_;
+  ::grpc::ClientContext* context_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
   bool started_;
   bool started_;
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>

+ 7 - 7
include/grpcpp/impl/codegen/async_unary_call_impl.h

@@ -21,7 +21,7 @@
 
 
 #include <grpcpp/impl/codegen/call.h>
 #include <grpcpp/impl/codegen/call.h>
 #include <grpcpp/impl/codegen/channel_interface.h>
 #include <grpcpp/impl/codegen/channel_interface.h>
-#include <grpcpp/impl/codegen/client_context_impl.h>
+#include <grpcpp/impl/codegen/client_context.h>
 #include <grpcpp/impl/codegen/server_context_impl.h>
 #include <grpcpp/impl/codegen/server_context_impl.h>
 #include <grpcpp/impl/codegen/service_type.h>
 #include <grpcpp/impl/codegen/service_type.h>
 #include <grpcpp/impl/codegen/status.h>
 #include <grpcpp/impl/codegen/status.h>
@@ -77,9 +77,9 @@ class ClientAsyncResponseReaderFactory {
   /// used to send to the server when starting the call.
   /// used to send to the server when starting the call.
   template <class W>
   template <class W>
   static ClientAsyncResponseReader<R>* Create(
   static ClientAsyncResponseReader<R>* Create(
-      ::grpc::ChannelInterface* channel, ::grpc_impl::CompletionQueue* cq,
-      const ::grpc::internal::RpcMethod& method,
-      ::grpc_impl::ClientContext* context, const W& request, bool start) {
+      ::grpc::ChannelInterface* channel, ::grpc::CompletionQueue* cq,
+      const ::grpc::internal::RpcMethod& method, ::grpc::ClientContext* context,
+      const W& request, bool start) {
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
     return new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
         call.call(), sizeof(ClientAsyncResponseReader<R>)))
         call.call(), sizeof(ClientAsyncResponseReader<R>)))
@@ -153,15 +153,15 @@ class ClientAsyncResponseReader final
 
 
  private:
  private:
   friend class internal::ClientAsyncResponseReaderFactory<R>;
   friend class internal::ClientAsyncResponseReaderFactory<R>;
-  ::grpc_impl::ClientContext* const context_;
+  ::grpc::ClientContext* const context_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
   bool started_;
   bool started_;
   bool initial_metadata_read_ = false;
   bool initial_metadata_read_ = false;
 
 
   template <class W>
   template <class W>
   ClientAsyncResponseReader(::grpc::internal::Call call,
   ClientAsyncResponseReader(::grpc::internal::Call call,
-                            ::grpc_impl::ClientContext* context,
-                            const W& request, bool start)
+                            ::grpc::ClientContext* context, const W& request,
+                            bool start)
       : context_(context), call_(call), started_(start) {
       : context_(context), call_(call), started_(start) {
     // Bind the metadata at time of StartCallInternal but set up the rest here
     // Bind the metadata at time of StartCallInternal but set up the rest here
     // TODO(ctiller): don't assert
     // TODO(ctiller): don't assert

+ 6 - 9
include/grpcpp/impl/codegen/call.h

@@ -21,11 +21,8 @@
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpcpp/impl/codegen/call_hook.h>
 #include <grpcpp/impl/codegen/call_hook.h>
 
 
-namespace grpc_impl {
-class CompletionQueue;
-}
-
 namespace grpc {
 namespace grpc {
+class CompletionQueue;
 namespace experimental {
 namespace experimental {
 class ClientRpcInfo;
 class ClientRpcInfo;
 class ServerRpcInfo;
 class ServerRpcInfo;
@@ -43,13 +40,13 @@ class Call final {
         call_(nullptr),
         call_(nullptr),
         max_receive_message_size_(-1) {}
         max_receive_message_size_(-1) {}
   /** call is owned by the caller */
   /** call is owned by the caller */
-  Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq)
+  Call(grpc_call* call, CallHook* call_hook, ::grpc::CompletionQueue* cq)
       : call_hook_(call_hook),
       : call_hook_(call_hook),
         cq_(cq),
         cq_(cq),
         call_(call),
         call_(call),
         max_receive_message_size_(-1) {}
         max_receive_message_size_(-1) {}
 
 
-  Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq,
+  Call(grpc_call* call, CallHook* call_hook, ::grpc::CompletionQueue* cq,
        experimental::ClientRpcInfo* rpc_info)
        experimental::ClientRpcInfo* rpc_info)
       : call_hook_(call_hook),
       : call_hook_(call_hook),
         cq_(cq),
         cq_(cq),
@@ -57,7 +54,7 @@ class Call final {
         max_receive_message_size_(-1),
         max_receive_message_size_(-1),
         client_rpc_info_(rpc_info) {}
         client_rpc_info_(rpc_info) {}
 
 
-  Call(grpc_call* call, CallHook* call_hook, ::grpc_impl::CompletionQueue* cq,
+  Call(grpc_call* call, CallHook* call_hook, ::grpc::CompletionQueue* cq,
        int max_receive_message_size, experimental::ServerRpcInfo* rpc_info)
        int max_receive_message_size, experimental::ServerRpcInfo* rpc_info)
       : call_hook_(call_hook),
       : call_hook_(call_hook),
         cq_(cq),
         cq_(cq),
@@ -70,7 +67,7 @@ class Call final {
   }
   }
 
 
   grpc_call* call() const { return call_; }
   grpc_call* call() const { return call_; }
-  ::grpc_impl::CompletionQueue* cq() const { return cq_; }
+  ::grpc::CompletionQueue* cq() const { return cq_; }
 
 
   int max_receive_message_size() const { return max_receive_message_size_; }
   int max_receive_message_size() const { return max_receive_message_size_; }
 
 
@@ -84,7 +81,7 @@ class Call final {
 
 
  private:
  private:
   CallHook* call_hook_;
   CallHook* call_hook_;
-  ::grpc_impl::CompletionQueue* cq_;
+  ::grpc::CompletionQueue* cq_;
   grpc_call* call_;
   grpc_call* call_;
   int max_receive_message_size_;
   int max_receive_message_size_;
   experimental::ClientRpcInfo* client_rpc_info_ = nullptr;
   experimental::ClientRpcInfo* client_rpc_info_ = nullptr;

+ 5 - 5
include/grpcpp/impl/codegen/call_op_set.h

@@ -29,8 +29,8 @@
 #include <grpcpp/impl/codegen/call.h>
 #include <grpcpp/impl/codegen/call.h>
 #include <grpcpp/impl/codegen/call_hook.h>
 #include <grpcpp/impl/codegen/call_hook.h>
 #include <grpcpp/impl/codegen/call_op_set_interface.h>
 #include <grpcpp/impl/codegen/call_op_set_interface.h>
-#include <grpcpp/impl/codegen/client_context_impl.h>
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
 #include <grpcpp/impl/codegen/completion_queue_tag.h>
 #include <grpcpp/impl/codegen/completion_queue_tag.h>
 #include <grpcpp/impl/codegen/config.h>
 #include <grpcpp/impl/codegen/config.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
@@ -721,7 +721,7 @@ class CallOpRecvInitialMetadata {
  public:
  public:
   CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
   CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
 
 
-  void RecvInitialMetadata(::grpc_impl::ClientContext* context) {
+  void RecvInitialMetadata(::grpc::ClientContext* context) {
     context->initial_metadata_received_ = true;
     context->initial_metadata_received_ = true;
     metadata_map_ = &context->recv_initial_metadata_;
     metadata_map_ = &context->recv_initial_metadata_;
   }
   }
@@ -770,7 +770,7 @@ class CallOpClientRecvStatus {
   CallOpClientRecvStatus()
   CallOpClientRecvStatus()
       : recv_status_(nullptr), debug_error_string_(nullptr) {}
       : recv_status_(nullptr), debug_error_string_(nullptr) {}
 
 
-  void ClientRecvStatus(::grpc_impl::ClientContext* context, Status* status) {
+  void ClientRecvStatus(::grpc::ClientContext* context, Status* status) {
     client_context_ = context;
     client_context_ = context;
     metadata_map_ = &client_context_->trailing_metadata_;
     metadata_map_ = &client_context_->trailing_metadata_;
     recv_status_ = status;
     recv_status_ = status;
@@ -836,7 +836,7 @@ class CallOpClientRecvStatus {
 
 
  private:
  private:
   bool hijacked_ = false;
   bool hijacked_ = false;
-  ::grpc_impl::ClientContext* client_context_;
+  ::grpc::ClientContext* client_context_;
   MetadataMap* metadata_map_;
   MetadataMap* metadata_map_;
   Status* recv_status_;
   Status* recv_status_;
   const char* debug_error_string_;
   const char* debug_error_string_;

+ 9 - 10
include/grpcpp/impl/codegen/channel_interface.h

@@ -25,8 +25,6 @@
 #include <grpcpp/impl/codegen/time.h>
 #include <grpcpp/impl/codegen/time.h>
 
 
 namespace grpc_impl {
 namespace grpc_impl {
-class ClientContext;
-class CompletionQueue;
 template <class R>
 template <class R>
 class ClientReader;
 class ClientReader;
 template <class W>
 template <class W>
@@ -56,6 +54,8 @@ class ClientCallbackUnaryFactory;
 
 
 namespace grpc {
 namespace grpc {
 class ChannelInterface;
 class ChannelInterface;
+class ClientContext;
+class CompletionQueue;
 
 
 namespace experimental {
 namespace experimental {
 class DelegatingChannel;
 class DelegatingChannel;
@@ -82,7 +82,7 @@ class ChannelInterface {
   /// deadline expires. \a GetState needs to called to get the current state.
   /// deadline expires. \a GetState needs to called to get the current state.
   template <typename T>
   template <typename T>
   void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline,
   void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline,
-                           ::grpc_impl::CompletionQueue* cq, void* tag) {
+                           ::grpc::CompletionQueue* cq, void* tag) {
     TimePoint<T> deadline_tp(deadline);
     TimePoint<T> deadline_tp(deadline);
     NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag);
     NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag);
   }
   }
@@ -135,14 +135,14 @@ class ChannelInterface {
   friend class ::grpc::experimental::DelegatingChannel;
   friend class ::grpc::experimental::DelegatingChannel;
   friend class ::grpc::internal::InterceptedChannel;
   friend class ::grpc::internal::InterceptedChannel;
   virtual internal::Call CreateCall(const internal::RpcMethod& method,
   virtual internal::Call CreateCall(const internal::RpcMethod& method,
-                                    ::grpc_impl::ClientContext* context,
-                                    ::grpc_impl::CompletionQueue* cq) = 0;
+                                    ::grpc::ClientContext* context,
+                                    ::grpc::CompletionQueue* cq) = 0;
   virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
   virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
                                 internal::Call* call) = 0;
                                 internal::Call* call) = 0;
   virtual void* RegisterMethod(const char* method) = 0;
   virtual void* RegisterMethod(const char* method) = 0;
   virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
   virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
                                        gpr_timespec deadline,
                                        gpr_timespec deadline,
-                                       ::grpc_impl::CompletionQueue* cq,
+                                       ::grpc::CompletionQueue* cq,
                                        void* tag) = 0;
                                        void* tag) = 0;
   virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
   virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
                                       gpr_timespec deadline) = 0;
                                       gpr_timespec deadline) = 0;
@@ -155,9 +155,8 @@ class ChannelInterface {
   // method and adding a new pure method to an interface would be a breaking
   // method and adding a new pure method to an interface would be a breaking
   // change (even though this is private and non-API)
   // change (even though this is private and non-API)
   virtual internal::Call CreateCallInternal(
   virtual internal::Call CreateCallInternal(
-      const internal::RpcMethod& /*method*/,
-      ::grpc_impl::ClientContext* /*context*/,
-      ::grpc_impl::CompletionQueue* /*cq*/, size_t /*interceptor_pos*/) {
+      const internal::RpcMethod& /*method*/, ::grpc::ClientContext* /*context*/,
+      ::grpc::CompletionQueue* /*cq*/, size_t /*interceptor_pos*/) {
     return internal::Call();
     return internal::Call();
   }
   }
 
 
@@ -169,7 +168,7 @@ class ChannelInterface {
   // Returns nullptr (rather than being pure) since this is a post-1.0 method
   // Returns nullptr (rather than being pure) since this is a post-1.0 method
   // and adding a new pure method to an interface would be a breaking change
   // and adding a new pure method to an interface would be a breaking change
   // (even though this is private and non-API)
   // (even though this is private and non-API)
-  virtual ::grpc_impl::CompletionQueue* CallbackCQ() { return nullptr; }
+  virtual ::grpc::CompletionQueue* CallbackCQ() { return nullptr; }
 };
 };
 }  // namespace grpc
 }  // namespace grpc
 
 

+ 18 - 22
include/grpcpp/impl/codegen/client_callback_impl.h

@@ -29,14 +29,14 @@
 #include <grpcpp/impl/codegen/status.h>
 #include <grpcpp/impl/codegen/status.h>
 
 
 namespace grpc {
 namespace grpc {
+class Channel;
+class ClientContext;
 namespace internal {
 namespace internal {
 class RpcMethod;
 class RpcMethod;
 }  // namespace internal
 }  // namespace internal
 }  // namespace grpc
 }  // namespace grpc
 
 
 namespace grpc_impl {
 namespace grpc_impl {
-class Channel;
-class ClientContext;
 
 
 namespace internal {
 namespace internal {
 
 
@@ -45,7 +45,7 @@ namespace internal {
 template <class InputMessage, class OutputMessage>
 template <class InputMessage, class OutputMessage>
 void CallbackUnaryCall(::grpc::ChannelInterface* channel,
 void CallbackUnaryCall(::grpc::ChannelInterface* channel,
                        const ::grpc::internal::RpcMethod& method,
                        const ::grpc::internal::RpcMethod& method,
-                       ::grpc_impl::ClientContext* context,
+                       ::grpc::ClientContext* context,
                        const InputMessage* request, OutputMessage* result,
                        const InputMessage* request, OutputMessage* result,
                        std::function<void(::grpc::Status)> on_completion) {
                        std::function<void(::grpc::Status)> on_completion) {
   CallbackUnaryCallImpl<InputMessage, OutputMessage> x(
   CallbackUnaryCallImpl<InputMessage, OutputMessage> x(
@@ -57,10 +57,10 @@ class CallbackUnaryCallImpl {
  public:
  public:
   CallbackUnaryCallImpl(::grpc::ChannelInterface* channel,
   CallbackUnaryCallImpl(::grpc::ChannelInterface* channel,
                         const ::grpc::internal::RpcMethod& method,
                         const ::grpc::internal::RpcMethod& method,
-                        ::grpc_impl::ClientContext* context,
+                        ::grpc::ClientContext* context,
                         const InputMessage* request, OutputMessage* result,
                         const InputMessage* request, OutputMessage* result,
                         std::function<void(::grpc::Status)> on_completion) {
                         std::function<void(::grpc::Status)> on_completion) {
-    ::grpc_impl::CompletionQueue* cq = channel->CallbackCQ();
+    ::grpc::CompletionQueue* cq = channel->CallbackCQ();
     GPR_CODEGEN_ASSERT(cq != nullptr);
     GPR_CODEGEN_ASSERT(cq != nullptr);
     grpc::internal::Call call(channel->CreateCall(method, context, cq));
     grpc::internal::Call call(channel->CreateCall(method, context, cq));
 
 
@@ -574,7 +574,7 @@ class ClientCallbackReaderWriterImpl
   friend class ClientCallbackReaderWriterFactory<Request, Response>;
   friend class ClientCallbackReaderWriterFactory<Request, Response>;
 
 
   ClientCallbackReaderWriterImpl(grpc::internal::Call call,
   ClientCallbackReaderWriterImpl(grpc::internal::Call call,
-                                 ::grpc_impl::ClientContext* context,
+                                 ::grpc::ClientContext* context,
                                  ClientBidiReactor<Request, Response>* reactor)
                                  ClientBidiReactor<Request, Response>* reactor)
       : context_(context),
       : context_(context),
         call_(call),
         call_(call),
@@ -641,7 +641,7 @@ class ClientCallbackReaderWriterImpl
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* const context_;
+  ::grpc::ClientContext* const context_;
   grpc::internal::Call call_;
   grpc::internal::Call call_;
   ClientBidiReactor<Request, Response>* const reactor_;
   ClientBidiReactor<Request, Response>* const reactor_;
 
 
@@ -690,7 +690,7 @@ class ClientCallbackReaderWriterFactory {
  public:
  public:
   static void Create(::grpc::ChannelInterface* channel,
   static void Create(::grpc::ChannelInterface* channel,
                      const ::grpc::internal::RpcMethod& method,
                      const ::grpc::internal::RpcMethod& method,
-                     ::grpc_impl::ClientContext* context,
+                     ::grpc::ClientContext* context,
                      ClientBidiReactor<Request, Response>* reactor) {
                      ClientBidiReactor<Request, Response>* reactor) {
     grpc::internal::Call call =
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
         channel->CreateCall(method, context, channel->CallbackCQ());
@@ -785,8 +785,7 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
 
 
   template <class Request>
   template <class Request>
   ClientCallbackReaderImpl(::grpc::internal::Call call,
   ClientCallbackReaderImpl(::grpc::internal::Call call,
-                           ::grpc_impl::ClientContext* context,
-                           Request* request,
+                           ::grpc::ClientContext* context, Request* request,
                            ClientReadReactor<Response>* reactor)
                            ClientReadReactor<Response>* reactor)
       : context_(context), call_(call), reactor_(reactor) {
       : context_(context), call_(call), reactor_(reactor) {
     this->BindReactor(reactor);
     this->BindReactor(reactor);
@@ -812,7 +811,7 @@ class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* const context_;
+  ::grpc::ClientContext* const context_;
   grpc::internal::Call call_;
   grpc::internal::Call call_;
   ClientReadReactor<Response>* const reactor_;
   ClientReadReactor<Response>* const reactor_;
 
 
@@ -848,8 +847,7 @@ class ClientCallbackReaderFactory {
   template <class Request>
   template <class Request>
   static void Create(::grpc::ChannelInterface* channel,
   static void Create(::grpc::ChannelInterface* channel,
                      const ::grpc::internal::RpcMethod& method,
                      const ::grpc::internal::RpcMethod& method,
-                     ::grpc_impl::ClientContext* context,
-                     const Request* request,
+                     ::grpc::ClientContext* context, const Request* request,
                      ClientReadReactor<Response>* reactor) {
                      ClientReadReactor<Response>* reactor) {
     grpc::internal::Call call =
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
         channel->CreateCall(method, context, channel->CallbackCQ());
@@ -970,8 +968,7 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
 
 
   template <class Response>
   template <class Response>
   ClientCallbackWriterImpl(::grpc::internal::Call call,
   ClientCallbackWriterImpl(::grpc::internal::Call call,
-                           ::grpc_impl::ClientContext* context,
-                           Response* response,
+                           ::grpc::ClientContext* context, Response* response,
                            ClientWriteReactor<Request>* reactor)
                            ClientWriteReactor<Request>* reactor)
       : context_(context),
       : context_(context),
         call_(call),
         call_(call),
@@ -1027,7 +1024,7 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* const context_;
+  ::grpc::ClientContext* const context_;
   grpc::internal::Call call_;
   grpc::internal::Call call_;
   ClientWriteReactor<Request>* const reactor_;
   ClientWriteReactor<Request>* const reactor_;
 
 
@@ -1074,7 +1071,7 @@ class ClientCallbackWriterFactory {
   template <class Response>
   template <class Response>
   static void Create(::grpc::ChannelInterface* channel,
   static void Create(::grpc::ChannelInterface* channel,
                      const ::grpc::internal::RpcMethod& method,
                      const ::grpc::internal::RpcMethod& method,
-                     ::grpc_impl::ClientContext* context, Response* response,
+                     ::grpc::ClientContext* context, Response* response,
                      ClientWriteReactor<Request>* reactor) {
                      ClientWriteReactor<Request>* reactor) {
     grpc::internal::Call call =
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
         channel->CreateCall(method, context, channel->CallbackCQ());
@@ -1130,7 +1127,7 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
 
 
   template <class Request, class Response>
   template <class Request, class Response>
   ClientCallbackUnaryImpl(::grpc::internal::Call call,
   ClientCallbackUnaryImpl(::grpc::internal::Call call,
-                          ::grpc_impl::ClientContext* context, Request* request,
+                          ::grpc::ClientContext* context, Request* request,
                           Response* response, ClientUnaryReactor* reactor)
                           Response* response, ClientUnaryReactor* reactor)
       : context_(context), call_(call), reactor_(reactor) {
       : context_(context), call_(call), reactor_(reactor) {
     this->BindReactor(reactor);
     this->BindReactor(reactor);
@@ -1156,7 +1153,7 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* const context_;
+  ::grpc::ClientContext* const context_;
   grpc::internal::Call call_;
   grpc::internal::Call call_;
   ClientUnaryReactor* const reactor_;
   ClientUnaryReactor* const reactor_;
 
 
@@ -1182,9 +1179,8 @@ class ClientCallbackUnaryFactory {
   template <class Request, class Response>
   template <class Request, class Response>
   static void Create(::grpc::ChannelInterface* channel,
   static void Create(::grpc::ChannelInterface* channel,
                      const ::grpc::internal::RpcMethod& method,
                      const ::grpc::internal::RpcMethod& method,
-                     ::grpc_impl::ClientContext* context,
-                     const Request* request, Response* response,
-                     ClientUnaryReactor* reactor) {
+                     ::grpc::ClientContext* context, const Request* request,
+                     Response* response, ClientUnaryReactor* reactor) {
     grpc::internal::Call call =
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
         channel->CreateCall(method, context, channel->CallbackCQ());
 
 

+ 501 - 4
include/grpcpp/impl/codegen/client_context.h

@@ -1,6 +1,6 @@
 /*
 /*
  *
  *
- * Copyright 2019 gRPC authors.
+ * Copyright 2015 gRPC authors.
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -16,15 +16,512 @@
  *
  *
  */
  */
 
 
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistent at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+
 #ifndef GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
 #ifndef GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
 #define GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
 #define GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
 
 
-#include <grpcpp/impl/codegen/client_context_impl.h>
+#include <map>
+#include <memory>
+#include <string>
+
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/propagation_bits.h>
+#include <grpcpp/impl/codegen/client_interceptor.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/create_auth_context.h>
+#include <grpcpp/impl/codegen/metadata_map.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+#include <grpcpp/impl/codegen/sync.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct census_context;
+struct grpc_call;
+
+namespace grpc_impl {
+
+namespace internal {
+template <class InputMessage, class OutputMessage>
+class CallbackUnaryCallImpl;
+template <class Request, class Response>
+class ClientCallbackReaderWriterImpl;
+template <class Response>
+class ClientCallbackReaderImpl;
+template <class Request>
+class ClientCallbackWriterImpl;
+class ClientCallbackUnaryImpl;
+class ClientContextAccessor;
+}  // namespace internal
+
+class ServerContext;
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+template <class R>
+class ClientAsyncReader;
+template <class W>
+class ClientAsyncWriter;
+template <class W, class R>
+class ClientAsyncReaderWriter;
+template <class R>
+class ClientAsyncResponseReader;
+
+class ServerContextBase;
+class CallbackServerContext;
+}  // namespace grpc_impl
 
 
 namespace grpc {
 namespace grpc {
 
 
-typedef ::grpc_impl::ClientContext ClientContext;
-typedef ::grpc_impl::PropagationOptions PropagationOptions;
+namespace testing {
+class InteropClientContextInspector;
+}  // namespace testing
+
+namespace internal {
+class RpcMethod;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+class CallOpClientRecvStatus;
+class CallOpRecvInitialMetadata;
+class ServerContextImpl;
+template <class InputMessage, class OutputMessage>
+class CallbackUnaryCallImpl;
+template <class Request, class Response>
+class ClientCallbackReaderWriterImpl;
+template <class Response>
+class ClientCallbackReaderImpl;
+template <class Request>
+class ClientCallbackWriterImpl;
+class ClientCallbackUnaryImpl;
+class ClientContextAccessor;
+}  // namespace internal
+
+class CallCredentials;
+class Channel;
+class ChannelInterface;
+class CompletionQueue;
+
+/// Options for \a ClientContext::FromServerContext specifying which traits from
+/// the \a ServerContext to propagate (copy) from it into a new \a
+/// ClientContext.
+///
+/// \see ClientContext::FromServerContext
+class PropagationOptions {
+ public:
+  PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {}
+
+  PropagationOptions& enable_deadline_propagation() {
+    propagate_ |= GRPC_PROPAGATE_DEADLINE;
+    return *this;
+  }
+
+  PropagationOptions& disable_deadline_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_DEADLINE;
+    return *this;
+  }
+
+  PropagationOptions& enable_census_stats_propagation() {
+    propagate_ |= GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& disable_census_stats_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& enable_census_tracing_propagation() {
+    propagate_ |= GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& disable_census_tracing_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& enable_cancellation_propagation() {
+    propagate_ |= GRPC_PROPAGATE_CANCELLATION;
+    return *this;
+  }
+
+  PropagationOptions& disable_cancellation_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_CANCELLATION;
+    return *this;
+  }
+
+  uint32_t c_bitmask() const { return propagate_; }
+
+ private:
+  uint32_t propagate_;
+};
+
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+///   side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistent at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+/// \warning The ClientContext instance used for creating an rpc must remain
+///          alive and valid for the lifetime of the rpc.
+class ClientContext {
+ public:
+  ClientContext();
+  ~ClientContext();
+
+  /// Create a new \a ClientContext as a child of an incoming server call,
+  /// according to \a options (\see PropagationOptions).
+  ///
+  /// \param server_context The source server context to use as the basis for
+  /// constructing the client context.
+  /// \param options The options controlling what to copy from the \a
+  /// server_context.
+  ///
+  /// \return A newly constructed \a ClientContext instance based on \a
+  /// server_context, with traits propagated (copied) according to \a options.
+  static std::unique_ptr<ClientContext> FromServerContext(
+      const grpc_impl::ServerContext& server_context,
+      PropagationOptions options = PropagationOptions());
+  static std::unique_ptr<ClientContext> FromCallbackServerContext(
+      const grpc_impl::CallbackServerContext& server_context,
+      PropagationOptions options = PropagationOptions());
+
+  /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with
+  /// a client call. These are made available at the server side by the \a
+  /// grpc::ServerContext::client_metadata() method.
+  ///
+  /// \warning This method should only be called before invoking the rpc.
+  ///
+  /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+  /// end in "-bin".
+  /// \param meta_value The metadata value. If its value is binary, the key name
+  /// must end in "-bin".
+  ///
+  /// Metadata must conform to the following format:
+  /// Custom-Metadata -> Binary-Header / ASCII-Header
+  /// Binary-Header -> {Header-Name "-bin" } {binary value}
+  /// ASCII-Header -> Header-Name ASCII-Value
+  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
+  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
+  void AddMetadata(const std::string& meta_key, const std::string& meta_value);
+
+  /// Return a collection of initial metadata key-value pairs. Note that keys
+  /// may happen more than once (ie, a \a std::multimap is returned).
+  ///
+  /// \warning This method should only be called after initial metadata has been
+  /// received. For streaming calls, see \a
+  /// ClientReaderInterface::WaitForInitialMetadata().
+  ///
+  /// \return A multimap of initial metadata key-value pairs from the server.
+  const std::multimap<grpc::string_ref, grpc::string_ref>&
+  GetServerInitialMetadata() const {
+    GPR_CODEGEN_ASSERT(initial_metadata_received_);
+    return *recv_initial_metadata_.map();
+  }
+
+  /// Return a collection of trailing metadata key-value pairs. Note that keys
+  /// may happen more than once (ie, a \a std::multimap is returned).
+  ///
+  /// \warning This method is only callable once the stream has finished.
+  ///
+  /// \return A multimap of metadata trailing key-value pairs from the server.
+  const std::multimap<grpc::string_ref, grpc::string_ref>&
+  GetServerTrailingMetadata() const {
+    // TODO(yangg) check finished
+    return *trailing_metadata_.map();
+  }
+
+  /// Set the deadline for the client call.
+  ///
+  /// \warning This method should only be called before invoking the rpc.
+  ///
+  /// \param deadline the deadline for the client call. Units are determined by
+  /// the type used. The deadline is an absolute (not relative) time.
+  template <typename T>
+  void set_deadline(const T& deadline) {
+    grpc::TimePoint<T> deadline_tp(deadline);
+    deadline_ = deadline_tp.raw_time();
+  }
+
+  /// EXPERIMENTAL: Indicate that this request is idempotent.
+  /// By default, RPCs are assumed to <i>not</i> be idempotent.
+  ///
+  /// If true, the gRPC library assumes that it's safe to initiate
+  /// this RPC multiple times.
+  void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
+
+  /// EXPERIMENTAL: Set this request to be cacheable.
+  /// If set, grpc is free to use the HTTP GET verb for sending the request,
+  /// with the possibility of receiving a cached response.
+  void set_cacheable(bool cacheable) { cacheable_ = cacheable; }
+
+  /// EXPERIMENTAL: Trigger wait-for-ready or not on this request.
+  /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
+  /// If set, if an RPC is made when a channel's connectivity state is
+  /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast",
+  /// and the channel will wait until the channel is READY before making the
+  /// call.
+  void set_wait_for_ready(bool wait_for_ready) {
+    wait_for_ready_ = wait_for_ready;
+    wait_for_ready_explicitly_set_ = true;
+  }
+
+  /// DEPRECATED: Use set_wait_for_ready() instead.
+  void set_fail_fast(bool fail_fast) { set_wait_for_ready(!fail_fast); }
+
+  /// Return the deadline for the client call.
+  std::chrono::system_clock::time_point deadline() const {
+    return grpc::Timespec2Timepoint(deadline_);
+  }
+
+  /// Return a \a gpr_timespec representation of the client call's deadline.
+  gpr_timespec raw_deadline() const { return deadline_; }
+
+  /// Set the per call authority header (see
+  /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3).
+  void set_authority(const std::string& authority) { authority_ = authority; }
+
+  /// Return the authentication context for the associated client call.
+  /// It is only valid to call this during the lifetime of the client call.
+  ///
+  /// \see grpc::AuthContext.
+  std::shared_ptr<const grpc::AuthContext> auth_context() const {
+    if (auth_context_.get() == nullptr) {
+      auth_context_ = grpc::CreateAuthContext(call_);
+    }
+    return auth_context_;
+  }
+
+  /// Set credentials for the client call.
+  ///
+  /// A credentials object encapsulates all the state needed by a client to
+  /// authenticate with a server and make various assertions, e.g., about the
+  /// client’s identity, role, or whether it is authorized to make a particular
+  /// call.
+  ///
+  /// It is legal to call this only before initial metadata is sent.
+  ///
+  /// \see  https://grpc.io/docs/guides/auth.html
+  void set_credentials(const std::shared_ptr<grpc::CallCredentials>& creds);
+
+  /// EXPERIMENTAL debugging API
+  ///
+  /// Returns the credentials for the client call. This should be used only in
+  /// tests and for diagnostic purposes, and should not be used by application
+  /// logic.
+  std::shared_ptr<grpc::CallCredentials> credentials() { return creds_; }
+
+  /// Return the compression algorithm the client call will request be used.
+  /// Note that the gRPC runtime may decide to ignore this request, for example,
+  /// due to resource constraints.
+  grpc_compression_algorithm compression_algorithm() const {
+    return compression_algorithm_;
+  }
+
+  /// Set \a algorithm to be the compression algorithm used for the client call.
+  ///
+  /// \param algorithm The compression algorithm used for the client call.
+  void set_compression_algorithm(grpc_compression_algorithm algorithm);
+
+  /// Flag whether the initial metadata should be \a corked
+  ///
+  /// If \a corked is true, then the initial metadata will be coalesced with the
+  /// write of first message in the stream. As a result, any tag set for the
+  /// initial metadata operation (starting a client-streaming or bidi-streaming
+  /// RPC) will not actually be sent to the completion queue or delivered
+  /// via Next.
+  ///
+  /// \param corked The flag indicating whether the initial metadata is to be
+  /// corked or not.
+  void set_initial_metadata_corked(bool corked) {
+    initial_metadata_corked_ = corked;
+  }
+
+  /// Return the peer uri in a string.
+  /// It is only valid to call this during the lifetime of the client call.
+  ///
+  /// \warning This value is never authenticated or subject to any security
+  /// related code. It must not be used for any authentication related
+  /// functionality. Instead, use auth_context.
+  ///
+  /// \return The call's peer URI.
+  std::string peer() const;
+
+  /// Sets the census context.
+  /// It is only valid to call this before the client call is created. A common
+  /// place of setting census context is from within the DefaultConstructor
+  /// method of GlobalCallbacks.
+  void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
+
+  /// Returns the census context that has been set, or nullptr if not set.
+  struct census_context* census_context() const {
+    return census_context_;
+  }
+
+  /// Send a best-effort out-of-band cancel on the call associated with
+  /// this client context.  The call could be in any stage; e.g., if it is
+  /// already finished, it may still return success.
+  ///
+  /// There is no guarantee the call will be cancelled.
+  ///
+  /// Note that TryCancel() does not change any of the tags that are pending
+  /// on the completion queue. All pending tags will still be delivered
+  /// (though their ok result may reflect the effect of cancellation).
+  void TryCancel();
+
+  /// Global Callbacks
+  ///
+  /// Can be set exactly once per application to install hooks whenever
+  /// a client context is constructed and destructed.
+  class GlobalCallbacks {
+   public:
+    virtual ~GlobalCallbacks() {}
+    virtual void DefaultConstructor(ClientContext* context) = 0;
+    virtual void Destructor(ClientContext* context) = 0;
+  };
+  static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
+  /// Should be used for framework-level extensions only.
+  /// Applications never need to call this method.
+  grpc_call* c_call() { return call_; }
+
+  /// EXPERIMENTAL debugging API
+  ///
+  /// if status is not ok() for an RPC, this will return a detailed string
+  /// of the gRPC Core error that led to the failure. It should not be relied
+  /// upon for anything other than gaining more debug data in failure cases.
+  std::string debug_error_string() const { return debug_error_string_; }
+
+ private:
+  // Disallow copy and assign.
+  ClientContext(const ClientContext&);
+  ClientContext& operator=(const ClientContext&);
+
+  friend class ::grpc::testing::InteropClientContextInspector;
+  friend class ::grpc::internal::CallOpClientRecvStatus;
+  friend class ::grpc::internal::CallOpRecvInitialMetadata;
+  friend class ::grpc::Channel;
+  template <class R>
+  friend class ::grpc_impl::ClientReader;
+  template <class W>
+  friend class ::grpc_impl::ClientWriter;
+  template <class W, class R>
+  friend class ::grpc_impl::ClientReaderWriter;
+  template <class R>
+  friend class ::grpc_impl::ClientAsyncReader;
+  template <class W>
+  friend class ::grpc_impl::ClientAsyncWriter;
+  template <class W, class R>
+  friend class ::grpc_impl::ClientAsyncReaderWriter;
+  template <class R>
+  friend class ::grpc_impl::ClientAsyncResponseReader;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::BlockingUnaryCallImpl;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc_impl::internal::CallbackUnaryCallImpl;
+  template <class Request, class Response>
+  friend class ::grpc_impl::internal::ClientCallbackReaderWriterImpl;
+  template <class Response>
+  friend class ::grpc_impl::internal::ClientCallbackReaderImpl;
+  template <class Request>
+  friend class ::grpc_impl::internal::ClientCallbackWriterImpl;
+  friend class ::grpc_impl::internal::ClientCallbackUnaryImpl;
+  friend class ::grpc_impl::internal::ClientContextAccessor;
+
+  // Used by friend class CallOpClientRecvStatus
+  void set_debug_error_string(const std::string& debug_error_string) {
+    debug_error_string_ = debug_error_string;
+  }
+
+  grpc_call* call() const { return call_; }
+  void set_call(grpc_call* call,
+                const std::shared_ptr<::grpc::Channel>& channel);
+
+  grpc::experimental::ClientRpcInfo* set_client_rpc_info(
+      const char* method, grpc::internal::RpcMethod::RpcType type,
+      grpc::ChannelInterface* channel,
+      const std::vector<std::unique_ptr<
+          grpc::experimental::ClientInterceptorFactoryInterface>>& creators,
+      size_t interceptor_pos) {
+    rpc_info_ = grpc::experimental::ClientRpcInfo(this, type, method, channel);
+    rpc_info_.RegisterInterceptors(creators, interceptor_pos);
+    return &rpc_info_;
+  }
+
+  uint32_t initial_metadata_flags() const {
+    return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) |
+           (wait_for_ready_ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0) |
+           (cacheable_ ? GRPC_INITIAL_METADATA_CACHEABLE_REQUEST : 0) |
+           (wait_for_ready_explicitly_set_
+                ? GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET
+                : 0) |
+           (initial_metadata_corked_ ? GRPC_INITIAL_METADATA_CORKED : 0);
+  }
+
+  std::string authority() { return authority_; }
+
+  void SendCancelToInterceptors();
+
+  static std::unique_ptr<ClientContext> FromInternalServerContext(
+      const grpc_impl::ServerContextBase& server_context,
+      PropagationOptions options);
+
+  bool initial_metadata_received_;
+  bool wait_for_ready_;
+  bool wait_for_ready_explicitly_set_;
+  bool idempotent_;
+  bool cacheable_;
+  std::shared_ptr<::grpc::Channel> channel_;
+  grpc::internal::Mutex mu_;
+  grpc_call* call_;
+  bool call_canceled_;
+  gpr_timespec deadline_;
+  grpc::string authority_;
+  std::shared_ptr<grpc::CallCredentials> creds_;
+  mutable std::shared_ptr<const grpc::AuthContext> auth_context_;
+  struct census_context* census_context_;
+  std::multimap<std::string, std::string> send_initial_metadata_;
+  mutable grpc::internal::MetadataMap recv_initial_metadata_;
+  mutable grpc::internal::MetadataMap trailing_metadata_;
+
+  grpc_call* propagate_from_call_;
+  PropagationOptions propagation_options_;
+
+  grpc_compression_algorithm compression_algorithm_;
+  bool initial_metadata_corked_;
+
+  std::string debug_error_string_;
+
+  grpc::experimental::ClientRpcInfo rpc_info_;
+};
 
 
 }  // namespace grpc
 }  // namespace grpc
 
 

+ 0 - 517
include/grpcpp/impl/codegen/client_context_impl.h

@@ -1,517 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/// A ClientContext allows the person implementing a service client to:
-///
-/// - Add custom metadata key-value pairs that will propagated to the server
-/// side.
-/// - Control call settings such as compression and authentication.
-/// - Initial and trailing metadata coming from the server.
-/// - Get performance metrics (ie, census).
-///
-/// Context settings are only relevant to the call they are invoked with, that
-/// is to say, they aren't sticky. Some of these settings, such as the
-/// compression options, can be made persistent at channel construction time
-/// (see \a grpc::CreateCustomChannel).
-///
-/// \warning ClientContext instances should \em not be reused across rpcs.
-
-#ifndef GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_IMPL_H
-#define GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_IMPL_H
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <grpc/impl/codegen/compression_types.h>
-#include <grpc/impl/codegen/propagation_bits.h>
-#include <grpcpp/impl/codegen/client_interceptor.h>
-#include <grpcpp/impl/codegen/config.h>
-#include <grpcpp/impl/codegen/core_codegen_interface.h>
-#include <grpcpp/impl/codegen/create_auth_context.h>
-#include <grpcpp/impl/codegen/metadata_map.h>
-#include <grpcpp/impl/codegen/rpc_method.h>
-#include <grpcpp/impl/codegen/security/auth_context.h>
-#include <grpcpp/impl/codegen/slice.h>
-#include <grpcpp/impl/codegen/status.h>
-#include <grpcpp/impl/codegen/string_ref.h>
-#include <grpcpp/impl/codegen/sync.h>
-#include <grpcpp/impl/codegen/time.h>
-
-struct census_context;
-struct grpc_call;
-
-namespace grpc {
-
-class CallCredentials;
-class ChannelInterface;
-
-namespace internal {
-class RpcMethod;
-template <class InputMessage, class OutputMessage>
-class BlockingUnaryCallImpl;
-class CallOpClientRecvStatus;
-class CallOpRecvInitialMetadata;
-class ServerContextImpl;
-}  // namespace internal
-
-namespace testing {
-class InteropClientContextInspector;
-}  // namespace testing
-}  // namespace grpc
-namespace grpc_impl {
-
-namespace internal {
-template <class InputMessage, class OutputMessage>
-class CallbackUnaryCallImpl;
-template <class Request, class Response>
-class ClientCallbackReaderWriterImpl;
-template <class Response>
-class ClientCallbackReaderImpl;
-template <class Request>
-class ClientCallbackWriterImpl;
-class ClientCallbackUnaryImpl;
-class ClientContextAccessor;
-}  // namespace internal
-
-class Channel;
-class CompletionQueue;
-class ServerContext;
-template <class R>
-class ClientReader;
-template <class W>
-class ClientWriter;
-template <class W, class R>
-class ClientReaderWriter;
-template <class R>
-class ClientAsyncReader;
-template <class W>
-class ClientAsyncWriter;
-template <class W, class R>
-class ClientAsyncReaderWriter;
-template <class R>
-class ClientAsyncResponseReader;
-
-class ServerContextBase;
-class CallbackServerContext;
-
-/// Options for \a ClientContext::FromServerContext specifying which traits from
-/// the \a ServerContext to propagate (copy) from it into a new \a
-/// ClientContext.
-///
-/// \see ClientContext::FromServerContext
-class PropagationOptions {
- public:
-  PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {}
-
-  PropagationOptions& enable_deadline_propagation() {
-    propagate_ |= GRPC_PROPAGATE_DEADLINE;
-    return *this;
-  }
-
-  PropagationOptions& disable_deadline_propagation() {
-    propagate_ &= ~GRPC_PROPAGATE_DEADLINE;
-    return *this;
-  }
-
-  PropagationOptions& enable_census_stats_propagation() {
-    propagate_ |= GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
-    return *this;
-  }
-
-  PropagationOptions& disable_census_stats_propagation() {
-    propagate_ &= ~GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
-    return *this;
-  }
-
-  PropagationOptions& enable_census_tracing_propagation() {
-    propagate_ |= GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
-    return *this;
-  }
-
-  PropagationOptions& disable_census_tracing_propagation() {
-    propagate_ &= ~GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
-    return *this;
-  }
-
-  PropagationOptions& enable_cancellation_propagation() {
-    propagate_ |= GRPC_PROPAGATE_CANCELLATION;
-    return *this;
-  }
-
-  PropagationOptions& disable_cancellation_propagation() {
-    propagate_ &= ~GRPC_PROPAGATE_CANCELLATION;
-    return *this;
-  }
-
-  uint32_t c_bitmask() const { return propagate_; }
-
- private:
-  uint32_t propagate_;
-};
-
-/// A ClientContext allows the person implementing a service client to:
-///
-/// - Add custom metadata key-value pairs that will propagated to the server
-///   side.
-/// - Control call settings such as compression and authentication.
-/// - Initial and trailing metadata coming from the server.
-/// - Get performance metrics (ie, census).
-///
-/// Context settings are only relevant to the call they are invoked with, that
-/// is to say, they aren't sticky. Some of these settings, such as the
-/// compression options, can be made persistent at channel construction time
-/// (see \a grpc::CreateCustomChannel).
-///
-/// \warning ClientContext instances should \em not be reused across rpcs.
-/// \warning The ClientContext instance used for creating an rpc must remain
-///          alive and valid for the lifetime of the rpc.
-class ClientContext {
- public:
-  ClientContext();
-  ~ClientContext();
-
-  /// Create a new \a ClientContext as a child of an incoming server call,
-  /// according to \a options (\see PropagationOptions).
-  ///
-  /// \param server_context The source server context to use as the basis for
-  /// constructing the client context.
-  /// \param options The options controlling what to copy from the \a
-  /// server_context.
-  ///
-  /// \return A newly constructed \a ClientContext instance based on \a
-  /// server_context, with traits propagated (copied) according to \a options.
-  static std::unique_ptr<ClientContext> FromServerContext(
-      const grpc_impl::ServerContext& server_context,
-      PropagationOptions options = PropagationOptions());
-  static std::unique_ptr<ClientContext> FromCallbackServerContext(
-      const grpc_impl::CallbackServerContext& server_context,
-      PropagationOptions options = PropagationOptions());
-
-  /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with
-  /// a client call. These are made available at the server side by the \a
-  /// grpc::ServerContext::client_metadata() method.
-  ///
-  /// \warning This method should only be called before invoking the rpc.
-  ///
-  /// \param meta_key The metadata key. If \a meta_value is binary data, it must
-  /// end in "-bin".
-  /// \param meta_value The metadata value. If its value is binary, the key name
-  /// must end in "-bin".
-  ///
-  /// Metadata must conform to the following format:
-  /// Custom-Metadata -> Binary-Header / ASCII-Header
-  /// Binary-Header -> {Header-Name "-bin" } {binary value}
-  /// ASCII-Header -> Header-Name ASCII-Value
-  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
-  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
-  void AddMetadata(const std::string& meta_key, const std::string& meta_value);
-
-  /// Return a collection of initial metadata key-value pairs. Note that keys
-  /// may happen more than once (ie, a \a std::multimap is returned).
-  ///
-  /// \warning This method should only be called after initial metadata has been
-  /// received. For streaming calls, see \a
-  /// ClientReaderInterface::WaitForInitialMetadata().
-  ///
-  /// \return A multimap of initial metadata key-value pairs from the server.
-  const std::multimap<grpc::string_ref, grpc::string_ref>&
-  GetServerInitialMetadata() const {
-    GPR_CODEGEN_ASSERT(initial_metadata_received_);
-    return *recv_initial_metadata_.map();
-  }
-
-  /// Return a collection of trailing metadata key-value pairs. Note that keys
-  /// may happen more than once (ie, a \a std::multimap is returned).
-  ///
-  /// \warning This method is only callable once the stream has finished.
-  ///
-  /// \return A multimap of metadata trailing key-value pairs from the server.
-  const std::multimap<grpc::string_ref, grpc::string_ref>&
-  GetServerTrailingMetadata() const {
-    // TODO(yangg) check finished
-    return *trailing_metadata_.map();
-  }
-
-  /// Set the deadline for the client call.
-  ///
-  /// \warning This method should only be called before invoking the rpc.
-  ///
-  /// \param deadline the deadline for the client call. Units are determined by
-  /// the type used. The deadline is an absolute (not relative) time.
-  template <typename T>
-  void set_deadline(const T& deadline) {
-    grpc::TimePoint<T> deadline_tp(deadline);
-    deadline_ = deadline_tp.raw_time();
-  }
-
-  /// EXPERIMENTAL: Indicate that this request is idempotent.
-  /// By default, RPCs are assumed to <i>not</i> be idempotent.
-  ///
-  /// If true, the gRPC library assumes that it's safe to initiate
-  /// this RPC multiple times.
-  void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
-
-  /// EXPERIMENTAL: Set this request to be cacheable.
-  /// If set, grpc is free to use the HTTP GET verb for sending the request,
-  /// with the possibility of receiving a cached response.
-  void set_cacheable(bool cacheable) { cacheable_ = cacheable; }
-
-  /// EXPERIMENTAL: Trigger wait-for-ready or not on this request.
-  /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
-  /// If set, if an RPC is made when a channel's connectivity state is
-  /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast",
-  /// and the channel will wait until the channel is READY before making the
-  /// call.
-  void set_wait_for_ready(bool wait_for_ready) {
-    wait_for_ready_ = wait_for_ready;
-    wait_for_ready_explicitly_set_ = true;
-  }
-
-  /// DEPRECATED: Use set_wait_for_ready() instead.
-  void set_fail_fast(bool fail_fast) { set_wait_for_ready(!fail_fast); }
-
-  /// Return the deadline for the client call.
-  std::chrono::system_clock::time_point deadline() const {
-    return grpc::Timespec2Timepoint(deadline_);
-  }
-
-  /// Return a \a gpr_timespec representation of the client call's deadline.
-  gpr_timespec raw_deadline() const { return deadline_; }
-
-  /// Set the per call authority header (see
-  /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3).
-  void set_authority(const std::string& authority) { authority_ = authority; }
-
-  /// Return the authentication context for the associated client call.
-  /// It is only valid to call this during the lifetime of the client call.
-  ///
-  /// \see grpc::AuthContext.
-  std::shared_ptr<const grpc::AuthContext> auth_context() const {
-    if (auth_context_.get() == nullptr) {
-      auth_context_ = grpc::CreateAuthContext(call_);
-    }
-    return auth_context_;
-  }
-
-  /// Set credentials for the client call.
-  ///
-  /// A credentials object encapsulates all the state needed by a client to
-  /// authenticate with a server and make various assertions, e.g., about the
-  /// client’s identity, role, or whether it is authorized to make a particular
-  /// call.
-  ///
-  /// It is legal to call this only before initial metadata is sent.
-  ///
-  /// \see  https://grpc.io/docs/guides/auth.html
-  void set_credentials(const std::shared_ptr<grpc::CallCredentials>& creds);
-
-  /// EXPERIMENTAL debugging API
-  ///
-  /// Returns the credentials for the client call. This should be used only in
-  /// tests and for diagnostic purposes, and should not be used by application
-  /// logic.
-  std::shared_ptr<grpc::CallCredentials> credentials() { return creds_; }
-
-  /// Return the compression algorithm the client call will request be used.
-  /// Note that the gRPC runtime may decide to ignore this request, for example,
-  /// due to resource constraints.
-  grpc_compression_algorithm compression_algorithm() const {
-    return compression_algorithm_;
-  }
-
-  /// Set \a algorithm to be the compression algorithm used for the client call.
-  ///
-  /// \param algorithm The compression algorithm used for the client call.
-  void set_compression_algorithm(grpc_compression_algorithm algorithm);
-
-  /// Flag whether the initial metadata should be \a corked
-  ///
-  /// If \a corked is true, then the initial metadata will be coalesced with the
-  /// write of first message in the stream. As a result, any tag set for the
-  /// initial metadata operation (starting a client-streaming or bidi-streaming
-  /// RPC) will not actually be sent to the completion queue or delivered
-  /// via Next.
-  ///
-  /// \param corked The flag indicating whether the initial metadata is to be
-  /// corked or not.
-  void set_initial_metadata_corked(bool corked) {
-    initial_metadata_corked_ = corked;
-  }
-
-  /// Return the peer uri in a string.
-  /// It is only valid to call this during the lifetime of the client call.
-  ///
-  /// \warning This value is never authenticated or subject to any security
-  /// related code. It must not be used for any authentication related
-  /// functionality. Instead, use auth_context.
-  ///
-  /// \return The call's peer URI.
-  std::string peer() const;
-
-  /// Sets the census context.
-  /// It is only valid to call this before the client call is created. A common
-  /// place of setting census context is from within the DefaultConstructor
-  /// method of GlobalCallbacks.
-  void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
-
-  /// Returns the census context that has been set, or nullptr if not set.
-  struct census_context* census_context() const {
-    return census_context_;
-  }
-
-  /// Send a best-effort out-of-band cancel on the call associated with
-  /// this client context.  The call could be in any stage; e.g., if it is
-  /// already finished, it may still return success.
-  ///
-  /// There is no guarantee the call will be cancelled.
-  ///
-  /// Note that TryCancel() does not change any of the tags that are pending
-  /// on the completion queue. All pending tags will still be delivered
-  /// (though their ok result may reflect the effect of cancellation).
-  void TryCancel();
-
-  /// Global Callbacks
-  ///
-  /// Can be set exactly once per application to install hooks whenever
-  /// a client context is constructed and destructed.
-  class GlobalCallbacks {
-   public:
-    virtual ~GlobalCallbacks() {}
-    virtual void DefaultConstructor(ClientContext* context) = 0;
-    virtual void Destructor(ClientContext* context) = 0;
-  };
-  static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
-
-  /// Should be used for framework-level extensions only.
-  /// Applications never need to call this method.
-  grpc_call* c_call() { return call_; }
-
-  /// EXPERIMENTAL debugging API
-  ///
-  /// if status is not ok() for an RPC, this will return a detailed string
-  /// of the gRPC Core error that led to the failure. It should not be relied
-  /// upon for anything other than gaining more debug data in failure cases.
-  std::string debug_error_string() const { return debug_error_string_; }
-
- private:
-  // Disallow copy and assign.
-  ClientContext(const ClientContext&);
-  ClientContext& operator=(const ClientContext&);
-
-  friend class ::grpc::testing::InteropClientContextInspector;
-  friend class ::grpc::internal::CallOpClientRecvStatus;
-  friend class ::grpc::internal::CallOpRecvInitialMetadata;
-  friend class ::grpc_impl::Channel;
-  template <class R>
-  friend class ::grpc_impl::ClientReader;
-  template <class W>
-  friend class ::grpc_impl::ClientWriter;
-  template <class W, class R>
-  friend class ::grpc_impl::ClientReaderWriter;
-  template <class R>
-  friend class ::grpc_impl::ClientAsyncReader;
-  template <class W>
-  friend class ::grpc_impl::ClientAsyncWriter;
-  template <class W, class R>
-  friend class ::grpc_impl::ClientAsyncReaderWriter;
-  template <class R>
-  friend class ::grpc_impl::ClientAsyncResponseReader;
-  template <class InputMessage, class OutputMessage>
-  friend class ::grpc::internal::BlockingUnaryCallImpl;
-  template <class InputMessage, class OutputMessage>
-  friend class ::grpc_impl::internal::CallbackUnaryCallImpl;
-  template <class Request, class Response>
-  friend class ::grpc_impl::internal::ClientCallbackReaderWriterImpl;
-  template <class Response>
-  friend class ::grpc_impl::internal::ClientCallbackReaderImpl;
-  template <class Request>
-  friend class ::grpc_impl::internal::ClientCallbackWriterImpl;
-  friend class ::grpc_impl::internal::ClientCallbackUnaryImpl;
-  friend class ::grpc_impl::internal::ClientContextAccessor;
-
-  // Used by friend class CallOpClientRecvStatus
-  void set_debug_error_string(const std::string& debug_error_string) {
-    debug_error_string_ = debug_error_string;
-  }
-
-  grpc_call* call() const { return call_; }
-  void set_call(grpc_call* call,
-                const std::shared_ptr<::grpc_impl::Channel>& channel);
-
-  grpc::experimental::ClientRpcInfo* set_client_rpc_info(
-      const char* method, grpc::internal::RpcMethod::RpcType type,
-      grpc::ChannelInterface* channel,
-      const std::vector<std::unique_ptr<
-          grpc::experimental::ClientInterceptorFactoryInterface>>& creators,
-      size_t interceptor_pos) {
-    rpc_info_ = grpc::experimental::ClientRpcInfo(this, type, method, channel);
-    rpc_info_.RegisterInterceptors(creators, interceptor_pos);
-    return &rpc_info_;
-  }
-
-  uint32_t initial_metadata_flags() const {
-    return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) |
-           (wait_for_ready_ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0) |
-           (cacheable_ ? GRPC_INITIAL_METADATA_CACHEABLE_REQUEST : 0) |
-           (wait_for_ready_explicitly_set_
-                ? GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET
-                : 0) |
-           (initial_metadata_corked_ ? GRPC_INITIAL_METADATA_CORKED : 0);
-  }
-
-  std::string authority() { return authority_; }
-
-  void SendCancelToInterceptors();
-
-  static std::unique_ptr<ClientContext> FromInternalServerContext(
-      const grpc_impl::ServerContextBase& server_context,
-      PropagationOptions options);
-
-  bool initial_metadata_received_;
-  bool wait_for_ready_;
-  bool wait_for_ready_explicitly_set_;
-  bool idempotent_;
-  bool cacheable_;
-  std::shared_ptr<::grpc_impl::Channel> channel_;
-  grpc::internal::Mutex mu_;
-  grpc_call* call_;
-  bool call_canceled_;
-  gpr_timespec deadline_;
-  grpc::string authority_;
-  std::shared_ptr<grpc::CallCredentials> creds_;
-  mutable std::shared_ptr<const grpc::AuthContext> auth_context_;
-  struct census_context* census_context_;
-  std::multimap<std::string, std::string> send_initial_metadata_;
-  mutable grpc::internal::MetadataMap recv_initial_metadata_;
-  mutable grpc::internal::MetadataMap trailing_metadata_;
-
-  grpc_call* propagate_from_call_;
-  PropagationOptions propagation_options_;
-
-  grpc_compression_algorithm compression_algorithm_;
-  bool initial_metadata_corked_;
-
-  std::string debug_error_string_;
-
-  grpc::experimental::ClientRpcInfo rpc_info_;
-};
-
-}  // namespace grpc_impl
-
-#endif  // GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_IMPL_H

+ 6 - 10
include/grpcpp/impl/codegen/client_interceptor.h

@@ -26,13 +26,10 @@
 #include <grpcpp/impl/codegen/rpc_method.h>
 #include <grpcpp/impl/codegen/rpc_method.h>
 #include <grpcpp/impl/codegen/string_ref.h>
 #include <grpcpp/impl/codegen/string_ref.h>
 
 
-namespace grpc_impl {
+namespace grpc {
 
 
 class Channel;
 class Channel;
 class ClientContext;
 class ClientContext;
-}  // namespace grpc_impl
-
-namespace grpc {
 
 
 namespace internal {
 namespace internal {
 class InterceptorBatchMethodsImpl;
 class InterceptorBatchMethodsImpl;
@@ -95,7 +92,7 @@ class ClientRpcInfo {
 
 
   /// Return a pointer to the underlying ClientContext structure associated
   /// Return a pointer to the underlying ClientContext structure associated
   /// with the RPC to support features that apply to it
   /// with the RPC to support features that apply to it
-  grpc_impl::ClientContext* client_context() { return ctx_; }
+  grpc::ClientContext* client_context() { return ctx_; }
 
 
   /// Return the type of the RPC (unary or a streaming flavor)
   /// Return the type of the RPC (unary or a streaming flavor)
   Type type() const { return type_; }
   Type type() const { return type_; }
@@ -118,9 +115,8 @@ class ClientRpcInfo {
   ClientRpcInfo() = default;
   ClientRpcInfo() = default;
 
 
   // Constructor will only be called from ClientContext
   // Constructor will only be called from ClientContext
-  ClientRpcInfo(grpc_impl::ClientContext* ctx,
-                internal::RpcMethod::RpcType type, const char* method,
-                grpc::ChannelInterface* channel)
+  ClientRpcInfo(grpc::ClientContext* ctx, internal::RpcMethod::RpcType type,
+                const char* method, grpc::ChannelInterface* channel)
       : ctx_(ctx),
       : ctx_(ctx),
         type_(static_cast<Type>(type)),
         type_(static_cast<Type>(type)),
         method_(method),
         method_(method),
@@ -162,7 +158,7 @@ class ClientRpcInfo {
     }
     }
   }
   }
 
 
-  grpc_impl::ClientContext* ctx_ = nullptr;
+  grpc::ClientContext* ctx_ = nullptr;
   // TODO(yashykt): make type_ const once move-assignment is deleted
   // TODO(yashykt): make type_ const once move-assignment is deleted
   Type type_{Type::UNKNOWN};
   Type type_{Type::UNKNOWN};
   const char* method_ = nullptr;
   const char* method_ = nullptr;
@@ -172,7 +168,7 @@ class ClientRpcInfo {
   size_t hijacked_interceptor_ = 0;
   size_t hijacked_interceptor_ = 0;
 
 
   friend class internal::InterceptorBatchMethodsImpl;
   friend class internal::InterceptorBatchMethodsImpl;
-  friend class grpc_impl::ClientContext;
+  friend class grpc::ClientContext;
 };
 };
 
 
 // PLEASE DO NOT USE THIS. ALWAYS PREFER PER CHANNEL INTERCEPTORS OVER A GLOBAL
 // PLEASE DO NOT USE THIS. ALWAYS PREFER PER CHANNEL INTERCEPTORS OVER A GLOBAL

+ 4 - 7
include/grpcpp/impl/codegen/client_unary_call.h

@@ -25,18 +25,15 @@
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
 #include <grpcpp/impl/codegen/status.h>
 #include <grpcpp/impl/codegen/status.h>
 
 
-namespace grpc_impl {
-
-class ClientContext;
-}  // namespace grpc_impl
 namespace grpc {
 namespace grpc {
 
 
+class ClientContext;
 namespace internal {
 namespace internal {
 class RpcMethod;
 class RpcMethod;
 /// Wrapper that performs a blocking unary call
 /// Wrapper that performs a blocking unary call
 template <class InputMessage, class OutputMessage>
 template <class InputMessage, class OutputMessage>
 Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
 Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
-                         grpc_impl::ClientContext* context,
+                         grpc::ClientContext* context,
                          const InputMessage& request, OutputMessage* result) {
                          const InputMessage& request, OutputMessage* result) {
   return BlockingUnaryCallImpl<InputMessage, OutputMessage>(
   return BlockingUnaryCallImpl<InputMessage, OutputMessage>(
              channel, method, context, request, result)
              channel, method, context, request, result)
@@ -47,9 +44,9 @@ template <class InputMessage, class OutputMessage>
 class BlockingUnaryCallImpl {
 class BlockingUnaryCallImpl {
  public:
  public:
   BlockingUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
   BlockingUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
-                        grpc_impl::ClientContext* context,
+                        grpc::ClientContext* context,
                         const InputMessage& request, OutputMessage* result) {
                         const InputMessage& request, OutputMessage* result) {
-    ::grpc_impl::CompletionQueue cq(grpc_completion_queue_attributes{
+    ::grpc::CompletionQueue cq(grpc_completion_queue_attributes{
         GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
         GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
         nullptr});  // Pluckable completion queue
         nullptr});  // Pluckable completion queue
     ::grpc::internal::Call call(channel->CreateCall(method, context, &cq));
     ::grpc::internal::Call call(channel->CreateCall(method, context, &cq));

+ 423 - 3
include/grpcpp/impl/codegen/completion_queue.h

@@ -16,15 +16,435 @@
  *
  *
  */
  */
 
 
+/// A completion queue implements a concurrent producer-consumer queue, with
+/// two main API-exposed methods: \a Next and \a AsyncNext. These
+/// methods are the essential component of the gRPC C++ asynchronous API.
+/// There is also a \a Shutdown method to indicate that a given completion queue
+/// will no longer have regular events. This must be called before the
+/// completion queue is destroyed.
+/// All completion queue APIs are thread-safe and may be used concurrently with
+/// any other completion queue API invocation; it is acceptable to have
+/// multiple threads calling \a Next or \a AsyncNext on the same or different
+/// completion queues, or to call these methods concurrently with a \a Shutdown
+/// elsewhere.
+/// \remark{All other API calls on completion queue should be completed before
+/// a completion queue destructor is called.}
 #ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
 #ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
 #define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
 #define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
 
 
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
+#include <list>
 
 
+#include <grpc/impl/codegen/atm.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/sync.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct grpc_completion_queue;
+
+namespace grpc_impl {
+
+class Server;
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+template <class R>
+class ServerReader;
+template <class W>
+class ServerWriter;
+class ServerContextBase;
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody;
+
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler;
+template <::grpc::StatusCode code>
+class ErrorMethodHandler;
+}  // namespace internal
+}  // namespace grpc_impl
 namespace grpc {
 namespace grpc {
 
 
-typedef ::grpc_impl::CompletionQueue CompletionQueue;
-typedef ::grpc_impl::ServerCompletionQueue ServerCompletionQueue;
+class Channel;
+class ChannelInterface;
+class ServerBuilder;
+class ServerInterface;
+
+namespace internal {
+class CompletionQueueTag;
+class RpcMethod;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
+class CallOpSet;
+}  // namespace internal
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// A thin wrapper around \ref grpc_completion_queue (see \ref
+/// src/core/lib/surface/completion_queue.h).
+/// See \ref doc/cpp/perf_notes.md for notes on best practices for high
+/// performance servers.
+class CompletionQueue : private ::grpc::GrpcLibraryCodegen {
+ public:
+  /// Default constructor. Implicitly creates a \a grpc_completion_queue
+  /// instance.
+  CompletionQueue()
+      : CompletionQueue(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING,
+            nullptr}) {}
+
+  /// Wrap \a take, taking ownership of the instance.
+  ///
+  /// \param take The completion queue instance to wrap. Ownership is taken.
+  explicit CompletionQueue(grpc_completion_queue* take);
+
+  /// Destructor. Destroys the owned wrapped completion queue / instance.
+  ~CompletionQueue() {
+    ::grpc::g_core_codegen_interface->grpc_completion_queue_destroy(cq_);
+  }
+
+  /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
+  enum NextStatus {
+    SHUTDOWN,   ///< The completion queue has been shutdown and fully-drained
+    GOT_EVENT,  ///< Got a new event; \a tag will be filled in with its
+                ///< associated value; \a ok indicating its success.
+    TIMEOUT     ///< deadline was reached.
+  };
+
+  /// Read from the queue, blocking until an event is available or the queue is
+  /// shutting down.
+  ///
+  /// \param tag [out] Updated to point to the read event's tag.
+  /// \param ok [out] true if read a successful event, false otherwise.
+  ///
+  /// Note that each tag sent to the completion queue (through RPC operations
+  /// or alarms) will be delivered out of the completion queue by a call to
+  /// Next (or a related method), regardless of whether the operation succeeded
+  /// or not. Success here means that this operation completed in the normal
+  /// valid manner.
+  ///
+  /// Server-side RPC request: \a ok indicates that the RPC has indeed
+  /// been started. If it is false, the server has been Shutdown
+  /// before this particular call got matched to an incoming RPC.
+  ///
+  /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is
+  /// going to go to the wire. If it is false, it not going to the wire. This
+  /// would happen if the channel is either permanently broken or
+  /// transiently broken but with the fail-fast option. (Note that async unary
+  /// RPCs don't post a CQ tag at this point, nor do client-streaming
+  /// or bidi-streaming RPCs that have the initial metadata corked option set.)
+  ///
+  /// Client-side Write, Client-side WritesDone, Server-side Write,
+  /// Server-side Finish, Server-side SendInitialMetadata (which is
+  /// typically included in Write or Finish when not done explicitly):
+  /// \a ok means that the data/metadata/status/etc is going to go to the
+  /// wire. If it is false, it not going to the wire because the call
+  /// is already dead (i.e., canceled, deadline expired, other side
+  /// dropped the channel, etc).
+  ///
+  /// Client-side Read, Server-side Read, Client-side
+  /// RecvInitialMetadata (which is typically included in Read if not
+  /// done explicitly): \a ok indicates whether there is a valid message
+  /// that got read. If not, you know that there are certainly no more
+  /// messages that can ever be read from this stream. For the client-side
+  /// operations, this only happens because the call is dead. For the
+  /// server-sider operation, though, this could happen because the client
+  /// has done a WritesDone already.
+  ///
+  /// Client-side Finish: \a ok should always be true
+  ///
+  /// Server-side AsyncNotifyWhenDone: \a ok should always be true
+  ///
+  /// Alarm: \a ok is true if it expired, false if it was canceled
+  ///
+  /// \return true if got an event, false if the queue is fully drained and
+  ///         shut down.
+  bool Next(void** tag, bool* ok) {
+    return (AsyncNextInternal(tag, ok,
+                              ::grpc::g_core_codegen_interface->gpr_inf_future(
+                                  GPR_CLOCK_REALTIME)) != SHUTDOWN);
+  }
+
+  /// Read from the queue, blocking up to \a deadline (or the queue's shutdown).
+  /// Both \a tag and \a ok are updated upon success (if an event is available
+  /// within the \a deadline).  A \a tag points to an arbitrary location usually
+  /// employed to uniquely identify an event.
+  ///
+  /// \param tag [out] Upon success, updated to point to the event's tag.
+  /// \param ok [out] Upon success, true if a successful event, false otherwise
+  ///        See documentation for CompletionQueue::Next for explanation of ok
+  /// \param deadline [in] How long to block in wait for an event.
+  ///
+  /// \return The type of event read.
+  template <typename T>
+  NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) {
+    ::grpc::TimePoint<T> deadline_tp(deadline);
+    return AsyncNextInternal(tag, ok, deadline_tp.raw_time());
+  }
+
+  /// EXPERIMENTAL
+  /// First executes \a F, then reads from the queue, blocking up to
+  /// \a deadline (or the queue's shutdown).
+  /// Both \a tag and \a ok are updated upon success (if an event is available
+  /// within the \a deadline).  A \a tag points to an arbitrary location usually
+  /// employed to uniquely identify an event.
+  ///
+  /// \param f [in] Function to execute before calling AsyncNext on this queue.
+  /// \param tag [out] Upon success, updated to point to the event's tag.
+  /// \param ok [out] Upon success, true if read a regular event, false
+  /// otherwise.
+  /// \param deadline [in] How long to block in wait for an event.
+  ///
+  /// \return The type of event read.
+  template <typename T, typename F>
+  NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) {
+    CompletionQueueTLSCache cache = CompletionQueueTLSCache(this);
+    f();
+    if (cache.Flush(tag, ok)) {
+      return GOT_EVENT;
+    } else {
+      return AsyncNext(tag, ok, deadline);
+    }
+  }
+
+  /// Request the shutdown of the queue.
+  ///
+  /// \warning This method must be called at some point if this completion queue
+  /// is accessed with Next or AsyncNext. \a Next will not return false
+  /// until this method has been called and all pending tags have been drained.
+  /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .)
+  /// Only once either one of these methods does that (that is, once the queue
+  /// has been \em drained) can an instance of this class be destroyed.
+  /// Also note that applications must ensure that no work is enqueued on this
+  /// completion queue after this method is called.
+  void Shutdown();
+
+  /// Returns a \em raw pointer to the underlying \a grpc_completion_queue
+  /// instance.
+  ///
+  /// \warning Remember that the returned instance is owned. No transfer of
+  /// owership is performed.
+  grpc_completion_queue* cq() { return cq_; }
+
+ protected:
+  /// Private constructor of CompletionQueue only visible to friend classes
+  CompletionQueue(const grpc_completion_queue_attributes& attributes) {
+    cq_ = ::grpc::g_core_codegen_interface->grpc_completion_queue_create(
+        ::grpc::g_core_codegen_interface->grpc_completion_queue_factory_lookup(
+            &attributes),
+        &attributes, NULL);
+    InitialAvalanching();  // reserve this for the future shutdown
+  }
+
+ private:
+  // Friends for access to server registration lists that enable checking and
+  // logging on shutdown
+  friend class ::grpc::ServerBuilder;
+  friend class ::grpc_impl::Server;
+
+  // Friend synchronous wrappers so that they can access Pluck(), which is
+  // a semi-private API geared towards the synchronous implementation.
+  template <class R>
+  friend class ::grpc_impl::ClientReader;
+  template <class W>
+  friend class ::grpc_impl::ClientWriter;
+  template <class W, class R>
+  friend class ::grpc_impl::ClientReaderWriter;
+  template <class R>
+  friend class ::grpc_impl::ServerReader;
+  template <class W>
+  friend class ::grpc_impl::ServerWriter;
+  template <class W, class R>
+  friend class ::grpc_impl::internal::ServerReaderWriterBody;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc_impl::internal::RpcMethodHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc_impl::internal::ClientStreamingHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc_impl::internal::ServerStreamingHandler;
+  template <class Streamer, bool WriteNeeded>
+  friend class ::grpc_impl::internal::TemplatedBidiStreamingHandler;
+  template <::grpc::StatusCode code>
+  friend class ::grpc_impl::internal::ErrorMethodHandler;
+  friend class ::grpc_impl::ServerContextBase;
+  friend class ::grpc::ServerInterface;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::BlockingUnaryCallImpl;
+
+  // Friends that need access to constructor for callback CQ
+  friend class ::grpc::Channel;
+
+  // For access to Register/CompleteAvalanching
+  template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
+  friend class ::grpc::internal::CallOpSet;
+
+  /// EXPERIMENTAL
+  /// Creates a Thread Local cache to store the first event
+  /// On this completion queue queued from this thread.  Once
+  /// initialized, it must be flushed on the same thread.
+  class CompletionQueueTLSCache {
+   public:
+    CompletionQueueTLSCache(CompletionQueue* cq);
+    ~CompletionQueueTLSCache();
+    bool Flush(void** tag, bool* ok);
+
+   private:
+    CompletionQueue* cq_;
+    bool flushed_;
+  };
+
+  NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline);
+
+  /// Wraps \a grpc_completion_queue_pluck.
+  /// \warning Must not be mixed with calls to \a Next.
+  bool Pluck(::grpc::internal::CompletionQueueTag* tag) {
+    auto deadline =
+        ::grpc::g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
+    while (true) {
+      auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck(
+          cq_, tag, deadline, nullptr);
+      bool ok = ev.success != 0;
+      void* ignored = tag;
+      if (tag->FinalizeResult(&ignored, &ok)) {
+        GPR_CODEGEN_ASSERT(ignored == tag);
+        return ok;
+      }
+    }
+  }
+
+  /// Performs a single polling pluck on \a tag.
+  /// \warning Must not be mixed with calls to \a Next.
+  ///
+  /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already
+  /// shutdown. This is most likely a bug and if it is a bug, then change this
+  /// implementation to simple call the other TryPluck function with a zero
+  /// timeout. i.e:
+  ///      TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME))
+  void TryPluck(::grpc::internal::CompletionQueueTag* tag) {
+    auto deadline =
+        ::grpc::g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME);
+    auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck(
+        cq_, tag, deadline, nullptr);
+    if (ev.type == GRPC_QUEUE_TIMEOUT) return;
+    bool ok = ev.success != 0;
+    void* ignored = tag;
+    // the tag must be swallowed if using TryPluck
+    GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
+  }
+
+  /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if
+  /// the pluck() was successful and returned the tag.
+  ///
+  /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects
+  /// that the tag is internal not something that is returned to the user.
+  void TryPluck(::grpc::internal::CompletionQueueTag* tag,
+                gpr_timespec deadline) {
+    auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck(
+        cq_, tag, deadline, nullptr);
+    if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) {
+      return;
+    }
+
+    bool ok = ev.success != 0;
+    void* ignored = tag;
+    GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
+  }
+
+  /// Manage state of avalanching operations : completion queue tags that
+  /// trigger other completion queue operations. The underlying core completion
+  /// queue should not really shutdown until all avalanching operations have
+  /// been finalized. Note that we maintain the requirement that an avalanche
+  /// registration must take place before CQ shutdown (which must be maintained
+  /// elsehwere)
+  void InitialAvalanching() {
+    gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1));
+  }
+  void RegisterAvalanching() {
+    gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
+                                 static_cast<gpr_atm>(1));
+  }
+  void CompleteAvalanching() {
+    if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
+                                     static_cast<gpr_atm>(-1)) == 1) {
+      ::grpc::g_core_codegen_interface->grpc_completion_queue_shutdown(cq_);
+    }
+  }
+
+  void RegisterServer(const ::grpc_impl::Server* server) {
+    (void)server;
+#ifndef NDEBUG
+    grpc::internal::MutexLock l(&server_list_mutex_);
+    server_list_.push_back(server);
+#endif
+  }
+  void UnregisterServer(const ::grpc_impl::Server* server) {
+    (void)server;
+#ifndef NDEBUG
+    grpc::internal::MutexLock l(&server_list_mutex_);
+    server_list_.remove(server);
+#endif
+  }
+  bool ServerListEmpty() const {
+#ifndef NDEBUG
+    grpc::internal::MutexLock l(&server_list_mutex_);
+    return server_list_.empty();
+#endif
+    return true;
+  }
+
+  grpc_completion_queue* cq_;  // owned
+
+  gpr_atm avalanches_in_flight_;
+
+  // List of servers associated with this CQ. Even though this is only used with
+  // NDEBUG, instantiate it in all cases since otherwise the size will be
+  // inconsistent.
+  mutable grpc::internal::Mutex server_list_mutex_;
+  std::list<const ::grpc_impl::Server*>
+      server_list_ /* GUARDED_BY(server_list_mutex_) */;
+};
+
+/// A specific type of completion queue used by the processing of notifications
+/// by servers. Instantiated by \a ServerBuilder or Server (for health checker).
+class ServerCompletionQueue : public CompletionQueue {
+ public:
+  bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; }
+
+ protected:
+  /// Default constructor
+  ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {}
+
+ private:
+  /// \param completion_type indicates whether this is a NEXT or CALLBACK
+  /// completion queue.
+  /// \param polling_type Informs the GRPC library about the type of polling
+  /// allowed on this completion queue. See grpc_cq_polling_type's description
+  /// in grpc_types.h for more details.
+  /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues
+  ServerCompletionQueue(grpc_cq_completion_type completion_type,
+                        grpc_cq_polling_type polling_type,
+                        grpc_experimental_completion_queue_functor* shutdown_cb)
+      : CompletionQueue(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, completion_type, polling_type,
+            shutdown_cb}),
+        polling_type_(polling_type) {}
+
+  grpc_cq_polling_type polling_type_;
+  friend class ::grpc::ServerBuilder;
+  friend class ::grpc_impl::Server;
+};
 
 
 }  // namespace grpc
 }  // namespace grpc
 
 

+ 0 - 454
include/grpcpp/impl/codegen/completion_queue_impl.h

@@ -1,454 +0,0 @@
-/*
- *
- * Copyright 2015-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.
- *
- */
-
-/// A completion queue implements a concurrent producer-consumer queue, with
-/// two main API-exposed methods: \a Next and \a AsyncNext. These
-/// methods are the essential component of the gRPC C++ asynchronous API.
-/// There is also a \a Shutdown method to indicate that a given completion queue
-/// will no longer have regular events. This must be called before the
-/// completion queue is destroyed.
-/// All completion queue APIs are thread-safe and may be used concurrently with
-/// any other completion queue API invocation; it is acceptable to have
-/// multiple threads calling \a Next or \a AsyncNext on the same or different
-/// completion queues, or to call these methods concurrently with a \a Shutdown
-/// elsewhere.
-/// \remark{All other API calls on completion queue should be completed before
-/// a completion queue destructor is called.}
-#ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H
-#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H
-
-#include <list>
-
-#include <grpc/impl/codegen/atm.h>
-#include <grpcpp/impl/codegen/completion_queue_tag.h>
-#include <grpcpp/impl/codegen/core_codegen_interface.h>
-#include <grpcpp/impl/codegen/grpc_library.h>
-#include <grpcpp/impl/codegen/status.h>
-#include <grpcpp/impl/codegen/sync.h>
-#include <grpcpp/impl/codegen/time.h>
-
-struct grpc_completion_queue;
-
-namespace grpc_impl {
-
-class Channel;
-class Server;
-template <class R>
-class ClientReader;
-template <class W>
-class ClientWriter;
-template <class W, class R>
-class ClientReaderWriter;
-template <class R>
-class ServerReader;
-template <class W>
-class ServerWriter;
-class ServerContextBase;
-namespace internal {
-template <class W, class R>
-class ServerReaderWriterBody;
-
-template <class ServiceType, class RequestType, class ResponseType>
-class RpcMethodHandler;
-template <class ServiceType, class RequestType, class ResponseType>
-class ClientStreamingHandler;
-template <class ServiceType, class RequestType, class ResponseType>
-class ServerStreamingHandler;
-template <class Streamer, bool WriteNeeded>
-class TemplatedBidiStreamingHandler;
-template <::grpc::StatusCode code>
-class ErrorMethodHandler;
-}  // namespace internal
-}  // namespace grpc_impl
-namespace grpc {
-
-class ChannelInterface;
-class ServerBuilder;
-class ServerInterface;
-
-namespace internal {
-class CompletionQueueTag;
-class RpcMethod;
-template <class InputMessage, class OutputMessage>
-class BlockingUnaryCallImpl;
-template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
-class CallOpSet;
-}  // namespace internal
-
-extern CoreCodegenInterface* g_core_codegen_interface;
-
-}  // namespace grpc
-
-namespace grpc_impl {
-
-/// A thin wrapper around \ref grpc_completion_queue (see \ref
-/// src/core/lib/surface/completion_queue.h).
-/// See \ref doc/cpp/perf_notes.md for notes on best practices for high
-/// performance servers.
-class CompletionQueue : private ::grpc::GrpcLibraryCodegen {
- public:
-  /// Default constructor. Implicitly creates a \a grpc_completion_queue
-  /// instance.
-  CompletionQueue()
-      : CompletionQueue(grpc_completion_queue_attributes{
-            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING,
-            nullptr}) {}
-
-  /// Wrap \a take, taking ownership of the instance.
-  ///
-  /// \param take The completion queue instance to wrap. Ownership is taken.
-  explicit CompletionQueue(grpc_completion_queue* take);
-
-  /// Destructor. Destroys the owned wrapped completion queue / instance.
-  ~CompletionQueue() {
-    ::grpc::g_core_codegen_interface->grpc_completion_queue_destroy(cq_);
-  }
-
-  /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
-  enum NextStatus {
-    SHUTDOWN,   ///< The completion queue has been shutdown and fully-drained
-    GOT_EVENT,  ///< Got a new event; \a tag will be filled in with its
-                ///< associated value; \a ok indicating its success.
-    TIMEOUT     ///< deadline was reached.
-  };
-
-  /// Read from the queue, blocking until an event is available or the queue is
-  /// shutting down.
-  ///
-  /// \param tag [out] Updated to point to the read event's tag.
-  /// \param ok [out] true if read a successful event, false otherwise.
-  ///
-  /// Note that each tag sent to the completion queue (through RPC operations
-  /// or alarms) will be delivered out of the completion queue by a call to
-  /// Next (or a related method), regardless of whether the operation succeeded
-  /// or not. Success here means that this operation completed in the normal
-  /// valid manner.
-  ///
-  /// Server-side RPC request: \a ok indicates that the RPC has indeed
-  /// been started. If it is false, the server has been Shutdown
-  /// before this particular call got matched to an incoming RPC.
-  ///
-  /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is
-  /// going to go to the wire. If it is false, it not going to the wire. This
-  /// would happen if the channel is either permanently broken or
-  /// transiently broken but with the fail-fast option. (Note that async unary
-  /// RPCs don't post a CQ tag at this point, nor do client-streaming
-  /// or bidi-streaming RPCs that have the initial metadata corked option set.)
-  ///
-  /// Client-side Write, Client-side WritesDone, Server-side Write,
-  /// Server-side Finish, Server-side SendInitialMetadata (which is
-  /// typically included in Write or Finish when not done explicitly):
-  /// \a ok means that the data/metadata/status/etc is going to go to the
-  /// wire. If it is false, it not going to the wire because the call
-  /// is already dead (i.e., canceled, deadline expired, other side
-  /// dropped the channel, etc).
-  ///
-  /// Client-side Read, Server-side Read, Client-side
-  /// RecvInitialMetadata (which is typically included in Read if not
-  /// done explicitly): \a ok indicates whether there is a valid message
-  /// that got read. If not, you know that there are certainly no more
-  /// messages that can ever be read from this stream. For the client-side
-  /// operations, this only happens because the call is dead. For the
-  /// server-sider operation, though, this could happen because the client
-  /// has done a WritesDone already.
-  ///
-  /// Client-side Finish: \a ok should always be true
-  ///
-  /// Server-side AsyncNotifyWhenDone: \a ok should always be true
-  ///
-  /// Alarm: \a ok is true if it expired, false if it was canceled
-  ///
-  /// \return true if got an event, false if the queue is fully drained and
-  ///         shut down.
-  bool Next(void** tag, bool* ok) {
-    return (AsyncNextInternal(tag, ok,
-                              ::grpc::g_core_codegen_interface->gpr_inf_future(
-                                  GPR_CLOCK_REALTIME)) != SHUTDOWN);
-  }
-
-  /// Read from the queue, blocking up to \a deadline (or the queue's shutdown).
-  /// Both \a tag and \a ok are updated upon success (if an event is available
-  /// within the \a deadline).  A \a tag points to an arbitrary location usually
-  /// employed to uniquely identify an event.
-  ///
-  /// \param tag [out] Upon success, updated to point to the event's tag.
-  /// \param ok [out] Upon success, true if a successful event, false otherwise
-  ///        See documentation for CompletionQueue::Next for explanation of ok
-  /// \param deadline [in] How long to block in wait for an event.
-  ///
-  /// \return The type of event read.
-  template <typename T>
-  NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) {
-    ::grpc::TimePoint<T> deadline_tp(deadline);
-    return AsyncNextInternal(tag, ok, deadline_tp.raw_time());
-  }
-
-  /// EXPERIMENTAL
-  /// First executes \a F, then reads from the queue, blocking up to
-  /// \a deadline (or the queue's shutdown).
-  /// Both \a tag and \a ok are updated upon success (if an event is available
-  /// within the \a deadline).  A \a tag points to an arbitrary location usually
-  /// employed to uniquely identify an event.
-  ///
-  /// \param f [in] Function to execute before calling AsyncNext on this queue.
-  /// \param tag [out] Upon success, updated to point to the event's tag.
-  /// \param ok [out] Upon success, true if read a regular event, false
-  /// otherwise.
-  /// \param deadline [in] How long to block in wait for an event.
-  ///
-  /// \return The type of event read.
-  template <typename T, typename F>
-  NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) {
-    CompletionQueueTLSCache cache = CompletionQueueTLSCache(this);
-    f();
-    if (cache.Flush(tag, ok)) {
-      return GOT_EVENT;
-    } else {
-      return AsyncNext(tag, ok, deadline);
-    }
-  }
-
-  /// Request the shutdown of the queue.
-  ///
-  /// \warning This method must be called at some point if this completion queue
-  /// is accessed with Next or AsyncNext. \a Next will not return false
-  /// until this method has been called and all pending tags have been drained.
-  /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .)
-  /// Only once either one of these methods does that (that is, once the queue
-  /// has been \em drained) can an instance of this class be destroyed.
-  /// Also note that applications must ensure that no work is enqueued on this
-  /// completion queue after this method is called.
-  void Shutdown();
-
-  /// Returns a \em raw pointer to the underlying \a grpc_completion_queue
-  /// instance.
-  ///
-  /// \warning Remember that the returned instance is owned. No transfer of
-  /// owership is performed.
-  grpc_completion_queue* cq() { return cq_; }
-
- protected:
-  /// Private constructor of CompletionQueue only visible to friend classes
-  CompletionQueue(const grpc_completion_queue_attributes& attributes) {
-    cq_ = ::grpc::g_core_codegen_interface->grpc_completion_queue_create(
-        ::grpc::g_core_codegen_interface->grpc_completion_queue_factory_lookup(
-            &attributes),
-        &attributes, NULL);
-    InitialAvalanching();  // reserve this for the future shutdown
-  }
-
- private:
-  // Friends for access to server registration lists that enable checking and
-  // logging on shutdown
-  friend class ::grpc::ServerBuilder;
-  friend class ::grpc_impl::Server;
-
-  // Friend synchronous wrappers so that they can access Pluck(), which is
-  // a semi-private API geared towards the synchronous implementation.
-  template <class R>
-  friend class ::grpc_impl::ClientReader;
-  template <class W>
-  friend class ::grpc_impl::ClientWriter;
-  template <class W, class R>
-  friend class ::grpc_impl::ClientReaderWriter;
-  template <class R>
-  friend class ::grpc_impl::ServerReader;
-  template <class W>
-  friend class ::grpc_impl::ServerWriter;
-  template <class W, class R>
-  friend class ::grpc_impl::internal::ServerReaderWriterBody;
-  template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc_impl::internal::RpcMethodHandler;
-  template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc_impl::internal::ClientStreamingHandler;
-  template <class ServiceType, class RequestType, class ResponseType>
-  friend class ::grpc_impl::internal::ServerStreamingHandler;
-  template <class Streamer, bool WriteNeeded>
-  friend class ::grpc_impl::internal::TemplatedBidiStreamingHandler;
-  template <::grpc::StatusCode code>
-  friend class ::grpc_impl::internal::ErrorMethodHandler;
-  friend class ::grpc_impl::ServerContextBase;
-  friend class ::grpc::ServerInterface;
-  template <class InputMessage, class OutputMessage>
-  friend class ::grpc::internal::BlockingUnaryCallImpl;
-
-  // Friends that need access to constructor for callback CQ
-  friend class ::grpc_impl::Channel;
-
-  // For access to Register/CompleteAvalanching
-  template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
-  friend class ::grpc::internal::CallOpSet;
-
-  /// EXPERIMENTAL
-  /// Creates a Thread Local cache to store the first event
-  /// On this completion queue queued from this thread.  Once
-  /// initialized, it must be flushed on the same thread.
-  class CompletionQueueTLSCache {
-   public:
-    CompletionQueueTLSCache(CompletionQueue* cq);
-    ~CompletionQueueTLSCache();
-    bool Flush(void** tag, bool* ok);
-
-   private:
-    CompletionQueue* cq_;
-    bool flushed_;
-  };
-
-  NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline);
-
-  /// Wraps \a grpc_completion_queue_pluck.
-  /// \warning Must not be mixed with calls to \a Next.
-  bool Pluck(::grpc::internal::CompletionQueueTag* tag) {
-    auto deadline =
-        ::grpc::g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
-    while (true) {
-      auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck(
-          cq_, tag, deadline, nullptr);
-      bool ok = ev.success != 0;
-      void* ignored = tag;
-      if (tag->FinalizeResult(&ignored, &ok)) {
-        GPR_CODEGEN_ASSERT(ignored == tag);
-        return ok;
-      }
-    }
-  }
-
-  /// Performs a single polling pluck on \a tag.
-  /// \warning Must not be mixed with calls to \a Next.
-  ///
-  /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already
-  /// shutdown. This is most likely a bug and if it is a bug, then change this
-  /// implementation to simple call the other TryPluck function with a zero
-  /// timeout. i.e:
-  ///      TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME))
-  void TryPluck(::grpc::internal::CompletionQueueTag* tag) {
-    auto deadline =
-        ::grpc::g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME);
-    auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck(
-        cq_, tag, deadline, nullptr);
-    if (ev.type == GRPC_QUEUE_TIMEOUT) return;
-    bool ok = ev.success != 0;
-    void* ignored = tag;
-    // the tag must be swallowed if using TryPluck
-    GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
-  }
-
-  /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if
-  /// the pluck() was successful and returned the tag.
-  ///
-  /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects
-  /// that the tag is internal not something that is returned to the user.
-  void TryPluck(::grpc::internal::CompletionQueueTag* tag,
-                gpr_timespec deadline) {
-    auto ev = ::grpc::g_core_codegen_interface->grpc_completion_queue_pluck(
-        cq_, tag, deadline, nullptr);
-    if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) {
-      return;
-    }
-
-    bool ok = ev.success != 0;
-    void* ignored = tag;
-    GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
-  }
-
-  /// Manage state of avalanching operations : completion queue tags that
-  /// trigger other completion queue operations. The underlying core completion
-  /// queue should not really shutdown until all avalanching operations have
-  /// been finalized. Note that we maintain the requirement that an avalanche
-  /// registration must take place before CQ shutdown (which must be maintained
-  /// elsehwere)
-  void InitialAvalanching() {
-    gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1));
-  }
-  void RegisterAvalanching() {
-    gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
-                                 static_cast<gpr_atm>(1));
-  }
-  void CompleteAvalanching() {
-    if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
-                                     static_cast<gpr_atm>(-1)) == 1) {
-      ::grpc::g_core_codegen_interface->grpc_completion_queue_shutdown(cq_);
-    }
-  }
-
-  void RegisterServer(const Server* server) {
-    (void)server;
-#ifndef NDEBUG
-    grpc::internal::MutexLock l(&server_list_mutex_);
-    server_list_.push_back(server);
-#endif
-  }
-  void UnregisterServer(const Server* server) {
-    (void)server;
-#ifndef NDEBUG
-    grpc::internal::MutexLock l(&server_list_mutex_);
-    server_list_.remove(server);
-#endif
-  }
-  bool ServerListEmpty() const {
-#ifndef NDEBUG
-    grpc::internal::MutexLock l(&server_list_mutex_);
-    return server_list_.empty();
-#endif
-    return true;
-  }
-
-  grpc_completion_queue* cq_;  // owned
-
-  gpr_atm avalanches_in_flight_;
-
-  // List of servers associated with this CQ. Even though this is only used with
-  // NDEBUG, instantiate it in all cases since otherwise the size will be
-  // inconsistent.
-  mutable grpc::internal::Mutex server_list_mutex_;
-  std::list<const Server*> server_list_ /* GUARDED_BY(server_list_mutex_) */;
-};
-
-/// A specific type of completion queue used by the processing of notifications
-/// by servers. Instantiated by \a ServerBuilder or Server (for health checker).
-class ServerCompletionQueue : public CompletionQueue {
- public:
-  bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; }
-
- protected:
-  /// Default constructor
-  ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {}
-
- private:
-  /// \param completion_type indicates whether this is a NEXT or CALLBACK
-  /// completion queue.
-  /// \param polling_type Informs the GRPC library about the type of polling
-  /// allowed on this completion queue. See grpc_cq_polling_type's description
-  /// in grpc_types.h for more details.
-  /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues
-  ServerCompletionQueue(grpc_cq_completion_type completion_type,
-                        grpc_cq_polling_type polling_type,
-                        grpc_experimental_completion_queue_functor* shutdown_cb)
-      : CompletionQueue(grpc_completion_queue_attributes{
-            GRPC_CQ_CURRENT_VERSION, completion_type, polling_type,
-            shutdown_cb}),
-        polling_type_(polling_type) {}
-
-  grpc_cq_polling_type polling_type_;
-  friend class ::grpc::ServerBuilder;
-  friend class ::grpc_impl::Server;
-};
-
-}  // namespace grpc_impl
-
-#endif  // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_IMPL_H

+ 4 - 4
include/grpcpp/impl/codegen/delegating_channel.h

@@ -40,7 +40,7 @@ class DelegatingChannel : public ::grpc::ChannelInterface {
  private:
  private:
   internal::Call CreateCall(const internal::RpcMethod& method,
   internal::Call CreateCall(const internal::RpcMethod& method,
                             ClientContext* context,
                             ClientContext* context,
-                            ::grpc_impl::CompletionQueue* cq) final {
+                            ::grpc::CompletionQueue* cq) final {
     return delegate_channel()->CreateCall(method, context, cq);
     return delegate_channel()->CreateCall(method, context, cq);
   }
   }
 
 
@@ -55,7 +55,7 @@ class DelegatingChannel : public ::grpc::ChannelInterface {
 
 
   void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
   void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
                                gpr_timespec deadline,
                                gpr_timespec deadline,
-                               ::grpc_impl::CompletionQueue* cq,
+                               ::grpc::CompletionQueue* cq,
                                void* tag) override {
                                void* tag) override {
     delegate_channel()->NotifyOnStateChangeImpl(last_observed, deadline, cq,
     delegate_channel()->NotifyOnStateChangeImpl(last_observed, deadline, cq,
                                                 tag);
                                                 tag);
@@ -68,13 +68,13 @@ class DelegatingChannel : public ::grpc::ChannelInterface {
 
 
   internal::Call CreateCallInternal(const internal::RpcMethod& method,
   internal::Call CreateCallInternal(const internal::RpcMethod& method,
                                     ClientContext* context,
                                     ClientContext* context,
-                                    ::grpc_impl::CompletionQueue* cq,
+                                    ::grpc::CompletionQueue* cq,
                                     size_t interceptor_pos) final {
                                     size_t interceptor_pos) final {
     return delegate_channel()->CreateCallInternal(method, context, cq,
     return delegate_channel()->CreateCallInternal(method, context, cq,
                                                   interceptor_pos);
                                                   interceptor_pos);
   }
   }
 
 
-  ::grpc_impl::CompletionQueue* CallbackCQ() final {
+  ::grpc::CompletionQueue* CallbackCQ() final {
     return delegate_channel()->CallbackCQ();
     return delegate_channel()->CallbackCQ();
   }
   }
 
 

+ 5 - 8
include/grpcpp/impl/codegen/intercepted_channel.h

@@ -21,11 +21,8 @@
 
 
 #include <grpcpp/impl/codegen/channel_interface.h>
 #include <grpcpp/impl/codegen/channel_interface.h>
 
 
-namespace grpc_impl {
-class CompletionQueue;
-}
-
 namespace grpc {
 namespace grpc {
+class CompletionQueue;
 
 
 namespace internal {
 namespace internal {
 
 
@@ -49,8 +46,8 @@ class InterceptedChannel : public ChannelInterface {
   InterceptedChannel(ChannelInterface* channel, size_t pos)
   InterceptedChannel(ChannelInterface* channel, size_t pos)
       : channel_(channel), interceptor_pos_(pos) {}
       : channel_(channel), interceptor_pos_(pos) {}
 
 
-  Call CreateCall(const RpcMethod& method, ::grpc_impl::ClientContext* context,
-                  ::grpc_impl::CompletionQueue* cq) override {
+  Call CreateCall(const RpcMethod& method, ::grpc::ClientContext* context,
+                  ::grpc::CompletionQueue* cq) override {
     return channel_->CreateCallInternal(method, context, cq, interceptor_pos_);
     return channel_->CreateCallInternal(method, context, cq, interceptor_pos_);
   }
   }
 
 
@@ -63,7 +60,7 @@ class InterceptedChannel : public ChannelInterface {
 
 
   void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
   void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
                                gpr_timespec deadline,
                                gpr_timespec deadline,
-                               ::grpc_impl::CompletionQueue* cq,
+                               ::grpc::CompletionQueue* cq,
                                void* tag) override {
                                void* tag) override {
     return channel_->NotifyOnStateChangeImpl(last_observed, deadline, cq, tag);
     return channel_->NotifyOnStateChangeImpl(last_observed, deadline, cq, tag);
   }
   }
@@ -72,7 +69,7 @@ class InterceptedChannel : public ChannelInterface {
     return channel_->WaitForStateChangeImpl(last_observed, deadline);
     return channel_->WaitForStateChangeImpl(last_observed, deadline);
   }
   }
 
 
-  ::grpc_impl::CompletionQueue* CallbackCQ() override {
+  ::grpc::CompletionQueue* CallbackCQ() override {
     return channel_->CallbackCQ();
     return channel_->CallbackCQ();
   }
   }
 
 

+ 4 - 4
include/grpcpp/impl/codegen/server_context_impl.h

@@ -49,8 +49,6 @@ struct grpc_call;
 struct census_context;
 struct census_context;
 
 
 namespace grpc_impl {
 namespace grpc_impl {
-class ClientContext;
-class CompletionQueue;
 class Server;
 class Server;
 template <class W, class R>
 template <class W, class R>
 class ServerAsyncReader;
 class ServerAsyncReader;
@@ -95,6 +93,8 @@ class ErrorMethodHandler;
 
 
 }  // namespace grpc_impl
 }  // namespace grpc_impl
 namespace grpc {
 namespace grpc {
+class ClientContext;
+class CompletionQueue;
 class GenericServerContext;
 class GenericServerContext;
 class ServerInterface;
 class ServerInterface;
 
 
@@ -373,7 +373,7 @@ class ServerContextBase {
   friend class ::grpc_impl::internal::ErrorMethodHandler;
   friend class ::grpc_impl::internal::ErrorMethodHandler;
   template <class Base>
   template <class Base>
   friend class ::grpc_impl::internal::FinishOnlyReactor;
   friend class ::grpc_impl::internal::FinishOnlyReactor;
-  friend class ::grpc_impl::ClientContext;
+  friend class ::grpc::ClientContext;
   friend class ::grpc::GenericServerContext;
   friend class ::grpc::GenericServerContext;
 #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
 #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
   friend class ::grpc::GenericCallbackServerContext;
   friend class ::grpc::GenericCallbackServerContext;
@@ -426,7 +426,7 @@ class ServerContextBase {
 
 
   gpr_timespec deadline_;
   gpr_timespec deadline_;
   grpc_call* call_;
   grpc_call* call_;
-  ::grpc_impl::CompletionQueue* cq_;
+  ::grpc::CompletionQueue* cq_;
   bool sent_initial_metadata_;
   bool sent_initial_metadata_;
   mutable std::shared_ptr<const ::grpc::AuthContext> auth_context_;
   mutable std::shared_ptr<const ::grpc::AuthContext> auth_context_;
   mutable ::grpc::internal::MetadataMap client_metadata_;
   mutable ::grpc::internal::MetadataMap client_metadata_;

+ 28 - 32
include/grpcpp/impl/codegen/server_interface.h

@@ -31,16 +31,13 @@
 #include <grpcpp/impl/codegen/rpc_service_method.h>
 #include <grpcpp/impl/codegen/rpc_service_method.h>
 #include <grpcpp/impl/codegen/server_context_impl.h>
 #include <grpcpp/impl/codegen/server_context_impl.h>
 
 
-namespace grpc_impl {
-
-class Channel;
-class CompletionQueue;
-class ServerCompletionQueue;
-}  // namespace grpc_impl
 namespace grpc {
 namespace grpc {
 
 
 class AsyncGenericService;
 class AsyncGenericService;
+class Channel;
+class CompletionQueue;
 class GenericServerContext;
 class GenericServerContext;
+class ServerCompletionQueue;
 class ServerCredentials;
 class ServerCredentials;
 class Service;
 class Service;
 
 
@@ -181,8 +178,7 @@ class ServerInterface : public internal::CallHook {
   /// caller is required to keep all completion queues live until the server is
   /// caller is required to keep all completion queues live until the server is
   /// destroyed.
   /// destroyed.
   /// \param num_cqs How many completion queues does \a cqs hold.
   /// \param num_cqs How many completion queues does \a cqs hold.
-  virtual void Start(::grpc_impl::ServerCompletionQueue** cqs,
-                     size_t num_cqs) = 0;
+  virtual void Start(::grpc::ServerCompletionQueue** cqs, size_t num_cqs) = 0;
 
 
   virtual void ShutdownInternal(gpr_timespec deadline) = 0;
   virtual void ShutdownInternal(gpr_timespec deadline) = 0;
 
 
@@ -198,9 +194,9 @@ class ServerInterface : public internal::CallHook {
     BaseAsyncRequest(ServerInterface* server,
     BaseAsyncRequest(ServerInterface* server,
                      ::grpc_impl::ServerContext* context,
                      ::grpc_impl::ServerContext* context,
                      internal::ServerAsyncStreamingInterface* stream,
                      internal::ServerAsyncStreamingInterface* stream,
-                     ::grpc_impl::CompletionQueue* call_cq,
-                     ::grpc_impl::ServerCompletionQueue* notification_cq,
-                     void* tag, bool delete_on_finalize);
+                     ::grpc::CompletionQueue* call_cq,
+                     ::grpc::ServerCompletionQueue* notification_cq, void* tag,
+                     bool delete_on_finalize);
     virtual ~BaseAsyncRequest();
     virtual ~BaseAsyncRequest();
 
 
     bool FinalizeResult(void** tag, bool* status) override;
     bool FinalizeResult(void** tag, bool* status) override;
@@ -212,8 +208,8 @@ class ServerInterface : public internal::CallHook {
     ServerInterface* const server_;
     ServerInterface* const server_;
     ::grpc_impl::ServerContext* const context_;
     ::grpc_impl::ServerContext* const context_;
     internal::ServerAsyncStreamingInterface* const stream_;
     internal::ServerAsyncStreamingInterface* const stream_;
-    ::grpc_impl::CompletionQueue* const call_cq_;
-    ::grpc_impl::ServerCompletionQueue* const notification_cq_;
+    ::grpc::CompletionQueue* const call_cq_;
+    ::grpc::ServerCompletionQueue* const notification_cq_;
     void* const tag_;
     void* const tag_;
     const bool delete_on_finalize_;
     const bool delete_on_finalize_;
     grpc_call* call_;
     grpc_call* call_;
@@ -228,8 +224,8 @@ class ServerInterface : public internal::CallHook {
     RegisteredAsyncRequest(ServerInterface* server,
     RegisteredAsyncRequest(ServerInterface* server,
                            ::grpc_impl::ServerContext* context,
                            ::grpc_impl::ServerContext* context,
                            internal::ServerAsyncStreamingInterface* stream,
                            internal::ServerAsyncStreamingInterface* stream,
-                           ::grpc_impl::CompletionQueue* call_cq,
-                           ::grpc_impl::ServerCompletionQueue* notification_cq,
+                           ::grpc::CompletionQueue* call_cq,
+                           ::grpc::ServerCompletionQueue* notification_cq,
                            void* tag, const char* name,
                            void* tag, const char* name,
                            internal::RpcMethod::RpcType type);
                            internal::RpcMethod::RpcType type);
 
 
@@ -247,7 +243,7 @@ class ServerInterface : public internal::CallHook {
 
 
    protected:
    protected:
     void IssueRequest(void* registered_method, grpc_byte_buffer** payload,
     void IssueRequest(void* registered_method, grpc_byte_buffer** payload,
-                      ::grpc_impl::ServerCompletionQueue* notification_cq);
+                      ::grpc::ServerCompletionQueue* notification_cq);
     const char* name_;
     const char* name_;
     const internal::RpcMethod::RpcType type_;
     const internal::RpcMethod::RpcType type_;
   };
   };
@@ -258,8 +254,8 @@ class ServerInterface : public internal::CallHook {
                           ServerInterface* server,
                           ServerInterface* server,
                           ::grpc_impl::ServerContext* context,
                           ::grpc_impl::ServerContext* context,
                           internal::ServerAsyncStreamingInterface* stream,
                           internal::ServerAsyncStreamingInterface* stream,
-                          ::grpc_impl::CompletionQueue* call_cq,
-                          ::grpc_impl::ServerCompletionQueue* notification_cq,
+                          ::grpc::CompletionQueue* call_cq,
+                          ::grpc::ServerCompletionQueue* notification_cq,
                           void* tag)
                           void* tag)
         : RegisteredAsyncRequest(
         : RegisteredAsyncRequest(
               server, context, stream, call_cq, notification_cq, tag,
               server, context, stream, call_cq, notification_cq, tag,
@@ -277,8 +273,8 @@ class ServerInterface : public internal::CallHook {
                         ServerInterface* server,
                         ServerInterface* server,
                         ::grpc_impl::ServerContext* context,
                         ::grpc_impl::ServerContext* context,
                         internal::ServerAsyncStreamingInterface* stream,
                         internal::ServerAsyncStreamingInterface* stream,
-                        ::grpc_impl::CompletionQueue* call_cq,
-                        ::grpc_impl::ServerCompletionQueue* notification_cq,
+                        ::grpc::CompletionQueue* call_cq,
+                        ::grpc::ServerCompletionQueue* notification_cq,
                         void* tag, Message* request)
                         void* tag, Message* request)
         : RegisteredAsyncRequest(
         : RegisteredAsyncRequest(
               server, context, stream, call_cq, notification_cq, tag,
               server, context, stream, call_cq, notification_cq, tag,
@@ -333,8 +329,8 @@ class ServerInterface : public internal::CallHook {
    public:
    public:
     GenericAsyncRequest(ServerInterface* server, GenericServerContext* context,
     GenericAsyncRequest(ServerInterface* server, GenericServerContext* context,
                         internal::ServerAsyncStreamingInterface* stream,
                         internal::ServerAsyncStreamingInterface* stream,
-                        ::grpc_impl::CompletionQueue* call_cq,
-                        ::grpc_impl::ServerCompletionQueue* notification_cq,
+                        ::grpc::CompletionQueue* call_cq,
+                        ::grpc::ServerCompletionQueue* notification_cq,
                         void* tag, bool delete_on_finalize);
                         void* tag, bool delete_on_finalize);
 
 
     bool FinalizeResult(void** tag, bool* status) override;
     bool FinalizeResult(void** tag, bool* status) override;
@@ -347,8 +343,8 @@ class ServerInterface : public internal::CallHook {
   void RequestAsyncCall(internal::RpcServiceMethod* method,
   void RequestAsyncCall(internal::RpcServiceMethod* method,
                         ::grpc_impl::ServerContext* context,
                         ::grpc_impl::ServerContext* context,
                         internal::ServerAsyncStreamingInterface* stream,
                         internal::ServerAsyncStreamingInterface* stream,
-                        ::grpc_impl::CompletionQueue* call_cq,
-                        ::grpc_impl::ServerCompletionQueue* notification_cq,
+                        ::grpc::CompletionQueue* call_cq,
+                        ::grpc::ServerCompletionQueue* notification_cq,
                         void* tag, Message* message) {
                         void* tag, Message* message) {
     GPR_CODEGEN_ASSERT(method);
     GPR_CODEGEN_ASSERT(method);
     new PayloadAsyncRequest<Message>(method, this, context, stream, call_cq,
     new PayloadAsyncRequest<Message>(method, this, context, stream, call_cq,
@@ -358,19 +354,19 @@ class ServerInterface : public internal::CallHook {
   void RequestAsyncCall(internal::RpcServiceMethod* method,
   void RequestAsyncCall(internal::RpcServiceMethod* method,
                         ::grpc_impl::ServerContext* context,
                         ::grpc_impl::ServerContext* context,
                         internal::ServerAsyncStreamingInterface* stream,
                         internal::ServerAsyncStreamingInterface* stream,
-                        ::grpc_impl::CompletionQueue* call_cq,
-                        ::grpc_impl::ServerCompletionQueue* notification_cq,
+                        ::grpc::CompletionQueue* call_cq,
+                        ::grpc::ServerCompletionQueue* notification_cq,
                         void* tag) {
                         void* tag) {
     GPR_CODEGEN_ASSERT(method);
     GPR_CODEGEN_ASSERT(method);
     new NoPayloadAsyncRequest(method, this, context, stream, call_cq,
     new NoPayloadAsyncRequest(method, this, context, stream, call_cq,
                               notification_cq, tag);
                               notification_cq, tag);
   }
   }
 
 
-  void RequestAsyncGenericCall(
-      GenericServerContext* context,
-      internal::ServerAsyncStreamingInterface* stream,
-      ::grpc_impl::CompletionQueue* call_cq,
-      ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) {
+  void RequestAsyncGenericCall(GenericServerContext* context,
+                               internal::ServerAsyncStreamingInterface* stream,
+                               ::grpc::CompletionQueue* call_cq,
+                               ::grpc::ServerCompletionQueue* notification_cq,
+                               void* tag) {
     new GenericAsyncRequest(this, context, stream, call_cq, notification_cq,
     new GenericAsyncRequest(this, context, stream, call_cq, notification_cq,
                             tag, true);
                             tag, true);
   }
   }
@@ -395,7 +391,7 @@ class ServerInterface : public internal::CallHook {
   // Returns nullptr (rather than being pure) since this is a post-1.0 method
   // Returns nullptr (rather than being pure) since this is a post-1.0 method
   // and adding a new pure method to an interface would be a breaking change
   // and adding a new pure method to an interface would be a breaking change
   // (even though this is private and non-API)
   // (even though this is private and non-API)
-  virtual ::grpc_impl::CompletionQueue* CallbackCQ() { return nullptr; }
+  virtual ::grpc::CompletionQueue* CallbackCQ() { return nullptr; }
 };
 };
 
 
 }  // namespace grpc
 }  // namespace grpc

+ 9 - 9
include/grpcpp/impl/codegen/service_type.h

@@ -29,11 +29,11 @@
 namespace grpc_impl {
 namespace grpc_impl {
 
 
 class Server;
 class Server;
-class CompletionQueue;
 class ServerContext;
 class ServerContext;
 }  // namespace grpc_impl
 }  // namespace grpc_impl
 namespace grpc {
 namespace grpc {
 
 
+class CompletionQueue;
 class ServerInterface;
 class ServerInterface;
 
 
 namespace internal {
 namespace internal {
@@ -130,8 +130,8 @@ class Service {
   void RequestAsyncUnary(int index, ::grpc_impl::ServerContext* context,
   void RequestAsyncUnary(int index, ::grpc_impl::ServerContext* context,
                          Message* request,
                          Message* request,
                          internal::ServerAsyncStreamingInterface* stream,
                          internal::ServerAsyncStreamingInterface* stream,
-                         ::grpc_impl::CompletionQueue* call_cq,
-                         ::grpc_impl::ServerCompletionQueue* notification_cq,
+                         ::grpc::CompletionQueue* call_cq,
+                         ::grpc::ServerCompletionQueue* notification_cq,
                          void* tag) {
                          void* tag) {
     // Typecast the index to size_t for indexing into a vector
     // Typecast the index to size_t for indexing into a vector
     // while preserving the API that existed before a compiler
     // while preserving the API that existed before a compiler
@@ -143,8 +143,8 @@ class Service {
   void RequestAsyncClientStreaming(
   void RequestAsyncClientStreaming(
       int index, ::grpc_impl::ServerContext* context,
       int index, ::grpc_impl::ServerContext* context,
       internal::ServerAsyncStreamingInterface* stream,
       internal::ServerAsyncStreamingInterface* stream,
-      ::grpc_impl::CompletionQueue* call_cq,
-      ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) {
+      ::grpc::CompletionQueue* call_cq,
+      ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
     size_t idx = static_cast<size_t>(index);
     size_t idx = static_cast<size_t>(index);
     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
                               notification_cq, tag);
                               notification_cq, tag);
@@ -153,8 +153,8 @@ class Service {
   void RequestAsyncServerStreaming(
   void RequestAsyncServerStreaming(
       int index, ::grpc_impl::ServerContext* context, Message* request,
       int index, ::grpc_impl::ServerContext* context, Message* request,
       internal::ServerAsyncStreamingInterface* stream,
       internal::ServerAsyncStreamingInterface* stream,
-      ::grpc_impl::CompletionQueue* call_cq,
-      ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) {
+      ::grpc::CompletionQueue* call_cq,
+      ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
     size_t idx = static_cast<size_t>(index);
     size_t idx = static_cast<size_t>(index);
     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
                               notification_cq, tag, request);
                               notification_cq, tag, request);
@@ -162,8 +162,8 @@ class Service {
   void RequestAsyncBidiStreaming(
   void RequestAsyncBidiStreaming(
       int index, ::grpc_impl::ServerContext* context,
       int index, ::grpc_impl::ServerContext* context,
       internal::ServerAsyncStreamingInterface* stream,
       internal::ServerAsyncStreamingInterface* stream,
-      ::grpc_impl::CompletionQueue* call_cq,
-      ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) {
+      ::grpc::CompletionQueue* call_cq,
+      ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
     size_t idx = static_cast<size_t>(index);
     size_t idx = static_cast<size_t>(index);
     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
                               notification_cq, tag);
                               notification_cq, tag);

+ 14 - 15
include/grpcpp/impl/codegen/sync_stream_impl.h

@@ -20,8 +20,8 @@
 
 
 #include <grpcpp/impl/codegen/call.h>
 #include <grpcpp/impl/codegen/call.h>
 #include <grpcpp/impl/codegen/channel_interface.h>
 #include <grpcpp/impl/codegen/channel_interface.h>
-#include <grpcpp/impl/codegen/client_context_impl.h>
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
 #include <grpcpp/impl/codegen/server_context_impl.h>
 #include <grpcpp/impl/codegen/server_context_impl.h>
 #include <grpcpp/impl/codegen/service_type.h>
 #include <grpcpp/impl/codegen/service_type.h>
@@ -162,7 +162,7 @@ class ClientReaderFactory {
   template <class W>
   template <class W>
   static ClientReader<R>* Create(::grpc::ChannelInterface* channel,
   static ClientReader<R>* Create(::grpc::ChannelInterface* channel,
                                  const ::grpc::internal::RpcMethod& method,
                                  const ::grpc::internal::RpcMethod& method,
-                                 ::grpc_impl::ClientContext* context,
+                                 ::grpc::ClientContext* context,
                                  const W& request) {
                                  const W& request) {
     return new ClientReader<R>(channel, method, context, request);
     return new ClientReader<R>(channel, method, context, request);
   }
   }
@@ -231,8 +231,8 @@ class ClientReader final : public ClientReaderInterface<R> {
 
 
  private:
  private:
   friend class internal::ClientReaderFactory<R>;
   friend class internal::ClientReaderFactory<R>;
-  ::grpc_impl::ClientContext* context_;
-  ::grpc_impl::CompletionQueue cq_;
+  ::grpc::ClientContext* context_;
+  ::grpc::CompletionQueue cq_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
 
 
   /// Block to create a stream and write the initial metadata and \a request
   /// Block to create a stream and write the initial metadata and \a request
@@ -241,7 +241,7 @@ class ClientReader final : public ClientReaderInterface<R> {
   template <class W>
   template <class W>
   ClientReader(::grpc::ChannelInterface* channel,
   ClientReader(::grpc::ChannelInterface* channel,
                const ::grpc::internal::RpcMethod& method,
                const ::grpc::internal::RpcMethod& method,
-               ::grpc_impl::ClientContext* context, const W& request)
+               ::grpc::ClientContext* context, const W& request)
       : context_(context),
       : context_(context),
         cq_(grpc_completion_queue_attributes{
         cq_(grpc_completion_queue_attributes{
             GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
             GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
@@ -282,8 +282,7 @@ class ClientWriterFactory {
   template <class R>
   template <class R>
   static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
   static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
                                  const ::grpc::internal::RpcMethod& method,
                                  const ::grpc::internal::RpcMethod& method,
-                                 ::grpc_impl::ClientContext* context,
-                                 R* response) {
+                                 ::grpc::ClientContext* context, R* response) {
     return new ClientWriter<W>(channel, method, context, response);
     return new ClientWriter<W>(channel, method, context, response);
   }
   }
 };
 };
@@ -376,7 +375,7 @@ class ClientWriter : public ClientWriterInterface<W> {
   template <class R>
   template <class R>
   ClientWriter(::grpc::ChannelInterface* channel,
   ClientWriter(::grpc::ChannelInterface* channel,
                const ::grpc::internal::RpcMethod& method,
                const ::grpc::internal::RpcMethod& method,
-               ::grpc_impl::ClientContext* context, R* response)
+               ::grpc::ClientContext* context, R* response)
       : context_(context),
       : context_(context),
         cq_(grpc_completion_queue_attributes{
         cq_(grpc_completion_queue_attributes{
             GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
             GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
@@ -395,12 +394,12 @@ class ClientWriter : public ClientWriterInterface<W> {
     }
     }
   }
   }
 
 
-  ::grpc_impl::ClientContext* context_;
+  ::grpc::ClientContext* context_;
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
   ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
                               ::grpc::internal::CallOpGenericRecvMessage,
                               ::grpc::internal::CallOpGenericRecvMessage,
                               ::grpc::internal::CallOpClientRecvStatus>
                               ::grpc::internal::CallOpClientRecvStatus>
       finish_ops_;
       finish_ops_;
-  ::grpc_impl::CompletionQueue cq_;
+  ::grpc::CompletionQueue cq_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
 };
 };
 
 
@@ -434,7 +433,7 @@ class ClientReaderWriterFactory {
   static ClientReaderWriter<W, R>* Create(
   static ClientReaderWriter<W, R>* Create(
       ::grpc::ChannelInterface* channel,
       ::grpc::ChannelInterface* channel,
       const ::grpc::internal::RpcMethod& method,
       const ::grpc::internal::RpcMethod& method,
-      ::grpc_impl::ClientContext* context) {
+      ::grpc::ClientContext* context) {
     return new ClientReaderWriter<W, R>(channel, method, context);
     return new ClientReaderWriter<W, R>(channel, method, context);
   }
   }
 };
 };
@@ -543,8 +542,8 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
  private:
  private:
   friend class internal::ClientReaderWriterFactory<W, R>;
   friend class internal::ClientReaderWriterFactory<W, R>;
 
 
-  ::grpc_impl::ClientContext* context_;
-  ::grpc_impl::CompletionQueue cq_;
+  ::grpc::ClientContext* context_;
+  ::grpc::CompletionQueue cq_;
   ::grpc::internal::Call call_;
   ::grpc::internal::Call call_;
 
 
   /// Block to create a stream and write the initial metadata and \a request
   /// Block to create a stream and write the initial metadata and \a request
@@ -552,7 +551,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
   /// used to send to the server when starting the call.
   /// used to send to the server when starting the call.
   ClientReaderWriter(::grpc::ChannelInterface* channel,
   ClientReaderWriter(::grpc::ChannelInterface* channel,
                      const ::grpc::internal::RpcMethod& method,
                      const ::grpc::internal::RpcMethod& method,
-                     ::grpc_impl::ClientContext* context)
+                     ::grpc::ClientContext* context)
       : context_(context),
       : context_(context),
         cq_(grpc_completion_queue_attributes{
         cq_(grpc_completion_queue_attributes{
             GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
             GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,

+ 2 - 2
include/grpcpp/server_builder.h

@@ -167,7 +167,7 @@ class ServerBuilder {
   /// not polling the completion queue frequently) will have a significantly
   /// not polling the completion queue frequently) will have a significantly
   /// negative performance impact and hence should not be used in production
   /// negative performance impact and hence should not be used in production
   /// use cases.
   /// use cases.
-  std::unique_ptr<grpc_impl::ServerCompletionQueue> AddCompletionQueue(
+  std::unique_ptr<grpc::ServerCompletionQueue> AddCompletionQueue(
       bool is_frequently_polled = true);
       bool is_frequently_polled = true);
 
 
   //////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////
@@ -382,7 +382,7 @@ class ServerBuilder {
   SyncServerSettings sync_server_settings_;
   SyncServerSettings sync_server_settings_;
 
 
   /// List of completion queues added via \a AddCompletionQueue method.
   /// List of completion queues added via \a AddCompletionQueue method.
-  std::vector<grpc_impl::ServerCompletionQueue*> cqs_;
+  std::vector<grpc::ServerCompletionQueue*> cqs_;
 
 
   std::shared_ptr<grpc::ServerCredentials> creds_;
   std::shared_ptr<grpc::ServerCredentials> creds_;
   std::vector<std::unique_ptr<grpc::ServerBuilderPlugin>> plugins_;
   std::vector<std::unique_ptr<grpc::ServerBuilderPlugin>> plugins_;

+ 24 - 22
include/grpcpp/server_impl.h

@@ -27,12 +27,12 @@
 
 
 #include <grpc/compression.h>
 #include <grpc/compression.h>
 #include <grpc/support/atm.h>
 #include <grpc/support/atm.h>
-#include <grpcpp/channel_impl.h>
-#include <grpcpp/completion_queue_impl.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/completion_queue.h>
 #include <grpcpp/health_check_service_interface.h>
 #include <grpcpp/health_check_service_interface.h>
 #include <grpcpp/impl/call.h>
 #include <grpcpp/impl/call.h>
 #include <grpcpp/impl/codegen/client_interceptor.h>
 #include <grpcpp/impl/codegen/client_interceptor.h>
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
 #include <grpcpp/impl/codegen/grpc_library.h>
 #include <grpcpp/impl/codegen/grpc_library.h>
 #include <grpcpp/impl/codegen/server_interface.h>
 #include <grpcpp/impl/codegen/server_interface.h>
 #include <grpcpp/impl/rpc_service_method.h>
 #include <grpcpp/impl/rpc_service_method.h>
@@ -109,7 +109,8 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   }
   }
 
 
   /// Establish a channel for in-process communication
   /// Establish a channel for in-process communication
-  std::shared_ptr<Channel> InProcessChannel(const grpc::ChannelArguments& args);
+  std::shared_ptr<grpc::Channel> InProcessChannel(
+      const grpc::ChannelArguments& args);
 
 
   /// NOTE: class experimental_type is not part of the public API of this class.
   /// NOTE: class experimental_type is not part of the public API of this class.
   /// TODO(yashykt): Integrate into public API when this is no longer
   /// TODO(yashykt): Integrate into public API when this is no longer
@@ -120,7 +121,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
 
 
     /// Establish a channel for in-process communication with client
     /// Establish a channel for in-process communication with client
     /// interceptors
     /// interceptors
-    std::shared_ptr<Channel> InProcessChannelWithInterceptors(
+    std::shared_ptr<grpc::Channel> InProcessChannelWithInterceptors(
         const grpc::ChannelArguments& args,
         const grpc::ChannelArguments& args,
         std::vector<std::unique_ptr<
         std::vector<std::unique_ptr<
             grpc::experimental::ClientInterceptorFactoryInterface>>
             grpc::experimental::ClientInterceptorFactoryInterface>>
@@ -179,18 +180,19 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   ///
   ///
   /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on
   /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on
   /// server completion queues passed via sync_server_cqs param.
   /// server completion queues passed via sync_server_cqs param.
-  Server(grpc::ChannelArguments* args,
-         std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
-             sync_server_cqs,
-         int min_pollers, int max_pollers, int sync_cq_timeout_msec,
-         std::vector<
-             std::shared_ptr<grpc::internal::ExternalConnectionAcceptorImpl>>
-             acceptors,
-         grpc_resource_quota* server_rq = nullptr,
-         std::vector<std::unique_ptr<
-             grpc::experimental::ServerInterceptorFactoryInterface>>
-             interceptor_creators = std::vector<std::unique_ptr<
-                 grpc::experimental::ServerInterceptorFactoryInterface>>());
+  Server(
+      grpc::ChannelArguments* args,
+      std::shared_ptr<std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>
+          sync_server_cqs,
+      int min_pollers, int max_pollers, int sync_cq_timeout_msec,
+      std::vector<
+          std::shared_ptr<grpc::internal::ExternalConnectionAcceptorImpl>>
+          acceptors,
+      grpc_resource_quota* server_rq = nullptr,
+      std::vector<std::unique_ptr<
+          grpc::experimental::ServerInterceptorFactoryInterface>>
+          interceptor_creators = std::vector<std::unique_ptr<
+              grpc::experimental::ServerInterceptorFactoryInterface>>());
 
 
   /// Start the server.
   /// Start the server.
   ///
   ///
@@ -198,7 +200,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   /// caller is required to keep all completion queues live until the server is
   /// caller is required to keep all completion queues live until the server is
   /// destroyed.
   /// destroyed.
   /// \param num_cqs How many completion queues does \a cqs hold.
   /// \param num_cqs How many completion queues does \a cqs hold.
-  void Start(ServerCompletionQueue** cqs, size_t num_cqs) override;
+  void Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) override;
 
 
   grpc_server* server() override { return server_; }
   grpc_server* server() override { return server_; }
 
 
@@ -287,7 +289,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
     return max_receive_message_size_;
     return max_receive_message_size_;
   }
   }
 
 
-  CompletionQueue* CallbackCQ() override;
+  grpc::CompletionQueue* CallbackCQ() override;
 
 
   grpc_impl::ServerInitializer* initializer();
   grpc_impl::ServerInitializer* initializer();
 
 
@@ -315,7 +317,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   /// The following completion queues are ONLY used in case of Sync API
   /// The following completion queues are ONLY used in case of Sync API
   /// i.e. if the server has any services with sync methods. The server uses
   /// i.e. if the server has any services with sync methods. The server uses
   /// these completion queues to poll for new RPCs
   /// these completion queues to poll for new RPCs
-  std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
+  std::shared_ptr<std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>
       sync_server_cqs_;
       sync_server_cqs_;
 
 
   /// List of \a ThreadManager instances (one for each cq in
   /// List of \a ThreadManager instances (one for each cq in
@@ -373,12 +375,12 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
   // with this server (if any). It is set on the first call to CallbackCQ().
   // with this server (if any). It is set on the first call to CallbackCQ().
   // It is _not owned_ by the server; ownership belongs with its internal
   // It is _not owned_ by the server; ownership belongs with its internal
   // shutdown callback tag (invoked when the CQ is fully shutdown).
   // shutdown callback tag (invoked when the CQ is fully shutdown).
-  CompletionQueue* callback_cq_ /* GUARDED_BY(mu_) */ = nullptr;
+  grpc::CompletionQueue* callback_cq_ /* GUARDED_BY(mu_) */ = nullptr;
 
 
   // List of CQs passed in by user that must be Shutdown only after Server is
   // List of CQs passed in by user that must be Shutdown only after Server is
   // Shutdown.  Even though this is only used with NDEBUG, instantiate it in all
   // Shutdown.  Even though this is only used with NDEBUG, instantiate it in all
   // cases since otherwise the size will be inconsistent.
   // cases since otherwise the size will be inconsistent.
-  std::vector<CompletionQueue*> cq_list_;
+  std::vector<grpc::CompletionQueue*> cq_list_;
 };
 };
 
 
 }  // namespace grpc_impl
 }  // namespace grpc_impl

+ 2 - 0
package.xml

@@ -1390,6 +1390,8 @@
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/kdf.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/fipsmodule/tls/kdf.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c" role="src" />
+    <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hpke/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hrss/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/hrss/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl-with-bazel/src/crypto/internal.h" role="src" />

+ 13 - 1
src/boringssl/boringssl_prefix_symbols.h

@@ -1,4 +1,4 @@
-// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: e8a935e323510419e0b37638716f6df4dcbbe6f6
+// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 412844d75b14b9090b58423fd5f5ed8c2fd80212
 
 
 // Copyright (c) 2018, Google Inc.
 // Copyright (c) 2018, Google Inc.
 //
 //
@@ -303,6 +303,7 @@
 #define SSL_get0_ocsp_response BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_ocsp_response)
 #define SSL_get0_ocsp_response BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_ocsp_response)
 #define SSL_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_param)
 #define SSL_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_param)
 #define SSL_get0_peer_certificates BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_peer_certificates)
 #define SSL_get0_peer_certificates BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_peer_certificates)
+#define SSL_get0_peer_delegation_algorithms BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_peer_delegation_algorithms)
 #define SSL_get0_peer_verify_algorithms BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_peer_verify_algorithms)
 #define SSL_get0_peer_verify_algorithms BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_peer_verify_algorithms)
 #define SSL_get0_server_requested_CAs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_server_requested_CAs)
 #define SSL_get0_server_requested_CAs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_server_requested_CAs)
 #define SSL_get0_session_id_context BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_session_id_context)
 #define SSL_get0_session_id_context BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_get0_session_id_context)
@@ -1491,6 +1492,15 @@
 #define EVP_EncryptInit BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptInit)
 #define EVP_EncryptInit BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptInit)
 #define EVP_EncryptInit_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptInit_ex)
 #define EVP_EncryptInit_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptInit_ex)
 #define EVP_EncryptUpdate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptUpdate)
 #define EVP_EncryptUpdate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptUpdate)
+#define EVP_HPKE_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_cleanup)
+#define EVP_HPKE_CTX_export BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_export)
+#define EVP_HPKE_CTX_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_init)
+#define EVP_HPKE_CTX_max_overhead BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_max_overhead)
+#define EVP_HPKE_CTX_open BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_open)
+#define EVP_HPKE_CTX_seal BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_seal)
+#define EVP_HPKE_CTX_setup_base_r_x25519 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_setup_base_r_x25519)
+#define EVP_HPKE_CTX_setup_base_s_x25519 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_setup_base_s_x25519)
+#define EVP_HPKE_CTX_setup_base_s_x25519_for_test BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_setup_base_s_x25519_for_test)
 #define EVP_MD_CTX_block_size BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_block_size)
 #define EVP_MD_CTX_block_size BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_block_size)
 #define EVP_MD_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_cleanup)
 #define EVP_MD_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_cleanup)
 #define EVP_MD_CTX_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_copy)
 #define EVP_MD_CTX_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_copy)
@@ -2403,6 +2413,8 @@
 #define X509_REVOKED_set_revocationDate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REVOKED_set_revocationDate)
 #define X509_REVOKED_set_revocationDate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REVOKED_set_revocationDate)
 #define X509_REVOKED_set_serialNumber BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REVOKED_set_serialNumber)
 #define X509_REVOKED_set_serialNumber BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REVOKED_set_serialNumber)
 #define X509_SIG_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_free)
 #define X509_SIG_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_free)
+#define X509_SIG_get0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_get0)
+#define X509_SIG_getm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_getm)
 #define X509_SIG_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_it)
 #define X509_SIG_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_it)
 #define X509_SIG_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_new)
 #define X509_SIG_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_SIG_new)
 #define X509_STORE_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_cleanup)
 #define X509_STORE_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_STORE_CTX_cleanup)

+ 1 - 1
src/compiler/BUILD

@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # limitations under the License.
 
 
-licenses(["notice"])  # Apache v2
+licenses(["notice"])
 
 
 exports_files(["LICENSE"])
 exports_files(["LICENSE"])
 
 

+ 1 - 1
src/compiler/ruby_generator_string-inl.h

@@ -124,7 +124,7 @@ inline std::string RubyTypeOf(const grpc::protobuf::Descriptor* descriptor) {
     ReplacePrefix(&proto_type, ".", "");  // remove the leading . (no package)
     ReplacePrefix(&proto_type, ".", "");  // remove the leading . (no package)
     proto_type = RubyPackage(descriptor->file()) + "." + proto_type;
     proto_type = RubyPackage(descriptor->file()) + "." + proto_type;
   }
   }
-  std::string res(proto_type);
+  std::string res("." + proto_type);
   if (res.find('.') == std::string::npos) {
   if (res.find('.') == std::string::npos) {
     return res;
     return res;
   } else {
   } else {

+ 47 - 8
src/core/ext/filters/client_channel/client_channel.cc

@@ -28,6 +28,8 @@
 
 
 #include <set>
 #include <set>
 
 
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/string_view.h"
 
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
@@ -330,6 +332,7 @@ class ChannelData {
   // applied in the data plane mutex when the picker is updated.
   // applied in the data plane mutex when the picker is updated.
   std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>>
   std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>>
       pending_subchannel_updates_;
       pending_subchannel_updates_;
+  int keepalive_time_ = -1;
 
 
   //
   //
   // Fields accessed from both data plane mutex and control plane
   // Fields accessed from both data plane mutex and control plane
@@ -971,6 +974,10 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
 
 
   void ResetBackoff() override { subchannel_->ResetBackoff(); }
   void ResetBackoff() override { subchannel_->ResetBackoff(); }
 
 
+  void ThrottleKeepaliveTime(int new_keepalive_time) {
+    subchannel_->ThrottleKeepaliveTime(new_keepalive_time);
+  }
+
   const grpc_channel_args* channel_args() override {
   const grpc_channel_args* channel_args() override {
     return subchannel_->channel_args();
     return subchannel_->channel_args();
   }
   }
@@ -1101,6 +1108,32 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
                 watcher_.get());
                 watcher_.get());
       }
       }
       ConnectivityStateChange state_change = PopConnectivityStateChange();
       ConnectivityStateChange state_change = PopConnectivityStateChange();
+      absl::optional<absl::Cord> keepalive_throttling =
+          state_change.status.GetPayload(grpc_core::kKeepaliveThrottlingKey);
+      if (keepalive_throttling.has_value()) {
+        int new_keepalive_time = -1;
+        if (absl::SimpleAtoi(std::string(keepalive_throttling.value()),
+                             &new_keepalive_time)) {
+          if (new_keepalive_time > parent_->chand_->keepalive_time_) {
+            parent_->chand_->keepalive_time_ = new_keepalive_time;
+            if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+              gpr_log(GPR_INFO, "chand=%p: throttling keepalive time to %d",
+                      parent_->chand_, parent_->chand_->keepalive_time_);
+            }
+            // Propagate the new keepalive time to all subchannels. This is so
+            // that new transports created by any subchannel (and not just the
+            // subchannel that received the GOAWAY), use the new keepalive time.
+            for (auto* subchannel_wrapper :
+                 parent_->chand_->subchannel_wrappers_) {
+              subchannel_wrapper->ThrottleKeepaliveTime(new_keepalive_time);
+            }
+          }
+        } else {
+          gpr_log(GPR_ERROR, "chand=%p: Illegal keepalive throttling value %s",
+                  parent_->chand_,
+                  std::string(keepalive_throttling.value()).c_str());
+        }
+      }
       // Ignore update if the parent WatcherWrapper has been replaced
       // Ignore update if the parent WatcherWrapper has been replaced
       // since this callback was scheduled.
       // since this callback was scheduled.
       if (watcher_ != nullptr) {
       if (watcher_ != nullptr) {
@@ -1349,6 +1382,7 @@ class ChannelData::ClientChannelControlHelper
         chand_->client_channel_factory_->CreateSubchannel(new_args);
         chand_->client_channel_factory_->CreateSubchannel(new_args);
     grpc_channel_args_destroy(new_args);
     grpc_channel_args_destroy(new_args);
     if (subchannel == nullptr) return nullptr;
     if (subchannel == nullptr) return nullptr;
+    subchannel->ThrottleKeepaliveTime(chand_->keepalive_time_);
     return MakeRefCounted<SubchannelWrapper>(
     return MakeRefCounted<SubchannelWrapper>(
         chand_, subchannel, std::move(health_check_service_name));
         chand_, subchannel, std::move(health_check_service_name));
   }
   }
@@ -1682,9 +1716,13 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
   channel_args_ = new_args != nullptr
   channel_args_ = new_args != nullptr
                       ? new_args
                       ? new_args
                       : grpc_channel_args_copy(args->channel_args);
                       : grpc_channel_args_copy(args->channel_args);
+  keepalive_time_ = grpc_channel_args_find_integer(
+      channel_args_, GRPC_ARG_KEEPALIVE_TIME_MS,
+      {-1 /* default value, unset */, 1, INT_MAX});
   if (!ResolverRegistry::IsValidTarget(target_uri_.get())) {
   if (!ResolverRegistry::IsValidTarget(target_uri_.get())) {
-    *error =
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING("the target uri is not valid.");
+    std::string error_message =
+        absl::StrCat("the target uri is not valid: ", target_uri_.get());
+    *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_message.c_str());
     return;
     return;
   }
   }
   *error = GRPC_ERROR_NONE;
   *error = GRPC_ERROR_NONE;
@@ -2138,13 +2176,14 @@ void CallData::Destroy(grpc_call_element* elem,
                        const grpc_call_final_info* /*final_info*/,
                        const grpc_call_final_info* /*final_info*/,
                        grpc_closure* then_schedule_closure) {
                        grpc_closure* then_schedule_closure) {
   CallData* calld = static_cast<CallData*>(elem->call_data);
   CallData* calld = static_cast<CallData*>(elem->call_data);
-  if (GPR_LIKELY(calld->subchannel_call_ != nullptr)) {
-    calld->subchannel_call_->SetAfterCallStackDestroy(then_schedule_closure);
-    then_schedule_closure = nullptr;
-  }
+  RefCountedPtr<SubchannelCall> subchannel_call = calld->subchannel_call_;
   calld->~CallData();
   calld->~CallData();
-  // TODO(yashkt) : This can potentially be a Closure::Run
-  ExecCtx::Run(DEBUG_LOCATION, then_schedule_closure, GRPC_ERROR_NONE);
+  if (GPR_LIKELY(subchannel_call != nullptr)) {
+    subchannel_call->SetAfterCallStackDestroy(then_schedule_closure);
+  } else {
+    // TODO(yashkt) : This can potentially be a Closure::Run
+    ExecCtx::Run(DEBUG_LOCATION, then_schedule_closure, GRPC_ERROR_NONE);
+  }
 }
 }
 
 
 void CallData::StartTransportStreamOpBatch(
 void CallData::StartTransportStreamOpBatch(

+ 2 - 1
src/core/ext/filters/client_channel/health/health_check_client.cc

@@ -91,11 +91,12 @@ void HealthCheckClient::SetHealthStatusLocked(grpc_connectivity_state state,
     gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%s reason=%s", this,
     gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%s reason=%s", this,
             ConnectivityStateName(state), reason);
             ConnectivityStateName(state), reason);
   }
   }
-  if (watcher_ != nullptr)
+  if (watcher_ != nullptr) {
     watcher_->Notify(state,
     watcher_->Notify(state,
                      state == GRPC_CHANNEL_TRANSIENT_FAILURE
                      state == GRPC_CHANNEL_TRANSIENT_FAILURE
                          ? absl::Status(absl::StatusCode::kUnavailable, reason)
                          ? absl::Status(absl::StatusCode::kUnavailable, reason)
                          : absl::Status());
                          : absl::Status());
+  }
 }
 }
 
 
 void HealthCheckClient::Orphan() {
 void HealthCheckClient::Orphan() {

+ 1 - 0
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc

@@ -457,6 +457,7 @@ void EdsLb::UpdateLocked(UpdateArgs args) {
       grpc_error* error = GRPC_ERROR_NONE;
       grpc_error* error = GRPC_ERROR_NONE;
       xds_client_ = MakeOrphanable<XdsClient>(
       xds_client_ = MakeOrphanable<XdsClient>(
           work_serializer(), interested_parties(), GetEdsResourceName(),
           work_serializer(), interested_parties(), GetEdsResourceName(),
+          std::vector<grpc_resolved_address>{},
           nullptr /* service config watcher */, *args_, &error);
           nullptr /* service config watcher */, *args_, &error);
       // TODO(roth): If we decide that we care about EDS-only mode, add
       // TODO(roth): If we decide that we care about EDS-only mode, add
       // proper error handling here.
       // proper error handling here.

+ 375 - 13
src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc

@@ -18,6 +18,8 @@
 
 
 #include <grpc/support/port_platform.h>
 #include <grpc/support/port_platform.h>
 
 
+#include "absl/strings/str_join.h"
+
 #include "src/core/ext/filters/client_channel/config_selector.h"
 #include "src/core/ext/filters/client_channel/config_selector.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/xds/xds_client.h"
 #include "src/core/ext/xds/xds_client.h"
@@ -68,12 +70,11 @@ class XdsResolver : public Resolver {
   }
   }
 
 
  private:
  private:
-  class ServiceConfigWatcher : public XdsClient::ServiceConfigWatcherInterface {
+  class ListenerWatcher : public XdsClient::ListenerWatcherInterface {
    public:
    public:
-    explicit ServiceConfigWatcher(RefCountedPtr<XdsResolver> resolver)
+    explicit ListenerWatcher(RefCountedPtr<XdsResolver> resolver)
         : resolver_(std::move(resolver)) {}
         : resolver_(std::move(resolver)) {}
-    void OnServiceConfigChanged(
-        RefCountedPtr<ServiceConfig> service_config) override;
+    void OnListenerChanged(XdsApi::LdsUpdate listener_data) override;
     void OnError(grpc_error* error) override;
     void OnError(grpc_error* error) override;
     void OnResourceDoesNotExist() override;
     void OnResourceDoesNotExist() override;
 
 
@@ -88,32 +89,75 @@ class XdsResolver : public Resolver {
     }
     }
   };
   };
 
 
+  // Returns the weighted_clusters action name to use from
+  // weighted_cluster_index_map_ for a WeightedClusters route action.
+  std::string WeightedClustersActionName(
+      const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
+          weighted_clusters);
+
+  // Updates weighted_cluster_index_map_ that will
+  // determine the names of the WeightedCluster actions for the current update.
+  void UpdateWeightedClusterIndexMap(const XdsApi::RdsUpdate& rds_update);
+
+  // Create the service config generated by the RdsUpdate.
+  grpc_error* CreateServiceConfig(const XdsApi::RdsUpdate& rds_update,
+                                  RefCountedPtr<ServiceConfig>* service_config);
+
   std::string server_name_;
   std::string server_name_;
   const grpc_channel_args* args_;
   const grpc_channel_args* args_;
   grpc_pollset_set* interested_parties_;
   grpc_pollset_set* interested_parties_;
   OrphanablePtr<XdsClient> xds_client_;
   OrphanablePtr<XdsClient> xds_client_;
   RefCountedPtr<XdsConfigSelector> config_selector_;
   RefCountedPtr<XdsConfigSelector> config_selector_;
+
+  // 2-level map to store WeightedCluster action names.
+  // Top level map is keyed by cluster names without weight like a_b_c; bottom
+  // level map is keyed by cluster names + weights like a10_b50_c40.
+  struct ClusterNamesInfo {
+    uint64_t next_index = 0;
+    std::map<std::string /*cluster names + weights*/,
+             uint64_t /*policy index number*/>
+        cluster_weights_map;
+  };
+  using WeightedClusterIndexMap =
+      std::map<std::string /*cluster names*/, ClusterNamesInfo>;
+
+  // Cache of action names for WeightedCluster targets in the current
+  // service config.
+  WeightedClusterIndexMap weighted_cluster_index_map_;
 };
 };
 
 
-void XdsResolver::ServiceConfigWatcher::OnServiceConfigChanged(
-    RefCountedPtr<ServiceConfig> service_config) {
+//
+// XdsResolver::ListenerWatcher
+//
+
+void XdsResolver::ListenerWatcher::OnListenerChanged(
+    XdsApi::LdsUpdate listener_data) {
   if (resolver_->xds_client_ == nullptr) return;
   if (resolver_->xds_client_ == nullptr) return;
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
-    gpr_log(GPR_INFO, "[xds_resolver %p] received updated service config: %s",
-            resolver_.get(), service_config->json_string().c_str());
+    gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data",
+            resolver_.get());
+  }
+  Result result;
+  grpc_error* error = resolver_->CreateServiceConfig(*listener_data.rds_update,
+                                                     &result.service_config);
+  if (error != GRPC_ERROR_NONE) {
+    OnError(error);
+    return;
+  }
+  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
+    gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s",
+            resolver_.get(), result.service_config->json_string().c_str());
   }
   }
   grpc_arg new_args[] = {
   grpc_arg new_args[] = {
       resolver_->xds_client_->MakeChannelArg(),
       resolver_->xds_client_->MakeChannelArg(),
       resolver_->config_selector_->MakeChannelArg(),
       resolver_->config_selector_->MakeChannelArg(),
   };
   };
-  Result result;
   result.args = grpc_channel_args_copy_and_add(resolver_->args_, new_args,
   result.args = grpc_channel_args_copy_and_add(resolver_->args_, new_args,
                                                GPR_ARRAY_SIZE(new_args));
                                                GPR_ARRAY_SIZE(new_args));
-  result.service_config = std::move(service_config);
   resolver_->result_handler()->ReturnResult(std::move(result));
   resolver_->result_handler()->ReturnResult(std::move(result));
 }
 }
 
 
-void XdsResolver::ServiceConfigWatcher::OnError(grpc_error* error) {
+void XdsResolver::ListenerWatcher::OnError(grpc_error* error) {
   if (resolver_->xds_client_ == nullptr) return;
   if (resolver_->xds_client_ == nullptr) return;
   gpr_log(GPR_ERROR, "[xds_resolver %p] received error: %s", resolver_.get(),
   gpr_log(GPR_ERROR, "[xds_resolver %p] received error: %s", resolver_.get(),
           grpc_error_string(error));
           grpc_error_string(error));
@@ -125,7 +169,7 @@ void XdsResolver::ServiceConfigWatcher::OnError(grpc_error* error) {
   resolver_->result_handler()->ReturnResult(std::move(result));
   resolver_->result_handler()->ReturnResult(std::move(result));
 }
 }
 
 
-void XdsResolver::ServiceConfigWatcher::OnResourceDoesNotExist() {
+void XdsResolver::ListenerWatcher::OnResourceDoesNotExist() {
   if (resolver_->xds_client_ == nullptr) return;
   if (resolver_->xds_client_ == nullptr) return;
   gpr_log(GPR_ERROR,
   gpr_log(GPR_ERROR,
           "[xds_resolver %p] LDS/RDS resource does not exist -- returning "
           "[xds_resolver %p] LDS/RDS resource does not exist -- returning "
@@ -139,11 +183,16 @@ void XdsResolver::ServiceConfigWatcher::OnResourceDoesNotExist() {
   resolver_->result_handler()->ReturnResult(std::move(result));
   resolver_->result_handler()->ReturnResult(std::move(result));
 }
 }
 
 
+//
+// XdsResolver
+//
+
 void XdsResolver::StartLocked() {
 void XdsResolver::StartLocked() {
   grpc_error* error = GRPC_ERROR_NONE;
   grpc_error* error = GRPC_ERROR_NONE;
   xds_client_ = MakeOrphanable<XdsClient>(
   xds_client_ = MakeOrphanable<XdsClient>(
       work_serializer(), interested_parties_, server_name_,
       work_serializer(), interested_parties_, server_name_,
-      absl::make_unique<ServiceConfigWatcher>(Ref()), *args_, &error);
+      std::vector<grpc_resolved_address>{},
+      absl::make_unique<ListenerWatcher>(Ref()), *args_, &error);
   if (error != GRPC_ERROR_NONE) {
   if (error != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR,
     gpr_log(GPR_ERROR,
             "Failed to create xds client -- channel will remain in "
             "Failed to create xds client -- channel will remain in "
@@ -153,6 +202,319 @@ void XdsResolver::StartLocked() {
   }
   }
 }
 }
 
 
+std::string CreateServiceConfigActionCluster(const std::string& cluster_name) {
+  return absl::StrFormat(
+      "      \"cds:%s\":{\n"
+      "        \"childPolicy\":[ {\n"
+      "          \"cds_experimental\":{\n"
+      "            \"cluster\": \"%s\"\n"
+      "          }\n"
+      "        } ]\n"
+      "       }",
+      cluster_name, cluster_name);
+}
+
+std::string CreateServiceConfigRoute(const std::string& action_name,
+                                     const XdsApi::RdsUpdate::RdsRoute& route) {
+  std::vector<std::string> headers;
+  for (const auto& header : route.matchers.header_matchers) {
+    std::string header_matcher;
+    switch (header.type) {
+      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
+          HeaderMatcherType::EXACT:
+        header_matcher = absl::StrFormat("             \"exact_match\": \"%s\"",
+                                         header.string_matcher);
+        break;
+      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
+          HeaderMatcherType::REGEX:
+        header_matcher = absl::StrFormat("             \"regex_match\": \"%s\"",
+                                         header.regex_match->pattern());
+        break;
+      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
+          HeaderMatcherType::RANGE:
+        header_matcher = absl::StrFormat(
+            "             \"range_match\":{\n"
+            "              \"start\":%d,\n"
+            "              \"end\":%d\n"
+            "             }",
+            header.range_start, header.range_end);
+        break;
+      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
+          HeaderMatcherType::PRESENT:
+        header_matcher =
+            absl::StrFormat("             \"present_match\": %s",
+                            header.present_match ? "true" : "false");
+        break;
+      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
+          HeaderMatcherType::PREFIX:
+        header_matcher = absl::StrFormat(
+            "             \"prefix_match\": \"%s\"", header.string_matcher);
+        break;
+      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
+          HeaderMatcherType::SUFFIX:
+        header_matcher = absl::StrFormat(
+            "             \"suffix_match\": \"%s\"", header.string_matcher);
+        break;
+      default:
+        break;
+    }
+    std::vector<std::string> header_parts;
+    header_parts.push_back(
+        absl::StrFormat("           { \n"
+                        "             \"name\": \"%s\",\n",
+                        header.name));
+    header_parts.push_back(header_matcher);
+    if (header.invert_match) {
+      header_parts.push_back(
+          absl::StrFormat(",\n"
+                          "             \"invert_match\": true"));
+    }
+    header_parts.push_back(
+        absl::StrFormat("\n"
+                        "           }"));
+    headers.push_back(absl::StrJoin(header_parts, ""));
+  }
+  std::vector<std::string> headers_service_config;
+  if (!headers.empty()) {
+    headers_service_config.push_back("\"headers\":[\n");
+    headers_service_config.push_back(absl::StrJoin(headers, ","));
+    headers_service_config.push_back("           ],\n");
+  }
+  std::string path_match_str;
+  switch (route.matchers.path_matcher.type) {
+    case XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcherType::
+        PREFIX:
+      path_match_str = absl::StrFormat(
+          "\"prefix\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
+      break;
+    case XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcherType::
+        PATH:
+      path_match_str = absl::StrFormat(
+          "\"path\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
+      break;
+    case XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcherType::
+        REGEX:
+      path_match_str =
+          absl::StrFormat("\"regex\": \"%s\",\n",
+                          route.matchers.path_matcher.regex_matcher->pattern());
+      break;
+  }
+  return absl::StrFormat(
+      "      { \n"
+      "           %s"
+      "           %s"
+      "           %s"
+      "           \"action\": \"%s\"\n"
+      "      }",
+      path_match_str, absl::StrJoin(headers_service_config, ""),
+      route.matchers.fraction_per_million.has_value()
+          ? absl::StrFormat("\"match_fraction\":%d,\n",
+                            route.matchers.fraction_per_million.value())
+          : "",
+      action_name);
+}
+
+// Create the service config for one weighted cluster.
+std::string CreateServiceConfigActionWeightedCluster(
+    const std::string& name,
+    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>& clusters) {
+  std::vector<std::string> config_parts;
+  config_parts.push_back(
+      absl::StrFormat("      \"weighted:%s\":{\n"
+                      "        \"childPolicy\":[ {\n"
+                      "          \"weighted_target_experimental\":{\n"
+                      "            \"targets\":{\n",
+                      name));
+  std::vector<std::string> weighted_targets;
+  weighted_targets.reserve(clusters.size());
+  for (const auto& cluster_weight : clusters) {
+    weighted_targets.push_back(absl::StrFormat(
+        "              \"%s\":{\n"
+        "                \"weight\":%d,\n"
+        "                \"childPolicy\":[ {\n"
+        "                  \"cds_experimental\":{\n"
+        "                    \"cluster\": \"%s\"\n"
+        "                  }\n"
+        "                } ]\n"
+        "               }",
+        cluster_weight.name, cluster_weight.weight, cluster_weight.name));
+  }
+  config_parts.push_back(absl::StrJoin(weighted_targets, ",\n"));
+  config_parts.push_back(
+      "            }\n"
+      "          }\n"
+      "        } ]\n"
+      "       }");
+  return absl::StrJoin(config_parts, "");
+}
+
+struct WeightedClustersKeys {
+  std::string cluster_names_key;
+  std::string cluster_weights_key;
+};
+
+// Returns the cluster names and weights key or the cluster names only key.
+WeightedClustersKeys GetWeightedClustersKey(
+    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
+        weighted_clusters) {
+  std::set<std::string> cluster_names;
+  std::set<std::string> cluster_weights;
+  for (const auto& cluster_weight : weighted_clusters) {
+    cluster_names.emplace(absl::StrFormat("%s", cluster_weight.name));
+    cluster_weights.emplace(
+        absl::StrFormat("%s_%d", cluster_weight.name, cluster_weight.weight));
+  }
+  return {absl::StrJoin(cluster_names, "_"),
+          absl::StrJoin(cluster_weights, "_")};
+}
+
+std::string XdsResolver::WeightedClustersActionName(
+    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
+        weighted_clusters) {
+  WeightedClustersKeys keys = GetWeightedClustersKey(weighted_clusters);
+  auto cluster_names_map_it =
+      weighted_cluster_index_map_.find(keys.cluster_names_key);
+  GPR_ASSERT(cluster_names_map_it != weighted_cluster_index_map_.end());
+  const auto& cluster_weights_map =
+      cluster_names_map_it->second.cluster_weights_map;
+  auto cluster_weights_map_it =
+      cluster_weights_map.find(keys.cluster_weights_key);
+  GPR_ASSERT(cluster_weights_map_it != cluster_weights_map.end());
+  return absl::StrFormat("%s_%d", keys.cluster_names_key,
+                         cluster_weights_map_it->second);
+}
+
+void XdsResolver::UpdateWeightedClusterIndexMap(
+    const XdsApi::RdsUpdate& rds_update) {
+  // Construct a list of unique WeightedCluster
+  // actions which we need to process: to find action names
+  std::map<std::string /* cluster_weights_key */,
+           std::string /* cluster_names_key */>
+      actions_to_process;
+  for (const auto& route : rds_update.routes) {
+    if (!route.weighted_clusters.empty()) {
+      WeightedClustersKeys keys =
+          GetWeightedClustersKey(route.weighted_clusters);
+      auto action_it = actions_to_process.find(keys.cluster_weights_key);
+      if (action_it == actions_to_process.end()) {
+        actions_to_process[std::move(keys.cluster_weights_key)] =
+            std::move(keys.cluster_names_key);
+      }
+    }
+  }
+  // First pass of all unique WeightedCluster actions: if the exact same
+  // weighted target policy (same clusters and weights) appears in the old map,
+  // then that old action name is taken again and should be moved to the new
+  // map; any other action names from the old set of actions are candidates for
+  // reuse.
+  XdsResolver::WeightedClusterIndexMap new_weighted_cluster_index_map;
+  for (auto action_it = actions_to_process.begin();
+       action_it != actions_to_process.end();) {
+    const std::string& cluster_names_key = action_it->second;
+    const std::string& cluster_weights_key = action_it->first;
+    auto old_cluster_names_map_it =
+        weighted_cluster_index_map_.find(cluster_names_key);
+    if (old_cluster_names_map_it != weighted_cluster_index_map_.end()) {
+      // Add cluster_names_key to the new map and copy next_index.
+      auto& new_cluster_names_info =
+          new_weighted_cluster_index_map[cluster_names_key];
+      new_cluster_names_info.next_index =
+          old_cluster_names_map_it->second.next_index;
+      // Lookup cluster_weights_key in old map.
+      auto& old_cluster_weights_map =
+          old_cluster_names_map_it->second.cluster_weights_map;
+      auto old_cluster_weights_map_it =
+          old_cluster_weights_map.find(cluster_weights_key);
+      if (old_cluster_weights_map_it != old_cluster_weights_map.end()) {
+        // same policy found, move from old map to new map.
+        new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
+            old_cluster_weights_map_it->second;
+        old_cluster_weights_map.erase(old_cluster_weights_map_it);
+        // This action has been added to new map, so no need to process it
+        // again.
+        action_it = actions_to_process.erase(action_it);
+        continue;
+      }
+    }
+    ++action_it;
+  }
+  // Second pass of all remaining unique WeightedCluster actions: if clusters
+  // for a new action are the same as an old unused action, reuse the name.  If
+  // clusters differ, use a brand new name.
+  for (const auto& action : actions_to_process) {
+    const std::string& cluster_names_key = action.second;
+    const std::string& cluster_weights_key = action.first;
+    auto& new_cluster_names_info =
+        new_weighted_cluster_index_map[cluster_names_key];
+    auto& old_cluster_weights_map =
+        weighted_cluster_index_map_[cluster_names_key].cluster_weights_map;
+    auto old_cluster_weights_it = old_cluster_weights_map.begin();
+    if (old_cluster_weights_it != old_cluster_weights_map.end()) {
+      // There is something to reuse: this action uses the same set
+      // of clusters as a previous action and that action name is not
+      // already taken.
+      new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
+          old_cluster_weights_it->second;
+      // Remove the name from being able to reuse again.
+      old_cluster_weights_map.erase(old_cluster_weights_it);
+    } else {
+      // There is nothing to reuse, take the next index to use and
+      // increment.
+      new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
+          new_cluster_names_info.next_index++;
+    }
+  }
+  weighted_cluster_index_map_ = std::move(new_weighted_cluster_index_map);
+}
+
+grpc_error* XdsResolver::CreateServiceConfig(
+    const XdsApi::RdsUpdate& rds_update,
+    RefCountedPtr<ServiceConfig>* service_config) {
+  UpdateWeightedClusterIndexMap(rds_update);
+  std::vector<std::string> actions_vector;
+  std::vector<std::string> route_table;
+  std::set<std::string> actions_set;
+  for (const auto& route : rds_update.routes) {
+    const std::string action_name =
+        route.weighted_clusters.empty()
+            ? route.cluster_name
+            : WeightedClustersActionName(route.weighted_clusters);
+    if (actions_set.find(action_name) == actions_set.end()) {
+      actions_set.emplace(action_name);
+      actions_vector.push_back(
+          route.weighted_clusters.empty()
+              ? CreateServiceConfigActionCluster(action_name)
+              : CreateServiceConfigActionWeightedCluster(
+                    action_name, route.weighted_clusters));
+    }
+    route_table.push_back(CreateServiceConfigRoute(
+        absl::StrFormat("%s:%s",
+                        route.weighted_clusters.empty() ? "cds" : "weighted",
+                        action_name),
+        route));
+  }
+  std::vector<std::string> config_parts;
+  config_parts.push_back(
+      "{\n"
+      "  \"loadBalancingConfig\":[\n"
+      "    { \"xds_routing_experimental\":{\n"
+      "      \"actions\":{\n");
+  config_parts.push_back(absl::StrJoin(actions_vector, ",\n"));
+  config_parts.push_back(
+      "    },\n"
+      "      \"routes\":[\n");
+  config_parts.push_back(absl::StrJoin(route_table, ",\n"));
+  config_parts.push_back(
+      "    ]\n"
+      "    } }\n"
+      "  ]\n"
+      "}");
+  std::string json = absl::StrJoin(config_parts, "");
+  grpc_error* error = GRPC_ERROR_NONE;
+  *service_config = ServiceConfig::Create(json.c_str(), &error);
+  return error;
+}
+
 //
 //
 // Factory
 // Factory
 //
 //

+ 19 - 0
src/core/ext/filters/client_channel/subchannel.cc

@@ -743,6 +743,25 @@ Subchannel* Subchannel::Create(OrphanablePtr<SubchannelConnector> connector,
   return registered;
   return registered;
 }
 }
 
 
+void Subchannel::ThrottleKeepaliveTime(int new_keepalive_time) {
+  MutexLock lock(&mu_);
+  // Only update the value if the new keepalive time is larger.
+  if (new_keepalive_time > keepalive_time_) {
+    keepalive_time_ = new_keepalive_time;
+    if (grpc_trace_subchannel.enabled()) {
+      gpr_log(GPR_INFO, "Subchannel=%p: Throttling keepalive time to %d", this,
+              new_keepalive_time);
+    }
+    const grpc_arg arg_to_add = grpc_channel_arg_integer_create(
+        const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS), new_keepalive_time);
+    const char* arg_to_remove = GRPC_ARG_KEEPALIVE_TIME_MS;
+    grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
+        args_, &arg_to_remove, 1, &arg_to_add, 1);
+    grpc_channel_args_destroy(args_);
+    args_ = new_args;
+  }
+}
+
 Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
 Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
   gpr_atm old_refs;
   gpr_atm old_refs;
   old_refs = RefMutate((1 << INTERNAL_REF_BITS),
   old_refs = RefMutate((1 << INTERNAL_REF_BITS),

+ 7 - 0
src/core/ext/filters/client_channel/subchannel.h

@@ -228,6 +228,11 @@ class Subchannel {
   static Subchannel* Create(OrphanablePtr<SubchannelConnector> connector,
   static Subchannel* Create(OrphanablePtr<SubchannelConnector> connector,
                             const grpc_channel_args* args);
                             const grpc_channel_args* args);
 
 
+  // Throttles keepalive time to \a new_keepalive_time iff \a new_keepalive_time
+  // is larger than the subchannel's current keepalive time. The updated value
+  // will have an affect when the subchannel creates a new ConnectedSubchannel.
+  void ThrottleKeepaliveTime(int new_keepalive_time);
+
   // Strong and weak refcounting.
   // Strong and weak refcounting.
   Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
   Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
   void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
   void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
@@ -422,6 +427,8 @@ class Subchannel {
   bool have_retry_alarm_ = false;
   bool have_retry_alarm_ = false;
   // reset_backoff() was called while alarm was pending.
   // reset_backoff() was called while alarm was pending.
   bool retry_immediately_ = false;
   bool retry_immediately_ = false;
+  // Keepalive time period (-1 for unset)
+  int keepalive_time_ = -1;
 
 
   // Channelz tracking.
   // Channelz tracking.
   RefCountedPtr<channelz::SubchannelNode> channelz_node_;
   RefCountedPtr<channelz::SubchannelNode> channelz_node_;

+ 5 - 4
src/core/ext/transport/chttp2/client/chttp2_connector.cc

@@ -199,6 +199,8 @@ void Chttp2Connector::OnReceiveSettings(void* arg, grpc_error* error) {
   {
   {
     MutexLock lock(&self->mu_);
     MutexLock lock(&self->mu_);
     if (!self->notify_error_.has_value()) {
     if (!self->notify_error_.has_value()) {
+      grpc_endpoint_delete_from_pollset_set(self->endpoint_,
+                                            self->args_.interested_parties);
       if (error != GRPC_ERROR_NONE) {
       if (error != GRPC_ERROR_NONE) {
         // Transport got an error while waiting on SETTINGS frame.
         // Transport got an error while waiting on SETTINGS frame.
         // TODO(yashykt): The following two lines should be moved to
         // TODO(yashykt): The following two lines should be moved to
@@ -225,6 +227,8 @@ void Chttp2Connector::OnTimeout(void* arg, grpc_error* error) {
     if (!self->notify_error_.has_value()) {
     if (!self->notify_error_.has_value()) {
       // The transport did not receive the settings frame in time. Destroy the
       // The transport did not receive the settings frame in time. Destroy the
       // transport.
       // transport.
+      grpc_endpoint_delete_from_pollset_set(self->endpoint_,
+                                            self->args_.interested_parties);
       // TODO(yashykt): The following two lines should be moved to
       // TODO(yashykt): The following two lines should be moved to
       // SubchannelConnector::Result::Reset()
       // SubchannelConnector::Result::Reset()
       grpc_transport_destroy(self->result_->transport);
       grpc_transport_destroy(self->result_->transport);
@@ -245,11 +249,8 @@ void Chttp2Connector::MaybeNotify(grpc_error* error) {
   if (notify_error_.has_value()) {
   if (notify_error_.has_value()) {
     GRPC_ERROR_UNREF(error);
     GRPC_ERROR_UNREF(error);
     NullThenSchedClosure(DEBUG_LOCATION, &notify_, notify_error_.value());
     NullThenSchedClosure(DEBUG_LOCATION, &notify_, notify_error_.value());
-    // Clear out the endpoint, since it is the responsibility of the transport
-    // to shut it down.
     // Clear state for a new Connect().
     // Clear state for a new Connect().
-    grpc_endpoint_delete_from_pollset_set(endpoint_, args_.interested_parties);
-    // We do not destroy the endpoint here, since it is the responsibility of
+    // Clear out the endpoint_, since it is the responsibility of
     // the transport to shut it down.
     // the transport to shut it down.
     endpoint_ = nullptr;
     endpoint_ = nullptr;
     notify_error_.reset();
     notify_error_.reset();

+ 55 - 93
src/core/ext/transport/chttp2/transport/chttp2_transport.cc

@@ -1084,6 +1084,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
     gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string.c_str(),
     gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string.c_str(),
             goaway_error, grpc_error_string(t->goaway_error));
             goaway_error, grpc_error_string(t->goaway_error));
   }
   }
+  absl::Status status = grpc_error_to_absl_status(t->goaway_error);
   // When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug
   // When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug
   // data equal to "too_many_pings", it should log the occurrence at a log level
   // data equal to "too_many_pings", it should log the occurrence at a log level
   // that is enabled by default and double the configured KEEPALIVE_TIME used
   // that is enabled by default and double the configured KEEPALIVE_TIME used
@@ -1102,8 +1103,9 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
             ? GRPC_MILLIS_INF_FUTURE
             ? GRPC_MILLIS_INF_FUTURE
             : static_cast<grpc_millis>(current_keepalive_time_ms *
             : static_cast<grpc_millis>(current_keepalive_time_ms *
                                        KEEPALIVE_TIME_BACKOFF_MULTIPLIER);
                                        KEEPALIVE_TIME_BACKOFF_MULTIPLIER);
+    status.SetPayload(grpc_core::kKeepaliveThrottlingKey,
+                      absl::Cord(std::to_string(t->keepalive_time)));
   }
   }
-  absl::Status status = grpc_error_to_absl_status(t->goaway_error);
   // lie: use transient failure from the transport to indicate goaway has been
   // lie: use transient failure from the transport to indicate goaway has been
   // received.
   // received.
   connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, status,
   connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, status,
@@ -1410,64 +1412,44 @@ static void perform_stream_op_locked(void* stream_op,
     s->send_initial_metadata_finished = add_closure_barrier(on_complete);
     s->send_initial_metadata_finished = add_closure_barrier(on_complete);
     s->send_initial_metadata =
     s->send_initial_metadata =
         op_payload->send_initial_metadata.send_initial_metadata;
         op_payload->send_initial_metadata.send_initial_metadata;
-    const size_t metadata_size =
-        grpc_metadata_batch_size(s->send_initial_metadata);
-    const size_t metadata_peer_limit =
-        t->settings[GRPC_PEER_SETTINGS]
-                   [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
     if (t->is_client) {
     if (t->is_client) {
       s->deadline = GPR_MIN(s->deadline, s->send_initial_metadata->deadline);
       s->deadline = GPR_MIN(s->deadline, s->send_initial_metadata->deadline);
     }
     }
-    if (metadata_size > metadata_peer_limit) {
-      grpc_chttp2_cancel_stream(
-          t, s,
-          grpc_error_set_int(
-              grpc_error_set_int(
-                  grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                                         "to-be-sent initial metadata size "
-                                         "exceeds peer limit"),
-                                     GRPC_ERROR_INT_SIZE,
-                                     static_cast<intptr_t>(metadata_size)),
-                  GRPC_ERROR_INT_LIMIT,
-                  static_cast<intptr_t>(metadata_peer_limit)),
-              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
-    } else {
-      if (contains_non_ok_status(s->send_initial_metadata)) {
-        s->seen_error = true;
-      }
-      if (!s->write_closed) {
-        if (t->is_client) {
-          if (t->closed_with_error == GRPC_ERROR_NONE) {
-            GPR_ASSERT(s->id == 0);
-            grpc_chttp2_list_add_waiting_for_concurrency(t, s);
-            maybe_start_some_streams(t);
-          } else {
-            grpc_chttp2_cancel_stream(
-                t, s,
-                grpc_error_set_int(
-                    GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
-                        "Transport closed", &t->closed_with_error, 1),
-                    GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
-          }
+    if (contains_non_ok_status(s->send_initial_metadata)) {
+      s->seen_error = true;
+    }
+    if (!s->write_closed) {
+      if (t->is_client) {
+        if (t->closed_with_error == GRPC_ERROR_NONE) {
+          GPR_ASSERT(s->id == 0);
+          grpc_chttp2_list_add_waiting_for_concurrency(t, s);
+          maybe_start_some_streams(t);
         } else {
         } else {
-          GPR_ASSERT(s->id != 0);
-          grpc_chttp2_mark_stream_writable(t, s);
-          if (!(op->send_message &&
-                (op->payload->send_message.send_message->flags() &
-                 GRPC_WRITE_BUFFER_HINT))) {
-            grpc_chttp2_initiate_write(
-                t, GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA);
-          }
+          grpc_chttp2_cancel_stream(
+              t, s,
+              grpc_error_set_int(
+                  GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+                      "Transport closed", &t->closed_with_error, 1),
+                  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
         }
         }
       } else {
       } else {
-        s->send_initial_metadata = nullptr;
-        grpc_chttp2_complete_closure_step(
-            t, s, &s->send_initial_metadata_finished,
-            GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
-                "Attempt to send initial metadata after stream was closed",
-                &s->write_closed_error, 1),
-            "send_initial_metadata_finished");
+        GPR_ASSERT(s->id != 0);
+        grpc_chttp2_mark_stream_writable(t, s);
+        if (!(op->send_message &&
+              (op->payload->send_message.send_message->flags() &
+               GRPC_WRITE_BUFFER_HINT))) {
+          grpc_chttp2_initiate_write(
+              t, GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA);
+        }
       }
       }
+    } else {
+      s->send_initial_metadata = nullptr;
+      grpc_chttp2_complete_closure_step(
+          t, s, &s->send_initial_metadata_finished,
+          GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+              "Attempt to send initial metadata after stream was closed",
+              &s->write_closed_error, 1),
+          "send_initial_metadata_finished");
     }
     }
     if (op_payload->send_initial_metadata.peer_string != nullptr) {
     if (op_payload->send_initial_metadata.peer_string != nullptr) {
       gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
       gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
@@ -1529,47 +1511,27 @@ static void perform_stream_op_locked(void* stream_op,
         op_payload->send_trailing_metadata.send_trailing_metadata;
         op_payload->send_trailing_metadata.send_trailing_metadata;
     s->sent_trailing_metadata_op = op_payload->send_trailing_metadata.sent;
     s->sent_trailing_metadata_op = op_payload->send_trailing_metadata.sent;
     s->write_buffering = false;
     s->write_buffering = false;
-    const size_t metadata_size =
-        grpc_metadata_batch_size(s->send_trailing_metadata);
-    const size_t metadata_peer_limit =
-        t->settings[GRPC_PEER_SETTINGS]
-                   [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
-    if (metadata_size > metadata_peer_limit) {
-      grpc_chttp2_cancel_stream(
-          t, s,
-          grpc_error_set_int(
-              grpc_error_set_int(
-                  grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                                         "to-be-sent trailing metadata size "
-                                         "exceeds peer limit"),
-                                     GRPC_ERROR_INT_SIZE,
-                                     static_cast<intptr_t>(metadata_size)),
-                  GRPC_ERROR_INT_LIMIT,
-                  static_cast<intptr_t>(metadata_peer_limit)),
-              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
-    } else {
-      if (contains_non_ok_status(s->send_trailing_metadata)) {
-        s->seen_error = true;
-      }
-      if (s->write_closed) {
-        s->send_trailing_metadata = nullptr;
-        s->sent_trailing_metadata_op = nullptr;
-        grpc_chttp2_complete_closure_step(
-            t, s, &s->send_trailing_metadata_finished,
-            grpc_metadata_batch_is_empty(
-                op->payload->send_trailing_metadata.send_trailing_metadata)
-                ? GRPC_ERROR_NONE
-                : GRPC_ERROR_CREATE_FROM_STATIC_STRING(
-                      "Attempt to send trailing metadata after "
-                      "stream was closed"),
-            "send_trailing_metadata_finished");
-      } else if (s->id != 0) {
-        // TODO(ctiller): check if there's flow control for any outstanding
-        //   bytes before going writable
-        grpc_chttp2_mark_stream_writable(t, s);
-        grpc_chttp2_initiate_write(
-            t, GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA);
-      }
+    if (contains_non_ok_status(s->send_trailing_metadata)) {
+      s->seen_error = true;
+    }
+    if (s->write_closed) {
+      s->send_trailing_metadata = nullptr;
+      s->sent_trailing_metadata_op = nullptr;
+      grpc_chttp2_complete_closure_step(
+          t, s, &s->send_trailing_metadata_finished,
+          grpc_metadata_batch_is_empty(
+              op->payload->send_trailing_metadata.send_trailing_metadata)
+              ? GRPC_ERROR_NONE
+              : GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                    "Attempt to send trailing metadata after "
+                    "stream was closed"),
+          "send_trailing_metadata_finished");
+    } else if (s->id != 0) {
+      // TODO(ctiller): check if there's flow control for any outstanding
+      //   bytes before going writable
+      grpc_chttp2_mark_stream_writable(t, s);
+      grpc_chttp2_initiate_write(
+          t, GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA);
     }
     }
   }
   }
 
 

+ 1 - 28
src/core/ext/transport/chttp2/transport/parsing.cc

@@ -391,27 +391,6 @@ static bool md_key_cmp(grpc_mdelem md, const grpc_slice& reference) {
   return GRPC_MDKEY(md).refcount == reference.refcount;
   return GRPC_MDKEY(md).refcount == reference.refcount;
 }
 }
 
 
-static bool md_cmp(grpc_mdelem md, grpc_mdelem ref_md,
-                   const grpc_slice& ref_key) {
-  if (GPR_LIKELY(GRPC_MDELEM_IS_INTERNED(md))) {
-    return md.payload == ref_md.payload;
-  }
-  if (md_key_cmp(md, ref_key)) {
-    return grpc_slice_eq_static_interned(GRPC_MDVALUE(md),
-                                         GRPC_MDVALUE(ref_md));
-  }
-  return false;
-}
-
-static bool is_nonzero_status(grpc_mdelem md) {
-  // If md.payload == GRPC_MDELEM_GRPC_STATUS_1 or GRPC_MDELEM_GRPC_STATUS_2,
-  // then we have seen an error. In fact, if it is a GRPC_STATUS and it's
-  // not equal to GRPC_MDELEM_GRPC_STATUS_0, then we have seen an error.
-  // TODO(ctiller): check for a status like " 0"
-  return md_key_cmp(md, GRPC_MDSTR_GRPC_STATUS) &&
-         !md_cmp(md, GRPC_MDELEM_GRPC_STATUS_0, GRPC_MDSTR_GRPC_STATUS);
-}
-
 static void GPR_ATTRIBUTE_NOINLINE on_initial_header_log(
 static void GPR_ATTRIBUTE_NOINLINE on_initial_header_log(
     grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_mdelem md) {
     grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_mdelem md) {
   char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
   char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
@@ -493,9 +472,7 @@ static grpc_error* on_initial_header(void* tp, grpc_mdelem md) {
     on_initial_header_log(t, s, md);
     on_initial_header_log(t, s, md);
   }
   }
 
 
-  if (is_nonzero_status(md)) {  // not GRPC_MDELEM_GRPC_STATUS_0?
-    s->seen_error = true;
-  } else if (md_key_cmp(md, GRPC_MDSTR_GRPC_TIMEOUT)) {
+  if (md_key_cmp(md, GRPC_MDSTR_GRPC_TIMEOUT)) {
     return handle_timeout(s, md);
     return handle_timeout(s, md);
   }
   }
 
 
@@ -534,10 +511,6 @@ static grpc_error* on_trailing_header(void* tp, grpc_mdelem md) {
     gpr_free(value);
     gpr_free(value);
   }
   }
 
 
-  if (is_nonzero_status(md)) {  // not GRPC_MDELEM_GRPC_STATUS_0?
-    s->seen_error = true;
-  }
-
   const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
   const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
   const size_t metadata_size_limit =
   const size_t metadata_size_limit =
       t->settings[GRPC_ACKED_SETTINGS]
       t->settings[GRPC_ACKED_SETTINGS]

+ 7 - 8
src/core/ext/transport/inproc/inproc_transport.cc

@@ -202,11 +202,6 @@ struct inproc_stream {
     }
     }
 
 
     t->unref();
     t->unref();
-
-    if (closure_at_destroy) {
-      grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure_at_destroy,
-                              GRPC_ERROR_NONE);
-    }
   }
   }
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -249,7 +244,6 @@ struct inproc_stream {
   bool other_side_closed = false;               // won't talk anymore
   bool other_side_closed = false;               // won't talk anymore
   bool write_buffer_other_side_closed = false;  // on hold
   bool write_buffer_other_side_closed = false;  // on hold
   grpc_stream_refcount* refs;
   grpc_stream_refcount* refs;
-  grpc_closure* closure_at_destroy = nullptr;
 
 
   grpc_core::Arena* arena;
   grpc_core::Arena* arena;
 
 
@@ -1183,12 +1177,17 @@ void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
   gpr_mu_unlock(&t->mu->mu);
   gpr_mu_unlock(&t->mu->mu);
 }
 }
 
 
-void destroy_stream(grpc_transport* /*gt*/, grpc_stream* gs,
+void destroy_stream(grpc_transport* gt, grpc_stream* gs,
                     grpc_closure* then_schedule_closure) {
                     grpc_closure* then_schedule_closure) {
   INPROC_LOG(GPR_INFO, "destroy_stream %p %p", gs, then_schedule_closure);
   INPROC_LOG(GPR_INFO, "destroy_stream %p %p", gs, then_schedule_closure);
+  inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
   inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
   inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
-  s->closure_at_destroy = then_schedule_closure;
+  gpr_mu_lock(&t->mu->mu);
+  close_stream_locked(s);
+  gpr_mu_unlock(&t->mu->mu);
   s->~inproc_stream();
   s->~inproc_stream();
+  grpc_core::ExecCtx::Run(DEBUG_LOCATION, then_schedule_closure,
+                          GRPC_ERROR_NONE);
 }
 }
 
 
 void destroy_transport(grpc_transport* gt) {
 void destroy_transport(grpc_transport* gt) {

+ 43 - 0
src/core/ext/upb-generated/third_party/istio/security/proto/providers/google/meshca.upb.c

@@ -0,0 +1,43 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     third_party/istio/security/proto/providers/google/meshca.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+#include "upb/msg.h"
+#include "third_party/istio/security/proto/providers/google/meshca.upb.h"
+#include "google/protobuf/duration.upb.h"
+
+#include "upb/port_def.inc"
+
+static const upb_msglayout *const google_security_meshca_v1_MeshCertificateRequest_submsgs[1] = {
+  &google_protobuf_Duration_msginit,
+};
+
+static const upb_msglayout_field google_security_meshca_v1_MeshCertificateRequest__fields[3] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 1},
+  {2, UPB_SIZE(8, 16), 0, 0, 9, 1},
+  {3, UPB_SIZE(16, 32), 0, 0, 11, 1},
+};
+
+const upb_msglayout google_security_meshca_v1_MeshCertificateRequest_msginit = {
+  &google_security_meshca_v1_MeshCertificateRequest_submsgs[0],
+  &google_security_meshca_v1_MeshCertificateRequest__fields[0],
+  UPB_SIZE(24, 48), 3, false,
+};
+
+static const upb_msglayout_field google_security_meshca_v1_MeshCertificateResponse__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 9, 3},
+};
+
+const upb_msglayout google_security_meshca_v1_MeshCertificateResponse_msginit = {
+  NULL,
+  &google_security_meshca_v1_MeshCertificateResponse__fields[0],
+  UPB_SIZE(4, 8), 1, false,
+};
+
+#include "upb/port_undef.inc"
+

+ 103 - 0
src/core/ext/upb-generated/third_party/istio/security/proto/providers/google/meshca.upb.h

@@ -0,0 +1,103 @@
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     third_party/istio/security/proto/providers/google/meshca.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef THIRD_PARTY_ISTIO_SECURITY_PROTO_PROVIDERS_GOOGLE_MESHCA_PROTO_UPB_H_
+#define THIRD_PARTY_ISTIO_SECURITY_PROTO_PROVIDERS_GOOGLE_MESHCA_PROTO_UPB_H_
+
+#include "upb/msg.h"
+#include "upb/decode.h"
+#include "upb/encode.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct google_security_meshca_v1_MeshCertificateRequest;
+struct google_security_meshca_v1_MeshCertificateResponse;
+typedef struct google_security_meshca_v1_MeshCertificateRequest google_security_meshca_v1_MeshCertificateRequest;
+typedef struct google_security_meshca_v1_MeshCertificateResponse google_security_meshca_v1_MeshCertificateResponse;
+extern const upb_msglayout google_security_meshca_v1_MeshCertificateRequest_msginit;
+extern const upb_msglayout google_security_meshca_v1_MeshCertificateResponse_msginit;
+struct google_protobuf_Duration;
+extern const upb_msglayout google_protobuf_Duration_msginit;
+
+
+/* google.security.meshca.v1.MeshCertificateRequest */
+
+UPB_INLINE google_security_meshca_v1_MeshCertificateRequest *google_security_meshca_v1_MeshCertificateRequest_new(upb_arena *arena) {
+  return (google_security_meshca_v1_MeshCertificateRequest *)_upb_msg_new(&google_security_meshca_v1_MeshCertificateRequest_msginit, arena);
+}
+UPB_INLINE google_security_meshca_v1_MeshCertificateRequest *google_security_meshca_v1_MeshCertificateRequest_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_security_meshca_v1_MeshCertificateRequest *ret = google_security_meshca_v1_MeshCertificateRequest_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_security_meshca_v1_MeshCertificateRequest_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *google_security_meshca_v1_MeshCertificateRequest_serialize(const google_security_meshca_v1_MeshCertificateRequest *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_security_meshca_v1_MeshCertificateRequest_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview google_security_meshca_v1_MeshCertificateRequest_request_id(const google_security_meshca_v1_MeshCertificateRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); }
+UPB_INLINE upb_strview google_security_meshca_v1_MeshCertificateRequest_csr(const google_security_meshca_v1_MeshCertificateRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_strview); }
+UPB_INLINE bool google_security_meshca_v1_MeshCertificateRequest_has_validity(const google_security_meshca_v1_MeshCertificateRequest *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const struct google_protobuf_Duration* google_security_meshca_v1_MeshCertificateRequest_validity(const google_security_meshca_v1_MeshCertificateRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct google_protobuf_Duration*); }
+
+UPB_INLINE void google_security_meshca_v1_MeshCertificateRequest_set_request_id(google_security_meshca_v1_MeshCertificateRequest *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value;
+}
+UPB_INLINE void google_security_meshca_v1_MeshCertificateRequest_set_csr(google_security_meshca_v1_MeshCertificateRequest *msg, upb_strview value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 16), upb_strview) = value;
+}
+UPB_INLINE void google_security_meshca_v1_MeshCertificateRequest_set_validity(google_security_meshca_v1_MeshCertificateRequest *msg, struct google_protobuf_Duration* value) {
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct google_protobuf_Duration*) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* google_security_meshca_v1_MeshCertificateRequest_mutable_validity(google_security_meshca_v1_MeshCertificateRequest *msg, upb_arena *arena) {
+  struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)google_security_meshca_v1_MeshCertificateRequest_validity(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena);
+    if (!sub) return NULL;
+    google_security_meshca_v1_MeshCertificateRequest_set_validity(msg, sub);
+  }
+  return sub;
+}
+
+/* google.security.meshca.v1.MeshCertificateResponse */
+
+UPB_INLINE google_security_meshca_v1_MeshCertificateResponse *google_security_meshca_v1_MeshCertificateResponse_new(upb_arena *arena) {
+  return (google_security_meshca_v1_MeshCertificateResponse *)_upb_msg_new(&google_security_meshca_v1_MeshCertificateResponse_msginit, arena);
+}
+UPB_INLINE google_security_meshca_v1_MeshCertificateResponse *google_security_meshca_v1_MeshCertificateResponse_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_security_meshca_v1_MeshCertificateResponse *ret = google_security_meshca_v1_MeshCertificateResponse_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_security_meshca_v1_MeshCertificateResponse_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE char *google_security_meshca_v1_MeshCertificateResponse_serialize(const google_security_meshca_v1_MeshCertificateResponse *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_security_meshca_v1_MeshCertificateResponse_msginit, arena, len);
+}
+
+UPB_INLINE upb_strview const* google_security_meshca_v1_MeshCertificateResponse_cert_chain(const google_security_meshca_v1_MeshCertificateResponse *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE upb_strview* google_security_meshca_v1_MeshCertificateResponse_mutable_cert_chain(google_security_meshca_v1_MeshCertificateResponse *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE upb_strview* google_security_meshca_v1_MeshCertificateResponse_resize_cert_chain(google_security_meshca_v1_MeshCertificateResponse *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_STRING, arena);
+}
+UPB_INLINE bool google_security_meshca_v1_MeshCertificateResponse_add_cert_chain(google_security_meshca_v1_MeshCertificateResponse *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor(msg, UPB_SIZE(0, 0), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
+      arena);
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif  /* THIRD_PARTY_ISTIO_SECURITY_PROTO_PROVIDERS_GOOGLE_MESHCA_PROTO_UPB_H_ */

+ 231 - 87
src/core/ext/xds/xds_api.cc

@@ -24,6 +24,7 @@
 #include <cstdlib>
 #include <cstdlib>
 #include <string>
 #include <string>
 
 
+#include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 #include "absl/strings/str_join.h"
@@ -39,6 +40,7 @@
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/useful.h"
 #include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/host_port.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/error.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/iomgr/sockaddr_utils.h"
 
 
@@ -74,101 +76,44 @@
 namespace grpc_core {
 namespace grpc_core {
 
 
 //
 //
-// XdsApi::PriorityListUpdate
+// XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher
 //
 //
 
 
-bool XdsApi::PriorityListUpdate::operator==(
-    const XdsApi::PriorityListUpdate& other) const {
-  if (priorities_.size() != other.priorities_.size()) return false;
-  for (size_t i = 0; i < priorities_.size(); ++i) {
-    if (priorities_[i].localities != other.priorities_[i].localities) {
-      return false;
-    }
+XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcher(
+    const PathMatcher& other)
+    : type(other.type) {
+  if (type == PathMatcherType::REGEX) {
+    regex_matcher = absl::make_unique<RE2>(other.regex_matcher->pattern());
+  } else {
+    string_matcher = other.string_matcher;
   }
   }
-  return true;
-}
-
-void XdsApi::PriorityListUpdate::Add(
-    XdsApi::PriorityListUpdate::LocalityMap::Locality locality) {
-  // Pad the missing priorities in case the localities are not ordered by
-  // priority.
-  if (!Contains(locality.priority)) priorities_.resize(locality.priority + 1);
-  LocalityMap& locality_map = priorities_[locality.priority];
-  locality_map.localities.emplace(locality.name, std::move(locality));
-}
-
-const XdsApi::PriorityListUpdate::LocalityMap* XdsApi::PriorityListUpdate::Find(
-    uint32_t priority) const {
-  if (!Contains(priority)) return nullptr;
-  return &priorities_[priority];
 }
 }
 
 
-bool XdsApi::PriorityListUpdate::Contains(
-    const RefCountedPtr<XdsLocalityName>& name) {
-  for (size_t i = 0; i < priorities_.size(); ++i) {
-    const LocalityMap& locality_map = priorities_[i];
-    if (locality_map.Contains(name)) return true;
+XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher&
+XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::operator=(
+    const PathMatcher& other) {
+  type = other.type;
+  if (type == PathMatcherType::REGEX) {
+    regex_matcher = absl::make_unique<RE2>(other.regex_matcher->pattern());
+  } else {
+    string_matcher = other.string_matcher;
   }
   }
-  return false;
+  return *this;
 }
 }
 
 
-//
-// XdsApi::DropConfig
-//
-
-bool XdsApi::DropConfig::ShouldDrop(const std::string** category_name) const {
-  for (size_t i = 0; i < drop_category_list_.size(); ++i) {
-    const auto& drop_category = drop_category_list_[i];
-    // Generate a random number in [0, 1000000).
-    const uint32_t random = static_cast<uint32_t>(rand()) % 1000000;
-    if (random < drop_category.parts_per_million) {
-      *category_name = &drop_category.name;
-      return true;
+bool XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::operator==(
+    const PathMatcher& other) const {
+  if (type != other.type) return false;
+  if (type == PathMatcherType::REGEX) {
+    // Should never be null.
+    if (regex_matcher == nullptr || other.regex_matcher == nullptr) {
+      return false;
     }
     }
+    return regex_matcher->pattern() == other.regex_matcher->pattern();
   }
   }
-  return false;
+  return string_matcher == other.string_matcher;
 }
 }
 
 
-//
-// XdsApi
-//
-
-const char* XdsApi::kLdsTypeUrl =
-    "type.googleapis.com/envoy.config.listener.v3.Listener";
-const char* XdsApi::kRdsTypeUrl =
-    "type.googleapis.com/envoy.config.route.v3.RouteConfiguration";
-const char* XdsApi::kCdsTypeUrl =
-    "type.googleapis.com/envoy.config.cluster.v3.Cluster";
-const char* XdsApi::kEdsTypeUrl =
-    "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment";
-
-namespace {
-
-const char* kLdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Listener";
-const char* kRdsV2TypeUrl =
-    "type.googleapis.com/envoy.api.v2.RouteConfiguration";
-const char* kCdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Cluster";
-const char* kEdsV2TypeUrl =
-    "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
-
-bool IsLds(absl::string_view type_url) {
-  return type_url == XdsApi::kLdsTypeUrl || type_url == kLdsV2TypeUrl;
-}
-
-bool IsRds(absl::string_view type_url) {
-  return type_url == XdsApi::kRdsTypeUrl || type_url == kRdsV2TypeUrl;
-}
-
-bool IsCds(absl::string_view type_url) {
-  return type_url == XdsApi::kCdsTypeUrl || type_url == kCdsV2TypeUrl;
-}
-
-bool IsEds(absl::string_view type_url) {
-  return type_url == XdsApi::kEdsTypeUrl || type_url == kEdsV2TypeUrl;
-}
-
-}  // namespace
-
 std::string XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::ToString()
 std::string XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::ToString()
     const {
     const {
   std::string path_type_string;
   std::string path_type_string;
@@ -185,12 +130,75 @@ std::string XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::ToString()
     default:
     default:
       break;
       break;
   }
   }
-  return absl::StrFormat("Path %s:/%s/", path_type_string,
+  return absl::StrFormat("Path %s:%s", path_type_string,
                          type == PathMatcherType::REGEX
                          type == PathMatcherType::REGEX
                              ? regex_matcher->pattern()
                              ? regex_matcher->pattern()
                              : string_matcher);
                              : string_matcher);
 }
 }
 
 
+//
+// XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher
+//
+
+XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::HeaderMatcher(
+    const HeaderMatcher& other)
+    : name(other.name), type(other.type), invert_match(other.invert_match) {
+  switch (type) {
+    case HeaderMatcherType::REGEX:
+      regex_match = absl::make_unique<RE2>(other.regex_match->pattern());
+      break;
+    case HeaderMatcherType::RANGE:
+      range_start = other.range_start;
+      range_end = other.range_end;
+      break;
+    case HeaderMatcherType::PRESENT:
+      present_match = other.present_match;
+      break;
+    default:
+      string_matcher = other.string_matcher;
+  }
+}
+
+XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher&
+XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::operator=(
+    const HeaderMatcher& other) {
+  name = other.name;
+  type = other.type;
+  invert_match = other.invert_match;
+  switch (type) {
+    case HeaderMatcherType::REGEX:
+      regex_match = absl::make_unique<RE2>(other.regex_match->pattern());
+      break;
+    case HeaderMatcherType::RANGE:
+      range_start = other.range_start;
+      range_end = other.range_end;
+      break;
+    case HeaderMatcherType::PRESENT:
+      present_match = other.present_match;
+      break;
+    default:
+      string_matcher = other.string_matcher;
+  }
+  return *this;
+}
+
+bool XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::operator==(
+    const HeaderMatcher& other) const {
+  if (name != other.name) return false;
+  if (type != other.type) return false;
+  if (invert_match != other.invert_match) return false;
+  switch (type) {
+    case HeaderMatcherType::REGEX:
+      return regex_match->pattern() != other.regex_match->pattern();
+    case HeaderMatcherType::RANGE:
+      return range_start != other.range_start && range_end != other.range_end;
+    case HeaderMatcherType::PRESENT:
+      return present_match != other.present_match;
+    default:
+      return string_matcher != other.string_matcher;
+  }
+}
+
 std::string XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::ToString()
 std::string XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::ToString()
     const {
     const {
   switch (type) {
   switch (type) {
@@ -257,6 +265,102 @@ std::string XdsApi::RdsUpdate::ToString() const {
   return absl::StrJoin(contents, ",\n");
   return absl::StrJoin(contents, ",\n");
 }
 }
 
 
+//
+// XdsApi::PriorityListUpdate
+//
+
+bool XdsApi::PriorityListUpdate::operator==(
+    const XdsApi::PriorityListUpdate& other) const {
+  if (priorities_.size() != other.priorities_.size()) return false;
+  for (size_t i = 0; i < priorities_.size(); ++i) {
+    if (priorities_[i].localities != other.priorities_[i].localities) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void XdsApi::PriorityListUpdate::Add(
+    XdsApi::PriorityListUpdate::LocalityMap::Locality locality) {
+  // Pad the missing priorities in case the localities are not ordered by
+  // priority.
+  if (!Contains(locality.priority)) priorities_.resize(locality.priority + 1);
+  LocalityMap& locality_map = priorities_[locality.priority];
+  locality_map.localities.emplace(locality.name, std::move(locality));
+}
+
+const XdsApi::PriorityListUpdate::LocalityMap* XdsApi::PriorityListUpdate::Find(
+    uint32_t priority) const {
+  if (!Contains(priority)) return nullptr;
+  return &priorities_[priority];
+}
+
+bool XdsApi::PriorityListUpdate::Contains(
+    const RefCountedPtr<XdsLocalityName>& name) {
+  for (size_t i = 0; i < priorities_.size(); ++i) {
+    const LocalityMap& locality_map = priorities_[i];
+    if (locality_map.Contains(name)) return true;
+  }
+  return false;
+}
+
+//
+// XdsApi::DropConfig
+//
+
+bool XdsApi::DropConfig::ShouldDrop(const std::string** category_name) const {
+  for (size_t i = 0; i < drop_category_list_.size(); ++i) {
+    const auto& drop_category = drop_category_list_[i];
+    // Generate a random number in [0, 1000000).
+    const uint32_t random = static_cast<uint32_t>(rand()) % 1000000;
+    if (random < drop_category.parts_per_million) {
+      *category_name = &drop_category.name;
+      return true;
+    }
+  }
+  return false;
+}
+
+//
+// XdsApi
+//
+
+const char* XdsApi::kLdsTypeUrl =
+    "type.googleapis.com/envoy.config.listener.v3.Listener";
+const char* XdsApi::kRdsTypeUrl =
+    "type.googleapis.com/envoy.config.route.v3.RouteConfiguration";
+const char* XdsApi::kCdsTypeUrl =
+    "type.googleapis.com/envoy.config.cluster.v3.Cluster";
+const char* XdsApi::kEdsTypeUrl =
+    "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment";
+
+namespace {
+
+const char* kLdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Listener";
+const char* kRdsV2TypeUrl =
+    "type.googleapis.com/envoy.api.v2.RouteConfiguration";
+const char* kCdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Cluster";
+const char* kEdsV2TypeUrl =
+    "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
+
+bool IsLds(absl::string_view type_url) {
+  return type_url == XdsApi::kLdsTypeUrl || type_url == kLdsV2TypeUrl;
+}
+
+bool IsRds(absl::string_view type_url) {
+  return type_url == XdsApi::kRdsTypeUrl || type_url == kRdsV2TypeUrl;
+}
+
+bool IsCds(absl::string_view type_url) {
+  return type_url == XdsApi::kCdsTypeUrl || type_url == kCdsV2TypeUrl;
+}
+
+bool IsEds(absl::string_view type_url) {
+  return type_url == XdsApi::kEdsTypeUrl || type_url == kEdsV2TypeUrl;
+}
+
+}  // namespace
+
 XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
 XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
                const XdsBootstrap* bootstrap)
                const XdsBootstrap* bootstrap)
     : client_(client),
     : client_(client),
@@ -361,6 +465,7 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap* bootstrap,
                   const std::string& build_version,
                   const std::string& build_version,
                   const std::string& user_agent_name,
                   const std::string& user_agent_name,
                   const std::string& server_name,
                   const std::string& server_name,
+                  const std::vector<grpc_resolved_address>& listening_addresses,
                   envoy_config_core_v3_Node* node_msg) {
                   envoy_config_core_v3_Node* node_msg) {
   const XdsBootstrap::Node* node = bootstrap->node();
   const XdsBootstrap::Node* node = bootstrap->node();
   if (node != nullptr) {
   if (node != nullptr) {
@@ -408,6 +513,21 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap* bootstrap,
   if (!bootstrap->server().ShouldUseV3()) {
   if (!bootstrap->server().ShouldUseV3()) {
     PopulateBuildVersion(arena, node_msg, build_version);
     PopulateBuildVersion(arena, node_msg, build_version);
   }
   }
+  for (const grpc_resolved_address& address : listening_addresses) {
+    std::string address_str = grpc_sockaddr_to_string(&address, false);
+    absl::string_view addr_str;
+    absl::string_view port_str;
+    GPR_ASSERT(SplitHostPort(address_str, &addr_str, &port_str));
+    uint32_t port;
+    GPR_ASSERT(absl::SimpleAtoi(port_str, &port));
+    auto* addr_msg =
+        envoy_config_core_v3_Node_add_listening_addresses(node_msg, arena);
+    auto* socket_addr_msg =
+        envoy_config_core_v3_Address_mutable_socket_address(addr_msg, arena);
+    envoy_config_core_v3_SocketAddress_set_address(
+        socket_addr_msg, upb_strview_make(addr_str.data(), addr_str.size()));
+    envoy_config_core_v3_SocketAddress_set_port_value(socket_addr_msg, port);
+  }
   envoy_config_core_v3_Node_set_user_agent_name(
   envoy_config_core_v3_Node_set_user_agent_name(
       node_msg,
       node_msg,
       upb_strview_make(user_agent_name.data(), user_agent_name.size()));
       upb_strview_make(user_agent_name.data(), user_agent_name.size()));
@@ -526,6 +646,29 @@ void AddNodeLogFields(const envoy_config_core_v3_Node* node,
     fields->emplace_back(
     fields->emplace_back(
         absl::StrCat("  build_version: \"", build_version, "\""));
         absl::StrCat("  build_version: \"", build_version, "\""));
   }
   }
+  // listening_addresses
+  size_t num_listening_addresses;
+  const envoy_config_core_v3_Address* const* listening_addresses =
+      envoy_config_core_v3_Node_listening_addresses(node,
+                                                    &num_listening_addresses);
+  for (size_t i = 0; i < num_listening_addresses; ++i) {
+    fields->emplace_back("  listening_address {");
+    const auto* socket_addr_msg =
+        envoy_config_core_v3_Address_socket_address(listening_addresses[i]);
+    if (socket_addr_msg != nullptr) {
+      fields->emplace_back("    socket_address {");
+      AddStringField(
+          "      address",
+          envoy_config_core_v3_SocketAddress_address(socket_addr_msg), fields);
+      if (envoy_config_core_v3_SocketAddress_has_port_value(socket_addr_msg)) {
+        fields->emplace_back(absl::StrCat(
+            "      port_value: ",
+            envoy_config_core_v3_SocketAddress_port_value(socket_addr_msg)));
+      }
+      fields->emplace_back("    }");
+    }
+    fields->emplace_back("  }");
+  }
   // user_agent_name
   // user_agent_name
   AddStringField("  user_agent_name",
   AddStringField("  user_agent_name",
                  envoy_config_core_v3_Node_user_agent_name(node), fields);
                  envoy_config_core_v3_Node_user_agent_name(node), fields);
@@ -628,7 +771,8 @@ grpc_slice XdsApi::CreateAdsRequest(
     const std::string& type_url,
     const std::string& type_url,
     const std::set<absl::string_view>& resource_names,
     const std::set<absl::string_view>& resource_names,
     const std::string& version, const std::string& nonce, grpc_error* error,
     const std::string& version, const std::string& nonce, grpc_error* error,
-    bool populate_node) {
+    bool populate_node,
+    const std::vector<grpc_resolved_address>& listening_addresses) {
   upb::Arena arena;
   upb::Arena arena;
   // Create a request.
   // Create a request.
   envoy_service_discovery_v3_DiscoveryRequest* request =
   envoy_service_discovery_v3_DiscoveryRequest* request =
@@ -669,7 +813,7 @@ grpc_slice XdsApi::CreateAdsRequest(
         envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
         envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
                                                                  arena.ptr());
                                                                  arena.ptr());
     PopulateNode(arena.ptr(), bootstrap_, build_version_, user_agent_name_, "",
     PopulateNode(arena.ptr(), bootstrap_, build_version_, user_agent_name_, "",
-                 node_msg);
+                 listening_addresses, node_msg);
   }
   }
   // Add resource_names.
   // Add resource_names.
   for (const auto& resource_name : resource_names) {
   for (const auto& resource_name : resource_names) {
@@ -2095,7 +2239,7 @@ grpc_slice XdsApi::CreateLrsInitialRequest(const std::string& server_name) {
       envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
       envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
                                                                 arena.ptr());
                                                                 arena.ptr());
   PopulateNode(arena.ptr(), bootstrap_, build_version_, user_agent_name_,
   PopulateNode(arena.ptr(), bootstrap_, build_version_, user_agent_name_,
-               server_name, node_msg);
+               server_name, {}, node_msg);
   envoy_config_core_v3_Node_add_client_features(
   envoy_config_core_v3_Node_add_client_features(
       node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
       node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
       arena.ptr());
       arena.ptr());

+ 23 - 25
src/core/ext/xds/xds_api.h

@@ -61,19 +61,14 @@ class XdsApi {
           PathMatcherType type;
           PathMatcherType type;
           std::string string_matcher;
           std::string string_matcher;
           std::unique_ptr<RE2> regex_matcher;
           std::unique_ptr<RE2> regex_matcher;
-          bool operator==(const PathMatcher& other) const {
-            if (type != other.type) return false;
-            if (type == PathMatcherType::REGEX) {
-              // Should never be null.
-              if (regex_matcher == nullptr || other.regex_matcher == nullptr) {
-                return false;
-              }
-              return regex_matcher->pattern() == other.regex_matcher->pattern();
-            }
-            return string_matcher == other.string_matcher;
-          }
+
+          PathMatcher() = default;
+          PathMatcher(const PathMatcher& other);
+          PathMatcher& operator=(const PathMatcher& other);
+          bool operator==(const PathMatcher& other) const;
           std::string ToString() const;
           std::string ToString() const;
         };
         };
+
         struct HeaderMatcher {
         struct HeaderMatcher {
           enum class HeaderMatcherType {
           enum class HeaderMatcherType {
             EXACT,    // value stored in string_matcher field
             EXACT,    // value stored in string_matcher field
@@ -93,19 +88,18 @@ class XdsApi {
           // invert_match field may or may not exisit, so initialize it to
           // invert_match field may or may not exisit, so initialize it to
           // false.
           // false.
           bool invert_match = false;
           bool invert_match = false;
-          bool operator==(const HeaderMatcher& other) const {
-            return (name == other.name && type == other.type &&
-                    range_start == other.range_start &&
-                    range_end == other.range_end &&
-                    string_matcher == other.string_matcher &&
-                    present_match == other.present_match &&
-                    invert_match == other.invert_match);
-          }
+
+          HeaderMatcher() = default;
+          HeaderMatcher(const HeaderMatcher& other);
+          HeaderMatcher& operator=(const HeaderMatcher& other);
+          bool operator==(const HeaderMatcher& other) const;
           std::string ToString() const;
           std::string ToString() const;
         };
         };
+
         PathMatcher path_matcher;
         PathMatcher path_matcher;
         std::vector<HeaderMatcher> header_matchers;
         std::vector<HeaderMatcher> header_matchers;
         absl::optional<uint32_t> fraction_per_million;
         absl::optional<uint32_t> fraction_per_million;
+
         bool operator==(const Matchers& other) const {
         bool operator==(const Matchers& other) const {
           return (path_matcher == other.path_matcher &&
           return (path_matcher == other.path_matcher &&
                   header_matchers == other.header_matchers &&
                   header_matchers == other.header_matchers &&
@@ -113,13 +107,16 @@ class XdsApi {
         }
         }
         std::string ToString() const;
         std::string ToString() const;
       };
       };
+
       Matchers matchers;
       Matchers matchers;
+
       // Action for this route.
       // Action for this route.
+      // TODO(roth): When we can use absl::variant<>, consider using that
+      // here, to enforce the fact that only one of the two fields can be set.
       std::string cluster_name;
       std::string cluster_name;
       struct ClusterWeight {
       struct ClusterWeight {
         std::string name;
         std::string name;
         uint32_t weight;
         uint32_t weight;
-
         bool operator==(const ClusterWeight& other) const {
         bool operator==(const ClusterWeight& other) const {
           return (name == other.name && weight == other.weight);
           return (name == other.name && weight == other.weight);
         }
         }
@@ -298,11 +295,12 @@ class XdsApi {
 
 
   // Creates an ADS request.
   // Creates an ADS request.
   // Takes ownership of \a error.
   // Takes ownership of \a error.
-  grpc_slice CreateAdsRequest(const std::string& type_url,
-                              const std::set<absl::string_view>& resource_names,
-                              const std::string& version,
-                              const std::string& nonce, grpc_error* error,
-                              bool populate_node);
+  grpc_slice CreateAdsRequest(
+      const std::string& type_url,
+      const std::set<absl::string_view>& resource_names,
+      const std::string& version, const std::string& nonce, grpc_error* error,
+      bool populate_node,
+      const std::vector<grpc_resolved_address>& listening_addresses);
 
 
   // Parses an ADS response.
   // Parses an ADS response.
   // If the response can't be parsed at the top level, the resulting
   // If the response can't be parsed at the top level, the resulting

+ 19 - 347
src/core/ext/xds/xds_client.cc

@@ -187,8 +187,7 @@ class XdsClient::ChannelState::AdsCallState
         }
         }
         if (type_url_ == XdsApi::kLdsTypeUrl ||
         if (type_url_ == XdsApi::kLdsTypeUrl ||
             type_url_ == XdsApi::kRdsTypeUrl) {
             type_url_ == XdsApi::kRdsTypeUrl) {
-          ads_calld_->xds_client()->service_config_watcher_->OnError(
-              watcher_error);
+          ads_calld_->xds_client()->listener_watcher_->OnError(watcher_error);
         } else if (type_url_ == XdsApi::kCdsTypeUrl) {
         } else if (type_url_ == XdsApi::kCdsTypeUrl) {
           ClusterState& state = ads_calld_->xds_client()->cluster_map_[name_];
           ClusterState& state = ads_calld_->xds_client()->cluster_map_[name_];
           for (const auto& p : state.watchers) {
           for (const auto& p : state.watchers) {
@@ -680,7 +679,6 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
   // activity in xds_client()->interested_parties_, which is comprised of
   // activity in xds_client()->interested_parties_, which is comprised of
   // the polling entities from client_channel.
   // the polling entities from client_channel.
   GPR_ASSERT(xds_client() != nullptr);
   GPR_ASSERT(xds_client() != nullptr);
-  GPR_ASSERT(!xds_client()->server_name_.empty());
   // Create a call with the specified method name.
   // Create a call with the specified method name.
   const auto& method =
   const auto& method =
       xds_client()->bootstrap_->server().ShouldUseV3()
       xds_client()->bootstrap_->server().ShouldUseV3()
@@ -719,7 +717,7 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
   // Op: send request message.
   // Op: send request message.
   GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this,
   GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this,
                     grpc_schedule_on_exec_ctx);
                     grpc_schedule_on_exec_ctx);
-  if (xds_client()->service_config_watcher_ != nullptr) {
+  if (xds_client()->listener_watcher_ != nullptr) {
     Subscribe(XdsApi::kLdsTypeUrl, xds_client()->server_name_);
     Subscribe(XdsApi::kLdsTypeUrl, xds_client()->server_name_);
     if (xds_client()->lds_result_.has_value() &&
     if (xds_client()->lds_result_.has_value() &&
         !xds_client()->lds_result_->route_config_name.empty()) {
         !xds_client()->lds_result_->route_config_name.empty()) {
@@ -807,7 +805,8 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
       ResourceNamesForRequest(type_url);
       ResourceNamesForRequest(type_url);
   request_payload_slice = xds_client()->api_.CreateAdsRequest(
   request_payload_slice = xds_client()->api_.CreateAdsRequest(
       type_url, resource_names, state.version, state.nonce,
       type_url, resource_names, state.version, state.nonce,
-      GRPC_ERROR_REF(state.error), !sent_initial_message_);
+      GRPC_ERROR_REF(state.error), !sent_initial_message_,
+      xds_client()->listening_addresses_);
   if (type_url != XdsApi::kLdsTypeUrl && type_url != XdsApi::kRdsTypeUrl &&
   if (type_url != XdsApi::kLdsTypeUrl && type_url != XdsApi::kRdsTypeUrl &&
       type_url != XdsApi::kCdsTypeUrl && type_url != XdsApi::kEdsTypeUrl) {
       type_url != XdsApi::kCdsTypeUrl && type_url != XdsApi::kEdsTypeUrl) {
     state_map_.erase(type_url);
     state_map_.erase(type_url);
@@ -882,7 +881,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate(
       xds_client()->rds_result_.reset();
       xds_client()->rds_result_.reset();
     }
     }
     xds_client()->lds_result_.reset();
     xds_client()->lds_result_.reset();
-    xds_client()->service_config_watcher_->OnResourceDoesNotExist();
+    xds_client()->listener_watcher_->OnResourceDoesNotExist();
     return;
     return;
   }
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@@ -925,15 +924,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate(
   if (xds_client()->lds_result_->rds_update.has_value()) {
   if (xds_client()->lds_result_->rds_update.has_value()) {
     // If the RouteConfiguration was found inlined in LDS response, notify
     // If the RouteConfiguration was found inlined in LDS response, notify
     // the watcher immediately.
     // the watcher immediately.
-    RefCountedPtr<ServiceConfig> service_config;
-    grpc_error* error = xds_client()->CreateServiceConfig(
-        xds_client()->lds_result_->rds_update.value(), &service_config);
-    if (error == GRPC_ERROR_NONE) {
-      xds_client()->service_config_watcher_->OnServiceConfigChanged(
-          std::move(service_config));
-    } else {
-      xds_client()->service_config_watcher_->OnError(error);
-    }
+    xds_client()->listener_watcher_->OnListenerChanged(
+        *xds_client()->lds_result_);
   } else {
   } else {
     // Send RDS request for dynamic resolution.
     // Send RDS request for dynamic resolution.
     Subscribe(XdsApi::kRdsTypeUrl,
     Subscribe(XdsApi::kRdsTypeUrl,
@@ -948,7 +940,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate(
             "[xds_client %p] RDS update does not include requested resource",
             "[xds_client %p] RDS update does not include requested resource",
             xds_client());
             xds_client());
     xds_client()->rds_result_.reset();
     xds_client()->rds_result_.reset();
-    xds_client()->service_config_watcher_->OnResourceDoesNotExist();
+    xds_client()->listener_watcher_->OnResourceDoesNotExist();
     return;
     return;
   }
   }
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@@ -977,15 +969,9 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate(
   }
   }
   xds_client()->rds_result_ = std::move(rds_update);
   xds_client()->rds_result_ = std::move(rds_update);
   // Notify the watcher.
   // Notify the watcher.
-  RefCountedPtr<ServiceConfig> service_config;
-  grpc_error* error = xds_client()->CreateServiceConfig(
-      xds_client()->rds_result_.value(), &service_config);
-  if (error == GRPC_ERROR_NONE) {
-    xds_client()->service_config_watcher_->OnServiceConfigChanged(
-        std::move(service_config));
-  } else {
-    xds_client()->service_config_watcher_->OnError(error);
-  }
+  XdsApi::LdsUpdate lds_result = *xds_client()->lds_result_;
+  lds_result.rds_update = xds_client()->rds_result_;
+  xds_client()->listener_watcher_->OnListenerChanged(lds_result);
 }
 }
 
 
 void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
 void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate(
@@ -1759,7 +1745,8 @@ grpc_millis GetRequestTimeout(const grpc_channel_args& args) {
 XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
 XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
                      grpc_pollset_set* interested_parties,
                      grpc_pollset_set* interested_parties,
                      absl::string_view server_name,
                      absl::string_view server_name,
-                     std::unique_ptr<ServiceConfigWatcherInterface> watcher,
+                     std::vector<grpc_resolved_address> listening_addresses,
+                     std::unique_ptr<ListenerWatcherInterface> watcher,
                      const grpc_channel_args& channel_args, grpc_error** error)
                      const grpc_channel_args& channel_args, grpc_error** error)
     : InternallyRefCounted<XdsClient>(&grpc_xds_client_trace),
     : InternallyRefCounted<XdsClient>(&grpc_xds_client_trace),
       request_timeout_(GetRequestTimeout(channel_args)),
       request_timeout_(GetRequestTimeout(channel_args)),
@@ -1769,7 +1756,8 @@ XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
           XdsBootstrap::ReadFromFile(this, &grpc_xds_client_trace, error)),
           XdsBootstrap::ReadFromFile(this, &grpc_xds_client_trace, error)),
       api_(this, &grpc_xds_client_trace, bootstrap_.get()),
       api_(this, &grpc_xds_client_trace, bootstrap_.get()),
       server_name_(server_name),
       server_name_(server_name),
-      service_config_watcher_(std::move(watcher)) {
+      listening_addresses_(std::move(listening_addresses)),
+      listener_watcher_(std::move(watcher)) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
     gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this);
     gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this);
   }
   }
@@ -1792,7 +1780,7 @@ XdsClient::XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
   }
   }
   chand_ = MakeOrphanable<ChannelState>(
   chand_ = MakeOrphanable<ChannelState>(
       Ref(DEBUG_LOCATION, "XdsClient+ChannelState"), channel);
       Ref(DEBUG_LOCATION, "XdsClient+ChannelState"), channel);
-  if (service_config_watcher_ != nullptr) {
+  if (listener_watcher_ != nullptr) {
     chand_->Subscribe(XdsApi::kLdsTypeUrl, std::string(server_name));
     chand_->Subscribe(XdsApi::kLdsTypeUrl, std::string(server_name));
   }
   }
 }
 }
@@ -1815,7 +1803,7 @@ void XdsClient::Orphan() {
   // possible for ADS calls to be in progress. Unreffing the loadbalancing
   // possible for ADS calls to be in progress. Unreffing the loadbalancing
   // policies before those calls are done would lead to issues such as
   // policies before those calls are done would lead to issues such as
   // https://github.com/grpc/grpc/issues/20928.
   // https://github.com/grpc/grpc/issues/20928.
-  if (service_config_watcher_ != nullptr) {
+  if (listener_watcher_ != nullptr) {
     cluster_map_.clear();
     cluster_map_.clear();
     endpoint_map_.clear();
     endpoint_map_.clear();
   }
   }
@@ -1990,322 +1978,6 @@ void XdsClient::ResetBackoff() {
   }
   }
 }
 }
 
 
-namespace {
-std::string CreateServiceConfigActionCluster(const std::string& cluster_name) {
-  return absl::StrFormat(
-      "      \"cds:%s\":{\n"
-      "        \"childPolicy\":[ {\n"
-      "          \"cds_experimental\":{\n"
-      "            \"cluster\": \"%s\"\n"
-      "          }\n"
-      "        } ]\n"
-      "       }",
-      cluster_name, cluster_name);
-}
-
-std::string CreateServiceConfigRoute(const std::string& action_name,
-                                     const XdsApi::RdsUpdate::RdsRoute& route) {
-  std::vector<std::string> headers;
-  for (const auto& header : route.matchers.header_matchers) {
-    std::string header_matcher;
-    switch (header.type) {
-      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
-          HeaderMatcherType::EXACT:
-        header_matcher = absl::StrFormat("             \"exact_match\": \"%s\"",
-                                         header.string_matcher);
-        break;
-      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
-          HeaderMatcherType::REGEX:
-        header_matcher = absl::StrFormat("             \"regex_match\": \"%s\"",
-                                         header.regex_match->pattern());
-        break;
-      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
-          HeaderMatcherType::RANGE:
-        header_matcher = absl::StrFormat(
-            "             \"range_match\":{\n"
-            "              \"start\":%d,\n"
-            "              \"end\":%d\n"
-            "             }",
-            header.range_start, header.range_end);
-        break;
-      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
-          HeaderMatcherType::PRESENT:
-        header_matcher =
-            absl::StrFormat("             \"present_match\": %s",
-                            header.present_match ? "true" : "false");
-        break;
-      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
-          HeaderMatcherType::PREFIX:
-        header_matcher = absl::StrFormat(
-            "             \"prefix_match\": \"%s\"", header.string_matcher);
-        break;
-      case XdsApi::RdsUpdate::RdsRoute::Matchers::HeaderMatcher::
-          HeaderMatcherType::SUFFIX:
-        header_matcher = absl::StrFormat(
-            "             \"suffix_match\": \"%s\"", header.string_matcher);
-        break;
-      default:
-        break;
-    }
-    std::vector<std::string> header_parts;
-    header_parts.push_back(
-        absl::StrFormat("           { \n"
-                        "             \"name\": \"%s\",\n",
-                        header.name));
-    header_parts.push_back(header_matcher);
-    if (header.invert_match) {
-      header_parts.push_back(
-          absl::StrFormat(",\n"
-                          "             \"invert_match\": true"));
-    }
-    header_parts.push_back(
-        absl::StrFormat("\n"
-                        "           }"));
-    headers.push_back(absl::StrJoin(header_parts, ""));
-  }
-  std::vector<std::string> headers_service_config;
-  if (!headers.empty()) {
-    headers_service_config.push_back("\"headers\":[\n");
-    headers_service_config.push_back(absl::StrJoin(headers, ","));
-    headers_service_config.push_back("           ],\n");
-  }
-  std::string path_match_str;
-  switch (route.matchers.path_matcher.type) {
-    case XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcherType::
-        PREFIX:
-      path_match_str = absl::StrFormat(
-          "\"prefix\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
-      break;
-    case XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcherType::
-        PATH:
-      path_match_str = absl::StrFormat(
-          "\"path\": \"%s\",\n", route.matchers.path_matcher.string_matcher);
-      break;
-    case XdsApi::RdsUpdate::RdsRoute::Matchers::PathMatcher::PathMatcherType::
-        REGEX:
-      path_match_str =
-          absl::StrFormat("\"regex\": \"%s\",\n",
-                          route.matchers.path_matcher.regex_matcher->pattern());
-      break;
-  }
-  return absl::StrFormat(
-      "      { \n"
-      "           %s"
-      "           %s"
-      "           %s"
-      "           \"action\": \"%s\"\n"
-      "      }",
-      path_match_str, absl::StrJoin(headers_service_config, ""),
-      route.matchers.fraction_per_million.has_value()
-          ? absl::StrFormat("\"match_fraction\":%d,\n",
-                            route.matchers.fraction_per_million.value())
-          : "",
-      action_name);
-}
-
-// Create the service config for one weighted cluster.
-std::string CreateServiceConfigActionWeightedCluster(
-    const std::string& name,
-    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>& clusters) {
-  std::vector<std::string> config_parts;
-  config_parts.push_back(
-      absl::StrFormat("      \"weighted:%s\":{\n"
-                      "        \"childPolicy\":[ {\n"
-                      "          \"weighted_target_experimental\":{\n"
-                      "            \"targets\":{\n",
-                      name));
-  std::vector<std::string> weighted_targets;
-  weighted_targets.reserve(clusters.size());
-  for (const auto& cluster_weight : clusters) {
-    weighted_targets.push_back(absl::StrFormat(
-        "              \"%s\":{\n"
-        "                \"weight\":%d,\n"
-        "                \"childPolicy\":[ {\n"
-        "                  \"cds_experimental\":{\n"
-        "                    \"cluster\": \"%s\"\n"
-        "                  }\n"
-        "                } ]\n"
-        "               }",
-        cluster_weight.name, cluster_weight.weight, cluster_weight.name));
-  }
-  config_parts.push_back(absl::StrJoin(weighted_targets, ",\n"));
-  config_parts.push_back(
-      "            }\n"
-      "          }\n"
-      "        } ]\n"
-      "       }");
-  return absl::StrJoin(config_parts, "");
-}
-
-struct WeightedClustersKeys {
-  std::string cluster_names_key;
-  std::string cluster_weights_key;
-};
-
-// Returns the cluster names and weights key or the cluster names only key.
-WeightedClustersKeys GetWeightedClustersKey(
-    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
-        weighted_clusters) {
-  std::set<std::string> cluster_names;
-  std::set<std::string> cluster_weights;
-  for (const auto& cluster_weight : weighted_clusters) {
-    cluster_names.emplace(absl::StrFormat("%s", cluster_weight.name));
-    cluster_weights.emplace(
-        absl::StrFormat("%s_%d", cluster_weight.name, cluster_weight.weight));
-  }
-  return {absl::StrJoin(cluster_names, "_"),
-          absl::StrJoin(cluster_weights, "_")};
-}
-
-}  // namespace
-
-std::string XdsClient::WeightedClustersActionName(
-    const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
-        weighted_clusters) {
-  WeightedClustersKeys keys = GetWeightedClustersKey(weighted_clusters);
-  auto cluster_names_map_it =
-      weighted_cluster_index_map_.find(keys.cluster_names_key);
-  GPR_ASSERT(cluster_names_map_it != weighted_cluster_index_map_.end());
-  const auto& cluster_weights_map =
-      cluster_names_map_it->second.cluster_weights_map;
-  auto cluster_weights_map_it =
-      cluster_weights_map.find(keys.cluster_weights_key);
-  GPR_ASSERT(cluster_weights_map_it != cluster_weights_map.end());
-  return absl::StrFormat("%s_%d", keys.cluster_names_key,
-                         cluster_weights_map_it->second);
-}
-
-void XdsClient::UpdateWeightedClusterIndexMap(
-    const XdsApi::RdsUpdate& rds_update) {
-  // Construct a list of unique WeightedCluster
-  // actions which we need to process: to find action names
-  std::map<std::string /* cluster_weights_key */,
-           std::string /* cluster_names_key */>
-      actions_to_process;
-  for (const auto& route : rds_update.routes) {
-    if (!route.weighted_clusters.empty()) {
-      WeightedClustersKeys keys =
-          GetWeightedClustersKey(route.weighted_clusters);
-      auto action_it = actions_to_process.find(keys.cluster_weights_key);
-      if (action_it == actions_to_process.end()) {
-        actions_to_process[std::move(keys.cluster_weights_key)] =
-            std::move(keys.cluster_names_key);
-      }
-    }
-  }
-  // First pass of all unique WeightedCluster actions: if the exact same
-  // weighted target policy (same clusters and weights) appears in the old map,
-  // then that old action name is taken again and should be moved to the new
-  // map; any other action names from the old set of actions are candidates for
-  // reuse.
-  XdsClient::WeightedClusterIndexMap new_weighted_cluster_index_map;
-  for (auto action_it = actions_to_process.begin();
-       action_it != actions_to_process.end();) {
-    const std::string& cluster_names_key = action_it->second;
-    const std::string& cluster_weights_key = action_it->first;
-    auto old_cluster_names_map_it =
-        weighted_cluster_index_map_.find(cluster_names_key);
-    if (old_cluster_names_map_it != weighted_cluster_index_map_.end()) {
-      // Add cluster_names_key to the new map and copy next_index.
-      auto& new_cluster_names_info =
-          new_weighted_cluster_index_map[cluster_names_key];
-      new_cluster_names_info.next_index =
-          old_cluster_names_map_it->second.next_index;
-      // Lookup cluster_weights_key in old map.
-      auto& old_cluster_weights_map =
-          old_cluster_names_map_it->second.cluster_weights_map;
-      auto old_cluster_weights_map_it =
-          old_cluster_weights_map.find(cluster_weights_key);
-      if (old_cluster_weights_map_it != old_cluster_weights_map.end()) {
-        // same policy found, move from old map to new map.
-        new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
-            old_cluster_weights_map_it->second;
-        old_cluster_weights_map.erase(old_cluster_weights_map_it);
-        // This action has been added to new map, so no need to process it
-        // again.
-        action_it = actions_to_process.erase(action_it);
-        continue;
-      }
-    }
-    ++action_it;
-  }
-  // Second pass of all remaining unique WeightedCluster actions: if clusters
-  // for a new action are the same as an old unused action, reuse the name.  If
-  // clusters differ, use a brand new name.
-  for (const auto& action : actions_to_process) {
-    const std::string& cluster_names_key = action.second;
-    const std::string& cluster_weights_key = action.first;
-    auto& new_cluster_names_info =
-        new_weighted_cluster_index_map[cluster_names_key];
-    auto& old_cluster_weights_map =
-        weighted_cluster_index_map_[cluster_names_key].cluster_weights_map;
-    auto old_cluster_weights_it = old_cluster_weights_map.begin();
-    if (old_cluster_weights_it != old_cluster_weights_map.end()) {
-      // There is something to reuse: this action uses the same set
-      // of clusters as a previous action and that action name is not
-      // already taken.
-      new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
-          old_cluster_weights_it->second;
-      // Remove the name from being able to reuse again.
-      old_cluster_weights_map.erase(old_cluster_weights_it);
-    } else {
-      // There is nothing to reuse, take the next index to use and
-      // increment.
-      new_cluster_names_info.cluster_weights_map[cluster_weights_key] =
-          new_cluster_names_info.next_index++;
-    }
-  }
-  weighted_cluster_index_map_ = std::move(new_weighted_cluster_index_map);
-}
-
-grpc_error* XdsClient::CreateServiceConfig(
-    const XdsApi::RdsUpdate& rds_update,
-    RefCountedPtr<ServiceConfig>* service_config) {
-  UpdateWeightedClusterIndexMap(rds_update);
-  std::vector<std::string> actions_vector;
-  std::vector<std::string> route_table;
-  std::set<std::string> actions_set;
-  for (const auto& route : rds_update.routes) {
-    const std::string action_name =
-        route.weighted_clusters.empty()
-            ? route.cluster_name
-            : WeightedClustersActionName(route.weighted_clusters);
-    if (actions_set.find(action_name) == actions_set.end()) {
-      actions_set.emplace(action_name);
-      actions_vector.push_back(
-          route.weighted_clusters.empty()
-              ? CreateServiceConfigActionCluster(action_name)
-              : CreateServiceConfigActionWeightedCluster(
-                    action_name, route.weighted_clusters));
-    }
-    route_table.push_back(CreateServiceConfigRoute(
-        absl::StrFormat("%s:%s",
-                        route.weighted_clusters.empty() ? "cds" : "weighted",
-                        action_name),
-        route));
-  }
-  std::vector<std::string> config_parts;
-  config_parts.push_back(
-      "{\n"
-      "  \"loadBalancingConfig\":[\n"
-      "    { \"xds_routing_experimental\":{\n"
-      "      \"actions\":{\n");
-  config_parts.push_back(absl::StrJoin(actions_vector, ",\n"));
-  config_parts.push_back(
-      "    },\n"
-      "      \"routes\":[\n");
-  config_parts.push_back(absl::StrJoin(route_table, ",\n"));
-  config_parts.push_back(
-      "    ]\n"
-      "    } }\n"
-      "  ]\n"
-      "}");
-  std::string json = absl::StrJoin(config_parts, "");
-  grpc_error* error = GRPC_ERROR_NONE;
-  *service_config = ServiceConfig::Create(json.c_str(), &error);
-  return error;
-}
-
 XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
 XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
     bool send_all_clusters, const std::set<std::string>& clusters) {
     bool send_all_clusters, const std::set<std::string>& clusters) {
   XdsApi::ClusterLoadReportMap snapshot_map;
   XdsApi::ClusterLoadReportMap snapshot_map;
@@ -2375,8 +2047,8 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshot(
 }
 }
 
 
 void XdsClient::NotifyOnError(grpc_error* error) {
 void XdsClient::NotifyOnError(grpc_error* error) {
-  if (service_config_watcher_ != nullptr) {
-    service_config_watcher_->OnError(GRPC_ERROR_REF(error));
+  if (listener_watcher_ != nullptr) {
+    listener_watcher_->OnError(GRPC_ERROR_REF(error));
   }
   }
   for (const auto& p : cluster_map_) {
   for (const auto& p : cluster_map_) {
     const ClusterState& cluster_state = p.second;
     const ClusterState& cluster_state = p.second;

+ 12 - 39
src/core/ext/xds/xds_client.h

@@ -20,11 +20,11 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/port_platform.h>
 
 
 #include <set>
 #include <set>
+#include <vector>
 
 
 #include "absl/strings/string_view.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 #include "absl/types/optional.h"
 
 
-#include "src/core/ext/filters/client_channel/service_config.h"
 #include "src/core/ext/xds/xds_api.h"
 #include "src/core/ext/xds/xds_api.h"
 #include "src/core/ext/xds/xds_bootstrap.h"
 #include "src/core/ext/xds/xds_bootstrap.h"
 #include "src/core/ext/xds/xds_client_stats.h"
 #include "src/core/ext/xds/xds_client_stats.h"
@@ -33,6 +33,7 @@
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/orphanable.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/work_serializer.h"
 #include "src/core/lib/iomgr/work_serializer.h"
 
 
 namespace grpc_core {
 namespace grpc_core {
@@ -41,13 +42,12 @@ extern TraceFlag xds_client_trace;
 
 
 class XdsClient : public InternallyRefCounted<XdsClient> {
 class XdsClient : public InternallyRefCounted<XdsClient> {
  public:
  public:
-  // Service config watcher interface.  Implemented by callers.
-  class ServiceConfigWatcherInterface {
+  // Listener data watcher interface.  Implemented by callers.
+  class ListenerWatcherInterface {
    public:
    public:
-    virtual ~ServiceConfigWatcherInterface() = default;
+    virtual ~ListenerWatcherInterface() = default;
 
 
-    virtual void OnServiceConfigChanged(
-        RefCountedPtr<ServiceConfig> service_config) = 0;
+    virtual void OnListenerChanged(XdsApi::LdsUpdate listener_data) = 0;
 
 
     virtual void OnError(grpc_error* error) = 0;
     virtual void OnError(grpc_error* error) = 0;
 
 
@@ -78,11 +78,14 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
     virtual void OnResourceDoesNotExist() = 0;
     virtual void OnResourceDoesNotExist() = 0;
   };
   };
 
 
+  // gRPC client should populate server_name.
+  // gRPC server should populate listening_addresses.
   // If *error is not GRPC_ERROR_NONE after construction, then there was
   // If *error is not GRPC_ERROR_NONE after construction, then there was
   // an error initializing the client.
   // an error initializing the client.
   XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
   XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
             grpc_pollset_set* interested_parties, absl::string_view server_name,
             grpc_pollset_set* interested_parties, absl::string_view server_name,
-            std::unique_ptr<ServiceConfigWatcherInterface> watcher,
+            std::vector<grpc_resolved_address> listening_addresses,
+            std::unique_ptr<ListenerWatcherInterface> watcher,
             const grpc_channel_args& channel_args, grpc_error** error);
             const grpc_channel_args& channel_args, grpc_error** error);
   ~XdsClient();
   ~XdsClient();
 
 
@@ -234,20 +237,6 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
   // Sends an error notification to all watchers.
   // Sends an error notification to all watchers.
   void NotifyOnError(grpc_error* error);
   void NotifyOnError(grpc_error* error);
 
 
-  // Returns the weighted_clusters action name to use from
-  // weighted_cluster_index_map_ for a WeightedClusters route action.
-  std::string WeightedClustersActionName(
-      const std::vector<XdsApi::RdsUpdate::RdsRoute::ClusterWeight>&
-          weighted_clusters);
-
-  // Updates weighted_cluster_index_map_ that will
-  // determine the names of the WeightedCluster actions for the current update.
-  void UpdateWeightedClusterIndexMap(const XdsApi::RdsUpdate& rds_update);
-
-  // Create the service config generated by the RdsUpdate.
-  grpc_error* CreateServiceConfig(const XdsApi::RdsUpdate& rds_update,
-                                  RefCountedPtr<ServiceConfig>* service_config);
-
   XdsApi::ClusterLoadReportMap BuildLoadReportSnapshot(
   XdsApi::ClusterLoadReportMap BuildLoadReportSnapshot(
       bool send_all_clusters, const std::set<std::string>& clusters);
       bool send_all_clusters, const std::set<std::string>& clusters);
 
 
@@ -267,8 +256,8 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
   XdsApi api_;
   XdsApi api_;
 
 
   const std::string server_name_;
   const std::string server_name_;
-
-  std::unique_ptr<ServiceConfigWatcherInterface> service_config_watcher_;
+  const std::vector<grpc_resolved_address> listening_addresses_;
+  std::unique_ptr<ListenerWatcherInterface> listener_watcher_;
 
 
   // The channel for communicating with the xds server.
   // The channel for communicating with the xds server.
   OrphanablePtr<ChannelState> chand_;
   OrphanablePtr<ChannelState> chand_;
@@ -285,22 +274,6 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
       LoadReportState>
       LoadReportState>
       load_report_map_;
       load_report_map_;
 
 
-  // 2-level map to store WeightedCluster action names.
-  // Top level map is keyed by cluster names without weight like a_b_c; bottom
-  // level map is keyed by cluster names + weights like a10_b50_c40.
-  struct ClusterNamesInfo {
-    uint64_t next_index = 0;
-    std::map<std::string /*cluster names + weights*/,
-             uint64_t /*policy index number*/>
-        cluster_weights_map;
-  };
-  using WeightedClusterIndexMap =
-      std::map<std::string /*cluster names*/, ClusterNamesInfo>;
-
-  // Cache of action names for WeightedCluster targets in the current
-  // service config.
-  WeightedClusterIndexMap weighted_cluster_index_map_;
-
   bool shutting_down_ = false;
   bool shutting_down_ = false;
 };
 };
 
 

+ 98 - 0
src/core/lib/security/authorization/evaluate_args.cc

@@ -0,0 +1,98 @@
+//
+//
+// Copyright 2020 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/security/authorization/evaluate_args.h"
+
+#include "src/core/lib/slice/slice_utils.h"
+
+namespace grpc_core {
+
+absl::string_view EvaluateArgs::GetPath() const {
+  absl::string_view path;
+  if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) {
+    grpc_linked_mdelem* elem = metadata_->idx.named.path;
+    const grpc_slice& val = GRPC_MDVALUE(elem->md);
+    path = StringViewFromSlice(val);
+  }
+  return path;
+}
+
+absl::string_view EvaluateArgs::GetHost() const {
+  absl::string_view host;
+  if (metadata_ != nullptr && metadata_->idx.named.host != nullptr) {
+    grpc_linked_mdelem* elem = metadata_->idx.named.host;
+    const grpc_slice& val = GRPC_MDVALUE(elem->md);
+    host = StringViewFromSlice(val);
+  }
+  return host;
+}
+
+absl::string_view EvaluateArgs::GetMethod() const {
+  absl::string_view method;
+  if (metadata_ != nullptr && metadata_->idx.named.method != nullptr) {
+    grpc_linked_mdelem* elem = metadata_->idx.named.method;
+    const grpc_slice& val = GRPC_MDVALUE(elem->md);
+    method = StringViewFromSlice(val);
+  }
+  return method;
+}
+
+std::multimap<absl::string_view, absl::string_view> EvaluateArgs::GetHeaders()
+    const {
+  std::multimap<absl::string_view, absl::string_view> headers;
+  if (metadata_ == nullptr) {
+    return headers;
+  }
+  for (grpc_linked_mdelem* elem = metadata_->list.head; elem != nullptr;
+       elem = elem->next) {
+    const grpc_slice& key = GRPC_MDKEY(elem->md);
+    const grpc_slice& val = GRPC_MDVALUE(elem->md);
+    headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val));
+  }
+  return headers;
+}
+
+absl::string_view EvaluateArgs::GetSpiffeId() const {
+  if (auth_context_ == nullptr) {
+    return "";
+  }
+  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
+      auth_context_, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
+  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
+  if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr) {
+    return "";
+  }
+  return absl::string_view(prop->value, prop->value_length);
+}
+
+absl::string_view EvaluateArgs::GetCertServerName() const {
+  if (auth_context_ == nullptr) {
+    return "";
+  }
+  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
+      auth_context_, GRPC_X509_CN_PROPERTY_NAME);
+  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
+  if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr) {
+    return "";
+  }
+  return absl::string_view(prop->value, prop->value_length);
+}
+
+}  // namespace grpc_core

+ 54 - 0
src/core/lib/security/authorization/evaluate_args.h

@@ -0,0 +1,54 @@
+//
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_EVALUATE_ARGS_H
+#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_EVALUATE_ARGS_H
+
+#include <grpc/support/port_platform.h>
+
+#include <map>
+
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+namespace grpc_core {
+
+class EvaluateArgs {
+ public:
+  EvaluateArgs(grpc_metadata_batch* metadata, grpc_auth_context* auth_context,
+               grpc_endpoint* endpoint);
+
+  absl::string_view GetPath() const;
+  absl::string_view GetHost() const;
+  absl::string_view GetMethod() const;
+  std::multimap<absl::string_view, absl::string_view> GetHeaders() const;
+  absl::string_view GetSpiffeId() const;
+  absl::string_view GetCertServerName() const;
+
+  // TODO: Add a getter function for source.principal
+
+ private:
+  grpc_metadata_batch* metadata_;
+  grpc_auth_context* auth_context_;
+  grpc_endpoint* endpoint_;
+};
+
+}  // namespace grpc_core
+
+#endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_EVALUATE_ARGS_H

+ 4 - 8
src/core/lib/security/authorization/mock_cel/activation.h

@@ -21,10 +21,8 @@
 
 
 #include "src/core/lib/security/authorization/mock_cel/cel_value.h"
 #include "src/core/lib/security/authorization/mock_cel/cel_value.h"
 
 
-namespace google {
-namespace api {
-namespace expr {
-namespace runtime {
+namespace grpc_core {
+namespace mock_cel {
 
 
 // Base class for an activation. This is a temporary stub implementation of CEL
 // Base class for an activation. This is a temporary stub implementation of CEL
 // APIs. Once gRPC imports the CEL library, this class will be removed.
 // APIs. Once gRPC imports the CEL library, this class will be removed.
@@ -53,9 +51,7 @@ class Activation : public BaseActivation {
   void InsertValue(absl::string_view name, const CelValue& value) {}
   void InsertValue(absl::string_view name, const CelValue& value) {}
 };
 };
 
 
-}  // namespace runtime
-}  // namespace expr
-}  // namespace api
-}  // namespace google
+}  // namespace mock_cel
+}  // namespace grpc_core
 
 
 #endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MOCK_CEL_ACTIVATION_H
 #endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MOCK_CEL_ACTIVATION_H

+ 4 - 8
src/core/lib/security/authorization/mock_cel/cel_value.h

@@ -34,10 +34,8 @@
 
 
 #include "absl/strings/string_view.h"
 #include "absl/strings/string_view.h"
 
 
-namespace google {
-namespace api {
-namespace expr {
-namespace runtime {
+namespace grpc_core {
+namespace mock_cel {
 
 
 // Break cyclic depdendencies for container types.
 // Break cyclic depdendencies for container types.
 class CelMap;
 class CelMap;
@@ -75,9 +73,7 @@ class CelValue {
   explicit CelValue(T value) {}
   explicit CelValue(T value) {}
 };
 };
 
 
-}  // namespace runtime
-}  // namespace expr
-}  // namespace api
-}  // namespace google
+}  // namespace mock_cel
+}  // namespace grpc_core
 
 
 #endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MOCK_CEL_CEL_VALUE_H
 #endif  // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MOCK_CEL_CEL_VALUE_H

+ 28 - 20
src/core/lib/surface/channel.cc

@@ -415,26 +415,33 @@ grpc_call* grpc_channel_create_pollset_set_call(
 
 
 namespace grpc_core {
 namespace grpc_core {
 
 
-RegisteredCall::RegisteredCall(const char* method, const char* host) {
-  path = grpc_mdelem_from_slices(GRPC_MDSTR_PATH,
-                                 grpc_core::ExternallyManagedSlice(method));
-  authority =
-      host ? grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
-                                     grpc_core::ExternallyManagedSlice(host))
-           : GRPC_MDNULL;
-}
+RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg)
+    : method(method_arg != nullptr ? method_arg : ""),
+      host(host_arg != nullptr ? host_arg : ""),
+      path(grpc_mdelem_from_slices(
+          GRPC_MDSTR_PATH, grpc_core::ExternallyManagedSlice(method.c_str()))),
+      authority(!host.empty()
+                    ? grpc_mdelem_from_slices(
+                          GRPC_MDSTR_AUTHORITY,
+                          grpc_core::ExternallyManagedSlice(host.c_str()))
+                    : GRPC_MDNULL) {}
 
 
 // TODO(vjpai): Delete copy-constructor when allowed by all supported compilers.
 // TODO(vjpai): Delete copy-constructor when allowed by all supported compilers.
-RegisteredCall::RegisteredCall(const RegisteredCall& other) {
-  path = other.path;
-  authority = other.authority;
-  GRPC_MDELEM_REF(path);
-  GRPC_MDELEM_REF(authority);
-}
-
-RegisteredCall::RegisteredCall(RegisteredCall&& other) noexcept {
-  path = other.path;
-  authority = other.authority;
+RegisteredCall::RegisteredCall(const RegisteredCall& other)
+    : RegisteredCall(other.method.c_str(), other.host.c_str()) {}
+
+RegisteredCall::RegisteredCall(RegisteredCall&& other) noexcept
+    : method(std::move(other.method)),
+      host(std::move(other.host)),
+      path(grpc_mdelem_from_slices(
+          GRPC_MDSTR_PATH, grpc_core::ExternallyManagedSlice(method.c_str()))),
+      authority(!host.empty()
+                    ? grpc_mdelem_from_slices(
+                          GRPC_MDSTR_AUTHORITY,
+                          grpc_core::ExternallyManagedSlice(host.c_str()))
+                    : GRPC_MDNULL) {
+  GRPC_MDELEM_UNREF(other.path);
+  GRPC_MDELEM_UNREF(other.authority);
   other.path = GRPC_MDNULL;
   other.path = GRPC_MDNULL;
   other.authority = GRPC_MDNULL;
   other.authority = GRPC_MDNULL;
 }
 }
@@ -457,13 +464,14 @@ void* grpc_channel_register_call(grpc_channel* channel, const char* method,
 
 
   grpc_core::MutexLock lock(&channel->registration_table->mu);
   grpc_core::MutexLock lock(&channel->registration_table->mu);
   channel->registration_table->method_registration_attempts++;
   channel->registration_table->method_registration_attempts++;
-  auto key = std::make_pair(host, method);
+  auto key = std::make_pair(std::string(host != nullptr ? host : ""),
+                            std::string(method != nullptr ? method : ""));
   auto rc_posn = channel->registration_table->map.find(key);
   auto rc_posn = channel->registration_table->map.find(key);
   if (rc_posn != channel->registration_table->map.end()) {
   if (rc_posn != channel->registration_table->map.end()) {
     return &rc_posn->second;
     return &rc_posn->second;
   }
   }
   auto insertion_result = channel->registration_table->map.insert(
   auto insertion_result = channel->registration_table->map.insert(
-      {key, grpc_core::RegisteredCall(method, host)});
+      {std::move(key), grpc_core::RegisteredCall(method, host)});
   return &insertion_result.first->second;
   return &insertion_result.first->second;
 }
 }
 
 

+ 9 - 2
src/core/lib/surface/channel.h

@@ -69,21 +69,28 @@ void grpc_channel_update_call_size_estimate(grpc_channel* channel, size_t size);
 namespace grpc_core {
 namespace grpc_core {
 
 
 struct RegisteredCall {
 struct RegisteredCall {
+  // The method and host are kept as part of this struct just to manage their
+  // lifetime since they must outlive the mdelem contents.
+  std::string method;
+  std::string host;
+
   grpc_mdelem path;
   grpc_mdelem path;
   grpc_mdelem authority;
   grpc_mdelem authority;
 
 
-  explicit RegisteredCall(const char* method, const char* host);
+  explicit RegisteredCall(const char* method_arg, const char* host_arg);
   // TODO(vjpai): delete copy constructor once all supported compilers allow
   // TODO(vjpai): delete copy constructor once all supported compilers allow
   //              std::map value_type to be MoveConstructible.
   //              std::map value_type to be MoveConstructible.
   RegisteredCall(const RegisteredCall& other);
   RegisteredCall(const RegisteredCall& other);
   RegisteredCall(RegisteredCall&& other) noexcept;
   RegisteredCall(RegisteredCall&& other) noexcept;
+  RegisteredCall& operator=(const RegisteredCall&) = delete;
+  RegisteredCall& operator=(RegisteredCall&&) = delete;
 
 
   ~RegisteredCall();
   ~RegisteredCall();
 };
 };
 
 
 struct CallRegistrationTable {
 struct CallRegistrationTable {
   grpc_core::Mutex mu;
   grpc_core::Mutex mu;
-  std::map<std::pair<const char*, const char*>, RegisteredCall>
+  std::map<std::pair<std::string, std::string>, RegisteredCall>
       map /* GUARDED_BY(mu) */;
       map /* GUARDED_BY(mu) */;
   int method_registration_attempts /* GUARDED_BY(mu) */ = 0;
   int method_registration_attempts /* GUARDED_BY(mu) */ = 0;
 };
 };

+ 7 - 0
src/core/lib/transport/transport.h

@@ -459,4 +459,11 @@ grpc_transport_op* grpc_make_transport_op(grpc_closure* on_consumed);
 grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
 grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
     grpc_closure* on_consumed);
     grpc_closure* on_consumed);
 
 
+namespace grpc_core {
+// This is the key to be used for loading/storing keepalive_throttling in the
+// absl::Status object.
+constexpr const char* kKeepaliveThrottlingKey =
+    "grpc.internal.keepalive_throttling";
+}  // namespace grpc_core
+
 #endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */
 #endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */

+ 23 - 21
src/core/lib/uri/uri_parser.cc

@@ -38,11 +38,12 @@
 /** a size_t default value... maps to all 1's */
 /** a size_t default value... maps to all 1's */
 #define NOT_SET (~(size_t)0)
 #define NOT_SET (~(size_t)0)
 
 
-static grpc_uri* bad_uri(const char* uri_text, size_t pos, const char* section,
-                         bool suppress_errors) {
+static grpc_uri* bad_uri(absl::string_view uri_text, size_t pos,
+                         const char* section, bool suppress_errors) {
   if (!suppress_errors) {
   if (!suppress_errors) {
     std::string line_prefix = absl::StrFormat("bad uri.%s: '", section);
     std::string line_prefix = absl::StrFormat("bad uri.%s: '", section);
-    gpr_log(GPR_ERROR, "%s%s'", line_prefix.c_str(), uri_text);
+    gpr_log(GPR_ERROR, "%s%s'", line_prefix.c_str(),
+            std::string(uri_text).c_str());
     size_t pfx_len = line_prefix.size() + pos;
     size_t pfx_len = line_prefix.size() + pos;
     gpr_log(GPR_ERROR, "%s^ here", std::string(pfx_len, ' ').c_str());
     gpr_log(GPR_ERROR, "%s^ here", std::string(pfx_len, ' ').c_str());
   }
   }
@@ -50,12 +51,12 @@ static grpc_uri* bad_uri(const char* uri_text, size_t pos, const char* section,
 }
 }
 
 
 /** Returns a copy of percent decoded \a src[begin, end) */
 /** Returns a copy of percent decoded \a src[begin, end) */
-static char* decode_and_copy_component(const char* src, size_t begin,
+static char* decode_and_copy_component(absl::string_view src, size_t begin,
                                        size_t end) {
                                        size_t end) {
   grpc_slice component =
   grpc_slice component =
       (begin == NOT_SET || end == NOT_SET)
       (begin == NOT_SET || end == NOT_SET)
           ? grpc_empty_slice()
           ? grpc_empty_slice()
-          : grpc_slice_from_copied_buffer(src + begin, end - begin);
+          : grpc_slice_from_copied_buffer(src.data() + begin, end - begin);
   grpc_slice decoded_component =
   grpc_slice decoded_component =
       grpc_permissive_percent_decode_slice(component);
       grpc_permissive_percent_decode_slice(component);
   char* out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII);
   char* out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII);
@@ -72,7 +73,7 @@ static bool valid_hex(char c) {
 /** Returns how many chars to advance if \a uri_text[i] begins a valid \a pchar
 /** Returns how many chars to advance if \a uri_text[i] begins a valid \a pchar
  * production. If \a uri_text[i] introduces an invalid \a pchar (such as percent
  * production. If \a uri_text[i] introduces an invalid \a pchar (such as percent
  * sign not followed by two hex digits), NOT_SET is returned. */
  * sign not followed by two hex digits), NOT_SET is returned. */
-static size_t parse_pchar(const char* uri_text, size_t i) {
+static size_t parse_pchar(absl::string_view uri_text, size_t i) {
   /* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
   /* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
    * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
    * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
    * pct-encoded = "%" HEXDIG HEXDIG
    * pct-encoded = "%" HEXDIG HEXDIG
@@ -105,7 +106,8 @@ static size_t parse_pchar(const char* uri_text, size_t i) {
     case '=':
     case '=':
       return 1;
       return 1;
     case '%': /* pct-encoded */
     case '%': /* pct-encoded */
-      if (valid_hex(uri_text[i + 1]) && valid_hex(uri_text[i + 2])) {
+      if (uri_text.size() > i + 2 && valid_hex(uri_text[i + 1]) &&
+          valid_hex(uri_text[i + 2])) {
         return 2;
         return 2;
       }
       }
       return NOT_SET;
       return NOT_SET;
@@ -114,9 +116,8 @@ static size_t parse_pchar(const char* uri_text, size_t i) {
 }
 }
 
 
 /* *( pchar / "?" / "/" ) */
 /* *( pchar / "?" / "/" ) */
-static int parse_fragment_or_query(const char* uri_text, size_t* i) {
-  char c;
-  while ((c = uri_text[*i]) != 0) {
+static int parse_fragment_or_query(absl::string_view uri_text, size_t* i) {
+  while (uri_text.size() > *i) {
     const size_t advance = parse_pchar(uri_text, *i); /* pchar */
     const size_t advance = parse_pchar(uri_text, *i); /* pchar */
     switch (advance) {
     switch (advance) {
       case 0: /* uri_text[i] isn't in pchar */
       case 0: /* uri_text[i] isn't in pchar */
@@ -178,7 +179,7 @@ static void parse_query_parts(grpc_uri* uri) {
   }
   }
 }
 }
 
 
-grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors) {
+grpc_uri* grpc_uri_parse(absl::string_view uri_text, bool suppress_errors) {
   grpc_uri* uri;
   grpc_uri* uri;
   size_t scheme_begin = 0;
   size_t scheme_begin = 0;
   size_t scheme_end = NOT_SET;
   size_t scheme_end = NOT_SET;
@@ -192,7 +193,7 @@ grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors) {
   size_t fragment_end = NOT_SET;
   size_t fragment_end = NOT_SET;
   size_t i;
   size_t i;
 
 
-  for (i = scheme_begin; uri_text[i] != 0; i++) {
+  for (i = scheme_begin; i < uri_text.size(); ++i) {
     if (uri_text[i] == ':') {
     if (uri_text[i] == ':') {
       scheme_end = i;
       scheme_end = i;
       break;
       break;
@@ -211,15 +212,16 @@ grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors) {
     return bad_uri(uri_text, i, "scheme", suppress_errors);
     return bad_uri(uri_text, i, "scheme", suppress_errors);
   }
   }
 
 
-  if (uri_text[scheme_end + 1] == '/' && uri_text[scheme_end + 2] == '/') {
+  if (uri_text.size() > scheme_end + 2 && uri_text[scheme_end + 1] == '/' &&
+      uri_text[scheme_end + 2] == '/') {
     authority_begin = scheme_end + 3;
     authority_begin = scheme_end + 3;
-    for (i = authority_begin; uri_text[i] != 0 && authority_end == NOT_SET;
+    for (i = authority_begin; uri_text.size() > i && authority_end == NOT_SET;
          i++) {
          i++) {
       if (uri_text[i] == '/' || uri_text[i] == '?' || uri_text[i] == '#') {
       if (uri_text[i] == '/' || uri_text[i] == '?' || uri_text[i] == '#') {
         authority_end = i;
         authority_end = i;
       }
       }
     }
     }
-    if (authority_end == NOT_SET && uri_text[i] == 0) {
+    if (authority_end == NOT_SET && uri_text.size() == i) {
       authority_end = i;
       authority_end = i;
     }
     }
     if (authority_end == NOT_SET) {
     if (authority_end == NOT_SET) {
@@ -231,34 +233,34 @@ grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors) {
     path_begin = scheme_end + 1;
     path_begin = scheme_end + 1;
   }
   }
 
 
-  for (i = path_begin; uri_text[i] != 0; i++) {
+  for (i = path_begin; i < uri_text.size(); ++i) {
     if (uri_text[i] == '?' || uri_text[i] == '#') {
     if (uri_text[i] == '?' || uri_text[i] == '#') {
       path_end = i;
       path_end = i;
       break;
       break;
     }
     }
   }
   }
-  if (path_end == NOT_SET && uri_text[i] == 0) {
+  if (path_end == NOT_SET && uri_text.size() == i) {
     path_end = i;
     path_end = i;
   }
   }
   if (path_end == NOT_SET) {
   if (path_end == NOT_SET) {
     return bad_uri(uri_text, i, "path", suppress_errors);
     return bad_uri(uri_text, i, "path", suppress_errors);
   }
   }
 
 
-  if (uri_text[i] == '?') {
+  if (uri_text.size() > i && uri_text[i] == '?') {
     query_begin = ++i;
     query_begin = ++i;
     if (!parse_fragment_or_query(uri_text, &i)) {
     if (!parse_fragment_or_query(uri_text, &i)) {
       return bad_uri(uri_text, i, "query", suppress_errors);
       return bad_uri(uri_text, i, "query", suppress_errors);
-    } else if (uri_text[i] != 0 && uri_text[i] != '#') {
+    } else if (uri_text.size() > i && uri_text[i] != '#') {
       /* We must be at the end or at the beginning of a fragment */
       /* We must be at the end or at the beginning of a fragment */
       return bad_uri(uri_text, i, "query", suppress_errors);
       return bad_uri(uri_text, i, "query", suppress_errors);
     }
     }
     query_end = i;
     query_end = i;
   }
   }
-  if (uri_text[i] == '#') {
+  if (uri_text.size() > i && uri_text[i] == '#') {
     fragment_begin = ++i;
     fragment_begin = ++i;
     if (!parse_fragment_or_query(uri_text, &i)) {
     if (!parse_fragment_or_query(uri_text, &i)) {
       return bad_uri(uri_text, i - fragment_end, "fragment", suppress_errors);
       return bad_uri(uri_text, i - fragment_end, "fragment", suppress_errors);
-    } else if (uri_text[i] != 0) {
+    } else if (uri_text.size() > i) {
       /* We must be at the end */
       /* We must be at the end */
       return bad_uri(uri_text, i, "fragment", suppress_errors);
       return bad_uri(uri_text, i, "fragment", suppress_errors);
     }
     }

+ 3 - 1
src/core/lib/uri/uri_parser.h

@@ -21,6 +21,8 @@
 
 
 #include <grpc/support/port_platform.h>
 #include <grpc/support/port_platform.h>
 
 
+#include "absl/strings/string_view.h"
+
 #include <stddef.h>
 #include <stddef.h>
 
 
 struct grpc_uri {
 struct grpc_uri {
@@ -37,7 +39,7 @@ struct grpc_uri {
   char* fragment;
   char* fragment;
 };
 };
 /** parse a uri, return NULL on failure */
 /** parse a uri, return NULL on failure */
-grpc_uri* grpc_uri_parse(const char* uri_text, bool suppress_errors);
+grpc_uri* grpc_uri_parse(absl::string_view uri_text, bool suppress_errors);
 
 
 /** return the part of a query string after the '=' in "?key=xxx&...", or NULL
 /** return the part of a query string after the '=' in "?key=xxx&...", or NULL
  * if key is not present */
  * if key is not present */

+ 3 - 9
src/core/tsi/ssl_transport_security.cc

@@ -1894,11 +1894,8 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
 #else
 #else
   ssl_context = SSL_CTX_new(TLSv1_2_method());
   ssl_context = SSL_CTX_new(TLSv1_2_method());
 #endif
 #endif
-  // TODO(mattstev): Re-enable TLS 1.3 by using |options.min_tls_version| and
-  // |options.max_tls_version|, rather than hardcoding in TLS 1.2 as the min and
-  // max.
   result = tsi_set_min_and_max_tls_versions(
   result = tsi_set_min_and_max_tls_versions(
-      ssl_context, tsi_tls_version::TSI_TLS1_2, tsi_tls_version::TSI_TLS1_2);
+      ssl_context, options->min_tls_version, options->max_tls_version);
   if (result != TSI_OK) return result;
   if (result != TSI_OK) return result;
   if (ssl_context == nullptr) {
   if (ssl_context == nullptr) {
     gpr_log(GPR_ERROR, "Could not create ssl context.");
     gpr_log(GPR_ERROR, "Could not create ssl context.");
@@ -2064,12 +2061,9 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
 #else
 #else
       impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
       impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
 #endif
 #endif
-      // TODO(mattstev): Re-enable TLS 1.3 by using |options.min_tls_version|
-      // and |options.max_tls_version|, rather than hardcoding in TLS 1.2 as the
-      // min and max.
       result = tsi_set_min_and_max_tls_versions(impl->ssl_contexts[i],
       result = tsi_set_min_and_max_tls_versions(impl->ssl_contexts[i],
-                                                tsi_tls_version::TSI_TLS1_2,
-                                                tsi_tls_version::TSI_TLS1_2);
+                                                options->min_tls_version,
+                                                options->max_tls_version);
       if (result != TSI_OK) return result;
       if (result != TSI_OK) return result;
       if (impl->ssl_contexts[i] == nullptr) {
       if (impl->ssl_contexts[i] == nullptr) {
         gpr_log(GPR_ERROR, "Could not create ssl context.");
         gpr_log(GPR_ERROR, "Could not create ssl context.");

+ 3 - 8
src/cpp/client/channel_cc.cc

@@ -41,11 +41,7 @@
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/surface/completion_queue.h"
 #include "src/core/lib/surface/completion_queue.h"
 
 
-void ::grpc::experimental::ChannelResetConnectionBackoff(Channel* channel) {
-  grpc_impl::experimental::ChannelResetConnectionBackoff(channel);
-}
-
-namespace grpc_impl {
+namespace grpc {
 
 
 static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer;
 static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer;
 Channel::Channel(const std::string& host, grpc_channel* channel,
 Channel::Channel(const std::string& host, grpc_channel* channel,
@@ -67,8 +63,7 @@ Channel::~Channel() {
 namespace {
 namespace {
 
 
 inline grpc_slice SliceFromArray(const char* arr, size_t len) {
 inline grpc_slice SliceFromArray(const char* arr, size_t len) {
-  return ::grpc::g_core_codegen_interface->grpc_slice_from_copied_buffer(arr,
-                                                                         len);
+  return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len);
 }
 }
 
 
 std::string GetChannelInfoField(grpc_channel* channel,
 std::string GetChannelInfoField(grpc_channel* channel,
@@ -254,4 +249,4 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor {
   return callback_cq_;
   return callback_cq_;
 }
 }
 
 
-}  // namespace grpc_impl
+}  // namespace grpc

+ 9 - 9
src/cpp/client/client_context.cc

@@ -31,7 +31,7 @@
 #include <grpcpp/server_context.h>
 #include <grpcpp/server_context.h>
 #include <grpcpp/support/time.h>
 #include <grpcpp/support/time.h>
 
 
-namespace grpc_impl {
+namespace grpc {
 
 
 class Channel;
 class Channel;
 
 
@@ -43,7 +43,7 @@ class DefaultGlobalClientCallbacks final
   void Destructor(ClientContext* /*context*/) override {}
   void Destructor(ClientContext* /*context*/) override {}
 };
 };
 
 
-static grpc::internal::GrpcLibraryInitializer g_gli_initializer;
+static internal::GrpcLibraryInitializer g_gli_initializer;
 static DefaultGlobalClientCallbacks* g_default_client_callbacks =
 static DefaultGlobalClientCallbacks* g_default_client_callbacks =
     new DefaultGlobalClientCallbacks();
     new DefaultGlobalClientCallbacks();
 static ClientContext::GlobalCallbacks* g_client_callbacks =
 static ClientContext::GlobalCallbacks* g_client_callbacks =
@@ -73,7 +73,7 @@ ClientContext::~ClientContext() {
 }
 }
 
 
 void ClientContext::set_credentials(
 void ClientContext::set_credentials(
-    const std::shared_ptr<grpc::CallCredentials>& creds) {
+    const std::shared_ptr<CallCredentials>& creds) {
   creds_ = creds;
   creds_ = creds;
   // If call_ is set, we have already created the call, and set the call
   // If call_ is set, we have already created the call, and set the call
   // credentials. This should only be done before we have started the batch
   // credentials. This should only be done before we have started the batch
@@ -113,9 +113,9 @@ void ClientContext::AddMetadata(const std::string& meta_key,
   send_initial_metadata_.insert(std::make_pair(meta_key, meta_value));
   send_initial_metadata_.insert(std::make_pair(meta_key, meta_value));
 }
 }
 
 
-void ClientContext::set_call(
-    grpc_call* call, const std::shared_ptr<::grpc_impl::Channel>& channel) {
-  grpc::internal::MutexLock lock(&mu_);
+void ClientContext::set_call(grpc_call* call,
+                             const std::shared_ptr<Channel>& channel) {
+  internal::MutexLock lock(&mu_);
   GPR_ASSERT(call_ == nullptr);
   GPR_ASSERT(call_ == nullptr);
   call_ = call;
   call_ = call;
   channel_ = channel;
   channel_ = channel;
@@ -145,7 +145,7 @@ void ClientContext::set_compression_algorithm(
 }
 }
 
 
 void ClientContext::TryCancel() {
 void ClientContext::TryCancel() {
-  grpc::internal::MutexLock lock(&mu_);
+  internal::MutexLock lock(&mu_);
   if (call_) {
   if (call_) {
     SendCancelToInterceptors();
     SendCancelToInterceptors();
     grpc_call_cancel(call_, nullptr);
     grpc_call_cancel(call_, nullptr);
@@ -155,7 +155,7 @@ void ClientContext::TryCancel() {
 }
 }
 
 
 void ClientContext::SendCancelToInterceptors() {
 void ClientContext::SendCancelToInterceptors() {
-  grpc::internal::CancelInterceptorBatchMethods cancel_methods;
+  internal::CancelInterceptorBatchMethods cancel_methods;
   for (size_t i = 0; i < rpc_info_.interceptors_.size(); i++) {
   for (size_t i = 0; i < rpc_info_.interceptors_.size(); i++) {
     rpc_info_.RunInterceptor(&cancel_methods, i);
     rpc_info_.RunInterceptor(&cancel_methods, i);
   }
   }
@@ -178,4 +178,4 @@ void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) {
   g_client_callbacks = client_callbacks;
   g_client_callbacks = client_callbacks;
 }
 }
 
 
-}  // namespace grpc_impl
+}  // namespace grpc

+ 1 - 4
src/cpp/client/secure_credentials.h

@@ -29,12 +29,9 @@
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/cpp/server/thread_pool_interface.h"
 #include "src/cpp/server/thread_pool_interface.h"
 
 
-namespace grpc_impl {
+namespace grpc {
 
 
 class Channel;
 class Channel;
-}  // namespace grpc_impl
-
-namespace grpc {
 
 
 class SecureChannelCredentials final : public ChannelCredentials {
 class SecureChannelCredentials final : public ChannelCredentials {
  public:
  public:

+ 3 - 3
src/cpp/common/completion_queue_cc.cc

@@ -24,9 +24,9 @@
 #include <grpcpp/impl/grpc_library.h>
 #include <grpcpp/impl/grpc_library.h>
 #include <grpcpp/support/time.h>
 #include <grpcpp/support/time.h>
 
 
-namespace grpc_impl {
+namespace grpc {
 
 
-static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer;
+static internal::GrpcLibraryInitializer g_gli_initializer;
 
 
 // 'CompletionQueue' constructor can safely call GrpcLibraryCodegen(false) here
 // 'CompletionQueue' constructor can safely call GrpcLibraryCodegen(false) here
 // i.e not have GrpcLibraryCodegen call grpc_init(). This is because, to create
 // i.e not have GrpcLibraryCodegen call grpc_init(). This is because, to create
@@ -96,4 +96,4 @@ bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) {
   return false;
   return false;
 }
 }
 
 
-}  // namespace grpc_impl
+}  // namespace grpc

+ 2 - 2
src/cpp/server/async_generic_service.cc

@@ -24,8 +24,8 @@ namespace grpc {
 
 
 void AsyncGenericService::RequestCall(
 void AsyncGenericService::RequestCall(
     GenericServerContext* ctx, GenericServerAsyncReaderWriter* reader_writer,
     GenericServerContext* ctx, GenericServerAsyncReaderWriter* reader_writer,
-    ::grpc_impl::CompletionQueue* call_cq,
-    ::grpc_impl::ServerCompletionQueue* notification_cq, void* tag) {
+    ::grpc::CompletionQueue* call_cq,
+    ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
   server_->RequestAsyncGenericCall(ctx, reader_writer, call_cq, notification_cq,
   server_->RequestAsyncGenericCall(ctx, reader_writer, call_cq, notification_cq,
                                    tag);
                                    tag);
 }
 }

+ 9 - 10
src/cpp/server/server_builder.cc

@@ -68,14 +68,14 @@ ServerBuilder::~ServerBuilder() {
   }
   }
 }
 }
 
 
-std::unique_ptr<grpc_impl::ServerCompletionQueue>
-ServerBuilder::AddCompletionQueue(bool is_frequently_polled) {
-  grpc_impl::ServerCompletionQueue* cq = new grpc_impl::ServerCompletionQueue(
+std::unique_ptr<grpc::ServerCompletionQueue> ServerBuilder::AddCompletionQueue(
+    bool is_frequently_polled) {
+  grpc::ServerCompletionQueue* cq = new grpc::ServerCompletionQueue(
       GRPC_CQ_NEXT,
       GRPC_CQ_NEXT,
       is_frequently_polled ? GRPC_CQ_DEFAULT_POLLING : GRPC_CQ_NON_LISTENING,
       is_frequently_polled ? GRPC_CQ_DEFAULT_POLLING : GRPC_CQ_NON_LISTENING,
       nullptr);
       nullptr);
   cqs_.push_back(cq);
   cqs_.push_back(cq);
-  return std::unique_ptr<grpc_impl::ServerCompletionQueue>(cq);
+  return std::unique_ptr<grpc::ServerCompletionQueue>(cq);
 }
 }
 
 
 ServerBuilder& ServerBuilder::RegisterService(Service* service) {
 ServerBuilder& ServerBuilder::RegisterService(Service* service) {
@@ -275,11 +275,10 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
   // This is different from the completion queues added to the server via
   // This is different from the completion queues added to the server via
   // ServerBuilder's AddCompletionQueue() method (those completion queues
   // ServerBuilder's AddCompletionQueue() method (those completion queues
   // are in 'cqs_' member variable of ServerBuilder object)
   // are in 'cqs_' member variable of ServerBuilder object)
-  std::shared_ptr<
-      std::vector<std::unique_ptr<grpc_impl::ServerCompletionQueue>>>
+  std::shared_ptr<std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>
       sync_server_cqs(
       sync_server_cqs(
-          std::make_shared<std::vector<
-              std::unique_ptr<grpc_impl::ServerCompletionQueue>>>());
+          std::make_shared<
+              std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>());
 
 
   bool has_frequently_polled_cqs = false;
   bool has_frequently_polled_cqs = false;
   for (const auto& cq : cqs_) {
   for (const auto& cq : cqs_) {
@@ -307,8 +306,8 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
 
 
     // Create completion queues to listen to incoming rpc requests
     // Create completion queues to listen to incoming rpc requests
     for (int i = 0; i < sync_server_settings_.num_cqs; i++) {
     for (int i = 0; i < sync_server_settings_.num_cqs; i++) {
-      sync_server_cqs->emplace_back(new grpc_impl::ServerCompletionQueue(
-          GRPC_CQ_NEXT, polling_type, nullptr));
+      sync_server_cqs->emplace_back(
+          new grpc::ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr));
     }
     }
   }
   }
 
 

+ 2 - 2
src/cpp/server/server_context.cc

@@ -27,7 +27,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpcpp/impl/call.h>
 #include <grpcpp/impl/call.h>
-#include <grpcpp/impl/codegen/completion_queue_impl.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
 #include <grpcpp/support/server_callback.h>
 #include <grpcpp/support/server_callback.h>
 #include <grpcpp/support/time.h>
 #include <grpcpp/support/time.h>
 
 
@@ -89,7 +89,7 @@ class ServerContextBase::CompletionOp final
 
 
   bool FinalizeResult(void** tag, bool* status) override;
   bool FinalizeResult(void** tag, bool* status) override;
 
 
-  bool CheckCancelled(CompletionQueue* cq) {
+  bool CheckCancelled(grpc::CompletionQueue* cq) {
     cq->TryPluck(this);
     cq->TryPluck(this);
     return CheckCancelledNoPluck();
     return CheckCancelledNoPluck();
   }
   }

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