grpc 1.36.0 → 1.37.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +65 -37
  3. data/include/grpc/grpc.h +15 -1
  4. data/include/grpc/impl/codegen/port_platform.h +2 -0
  5. data/src/core/ext/filters/client_channel/client_channel.cc +327 -305
  6. data/src/core/ext/filters/client_channel/client_channel_factory.h +2 -1
  7. data/src/core/ext/filters/client_channel/config_selector.h +8 -0
  8. data/src/core/ext/filters/client_channel/dynamic_filters.cc +9 -4
  9. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +24 -142
  10. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +15 -10
  11. data/src/core/ext/filters/client_channel/lb_policy.cc +3 -0
  12. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +23 -0
  13. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +27 -0
  14. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +7 -22
  15. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +1 -1
  16. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +2 -2
  17. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +27 -67
  18. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +10 -9
  19. data/src/core/ext/filters/client_channel/resolver.cc +3 -0
  20. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +2 -2
  21. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +3 -1
  22. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +5 -9
  23. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +18 -3
  24. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +295 -91
  25. data/src/core/ext/filters/client_channel/server_address.cc +3 -0
  26. data/src/core/ext/filters/client_channel/subchannel.cc +69 -146
  27. data/src/core/ext/filters/client_channel/subchannel.h +63 -95
  28. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +16 -2
  29. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +10 -8
  30. data/src/core/ext/filters/client_idle/client_idle_filter.cc +1 -1
  31. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +495 -0
  32. data/src/core/ext/filters/fault_injection/fault_injection_filter.h +39 -0
  33. data/src/core/ext/filters/fault_injection/service_config_parser.cc +189 -0
  34. data/src/core/ext/filters/fault_injection/service_config_parser.h +85 -0
  35. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc +1 -1
  36. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +1 -1
  37. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +3 -2
  38. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +1 -1
  39. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +3 -2
  40. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +457 -170
  41. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +1 -1
  42. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +39 -7
  43. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +12 -1
  44. data/src/core/ext/transport/chttp2/transport/frame_data.cc +5 -1
  45. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
  46. data/src/core/ext/transport/chttp2/transport/internal.h +1 -0
  47. data/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c +406 -0
  48. data/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h +1459 -0
  49. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c +350 -0
  50. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h +1348 -0
  51. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +6 -0
  52. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +25 -0
  53. data/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c +144 -0
  54. data/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h +488 -0
  55. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c +141 -0
  56. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h +452 -0
  57. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +15 -0
  58. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +44 -0
  59. data/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c +79 -0
  60. data/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h +268 -0
  61. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c +78 -0
  62. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h +281 -0
  63. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c +41 -0
  64. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h +113 -0
  65. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +6 -5
  66. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +13 -9
  67. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c +93 -0
  68. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h +323 -0
  69. data/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c +36 -0
  70. data/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h +90 -0
  71. data/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c +46 -0
  72. data/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h +124 -0
  73. data/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c +33 -0
  74. data/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h +77 -0
  75. data/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c +354 -0
  76. data/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h +140 -0
  77. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c +383 -0
  78. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h +115 -0
  79. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c +10 -7
  80. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.h +5 -0
  81. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c +141 -0
  82. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h +70 -0
  83. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c +141 -0
  84. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h +70 -0
  85. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c +13 -7
  86. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h +5 -0
  87. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c +102 -0
  88. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h +55 -0
  89. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c +120 -0
  90. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h +45 -0
  91. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c +76 -0
  92. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h +35 -0
  93. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c +21 -20
  94. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c +130 -0
  95. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h +50 -0
  96. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c +56 -0
  97. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h +35 -0
  98. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c +63 -0
  99. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h +40 -0
  100. data/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c +44 -0
  101. data/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h +35 -0
  102. data/src/core/ext/xds/xds_api.cc +1591 -279
  103. data/src/core/ext/xds/xds_api.h +279 -39
  104. data/src/core/ext/xds/xds_bootstrap.cc +21 -5
  105. data/src/core/ext/xds/xds_bootstrap.h +5 -1
  106. data/src/core/ext/xds/xds_client.cc +168 -23
  107. data/src/core/ext/xds/xds_client.h +26 -0
  108. data/src/core/ext/xds/xds_client_stats.h +2 -2
  109. data/src/core/ext/xds/xds_http_fault_filter.cc +226 -0
  110. data/src/core/ext/xds/xds_http_fault_filter.h +63 -0
  111. data/src/core/ext/xds/xds_http_filters.cc +114 -0
  112. data/src/core/ext/xds/xds_http_filters.h +130 -0
  113. data/src/core/ext/xds/xds_server_config_fetcher.cc +391 -126
  114. data/src/core/lib/channel/channel_stack.cc +12 -0
  115. data/src/core/lib/channel/channel_stack.h +7 -0
  116. data/src/core/lib/channel/channelz.cc +92 -4
  117. data/src/core/lib/channel/channelz.h +30 -1
  118. data/src/core/lib/channel/channelz_registry.cc +14 -0
  119. data/src/core/lib/channel/handshaker.cc +0 -39
  120. data/src/core/lib/channel/handshaker.h +0 -17
  121. data/src/core/lib/channel/status_util.cc +12 -2
  122. data/src/core/lib/channel/status_util.h +5 -0
  123. data/src/core/lib/gpr/sync_abseil.cc +3 -6
  124. data/src/core/lib/gpr/sync_windows.cc +2 -2
  125. data/src/core/lib/gprpp/atomic.h +3 -3
  126. data/src/core/lib/gprpp/dual_ref_counted.h +3 -3
  127. data/src/core/lib/gprpp/ref_counted_ptr.h +2 -0
  128. data/src/core/lib/gprpp/thd.h +1 -1
  129. data/src/core/lib/iomgr/buffer_list.h +1 -1
  130. data/src/core/lib/iomgr/cfstream_handle.cc +2 -2
  131. data/src/core/lib/iomgr/error.h +1 -1
  132. data/src/core/lib/iomgr/ev_apple.cc +1 -1
  133. data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -3
  134. data/src/core/lib/iomgr/ev_posix.cc +3 -3
  135. data/src/core/lib/iomgr/exec_ctx.cc +6 -2
  136. data/src/core/lib/iomgr/resource_quota.cc +1 -1
  137. data/src/core/lib/iomgr/sockaddr_utils.cc +120 -0
  138. data/src/core/lib/iomgr/sockaddr_utils.h +25 -0
  139. data/src/core/lib/iomgr/tcp_posix.cc +1 -4
  140. data/src/core/lib/iomgr/tcp_uv.cc +2 -2
  141. data/src/core/lib/iomgr/timer_generic.cc +2 -2
  142. data/src/core/lib/iomgr/timer_manager.cc +1 -1
  143. data/src/core/lib/iomgr/wakeup_fd_nospecial.cc +1 -1
  144. data/src/core/lib/{security/authorization → matchers}/matchers.cc +8 -8
  145. data/src/core/lib/{security/authorization → matchers}/matchers.h +14 -12
  146. data/src/core/lib/security/security_connector/ssl_utils.cc +6 -4
  147. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +6 -0
  148. data/src/core/lib/security/transport/security_handshaker.cc +32 -2
  149. data/src/core/lib/slice/slice_intern.cc +6 -7
  150. data/src/core/lib/surface/channel.h +3 -3
  151. data/src/core/lib/surface/completion_queue.cc +1 -1
  152. data/src/core/lib/surface/lame_client.cc +38 -19
  153. data/src/core/lib/surface/lame_client.h +4 -3
  154. data/src/core/lib/surface/server.cc +40 -33
  155. data/src/core/lib/surface/server.h +74 -15
  156. data/src/core/lib/surface/version.cc +1 -1
  157. data/src/core/lib/transport/metadata_batch.cc +27 -0
  158. data/src/core/lib/transport/metadata_batch.h +14 -0
  159. data/src/core/plugin_registry/grpc_plugin_registry.cc +6 -0
  160. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -4
  161. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
  162. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +1 -3
  163. data/src/core/tsi/fake_transport_security.cc +10 -1
  164. data/src/ruby/ext/grpc/extconf.rb +9 -1
  165. data/src/ruby/ext/grpc/rb_channel.c +10 -1
  166. data/src/ruby/ext/grpc/rb_channel_credentials.c +11 -1
  167. data/src/ruby/ext/grpc/rb_channel_credentials.h +4 -0
  168. data/src/ruby/ext/grpc/rb_compression_options.c +1 -1
  169. data/src/ruby/ext/grpc/rb_enable_cpp.cc +1 -1
  170. data/src/ruby/ext/grpc/rb_grpc.c +4 -0
  171. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  172. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  173. data/src/ruby/ext/grpc/rb_server.c +13 -1
  174. data/src/ruby/ext/grpc/rb_server_credentials.c +19 -3
  175. data/src/ruby/ext/grpc/rb_server_credentials.h +4 -0
  176. data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +215 -0
  177. data/src/ruby/ext/grpc/rb_xds_channel_credentials.h +35 -0
  178. data/src/ruby/ext/grpc/rb_xds_server_credentials.c +169 -0
  179. data/src/ruby/ext/grpc/rb_xds_server_credentials.h +35 -0
  180. data/src/ruby/lib/grpc/generic/client_stub.rb +4 -2
  181. data/src/ruby/lib/grpc/version.rb +1 -1
  182. data/src/ruby/spec/call_spec.rb +1 -1
  183. data/src/ruby/spec/channel_credentials_spec.rb +32 -0
  184. data/src/ruby/spec/channel_spec.rb +17 -6
  185. data/src/ruby/spec/client_auth_spec.rb +27 -1
  186. data/src/ruby/spec/errors_spec.rb +1 -1
  187. data/src/ruby/spec/generic/active_call_spec.rb +2 -2
  188. data/src/ruby/spec/generic/client_stub_spec.rb +4 -4
  189. data/src/ruby/spec/generic/rpc_server_spec.rb +1 -1
  190. data/src/ruby/spec/server_credentials_spec.rb +25 -0
  191. data/src/ruby/spec/server_spec.rb +22 -0
  192. data/third_party/boringssl-with-bazel/err_data.c +255 -255
  193. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm-linux.c +11 -2
  194. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm.c +3 -3
  195. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/cipher/cipher.c +21 -13
  196. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +7 -5
  197. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +0 -28
  198. data/third_party/boringssl-with-bazel/src/crypto/x509/x_attrib.c +22 -17
  199. data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509.c +3 -1
  200. data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +4 -0
  201. data/third_party/boringssl-with-bazel/src/include/openssl/cpu.h +22 -32
  202. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +25 -9
  203. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +0 -1
  204. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +33 -19
  205. data/third_party/xxhash/xxhash.h +5443 -0
  206. metadata +93 -49
  207. data/src/core/lib/security/authorization/authorization_engine.cc +0 -177
  208. data/src/core/lib/security/authorization/authorization_engine.h +0 -84
  209. data/src/core/lib/security/authorization/evaluate_args.cc +0 -148
  210. data/src/core/lib/security/authorization/evaluate_args.h +0 -59
  211. data/src/core/lib/security/authorization/mock_cel/activation.h +0 -57
  212. data/src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h +0 -44
  213. data/src/core/lib/security/authorization/mock_cel/cel_expression.h +0 -69
  214. data/src/core/lib/security/authorization/mock_cel/cel_value.h +0 -99
  215. data/src/core/lib/security/authorization/mock_cel/evaluator_core.h +0 -67
  216. data/src/core/lib/security/authorization/mock_cel/flat_expr_builder.h +0 -57
  217. data/third_party/abseil-cpp/absl/container/flat_hash_set.h +0 -504
  218. data/third_party/upb/upb/json_decode.c +0 -1443
  219. data/third_party/upb/upb/json_decode.h +0 -23
  220. data/third_party/upb/upb/json_encode.c +0 -713
  221. data/third_party/upb/upb/json_encode.h +0 -36
@@ -0,0 +1,39 @@
1
+ //
2
+ // Copyright 2021 gRPC authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+
17
+ #ifndef GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_FAULT_INJECTION_FILTER_H
18
+ #define GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_FAULT_INJECTION_FILTER_H
19
+
20
+ #include <grpc/support/port_platform.h>
21
+
22
+ #include "src/core/ext/filters/fault_injection/service_config_parser.h"
23
+ #include "src/core/lib/channel/channel_stack.h"
24
+
25
+ // Channel arg key for enabling parsing fault injection via method config.
26
+ #define GRPC_ARG_PARSE_FAULT_INJECTION_METHOD_CONFIG \
27
+ "grpc.parse_fault_injection_method_config"
28
+
29
+ namespace grpc_core {
30
+
31
+ // This channel filter is intended to be used by the dynamic filters, instead
32
+ // of the ordinary channel stack. The fault injection filter fetches fault
33
+ // injection policy from the method config of service config returned by the
34
+ // resolver, and enforces the fault injection policy.
35
+ extern const grpc_channel_filter FaultInjectionFilterVtable;
36
+
37
+ } // namespace grpc_core
38
+
39
+ #endif // GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_FAULT_INJECTION_FILTER_H
@@ -0,0 +1,189 @@
1
+ //
2
+ // Copyright 2021 gRPC authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+
17
+ #include <grpc/support/port_platform.h>
18
+
19
+ #include "src/core/ext/filters/fault_injection/service_config_parser.h"
20
+
21
+ #include <vector>
22
+
23
+ #include "absl/strings/str_cat.h"
24
+ #include "absl/strings/string_view.h"
25
+ #include "src/core/ext/filters/client_channel/service_config.h"
26
+ #include "src/core/ext/filters/fault_injection/fault_injection_filter.h"
27
+ #include "src/core/lib/channel/channel_args.h"
28
+ #include "src/core/lib/channel/status_util.h"
29
+ #include "src/core/lib/gpr/string.h"
30
+ #include "src/core/lib/json/json_util.h"
31
+
32
+ namespace grpc_core {
33
+
34
+ namespace {
35
+
36
+ size_t g_fault_injection_parser_index;
37
+
38
+ std::vector<FaultInjectionMethodParsedConfig::FaultInjectionPolicy>
39
+ ParseFaultInjectionPolicy(const Json::Array& policies_json_array,
40
+ std::vector<grpc_error*>* error_list) {
41
+ std::vector<FaultInjectionMethodParsedConfig::FaultInjectionPolicy> policies;
42
+ for (size_t i = 0; i < policies_json_array.size(); i++) {
43
+ FaultInjectionMethodParsedConfig::FaultInjectionPolicy
44
+ fault_injection_policy;
45
+ std::vector<grpc_error*> sub_error_list;
46
+ if (policies_json_array[i].type() != Json::Type::OBJECT) {
47
+ error_list->push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
48
+ absl::StrCat("faultInjectionPolicy index ", i,
49
+ " is not a JSON object")
50
+ .c_str()));
51
+ continue;
52
+ }
53
+ const Json::Object& json_object = policies_json_array[i].object_value();
54
+ // Parse abort_code
55
+ std::string abort_code_string;
56
+ if (ParseJsonObjectField(json_object, "abortCode", &abort_code_string,
57
+ &sub_error_list, false)) {
58
+ if (!grpc_status_code_from_string(abort_code_string.c_str(),
59
+ &(fault_injection_policy.abort_code))) {
60
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
61
+ "field:abortCode error:failed to parse status code"));
62
+ }
63
+ }
64
+ // Parse abort_message
65
+ if (!ParseJsonObjectField(json_object, "abortMessage",
66
+ &fault_injection_policy.abort_message,
67
+ &sub_error_list, false)) {
68
+ fault_injection_policy.abort_message = "Fault injected";
69
+ }
70
+ // Parse abort_code_header
71
+ ParseJsonObjectField(json_object, "abortCodeHeader",
72
+ &fault_injection_policy.abort_code_header,
73
+ &sub_error_list, false);
74
+ // Parse abort_percentage_header
75
+ ParseJsonObjectField(json_object, "abortPercentageHeader",
76
+ &fault_injection_policy.abort_percentage_header,
77
+ &sub_error_list, false);
78
+ // Parse abort_percentage_numerator
79
+ ParseJsonObjectField(json_object, "abortPercentageNumerator",
80
+ &fault_injection_policy.abort_percentage_numerator,
81
+ &sub_error_list, false);
82
+ // Parse abort_percentage_denominator
83
+ if (ParseJsonObjectField(
84
+ json_object, "abortPercentageDenominator",
85
+ &fault_injection_policy.abort_percentage_denominator,
86
+ &sub_error_list, false)) {
87
+ if (fault_injection_policy.abort_percentage_denominator != 100 &&
88
+ fault_injection_policy.abort_percentage_denominator != 10000 &&
89
+ fault_injection_policy.abort_percentage_denominator != 1000000) {
90
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
91
+ "field:abortPercentageDenominator error:Denominator can only be "
92
+ "one of "
93
+ "100, 10000, 1000000"));
94
+ }
95
+ }
96
+ // Parse delay
97
+ ParseJsonObjectFieldAsDuration(json_object, "delay",
98
+ &fault_injection_policy.delay,
99
+ &sub_error_list, false);
100
+ // Parse delay_header
101
+ ParseJsonObjectField(json_object, "delayHeader",
102
+ &fault_injection_policy.delay_header, &sub_error_list,
103
+ false);
104
+ // Parse delay_percentage_header
105
+ ParseJsonObjectField(json_object, "delayPercentageHeader",
106
+ &fault_injection_policy.delay_percentage_header,
107
+ &sub_error_list, false);
108
+ // Parse delay_percentage_numerator
109
+ ParseJsonObjectField(json_object, "delayPercentageNumerator",
110
+ &fault_injection_policy.delay_percentage_numerator,
111
+ &sub_error_list, false);
112
+ // Parse delay_percentage_denominator
113
+ if (ParseJsonObjectField(
114
+ json_object, "delayPercentageDenominator",
115
+ &fault_injection_policy.delay_percentage_denominator,
116
+ &sub_error_list, false)) {
117
+ if (fault_injection_policy.delay_percentage_denominator != 100 &&
118
+ fault_injection_policy.delay_percentage_denominator != 10000 &&
119
+ fault_injection_policy.delay_percentage_denominator != 1000000) {
120
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
121
+ "field:delayPercentageDenominator error:Denominator can only be "
122
+ "one of "
123
+ "100, 10000, 1000000"));
124
+ }
125
+ }
126
+ // Parse max_faults
127
+ if (ParseJsonObjectField(json_object, "maxFaults",
128
+ &fault_injection_policy.max_faults,
129
+ &sub_error_list, false)) {
130
+ if (fault_injection_policy.max_faults < 0) {
131
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
132
+ "field:maxFaults error:should be zero or positive"));
133
+ }
134
+ }
135
+ if (!sub_error_list.empty()) {
136
+ // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
137
+ // string is not static in this case.
138
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
139
+ absl::StrCat("failed to parse faultInjectionPolicy index ", i)
140
+ .c_str());
141
+ for (size_t i = 0; i < sub_error_list.size(); ++i) {
142
+ error = grpc_error_add_child(error, sub_error_list[i]);
143
+ }
144
+ error_list->push_back(error);
145
+ }
146
+ policies.push_back(std::move(fault_injection_policy));
147
+ }
148
+ return policies;
149
+ }
150
+
151
+ } // namespace
152
+
153
+ std::unique_ptr<ServiceConfigParser::ParsedConfig>
154
+ FaultInjectionServiceConfigParser::ParsePerMethodParams(
155
+ const grpc_channel_args* args, const Json& json, grpc_error** error) {
156
+ GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
157
+ // Only parse fault injection policy if the following channel arg is present.
158
+ if (!grpc_channel_args_find_bool(
159
+ args, GRPC_ARG_PARSE_FAULT_INJECTION_METHOD_CONFIG, false)) {
160
+ return nullptr;
161
+ }
162
+ // Parse fault injection policy from given Json
163
+ std::vector<FaultInjectionMethodParsedConfig::FaultInjectionPolicy>
164
+ fault_injection_policies;
165
+ std::vector<grpc_error*> error_list;
166
+ const Json::Array* policies_json_array;
167
+ if (ParseJsonObjectField(json.object_value(), "faultInjectionPolicy",
168
+ &policies_json_array, &error_list)) {
169
+ fault_injection_policies =
170
+ ParseFaultInjectionPolicy(*policies_json_array, &error_list);
171
+ }
172
+ *error = GRPC_ERROR_CREATE_FROM_VECTOR("Fault injection parser", &error_list);
173
+ if (*error != GRPC_ERROR_NONE || fault_injection_policies.empty()) {
174
+ return nullptr;
175
+ }
176
+ return absl::make_unique<FaultInjectionMethodParsedConfig>(
177
+ std::move(fault_injection_policies));
178
+ }
179
+
180
+ void FaultInjectionServiceConfigParser::Register() {
181
+ g_fault_injection_parser_index = ServiceConfigParser::RegisterParser(
182
+ absl::make_unique<FaultInjectionServiceConfigParser>());
183
+ }
184
+
185
+ size_t FaultInjectionServiceConfigParser::ParserIndex() {
186
+ return g_fault_injection_parser_index;
187
+ }
188
+
189
+ } // namespace grpc_core
@@ -0,0 +1,85 @@
1
+ //
2
+ // Copyright 2021 gRPC authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+
17
+ #ifndef GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_SERVICE_CONFIG_PARSER_H
18
+ #define GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_SERVICE_CONFIG_PARSER_H
19
+
20
+ #include <grpc/support/port_platform.h>
21
+
22
+ #include <vector>
23
+
24
+ #include "src/core/ext/filters/client_channel/service_config.h"
25
+ #include "src/core/lib/iomgr/exec_ctx.h"
26
+
27
+ namespace grpc_core {
28
+
29
+ class FaultInjectionMethodParsedConfig
30
+ : public ServiceConfigParser::ParsedConfig {
31
+ public:
32
+ struct FaultInjectionPolicy {
33
+ grpc_status_code abort_code = GRPC_STATUS_OK;
34
+ std::string abort_message;
35
+ std::string abort_code_header;
36
+ std::string abort_percentage_header;
37
+ uint32_t abort_percentage_numerator = 0;
38
+ uint32_t abort_percentage_denominator = 100;
39
+
40
+ grpc_millis delay = 0;
41
+ std::string delay_header;
42
+ std::string delay_percentage_header;
43
+ uint32_t delay_percentage_numerator = 0;
44
+ uint32_t delay_percentage_denominator = 100;
45
+
46
+ // By default, the max allowed active faults are unlimited.
47
+ uint32_t max_faults = std::numeric_limits<uint32_t>::max();
48
+ };
49
+
50
+ explicit FaultInjectionMethodParsedConfig(
51
+ std::vector<FaultInjectionPolicy> fault_injection_policies)
52
+ : fault_injection_policies_(std::move(fault_injection_policies)) {}
53
+
54
+ // Returns the fault injection policy at certain index.
55
+ // There might be multiple fault injection policies functioning at the same
56
+ // time. The order between the policies are stable, and an index is used to
57
+ // keep track of their relative positions. The FaultInjectionFilter uses this
58
+ // method to access the parsed fault injection policy in service config,
59
+ // whether it came from xDS resolver or directly from service config
60
+ const FaultInjectionPolicy* fault_injection_policy(int index) const {
61
+ if (static_cast<size_t>(index) >= fault_injection_policies_.size()) {
62
+ return nullptr;
63
+ }
64
+ return &fault_injection_policies_[index];
65
+ }
66
+
67
+ private:
68
+ std::vector<FaultInjectionPolicy> fault_injection_policies_;
69
+ };
70
+
71
+ class FaultInjectionServiceConfigParser : public ServiceConfigParser::Parser {
72
+ public:
73
+ // Parses the per-method service config for fault injection filter.
74
+ std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
75
+ const grpc_channel_args* args, const Json& json,
76
+ grpc_error** error) override;
77
+ // Returns the parser index for FaultInjectionServiceConfigParser.
78
+ static size_t ParserIndex();
79
+ // Registers FaultInjectionServiceConfigParser to ServiceConfigParser.
80
+ static void Register();
81
+ };
82
+
83
+ } // namespace grpc_core
84
+
85
+ #endif // GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_SERVICE_CONFIG_PARSER_H
@@ -192,7 +192,7 @@ static bool register_workaround_cronet_compression(
192
192
  if (a == nullptr) {
193
193
  return true;
194
194
  }
195
- if (grpc_channel_arg_get_bool(a, false) == false) {
195
+ if (!grpc_channel_arg_get_bool(a, false)) {
196
196
  return true;
197
197
  }
198
198
  return grpc_channel_stack_builder_prepend_filter(
@@ -178,7 +178,7 @@ void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error* error) {
178
178
  self->Ref().release(); // Ref held by OnTimeout()
179
179
  grpc_chttp2_transport_start_reading(self->result_->transport,
180
180
  args->read_buffer,
181
- &self->on_receive_settings_);
181
+ &self->on_receive_settings_, nullptr);
182
182
  GRPC_CLOSURE_INIT(&self->on_timeout_, OnTimeout, self,
183
183
  grpc_schedule_on_exec_ctx);
184
184
  grpc_timer_init(&self->timer_, self->args_.deadline, &self->on_timeout_);
@@ -37,10 +37,11 @@ namespace grpc_core {
37
37
 
38
38
  class Chttp2InsecureClientChannelFactory : public ClientChannelFactory {
39
39
  public:
40
- Subchannel* CreateSubchannel(const grpc_channel_args* args) override {
40
+ RefCountedPtr<Subchannel> CreateSubchannel(
41
+ const grpc_channel_args* args) override {
41
42
  grpc_channel_args* new_args =
42
43
  grpc_default_authority_add_if_not_present(args);
43
- Subchannel* s =
44
+ RefCountedPtr<Subchannel> s =
44
45
  Subchannel::Create(MakeOrphanable<Chttp2Connector>(), new_args);
45
46
  grpc_channel_args_destroy(new_args);
46
47
  return s;
@@ -62,7 +62,7 @@ grpc_channel* grpc_insecure_channel_create_from_fd(
62
62
  transport, nullptr, &error);
63
63
  grpc_channel_args_destroy(final_args);
64
64
  if (channel != nullptr) {
65
- grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);
65
+ grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr);
66
66
  grpc_core::ExecCtx::Get()->Flush();
67
67
  } else {
68
68
  intptr_t integer;
@@ -43,14 +43,15 @@ namespace grpc_core {
43
43
 
44
44
  class Chttp2SecureClientChannelFactory : public ClientChannelFactory {
45
45
  public:
46
- Subchannel* CreateSubchannel(const grpc_channel_args* args) override {
46
+ RefCountedPtr<Subchannel> CreateSubchannel(
47
+ const grpc_channel_args* args) override {
47
48
  grpc_channel_args* new_args = GetSecureNamingChannelArgs(args);
48
49
  if (new_args == nullptr) {
49
50
  gpr_log(GPR_ERROR,
50
51
  "Failed to create channel args during subchannel creation.");
51
52
  return nullptr;
52
53
  }
53
- Subchannel* s =
54
+ RefCountedPtr<Subchannel> s =
54
55
  Subchannel::Create(MakeOrphanable<Chttp2Connector>(), new_args);
55
56
  grpc_channel_args_destroy(new_args);
56
57
  return s;
@@ -90,98 +90,209 @@ class Chttp2ServerListener : public Server::ListenerInterface {
90
90
  class ConfigFetcherWatcher
91
91
  : public grpc_server_config_fetcher::WatcherInterface {
92
92
  public:
93
- explicit ConfigFetcherWatcher(Chttp2ServerListener* listener)
94
- : listener_(listener) {}
95
-
96
- void UpdateConfig(grpc_channel_args* args) override {
97
- {
98
- MutexLock lock(&listener_->mu_);
99
- grpc_channel_args_destroy(listener_->args_);
100
- grpc_error* error = GRPC_ERROR_NONE;
101
- args = listener_->args_modifier_(args, &error);
102
- if (error != GRPC_ERROR_NONE) {
103
- // TODO(yashykt): Set state to close down connections immediately
104
- // after accepting.
105
- GPR_ASSERT(0);
106
- }
107
- listener_->args_ = args;
108
- if (!listener_->shutdown_) return; // Already started listening.
109
- }
110
- int port_temp;
111
- grpc_error* error = grpc_tcp_server_add_port(
112
- listener_->tcp_server_, &listener_->resolved_address_, &port_temp);
113
- if (error != GRPC_ERROR_NONE) {
114
- GRPC_ERROR_UNREF(error);
115
- gpr_log(GPR_ERROR, "Error adding port to server: %s",
116
- grpc_error_string(error));
117
- // TODO(yashykt): We wouldn't need to assert here if we bound to the
118
- // port earlier during AddPort.
119
- GPR_ASSERT(0);
120
- }
121
- listener_->StartListening();
122
- }
93
+ explicit ConfigFetcherWatcher(RefCountedPtr<Chttp2ServerListener> listener)
94
+ : listener_(std::move(listener)) {}
95
+
96
+ void UpdateConnectionManager(
97
+ RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
98
+ connection_manager) override;
99
+
100
+ void StopServing() override;
123
101
 
124
102
  private:
125
- Chttp2ServerListener* listener_;
103
+ RefCountedPtr<Chttp2ServerListener> listener_;
126
104
  };
127
105
 
128
- class ConnectionState : public RefCounted<ConnectionState> {
106
+ class ActiveConnection : public InternallyRefCounted<ActiveConnection> {
129
107
  public:
130
- ConnectionState(Chttp2ServerListener* listener,
131
- grpc_pollset* accepting_pollset,
132
- grpc_tcp_server_acceptor* acceptor,
133
- RefCountedPtr<HandshakeManager> handshake_mgr,
134
- grpc_channel_args* args, grpc_endpoint* endpoint);
108
+ class HandshakingState : public InternallyRefCounted<HandshakingState> {
109
+ public:
110
+ HandshakingState(RefCountedPtr<ActiveConnection> connection_ref,
111
+ grpc_pollset* accepting_pollset,
112
+ grpc_tcp_server_acceptor* acceptor,
113
+ grpc_channel_args* args);
114
+
115
+ ~HandshakingState() override;
116
+
117
+ void Orphan() override;
135
118
 
136
- ~ConnectionState() override;
119
+ void Start(grpc_endpoint* endpoint, grpc_channel_args* args);
120
+
121
+ // Needed to be able to grab an external ref in ActiveConnection::Start()
122
+ using InternallyRefCounted<HandshakingState>::Ref;
123
+
124
+ private:
125
+ static void OnTimeout(void* arg, grpc_error* error);
126
+ static void OnReceiveSettings(void* arg, grpc_error* /* error */);
127
+ static void OnHandshakeDone(void* arg, grpc_error* error);
128
+ RefCountedPtr<ActiveConnection> const connection_;
129
+ grpc_pollset* const accepting_pollset_;
130
+ grpc_tcp_server_acceptor* const acceptor_;
131
+ RefCountedPtr<HandshakeManager> handshake_mgr_
132
+ ABSL_GUARDED_BY(&connection_->mu_);
133
+ // State for enforcing handshake timeout on receiving HTTP/2 settings.
134
+ grpc_millis const deadline_;
135
+ grpc_timer timer_ ABSL_GUARDED_BY(&connection_->mu_);
136
+ grpc_closure on_timeout_ ABSL_GUARDED_BY(&connection_->mu_);
137
+ grpc_closure on_receive_settings_ ABSL_GUARDED_BY(&connection_->mu_);
138
+ grpc_pollset_set* const interested_parties_;
139
+ };
140
+
141
+ ActiveConnection(grpc_pollset* accepting_pollset,
142
+ grpc_tcp_server_acceptor* acceptor,
143
+ grpc_channel_args* args);
144
+ ~ActiveConnection() override;
145
+
146
+ void Orphan() override;
147
+
148
+ void SendGoAway();
149
+
150
+ void Start(RefCountedPtr<Chttp2ServerListener> listener,
151
+ grpc_endpoint* endpoint, grpc_channel_args* args);
152
+
153
+ // Needed to be able to grab an external ref in
154
+ // Chttp2ServerListener::OnAccept()
155
+ using InternallyRefCounted<ActiveConnection>::Ref;
137
156
 
138
157
  private:
139
- static void OnTimeout(void* arg, grpc_error* error);
140
- static void OnReceiveSettings(void* arg, grpc_error* error);
141
- static void OnHandshakeDone(void* arg, grpc_error* error);
142
-
143
- Chttp2ServerListener* const listener_;
144
- grpc_pollset* const accepting_pollset_;
145
- grpc_tcp_server_acceptor* const acceptor_;
146
- RefCountedPtr<HandshakeManager> handshake_mgr_;
147
- // State for enforcing handshake timeout on receiving HTTP/2 settings.
148
- grpc_chttp2_transport* transport_ = nullptr;
149
- grpc_millis deadline_;
150
- grpc_timer timer_;
151
- grpc_closure on_timeout_;
152
- grpc_closure on_receive_settings_;
153
- grpc_pollset_set* const interested_parties_;
158
+ static void OnClose(void* arg, grpc_error* error);
159
+
160
+ RefCountedPtr<Chttp2ServerListener> listener_;
161
+ Mutex mu_ ABSL_ACQUIRED_AFTER(&listener_->mu_);
162
+ // Set by HandshakingState before the handshaking begins and reset when
163
+ // handshaking is done.
164
+ OrphanablePtr<HandshakingState> handshaking_state_ ABSL_GUARDED_BY(&mu_);
165
+ // Set by HandshakingState when handshaking is done and a valid transport is
166
+ // created.
167
+ grpc_chttp2_transport* transport_ ABSL_GUARDED_BY(&mu_) = nullptr;
168
+ grpc_closure on_close_;
169
+ bool shutdown_ ABSL_GUARDED_BY(&mu_) = false;
154
170
  };
155
171
 
172
+ // To allow access to RefCounted<> like interface.
173
+ friend class RefCountedPtr<Chttp2ServerListener>;
174
+
175
+ // Should only be called once so as to start the TCP server.
156
176
  void StartListening();
157
177
 
158
178
  static void OnAccept(void* arg, grpc_endpoint* tcp,
159
179
  grpc_pollset* accepting_pollset,
160
180
  grpc_tcp_server_acceptor* acceptor);
161
181
 
162
- RefCountedPtr<HandshakeManager> CreateHandshakeManager();
163
-
164
182
  static void TcpServerShutdownComplete(void* arg, grpc_error* error);
165
183
 
166
184
  static void DestroyListener(Server* /*server*/, void* arg,
167
185
  grpc_closure* destroy_done);
168
186
 
187
+ // The interface required by RefCountedPtr<> has been manually implemented
188
+ // here to take a ref on tcp_server_ instead. Note that, the handshaker needs
189
+ // tcp_server_ to exist for the lifetime of the handshake since it's needed by
190
+ // acceptor. Sharing refs between the listener and tcp_server_ is just an
191
+ // optimization to avoid taking additional refs on the listener, since
192
+ // TcpServerShutdownComplete already holds a ref to the listener.
193
+ void IncrementRefCount() { grpc_tcp_server_ref(tcp_server_); }
194
+ void IncrementRefCount(const DebugLocation& /* location */,
195
+ const char* /* reason */) {
196
+ IncrementRefCount();
197
+ }
198
+
199
+ RefCountedPtr<Chttp2ServerListener> Ref() GRPC_MUST_USE_RESULT {
200
+ IncrementRefCount();
201
+ return RefCountedPtr<Chttp2ServerListener>(this);
202
+ }
203
+ RefCountedPtr<Chttp2ServerListener> Ref(const DebugLocation& /* location */,
204
+ const char* /* reason */)
205
+ GRPC_MUST_USE_RESULT {
206
+ return Ref();
207
+ }
208
+
209
+ void Unref() { grpc_tcp_server_unref(tcp_server_); }
210
+ void Unref(const DebugLocation& /* location */, const char* /* reason */) {
211
+ Unref();
212
+ }
213
+
169
214
  Server* const server_;
170
215
  grpc_tcp_server* tcp_server_;
171
216
  grpc_resolved_address resolved_address_;
172
- Chttp2ServerArgsModifier args_modifier_;
173
- Mutex mu_;
174
- grpc_channel_args* args_; // guarded by mu_
217
+ Chttp2ServerArgsModifier const args_modifier_;
175
218
  ConfigFetcherWatcher* config_fetcher_watcher_ = nullptr;
176
- bool shutdown_ = true;
177
- grpc_closure tcp_server_shutdown_complete_;
178
- grpc_closure* on_destroy_done_ = nullptr;
179
- HandshakeManager* pending_handshake_mgrs_ = nullptr;
219
+ Mutex channel_args_mu_;
220
+ grpc_channel_args* args_ ABSL_GUARDED_BY(channel_args_mu_);
221
+ RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
222
+ connection_manager_ ABSL_GUARDED_BY(channel_args_mu_);
223
+ Mutex mu_;
224
+ // Signals whether grpc_tcp_server_start() has been called.
225
+ bool started_ ABSL_GUARDED_BY(mu_) = false;
226
+ // Signals whether grpc_tcp_server_start() has completed.
227
+ CondVar started_cv_ ABSL_GUARDED_BY(mu_);
228
+ // Signals whether new requests/connections are to be accepted.
229
+ bool is_serving_ ABSL_GUARDED_BY(mu_) = false;
230
+ // Signals whether the application has triggered shutdown.
231
+ bool shutdown_ ABSL_GUARDED_BY(mu_) = false;
232
+ std::map<ActiveConnection*, OrphanablePtr<ActiveConnection>> connections_
233
+ ABSL_GUARDED_BY(mu_);
234
+ grpc_closure tcp_server_shutdown_complete_ ABSL_GUARDED_BY(mu_);
235
+ grpc_closure* on_destroy_done_ ABSL_GUARDED_BY(mu_) = nullptr;
180
236
  RefCountedPtr<channelz::ListenSocketNode> channelz_listen_socket_;
181
237
  };
182
238
 
183
239
  //
184
- // Chttp2ServerListener::ConnectionState
240
+ // Chttp2ServerListener::ConfigFetcherWatcher
241
+ //
242
+
243
+ void Chttp2ServerListener::ConfigFetcherWatcher::UpdateConnectionManager(
244
+ RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
245
+ connection_manager) {
246
+ RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
247
+ connection_manager_to_destroy;
248
+ {
249
+ MutexLock lock(&listener_->channel_args_mu_);
250
+ connection_manager_to_destroy = listener_->connection_manager_;
251
+ listener_->connection_manager_ = std::move(connection_manager);
252
+ }
253
+ {
254
+ MutexLock lock(&listener_->mu_);
255
+ if (listener_->shutdown_) {
256
+ return;
257
+ }
258
+ listener_->is_serving_ = true;
259
+ if (listener_->started_) return;
260
+ }
261
+ int port_temp;
262
+ grpc_error* error = grpc_tcp_server_add_port(
263
+ listener_->tcp_server_, &listener_->resolved_address_, &port_temp);
264
+ if (error != GRPC_ERROR_NONE) {
265
+ GRPC_ERROR_UNREF(error);
266
+ gpr_log(GPR_ERROR, "Error adding port to server: %s",
267
+ grpc_error_string(error));
268
+ // TODO(yashykt): We wouldn't need to assert here if we bound to the
269
+ // port earlier during AddPort.
270
+ GPR_ASSERT(0);
271
+ }
272
+ listener_->StartListening();
273
+ {
274
+ MutexLock lock(&listener_->mu_);
275
+ listener_->started_ = true;
276
+ listener_->started_cv_.SignalAll();
277
+ }
278
+ }
279
+
280
+ void Chttp2ServerListener::ConfigFetcherWatcher::StopServing() {
281
+ std::map<ActiveConnection*, OrphanablePtr<ActiveConnection>> connections;
282
+ {
283
+ MutexLock lock(&listener_->mu_);
284
+ listener_->is_serving_ = false;
285
+ connections = std::move(listener_->connections_);
286
+ }
287
+ // Send GOAWAYs on the transports so that they disconnected when existing RPCs
288
+ // finish.
289
+ for (auto& connection : connections) {
290
+ connection.first->SendGoAway();
291
+ }
292
+ }
293
+
294
+ //
295
+ // Chttp2ServerListener::ActiveConnection::HandshakingState
185
296
  //
186
297
 
187
298
  grpc_millis GetConnectionDeadline(const grpc_channel_args* args) {
@@ -191,73 +302,96 @@ grpc_millis GetConnectionDeadline(const grpc_channel_args* args) {
191
302
  return ExecCtx::Get()->Now() + timeout_ms;
192
303
  }
193
304
 
194
- Chttp2ServerListener::ConnectionState::ConnectionState(
195
- Chttp2ServerListener* listener, grpc_pollset* accepting_pollset,
196
- grpc_tcp_server_acceptor* acceptor,
197
- RefCountedPtr<HandshakeManager> handshake_mgr, grpc_channel_args* args,
198
- grpc_endpoint* endpoint)
199
- : listener_(listener),
305
+ Chttp2ServerListener::ActiveConnection::HandshakingState::HandshakingState(
306
+ RefCountedPtr<ActiveConnection> connection_ref,
307
+ grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor,
308
+ grpc_channel_args* args)
309
+ : connection_(std::move(connection_ref)),
200
310
  accepting_pollset_(accepting_pollset),
201
311
  acceptor_(acceptor),
202
- handshake_mgr_(std::move(handshake_mgr)),
312
+ handshake_mgr_(MakeRefCounted<HandshakeManager>()),
203
313
  deadline_(GetConnectionDeadline(args)),
204
314
  interested_parties_(grpc_pollset_set_create()) {
205
315
  grpc_pollset_set_add_pollset(interested_parties_, accepting_pollset_);
206
316
  HandshakerRegistry::AddHandshakers(HANDSHAKER_SERVER, args,
207
317
  interested_parties_, handshake_mgr_.get());
208
- handshake_mgr_->DoHandshake(endpoint, args, deadline_, acceptor_,
209
- OnHandshakeDone, this);
210
318
  }
211
319
 
212
- Chttp2ServerListener::ConnectionState::~ConnectionState() {
213
- if (transport_ != nullptr) {
214
- GRPC_CHTTP2_UNREF_TRANSPORT(transport_, "receive settings timeout");
215
- }
320
+ Chttp2ServerListener::ActiveConnection::HandshakingState::~HandshakingState() {
216
321
  grpc_pollset_set_del_pollset(interested_parties_, accepting_pollset_);
217
322
  grpc_pollset_set_destroy(interested_parties_);
218
323
  }
219
324
 
220
- void Chttp2ServerListener::ConnectionState::OnTimeout(void* arg,
221
- grpc_error* error) {
222
- ConnectionState* self = static_cast<ConnectionState*>(arg);
325
+ void Chttp2ServerListener::ActiveConnection::HandshakingState::Orphan() {
326
+ {
327
+ MutexLock lock(&connection_->mu_);
328
+ if (handshake_mgr_ != nullptr) {
329
+ handshake_mgr_->Shutdown(
330
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("Listener stopped serving."));
331
+ }
332
+ }
333
+ Unref();
334
+ }
335
+
336
+ void Chttp2ServerListener::ActiveConnection::HandshakingState::Start(
337
+ grpc_endpoint* endpoint, grpc_channel_args* args) {
338
+ Ref().release(); // Held by OnHandshakeDone
339
+ RefCountedPtr<HandshakeManager> handshake_mgr;
340
+ {
341
+ MutexLock lock(&connection_->mu_);
342
+ if (handshake_mgr_ == nullptr) return;
343
+ handshake_mgr = handshake_mgr_;
344
+ }
345
+ handshake_mgr->DoHandshake(endpoint, args, deadline_, acceptor_,
346
+ OnHandshakeDone, this);
347
+ }
348
+
349
+ void Chttp2ServerListener::ActiveConnection::HandshakingState::OnTimeout(
350
+ void* arg, grpc_error* error) {
351
+ HandshakingState* self = static_cast<HandshakingState*>(arg);
223
352
  // Note that we may be called with GRPC_ERROR_NONE when the timer fires
224
353
  // or with an error indicating that the timer system is being shut down.
225
354
  if (error != GRPC_ERROR_CANCELLED) {
226
355
  grpc_transport_op* op = grpc_make_transport_op(nullptr);
227
356
  op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
228
357
  "Did not receive HTTP/2 settings before handshake timeout");
229
- grpc_transport_perform_op(&self->transport_->base, op);
358
+ grpc_chttp2_transport* transport = nullptr;
359
+ {
360
+ MutexLock lock(&self->connection_->mu_);
361
+ transport = self->connection_->transport_;
362
+ }
363
+ grpc_transport_perform_op(&transport->base, op);
230
364
  }
231
365
  self->Unref();
232
366
  }
233
367
 
234
- void Chttp2ServerListener::ConnectionState::OnReceiveSettings(
235
- void* arg, grpc_error* error) {
236
- ConnectionState* self = static_cast<ConnectionState*>(arg);
237
- if (error == GRPC_ERROR_NONE) {
238
- grpc_timer_cancel(&self->timer_);
239
- }
368
+ void Chttp2ServerListener::ActiveConnection::HandshakingState::
369
+ OnReceiveSettings(void* arg, grpc_error* /* error */) {
370
+ HandshakingState* self = static_cast<HandshakingState*>(arg);
371
+ grpc_timer_cancel(&self->timer_);
240
372
  self->Unref();
241
373
  }
242
374
 
243
- void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg,
244
- grpc_error* error) {
375
+ void Chttp2ServerListener::ActiveConnection::HandshakingState::OnHandshakeDone(
376
+ void* arg, grpc_error* error) {
245
377
  auto* args = static_cast<HandshakerArgs*>(arg);
246
- ConnectionState* self = static_cast<ConnectionState*>(args->user_data);
378
+ HandshakingState* self = static_cast<HandshakingState*>(args->user_data);
379
+ OrphanablePtr<HandshakingState> handshaking_state_ref;
380
+ RefCountedPtr<HandshakeManager> handshake_mgr;
381
+ bool cleanup_connection = false;
382
+ bool free_resource_quota = false;
383
+ grpc_resource_user* resource_user =
384
+ self->connection_->listener_->server_->default_resource_user();
247
385
  {
248
- MutexLock lock(&self->listener_->mu_);
249
- grpc_resource_user* resource_user =
250
- self->listener_->server_->default_resource_user();
251
- if (error != GRPC_ERROR_NONE || self->listener_->shutdown_) {
386
+ MutexLock connection_lock(&self->connection_->mu_);
387
+ if (error != GRPC_ERROR_NONE || self->connection_->shutdown_) {
252
388
  const char* error_str = grpc_error_string(error);
253
389
  gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
254
- if (resource_user != nullptr) {
255
- grpc_resource_user_free(resource_user,
256
- GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
257
- }
390
+ cleanup_connection = true;
391
+ free_resource_quota = true;
258
392
  if (error == GRPC_ERROR_NONE && args->endpoint != nullptr) {
259
- // We were shut down after handshaking completed successfully, so
260
- // destroy the endpoint here.
393
+ // We were shut down or stopped serving after handshaking completed
394
+ // successfully, so destroy the endpoint here.
261
395
  // TODO(ctiller): It is currently necessary to shutdown endpoints
262
396
  // before destroying them, even if we know that there are no
263
397
  // pending read/write callbacks. This should be fixed, at which
@@ -275,9 +409,11 @@ void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg,
275
409
  if (args->endpoint != nullptr) {
276
410
  grpc_transport* transport = grpc_create_chttp2_transport(
277
411
  args->args, args->endpoint, false, resource_user);
278
- grpc_error* channel_init_err = self->listener_->server_->SetupTransport(
279
- transport, self->accepting_pollset_, args->args,
280
- grpc_chttp2_transport_get_socket_node(transport), resource_user);
412
+ grpc_error* channel_init_err =
413
+ self->connection_->listener_->server_->SetupTransport(
414
+ transport, self->accepting_pollset_, args->args,
415
+ grpc_chttp2_transport_get_socket_node(transport),
416
+ resource_user);
281
417
  if (channel_init_err == GRPC_ERROR_NONE) {
282
418
  // Use notify_on_receive_settings callback to enforce the
283
419
  // handshake deadline.
@@ -287,18 +423,32 @@ void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg,
287
423
  // static_cast<> to a derived class.
288
424
  // TODO(roth): Change to static_cast<> when we C++-ify the
289
425
  // transport API.
290
- self->transport_ =
426
+ self->connection_->transport_ =
291
427
  reinterpret_cast<grpc_chttp2_transport*>(transport);
428
+ GRPC_CHTTP2_REF_TRANSPORT(self->connection_->transport_,
429
+ "ActiveConnection"); // Held by connection_
292
430
  self->Ref().release(); // Held by OnReceiveSettings().
293
431
  GRPC_CLOSURE_INIT(&self->on_receive_settings_, OnReceiveSettings,
294
432
  self, grpc_schedule_on_exec_ctx);
433
+ // If the listener has been configured with a config fetcher, we need
434
+ // to watch on the transport being closed so that we can an updated
435
+ // list of active connections.
436
+ grpc_closure* on_close = nullptr;
437
+ if (self->connection_->listener_->config_fetcher_watcher_ !=
438
+ nullptr) {
439
+ // Refs helds by OnClose()
440
+ self->connection_->Ref().release();
441
+ on_close = &self->connection_->on_close_;
442
+ } else {
443
+ // Remove the connection from the connections_ map since OnClose()
444
+ // will not be invoked when a config fetcher is set.
445
+ cleanup_connection = true;
446
+ }
295
447
  grpc_chttp2_transport_start_reading(transport, args->read_buffer,
296
- &self->on_receive_settings_);
448
+ &self->on_receive_settings_,
449
+ on_close);
297
450
  grpc_channel_args_destroy(args->args);
298
451
  self->Ref().release(); // Held by OnTimeout().
299
- GRPC_CHTTP2_REF_TRANSPORT(
300
- reinterpret_cast<grpc_chttp2_transport*>(transport),
301
- "receive settings timeout");
302
452
  GRPC_CLOSURE_INIT(&self->on_timeout_, OnTimeout, self,
303
453
  grpc_schedule_on_exec_ctx);
304
454
  grpc_timer_init(&self->timer_, self->deadline_, &self->on_timeout_);
@@ -310,25 +460,116 @@ void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg,
310
460
  grpc_transport_destroy(transport);
311
461
  grpc_slice_buffer_destroy_internal(args->read_buffer);
312
462
  gpr_free(args->read_buffer);
313
- if (resource_user != nullptr) {
314
- grpc_resource_user_free(resource_user,
315
- GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
316
- }
463
+ cleanup_connection = true;
464
+ free_resource_quota = true;
317
465
  grpc_channel_args_destroy(args->args);
318
466
  }
319
467
  } else {
320
- if (resource_user != nullptr) {
321
- grpc_resource_user_free(resource_user,
322
- GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
323
- }
468
+ cleanup_connection = true;
469
+ free_resource_quota = true;
324
470
  }
325
471
  }
326
- self->handshake_mgr_->RemoveFromPendingMgrList(
327
- &self->listener_->pending_handshake_mgrs_);
472
+ // Since the handshake manager is done, the connection no longer needs to
473
+ // shutdown the handshake when the listener needs to stop serving.
474
+ // Avoid calling the destructor of HandshakeManager and HandshakingState
475
+ // from within the critical region.
476
+ handshake_mgr = std::move(self->handshake_mgr_);
477
+ handshaking_state_ref = std::move(self->connection_->handshaking_state_);
328
478
  }
329
- self->handshake_mgr_.reset();
330
479
  gpr_free(self->acceptor_);
331
- grpc_tcp_server_unref(self->listener_->tcp_server_);
480
+ OrphanablePtr<ActiveConnection> connection;
481
+ if (free_resource_quota && resource_user != nullptr) {
482
+ grpc_resource_user_free(resource_user, GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
483
+ }
484
+ if (cleanup_connection) {
485
+ MutexLock listener_lock(&self->connection_->listener_->mu_);
486
+ auto it = self->connection_->listener_->connections_.find(
487
+ self->connection_.get());
488
+ if (it != self->connection_->listener_->connections_.end()) {
489
+ connection = std::move(it->second);
490
+ self->connection_->listener_->connections_.erase(it);
491
+ }
492
+ }
493
+ self->Unref();
494
+ }
495
+
496
+ //
497
+ // Chttp2ServerListener::ActiveConnection
498
+ //
499
+
500
+ Chttp2ServerListener::ActiveConnection::ActiveConnection(
501
+ grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor,
502
+ grpc_channel_args* args)
503
+ : handshaking_state_(MakeOrphanable<HandshakingState>(
504
+ Ref(), accepting_pollset, acceptor, args)) {
505
+ GRPC_CLOSURE_INIT(&on_close_, ActiveConnection::OnClose, this,
506
+ grpc_schedule_on_exec_ctx);
507
+ }
508
+
509
+ Chttp2ServerListener::ActiveConnection::~ActiveConnection() {
510
+ if (transport_ != nullptr) {
511
+ GRPC_CHTTP2_UNREF_TRANSPORT(transport_, "ActiveConnection");
512
+ }
513
+ }
514
+
515
+ void Chttp2ServerListener::ActiveConnection::Orphan() {
516
+ OrphanablePtr<HandshakingState> handshaking_state;
517
+ {
518
+ MutexLock lock(&mu_);
519
+ shutdown_ = true;
520
+ // Reset handshaking_state_ since we have been orphaned by the listener
521
+ // signaling that the listener has stopped serving.
522
+ handshaking_state = std::move(handshaking_state_);
523
+ }
524
+ Unref();
525
+ }
526
+
527
+ void Chttp2ServerListener::ActiveConnection::SendGoAway() {
528
+ grpc_chttp2_transport* transport = nullptr;
529
+ {
530
+ MutexLock lock(&mu_);
531
+ transport = transport_;
532
+ }
533
+ if (transport != nullptr) {
534
+ grpc_transport_op* op = grpc_make_transport_op(nullptr);
535
+ op->goaway_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
536
+ "Server is stopping to serve requests.");
537
+ grpc_transport_perform_op(&transport->base, op);
538
+ }
539
+ }
540
+
541
+ void Chttp2ServerListener::ActiveConnection::Start(
542
+ RefCountedPtr<Chttp2ServerListener> listener, grpc_endpoint* endpoint,
543
+ grpc_channel_args* args) {
544
+ RefCountedPtr<HandshakingState> handshaking_state_ref;
545
+ listener_ = std::move(listener);
546
+ {
547
+ MutexLock lock(&mu_);
548
+ if (shutdown_) return;
549
+ // Hold a ref to HandshakingState to allow starting the handshake outside
550
+ // the critical region.
551
+ handshaking_state_ref = handshaking_state_->Ref();
552
+ }
553
+ handshaking_state_ref->Start(endpoint, args);
554
+ }
555
+
556
+ void Chttp2ServerListener::ActiveConnection::OnClose(void* arg,
557
+ grpc_error* /* error */) {
558
+ ActiveConnection* self = static_cast<ActiveConnection*>(arg);
559
+ OrphanablePtr<ActiveConnection> connection;
560
+ {
561
+ MutexLock listener_lock(&self->listener_->mu_);
562
+ MutexLock connection_lock(&self->mu_);
563
+ // The node was already deleted from the connections_ list if the connection
564
+ // is shutdown.
565
+ if (!self->shutdown_) {
566
+ auto it = self->listener_->connections_.find(self);
567
+ if (it != self->listener_->connections_.end()) {
568
+ connection = std::move(it->second);
569
+ self->listener_->connections_.erase(it);
570
+ }
571
+ }
572
+ }
332
573
  self->Unref();
333
574
  }
334
575
 
@@ -361,7 +602,7 @@ grpc_error* Chttp2ServerListener::Create(Server* server,
361
602
  // Create channelz node.
362
603
  if (grpc_channel_args_find_bool(args, GRPC_ARG_ENABLE_CHANNELZ,
363
604
  GRPC_ENABLE_CHANNELZ_DEFAULT)) {
364
- std::string string_address = grpc_sockaddr_to_string(addr, false);
605
+ std::string string_address = grpc_sockaddr_to_uri(addr);
365
606
  listener->channelz_listen_socket_ =
366
607
  MakeRefCounted<channelz::ListenSocketNode>(
367
608
  string_address.c_str(),
@@ -414,6 +655,13 @@ Chttp2ServerListener::Chttp2ServerListener(
414
655
  }
415
656
 
416
657
  Chttp2ServerListener::~Chttp2ServerListener() {
658
+ // Flush queued work before destroying handshaker factory, since that
659
+ // may do a synchronous unref.
660
+ ExecCtx::Get()->Flush();
661
+ if (on_destroy_done_ != nullptr) {
662
+ ExecCtx::Run(DEBUG_LOCATION, on_destroy_done_, GRPC_ERROR_NONE);
663
+ ExecCtx::Get()->Flush();
664
+ }
417
665
  grpc_channel_args_destroy(args_);
418
666
  }
419
667
 
@@ -422,24 +670,27 @@ void Chttp2ServerListener::Start(
422
670
  Server* /*server*/, const std::vector<grpc_pollset*>* /* pollsets */) {
423
671
  if (server_->config_fetcher() != nullptr) {
424
672
  grpc_channel_args* args = nullptr;
425
- auto watcher = absl::make_unique<ConfigFetcherWatcher>(this);
673
+ auto watcher = absl::make_unique<ConfigFetcherWatcher>(Ref());
674
+ config_fetcher_watcher_ = watcher.get();
426
675
  {
427
- MutexLock lock(&mu_);
428
- config_fetcher_watcher_ = watcher.get();
676
+ MutexLock lock(&channel_args_mu_);
429
677
  args = grpc_channel_args_copy(args_);
430
678
  }
431
679
  server_->config_fetcher()->StartWatch(
432
680
  grpc_sockaddr_to_string(&resolved_address_, false), args,
433
681
  std::move(watcher));
434
682
  } else {
683
+ {
684
+ MutexLock lock(&mu_);
685
+ started_ = true;
686
+ is_serving_ = true;
687
+ }
435
688
  StartListening();
436
689
  }
437
690
  }
438
691
 
439
692
  void Chttp2ServerListener::StartListening() {
440
693
  grpc_tcp_server_start(tcp_server_, &server_->pollsets(), OnAccept, this);
441
- MutexLock lock(&mu_);
442
- shutdown_ = false;
443
694
  }
444
695
 
445
696
  void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) {
@@ -447,67 +698,93 @@ void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) {
447
698
  on_destroy_done_ = on_destroy_done;
448
699
  }
449
700
 
450
- RefCountedPtr<HandshakeManager> Chttp2ServerListener::CreateHandshakeManager() {
451
- MutexLock lock(&mu_);
452
- if (shutdown_) return nullptr;
453
- grpc_resource_user* resource_user = server_->default_resource_user();
454
- if (resource_user != nullptr &&
455
- !grpc_resource_user_safe_alloc(resource_user,
456
- GRPC_RESOURCE_QUOTA_CHANNEL_SIZE)) {
457
- gpr_log(GPR_ERROR,
458
- "Memory quota exhausted, rejecting connection, no handshaking.");
459
- return nullptr;
460
- }
461
- auto handshake_mgr = MakeRefCounted<HandshakeManager>();
462
- handshake_mgr->AddToPendingMgrList(&pending_handshake_mgrs_);
463
- grpc_tcp_server_ref(tcp_server_); // Ref held by ConnectionState.
464
- return handshake_mgr;
465
- }
466
-
467
701
  void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
468
702
  grpc_pollset* accepting_pollset,
469
703
  grpc_tcp_server_acceptor* acceptor) {
470
704
  Chttp2ServerListener* self = static_cast<Chttp2ServerListener*>(arg);
471
- RefCountedPtr<HandshakeManager> handshake_mgr =
472
- self->CreateHandshakeManager();
473
- if (handshake_mgr == nullptr) {
474
- grpc_endpoint_shutdown(tcp, GRPC_ERROR_NONE);
705
+ grpc_channel_args* args = nullptr;
706
+ RefCountedPtr<grpc_server_config_fetcher::ConnectionManager>
707
+ connection_manager;
708
+ {
709
+ MutexLock lock(&self->channel_args_mu_);
710
+ args = grpc_channel_args_copy(self->args_);
711
+ connection_manager = self->connection_manager_;
712
+ }
713
+ auto endpoint_cleanup = [&](grpc_error* error) {
714
+ grpc_endpoint_shutdown(tcp, error);
475
715
  grpc_endpoint_destroy(tcp);
476
716
  gpr_free(acceptor);
477
- return;
717
+ };
718
+ if (self->server_->config_fetcher() != nullptr) {
719
+ if (connection_manager == nullptr) {
720
+ grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
721
+ "No ConnectionManager configured. Closing connection.");
722
+ endpoint_cleanup(error);
723
+ grpc_channel_args_destroy(args);
724
+ return;
725
+ }
726
+ // TODO(yashykt): Maybe combine the following two arg modifiers into a
727
+ // single one.
728
+ absl::StatusOr<grpc_channel_args*> args_result =
729
+ connection_manager->UpdateChannelArgsForConnection(args, tcp);
730
+ if (!args_result.ok()) {
731
+ gpr_log(GPR_DEBUG, "Closing connection: %s",
732
+ args_result.status().ToString().c_str());
733
+ endpoint_cleanup(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
734
+ args_result.status().ToString().c_str()));
735
+ return;
736
+ }
737
+ grpc_error* error = GRPC_ERROR_NONE;
738
+ args = self->args_modifier_(*args_result, &error);
739
+ if (error != GRPC_ERROR_NONE) {
740
+ gpr_log(GPR_DEBUG, "Closing connection: %s", grpc_error_string(error));
741
+ endpoint_cleanup(error);
742
+ grpc_channel_args_destroy(args);
743
+ return;
744
+ }
478
745
  }
479
- grpc_channel_args* args = nullptr;
746
+ auto connection =
747
+ MakeOrphanable<ActiveConnection>(accepting_pollset, acceptor, args);
748
+ // Hold a ref to connection to allow starting handshake outside the
749
+ // critical region
750
+ RefCountedPtr<ActiveConnection> connection_ref = connection->Ref();
751
+ RefCountedPtr<Chttp2ServerListener> listener_ref;
480
752
  {
481
753
  MutexLock lock(&self->mu_);
482
- args = grpc_channel_args_copy(self->args_);
754
+ // Shutdown the the connection if listener's stopped serving.
755
+ if (!self->shutdown_ && self->is_serving_) {
756
+ grpc_resource_user* resource_user =
757
+ self->server_->default_resource_user();
758
+ if (resource_user != nullptr &&
759
+ !grpc_resource_user_safe_alloc(resource_user,
760
+ GRPC_RESOURCE_QUOTA_CHANNEL_SIZE)) {
761
+ gpr_log(
762
+ GPR_ERROR,
763
+ "Memory quota exhausted, rejecting connection, no handshaking.");
764
+ } else {
765
+ // This ref needs to be taken in the critical region after having made
766
+ // sure that the listener has not been Orphaned, so as to avoid
767
+ // heap-use-after-free issues where `Ref()` is invoked when the ref of
768
+ // tcp_server_ has already reached 0. (Ref() implementation of
769
+ // Chttp2ServerListener is grpc_tcp_server_ref().)
770
+ listener_ref = self->Ref();
771
+ self->connections_.emplace(connection.get(), std::move(connection));
772
+ }
773
+ }
774
+ }
775
+ if (connection != nullptr) {
776
+ endpoint_cleanup(GRPC_ERROR_NONE);
777
+ } else {
778
+ connection_ref->Start(std::move(listener_ref), tcp, args);
483
779
  }
484
- // Deletes itself when done.
485
- new ConnectionState(self, accepting_pollset, acceptor,
486
- std::move(handshake_mgr), args, tcp);
487
780
  grpc_channel_args_destroy(args);
488
781
  }
489
782
 
490
783
  void Chttp2ServerListener::TcpServerShutdownComplete(void* arg,
491
784
  grpc_error* error) {
492
785
  Chttp2ServerListener* self = static_cast<Chttp2ServerListener*>(arg);
493
- /* ensure all threads have unlocked */
494
- grpc_closure* destroy_done = nullptr;
495
- {
496
- MutexLock lock(&self->mu_);
497
- destroy_done = self->on_destroy_done_;
498
- GPR_ASSERT(self->shutdown_);
499
- if (self->pending_handshake_mgrs_ != nullptr) {
500
- self->pending_handshake_mgrs_->ShutdownAllPending(GRPC_ERROR_REF(error));
501
- }
502
- self->channelz_listen_socket_.reset();
503
- }
504
- // Flush queued work before destroying handshaker factory, since that
505
- // may do a synchronous unref.
506
- ExecCtx::Get()->Flush();
507
- if (destroy_done != nullptr) {
508
- ExecCtx::Run(DEBUG_LOCATION, destroy_done, GRPC_ERROR_REF(error));
509
- ExecCtx::Get()->Flush();
510
- }
786
+ self->channelz_listen_socket_.reset();
787
+ GRPC_ERROR_UNREF(error);
511
788
  delete self;
512
789
  }
513
790
 
@@ -519,10 +796,20 @@ void Chttp2ServerListener::Orphan() {
519
796
  if (config_fetcher_watcher_ != nullptr) {
520
797
  server_->config_fetcher()->CancelWatch(config_fetcher_watcher_);
521
798
  }
799
+ std::map<ActiveConnection*, OrphanablePtr<ActiveConnection>> connections;
522
800
  grpc_tcp_server* tcp_server;
523
801
  {
524
802
  MutexLock lock(&mu_);
525
803
  shutdown_ = true;
804
+ is_serving_ = false;
805
+ // Orphan the connections so that they can start cleaning up.
806
+ connections = std::move(connections_);
807
+ // If the listener is currently set to be serving but has not been started
808
+ // yet, it means that `grpc_tcp_server_start` is in progress. Wait for the
809
+ // operation to finish to avoid causing races.
810
+ while (is_serving_ && !started_) {
811
+ started_cv_.Wait(&mu_);
812
+ }
526
813
  tcp_server = tcp_server_;
527
814
  }
528
815
  grpc_tcp_server_shutdown_listeners(tcp_server);