grpc 1.18.0 → 1.19.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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +301 -33
  3. data/include/grpc/grpc_security.h +195 -0
  4. data/include/grpc/impl/codegen/grpc_types.h +17 -1
  5. data/include/grpc/impl/codegen/port_platform.h +36 -0
  6. data/include/grpc/impl/codegen/slice.h +1 -1
  7. data/src/core/ext/filters/client_channel/channel_connectivity.cc +2 -0
  8. data/src/core/ext/filters/client_channel/client_channel.cc +74 -69
  9. data/src/core/ext/filters/client_channel/client_channel.h +2 -2
  10. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +5 -6
  11. data/src/core/ext/filters/client_channel/client_channel_channelz.h +5 -4
  12. data/src/core/ext/filters/client_channel/client_channel_factory.cc +2 -2
  13. data/src/core/ext/filters/client_channel/client_channel_factory.h +4 -4
  14. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +3 -3
  15. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +176 -0
  16. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +68 -0
  17. data/src/core/ext/filters/client_channel/health/health_check_client.cc +10 -8
  18. data/src/core/ext/filters/client_channel/health/health_check_client.h +1 -1
  19. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +146 -156
  20. data/src/core/ext/filters/client_channel/lb_policy.cc +30 -1
  21. data/src/core/ext/filters/client_channel/lb_policy.h +29 -1
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +28 -30
  23. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +5 -8
  24. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +5 -8
  25. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +23 -24
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +80 -15
  27. data/src/core/ext/filters/client_channel/lb_policy_factory.h +6 -1
  28. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +2 -2
  29. data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
  30. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +96 -0
  31. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +56 -0
  32. data/src/core/ext/filters/client_channel/parse_address.cc +24 -5
  33. data/src/core/ext/filters/client_channel/request_routing.cc +13 -3
  34. data/src/core/ext/filters/client_channel/request_routing.h +5 -1
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +11 -6
  36. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +2 -2
  37. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +7 -35
  38. data/src/core/ext/filters/client_channel/subchannel.cc +698 -791
  39. data/src/core/ext/filters/client_channel/subchannel.h +213 -123
  40. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +97 -0
  41. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +94 -0
  42. data/src/core/ext/filters/http/client_authority_filter.cc +5 -2
  43. data/src/core/ext/filters/max_age/max_age_filter.cc +1 -1
  44. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -12
  45. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +5 -7
  46. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +19 -27
  47. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +18 -19
  48. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +27 -6
  49. data/src/core/ext/transport/chttp2/transport/flow_control.cc +1 -1
  50. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +3 -2
  51. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
  52. data/src/core/ext/transport/chttp2/transport/writing.cc +8 -5
  53. data/src/core/lib/channel/handshaker.cc +141 -214
  54. data/src/core/lib/channel/handshaker.h +110 -101
  55. data/src/core/lib/channel/handshaker_factory.h +11 -19
  56. data/src/core/lib/channel/handshaker_registry.cc +64 -52
  57. data/src/core/lib/channel/handshaker_registry.h +21 -16
  58. data/src/core/lib/gpr/log_posix.cc +2 -1
  59. data/src/core/lib/gpr/time.cc +8 -0
  60. data/src/core/lib/gpr/time_posix.cc +8 -2
  61. data/src/core/lib/gprpp/optional.h +47 -0
  62. data/src/core/lib/http/httpcli_security_connector.cc +13 -14
  63. data/src/core/lib/iomgr/buffer_list.cc +182 -24
  64. data/src/core/lib/iomgr/buffer_list.h +70 -8
  65. data/src/core/lib/iomgr/combiner.cc +11 -3
  66. data/src/core/lib/iomgr/error.cc +9 -5
  67. data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -0
  68. data/src/core/lib/iomgr/ev_epollex_linux.cc +136 -162
  69. data/src/core/lib/iomgr/ev_poll_posix.cc +3 -0
  70. data/src/core/lib/iomgr/ev_posix.cc +4 -0
  71. data/src/core/lib/iomgr/ev_posix.h +4 -0
  72. data/src/core/lib/iomgr/exec_ctx.cc +1 -0
  73. data/src/core/lib/iomgr/exec_ctx.h +137 -8
  74. data/src/core/lib/iomgr/executor.cc +122 -87
  75. data/src/core/lib/iomgr/executor.h +53 -48
  76. data/src/core/lib/iomgr/fork_posix.cc +6 -4
  77. data/src/core/lib/iomgr/{network_status_tracker.cc → grpc_if_nametoindex.h} +8 -14
  78. data/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +42 -0
  79. data/src/core/lib/iomgr/{network_status_tracker.h → grpc_if_nametoindex_unsupported.cc} +15 -9
  80. data/src/core/lib/iomgr/internal_errqueue.h +105 -3
  81. data/src/core/lib/iomgr/iomgr.cc +6 -5
  82. data/src/core/lib/iomgr/iomgr.h +8 -0
  83. data/src/core/lib/iomgr/iomgr_custom.cc +6 -2
  84. data/src/core/lib/iomgr/iomgr_internal.cc +4 -0
  85. data/src/core/lib/iomgr/iomgr_internal.h +4 -0
  86. data/src/core/lib/iomgr/iomgr_posix.cc +10 -1
  87. data/src/core/lib/iomgr/iomgr_windows.cc +8 -1
  88. data/src/core/lib/iomgr/port.h +1 -0
  89. data/src/core/lib/iomgr/resolve_address_posix.cc +4 -3
  90. data/src/core/lib/iomgr/resolve_address_windows.cc +2 -1
  91. data/src/core/lib/iomgr/tcp_custom.cc +0 -4
  92. data/src/core/lib/iomgr/tcp_posix.cc +58 -44
  93. data/src/core/lib/iomgr/tcp_uv.cc +0 -1
  94. data/src/core/lib/iomgr/tcp_windows.cc +0 -4
  95. data/src/core/lib/iomgr/timer_manager.cc +8 -0
  96. data/src/core/lib/iomgr/udp_server.cc +6 -4
  97. data/src/core/lib/json/json.cc +1 -4
  98. data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
  99. data/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +2 -2
  100. data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -0
  101. data/src/core/lib/security/credentials/credentials.h +9 -1
  102. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +15 -2
  103. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -0
  104. data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
  105. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -0
  106. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +3 -2
  107. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +2 -2
  108. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -0
  109. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +192 -0
  110. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +213 -0
  111. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +10 -8
  112. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +6 -10
  113. data/src/core/lib/security/security_connector/local/local_security_connector.cc +10 -8
  114. data/src/core/lib/security/security_connector/security_connector.h +2 -2
  115. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +4 -6
  116. data/src/core/lib/security/security_connector/ssl_utils.h +33 -0
  117. data/src/core/lib/security/transport/security_handshaker.cc +267 -300
  118. data/src/core/lib/security/transport/security_handshaker.h +11 -2
  119. data/src/core/lib/security/transport/server_auth_filter.cc +1 -0
  120. data/src/core/lib/surface/call.cc +5 -1
  121. data/src/core/lib/surface/channel_init.h +5 -0
  122. data/src/core/lib/surface/completion_queue.cc +4 -7
  123. data/src/core/lib/surface/init.cc +5 -3
  124. data/src/core/lib/surface/init_secure.cc +1 -1
  125. data/src/core/lib/surface/server.cc +19 -17
  126. data/src/core/lib/surface/version.cc +1 -1
  127. data/src/core/lib/transport/service_config.h +1 -0
  128. data/src/core/lib/transport/static_metadata.cc +279 -279
  129. data/src/core/lib/transport/transport.cc +5 -3
  130. data/src/core/tsi/ssl_transport_security.cc +10 -4
  131. data/src/ruby/ext/grpc/extconf.rb +12 -4
  132. data/src/ruby/ext/grpc/rb_call_credentials.c +8 -5
  133. data/src/ruby/ext/grpc/rb_channel.c +14 -10
  134. data/src/ruby/ext/grpc/rb_channel_credentials.c +8 -4
  135. data/src/ruby/ext/grpc/rb_compression_options.c +9 -7
  136. data/src/ruby/ext/grpc/rb_event_thread.c +2 -0
  137. data/src/ruby/ext/grpc/rb_grpc.c +22 -23
  138. data/src/ruby/ext/grpc/rb_grpc.h +4 -2
  139. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +18 -0
  140. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +27 -0
  141. data/src/ruby/ext/grpc/rb_server.c +8 -4
  142. data/src/ruby/lib/grpc/version.rb +1 -1
  143. metadata +46 -39
  144. data/src/core/ext/filters/client_channel/subchannel_index.cc +0 -248
  145. data/src/core/ext/filters/client_channel/subchannel_index.h +0 -76
  146. data/src/core/lib/channel/handshaker_factory.cc +0 -42
@@ -60,7 +60,7 @@ void grpc_client_channel_watch_connectivity_state(
60
60
  grpc_closure* watcher_timer_init);
61
61
 
62
62
  /* Debug helper: pull the subchannel call from a call stack element */
63
- grpc_subchannel_call* grpc_client_channel_get_subchannel_call(
64
- grpc_call_element* elem);
63
+ grpc_core::RefCountedPtr<grpc_core::SubchannelCall>
64
+ grpc_client_channel_get_subchannel_call(grpc_call_element* elem);
65
65
 
66
66
  #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */
@@ -113,12 +113,11 @@ RefCountedPtr<ChannelNode> ClientChannelNode::MakeClientChannelNode(
113
113
  is_top_level_channel);
114
114
  }
115
115
 
116
- SubchannelNode::SubchannelNode(grpc_subchannel* subchannel,
116
+ SubchannelNode::SubchannelNode(Subchannel* subchannel,
117
117
  size_t channel_tracer_max_nodes)
118
118
  : BaseNode(EntityType::kSubchannel),
119
119
  subchannel_(subchannel),
120
- target_(
121
- UniquePtr<char>(gpr_strdup(grpc_subchannel_get_target(subchannel_)))),
120
+ target_(UniquePtr<char>(gpr_strdup(subchannel_->GetTargetAddress()))),
122
121
  trace_(channel_tracer_max_nodes) {}
123
122
 
124
123
  SubchannelNode::~SubchannelNode() {}
@@ -128,8 +127,8 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
128
127
  if (subchannel_ == nullptr) {
129
128
  state = GRPC_CHANNEL_SHUTDOWN;
130
129
  } else {
131
- state = grpc_subchannel_check_connectivity(
132
- subchannel_, nullptr, true /* inhibit_health_checking */);
130
+ state = subchannel_->CheckConnectivity(nullptr,
131
+ true /* inhibit_health_checking */);
133
132
  }
134
133
  json = grpc_json_create_child(nullptr, json, "state", nullptr,
135
134
  GRPC_JSON_OBJECT, false);
@@ -170,7 +169,7 @@ grpc_json* SubchannelNode::RenderJson() {
170
169
  call_counter_.PopulateCallCounts(json);
171
170
  json = top_level_json;
172
171
  // populate the child socket.
173
- intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_);
172
+ intptr_t socket_uuid = subchannel_->GetChildSocketUuid();
174
173
  if (socket_uuid != 0) {
175
174
  grpc_json* array_parent = grpc_json_create_child(
176
175
  nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
@@ -26,9 +26,10 @@
26
26
  #include "src/core/lib/channel/channel_trace.h"
27
27
  #include "src/core/lib/channel/channelz.h"
28
28
 
29
- typedef struct grpc_subchannel grpc_subchannel;
30
-
31
29
  namespace grpc_core {
30
+
31
+ class Subchannel;
32
+
32
33
  namespace channelz {
33
34
 
34
35
  // Subtype of ChannelNode that overrides and provides client_channel specific
@@ -59,7 +60,7 @@ class ClientChannelNode : public ChannelNode {
59
60
  // Handles channelz bookkeeping for sockets
60
61
  class SubchannelNode : public BaseNode {
61
62
  public:
62
- SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes);
63
+ SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes);
63
64
  ~SubchannelNode() override;
64
65
 
65
66
  void MarkSubchannelDestroyed() {
@@ -84,7 +85,7 @@ class SubchannelNode : public BaseNode {
84
85
  void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); }
85
86
 
86
87
  private:
87
- grpc_subchannel* subchannel_;
88
+ Subchannel* subchannel_;
88
89
  UniquePtr<char> target_;
89
90
  CallCountingHelper call_counter_;
90
91
  ChannelTrace trace_;
@@ -29,8 +29,8 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) {
29
29
  factory->vtable->unref(factory);
30
30
  }
31
31
 
32
- grpc_subchannel* grpc_client_channel_factory_create_subchannel(
33
- grpc_client_channel_factory* factory, const grpc_subchannel_args* args) {
32
+ grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel(
33
+ grpc_client_channel_factory* factory, const grpc_channel_args* args) {
34
34
  return factory->vtable->create_subchannel(factory, args);
35
35
  }
36
36
 
@@ -48,8 +48,8 @@ struct grpc_client_channel_factory {
48
48
  struct grpc_client_channel_factory_vtable {
49
49
  void (*ref)(grpc_client_channel_factory* factory);
50
50
  void (*unref)(grpc_client_channel_factory* factory);
51
- grpc_subchannel* (*create_subchannel)(grpc_client_channel_factory* factory,
52
- const grpc_subchannel_args* args);
51
+ grpc_core::Subchannel* (*create_subchannel)(
52
+ grpc_client_channel_factory* factory, const grpc_channel_args* args);
53
53
  grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory,
54
54
  const char* target,
55
55
  grpc_client_channel_type type,
@@ -60,8 +60,8 @@ void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory);
60
60
  void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory);
61
61
 
62
62
  /** Create a new grpc_subchannel */
63
- grpc_subchannel* grpc_client_channel_factory_create_subchannel(
64
- grpc_client_channel_factory* factory, const grpc_subchannel_args* args);
63
+ grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel(
64
+ grpc_client_channel_factory* factory, const grpc_channel_args* args);
65
65
 
66
66
  /** Create a new grpc_channel */
67
67
  grpc_channel* grpc_client_channel_factory_create_channel(
@@ -26,13 +26,13 @@
26
26
 
27
27
  #include "src/core/ext/filters/client_channel/client_channel.h"
28
28
  #include "src/core/ext/filters/client_channel/client_channel_channelz.h"
29
+ #include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
29
30
  #include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
30
31
  #include "src/core/ext/filters/client_channel/http_proxy.h"
31
32
  #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
32
33
  #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
33
34
  #include "src/core/ext/filters/client_channel/resolver_registry.h"
34
35
  #include "src/core/ext/filters/client_channel/retry_throttle.h"
35
- #include "src/core/ext/filters/client_channel/subchannel_index.h"
36
36
  #include "src/core/lib/surface/channel_init.h"
37
37
 
38
38
  static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
@@ -54,7 +54,7 @@ void grpc_client_channel_init(void) {
54
54
  grpc_core::internal::ServerRetryThrottleMap::Init();
55
55
  grpc_proxy_mapper_registry_init();
56
56
  grpc_register_http_proxy_mapper();
57
- grpc_subchannel_index_init();
57
+ grpc_core::GlobalSubchannelPool::Init();
58
58
  grpc_channel_init_register_stage(
59
59
  GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
60
60
  (void*)&grpc_client_channel_filter);
@@ -62,7 +62,7 @@ void grpc_client_channel_init(void) {
62
62
  }
63
63
 
64
64
  void grpc_client_channel_shutdown(void) {
65
- grpc_subchannel_index_shutdown();
65
+ grpc_core::GlobalSubchannelPool::Shutdown();
66
66
  grpc_channel_init_shutdown();
67
67
  grpc_proxy_mapper_registry_shutdown();
68
68
  grpc_core::internal::ServerRetryThrottleMap::Shutdown();
@@ -0,0 +1,176 @@
1
+ //
2
+ //
3
+ // Copyright 2018 gRPC authors.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ //
17
+ //
18
+
19
+ #include <grpc/support/port_platform.h>
20
+
21
+ #include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
22
+
23
+ #include "src/core/ext/filters/client_channel/subchannel.h"
24
+
25
+ namespace grpc_core {
26
+
27
+ GlobalSubchannelPool::GlobalSubchannelPool() {
28
+ subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_);
29
+ gpr_mu_init(&mu_);
30
+ }
31
+
32
+ GlobalSubchannelPool::~GlobalSubchannelPool() {
33
+ gpr_mu_destroy(&mu_);
34
+ grpc_avl_unref(subchannel_map_, nullptr);
35
+ }
36
+
37
+ void GlobalSubchannelPool::Init() {
38
+ instance_ = New<RefCountedPtr<GlobalSubchannelPool>>(
39
+ MakeRefCounted<GlobalSubchannelPool>());
40
+ }
41
+
42
+ void GlobalSubchannelPool::Shutdown() {
43
+ // To ensure Init() was called before.
44
+ GPR_ASSERT(instance_ != nullptr);
45
+ // To ensure Shutdown() was not called before.
46
+ GPR_ASSERT(*instance_ != nullptr);
47
+ instance_->reset();
48
+ Delete(instance_);
49
+ }
50
+
51
+ RefCountedPtr<GlobalSubchannelPool> GlobalSubchannelPool::instance() {
52
+ GPR_ASSERT(instance_ != nullptr);
53
+ GPR_ASSERT(*instance_ != nullptr);
54
+ return *instance_;
55
+ }
56
+
57
+ Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key,
58
+ Subchannel* constructed) {
59
+ Subchannel* c = nullptr;
60
+ // Compare and swap (CAS) loop:
61
+ while (c == nullptr) {
62
+ // Ref the shared map to have a local copy.
63
+ gpr_mu_lock(&mu_);
64
+ grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr);
65
+ gpr_mu_unlock(&mu_);
66
+ // Check to see if a subchannel already exists.
67
+ c = static_cast<Subchannel*>(grpc_avl_get(old_map, key, nullptr));
68
+ if (c != nullptr) {
69
+ // The subchannel already exists. Reuse it.
70
+ c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse");
71
+ GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing");
72
+ // Exit the CAS loop without modifying the shared map.
73
+ } else {
74
+ // There hasn't been such subchannel. Add one.
75
+ // Note that we should ref the old map first because grpc_avl_add() will
76
+ // unref it while we still need to access it later.
77
+ grpc_avl new_map = grpc_avl_add(
78
+ grpc_avl_ref(old_map, nullptr), New<SubchannelKey>(*key),
79
+ GRPC_SUBCHANNEL_WEAK_REF(constructed, "subchannel_register+new"),
80
+ nullptr);
81
+ // Try to publish the change to the shared map. It may happen (but
82
+ // unlikely) that some other thread has changed the shared map, so compare
83
+ // to make sure it's unchanged before swapping. Retry if it's changed.
84
+ gpr_mu_lock(&mu_);
85
+ if (old_map.root == subchannel_map_.root) {
86
+ GPR_SWAP(grpc_avl, new_map, subchannel_map_);
87
+ c = constructed;
88
+ }
89
+ gpr_mu_unlock(&mu_);
90
+ grpc_avl_unref(new_map, nullptr);
91
+ }
92
+ grpc_avl_unref(old_map, nullptr);
93
+ }
94
+ return c;
95
+ }
96
+
97
+ void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) {
98
+ bool done = false;
99
+ // Compare and swap (CAS) loop:
100
+ while (!done) {
101
+ // Ref the shared map to have a local copy.
102
+ gpr_mu_lock(&mu_);
103
+ grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr);
104
+ gpr_mu_unlock(&mu_);
105
+ // Remove the subchannel.
106
+ // Note that we should ref the old map first because grpc_avl_remove() will
107
+ // unref it while we still need to access it later.
108
+ grpc_avl new_map =
109
+ grpc_avl_remove(grpc_avl_ref(old_map, nullptr), key, nullptr);
110
+ // Try to publish the change to the shared map. It may happen (but
111
+ // unlikely) that some other thread has changed the shared map, so compare
112
+ // to make sure it's unchanged before swapping. Retry if it's changed.
113
+ gpr_mu_lock(&mu_);
114
+ if (old_map.root == subchannel_map_.root) {
115
+ GPR_SWAP(grpc_avl, new_map, subchannel_map_);
116
+ done = true;
117
+ }
118
+ gpr_mu_unlock(&mu_);
119
+ grpc_avl_unref(new_map, nullptr);
120
+ grpc_avl_unref(old_map, nullptr);
121
+ }
122
+ }
123
+
124
+ Subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) {
125
+ // Lock, and take a reference to the subchannel map.
126
+ // We don't need to do the search under a lock as AVL's are immutable.
127
+ gpr_mu_lock(&mu_);
128
+ grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr);
129
+ gpr_mu_unlock(&mu_);
130
+ Subchannel* c = static_cast<Subchannel*>(grpc_avl_get(index, key, nullptr));
131
+ if (c != nullptr) GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "found_from_pool");
132
+ grpc_avl_unref(index, nullptr);
133
+ return c;
134
+ }
135
+
136
+ RefCountedPtr<GlobalSubchannelPool>* GlobalSubchannelPool::instance_ = nullptr;
137
+
138
+ namespace {
139
+
140
+ void sck_avl_destroy(void* p, void* user_data) {
141
+ SubchannelKey* key = static_cast<SubchannelKey*>(p);
142
+ Delete(key);
143
+ }
144
+
145
+ void* sck_avl_copy(void* p, void* unused) {
146
+ const SubchannelKey* key = static_cast<const SubchannelKey*>(p);
147
+ auto* new_key = New<SubchannelKey>(*key);
148
+ return static_cast<void*>(new_key);
149
+ }
150
+
151
+ long sck_avl_compare(void* a, void* b, void* unused) {
152
+ const SubchannelKey* key_a = static_cast<const SubchannelKey*>(a);
153
+ const SubchannelKey* key_b = static_cast<const SubchannelKey*>(b);
154
+ return key_a->Cmp(*key_b);
155
+ }
156
+
157
+ void scv_avl_destroy(void* p, void* user_data) {
158
+ GRPC_SUBCHANNEL_WEAK_UNREF((Subchannel*)p, "global_subchannel_pool");
159
+ }
160
+
161
+ void* scv_avl_copy(void* p, void* unused) {
162
+ GRPC_SUBCHANNEL_WEAK_REF((Subchannel*)p, "global_subchannel_pool");
163
+ return p;
164
+ }
165
+
166
+ } // namespace
167
+
168
+ const grpc_avl_vtable GlobalSubchannelPool::subchannel_avl_vtable_ = {
169
+ sck_avl_destroy, // destroy_key
170
+ sck_avl_copy, // copy_key
171
+ sck_avl_compare, // compare_keys
172
+ scv_avl_destroy, // destroy_value
173
+ scv_avl_copy // copy_value
174
+ };
175
+
176
+ } // namespace grpc_core
@@ -0,0 +1,68 @@
1
+ /*
2
+ *
3
+ * Copyright 2018 gRPC authors.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ */
18
+
19
+ #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H
20
+ #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H
21
+
22
+ #include <grpc/support/port_platform.h>
23
+
24
+ #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
25
+
26
+ namespace grpc_core {
27
+
28
+ // The global subchannel pool. It shares subchannels among channels. There
29
+ // should be only one instance of this class. Init() should be called once at
30
+ // the filter initialization time; Shutdown() should be called once at the
31
+ // filter shutdown time.
32
+ // TODO(juanlishen): Enable subchannel retention.
33
+ class GlobalSubchannelPool final : public SubchannelPoolInterface {
34
+ public:
35
+ // The ctor and dtor are not intended to use directly.
36
+ GlobalSubchannelPool();
37
+ ~GlobalSubchannelPool() override;
38
+
39
+ // Should be called exactly once at filter initialization time.
40
+ static void Init();
41
+ // Should be called exactly once at filter shutdown time.
42
+ static void Shutdown();
43
+
44
+ // Gets the singleton instance.
45
+ static RefCountedPtr<GlobalSubchannelPool> instance();
46
+
47
+ // Implements interface methods.
48
+ Subchannel* RegisterSubchannel(SubchannelKey* key,
49
+ Subchannel* constructed) override;
50
+ void UnregisterSubchannel(SubchannelKey* key) override;
51
+ Subchannel* FindSubchannel(SubchannelKey* key) override;
52
+
53
+ private:
54
+ // The singleton instance. (It's a pointer to RefCountedPtr so that this
55
+ // non-local static object can be trivially destructible.)
56
+ static RefCountedPtr<GlobalSubchannelPool>* instance_;
57
+
58
+ // The vtable for subchannel operations in an AVL tree.
59
+ static const grpc_avl_vtable subchannel_avl_vtable_;
60
+ // A map from subchannel key to subchannel.
61
+ grpc_avl subchannel_map_;
62
+ // To protect subchannel_map_.
63
+ gpr_mu mu_;
64
+ };
65
+
66
+ } // namespace grpc_core
67
+
68
+ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H */
@@ -295,7 +295,9 @@ HealthCheckClient::CallState::~CallState() {
295
295
  gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p",
296
296
  health_check_client_.get(), this);
297
297
  }
298
- if (call_ != nullptr) GRPC_SUBCHANNEL_CALL_UNREF(call_, "call_ended");
298
+ // The subchannel call is in the arena, so reset the pointer before we destroy
299
+ // the arena.
300
+ call_.reset();
299
301
  for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) {
300
302
  if (context_[i].destroy != nullptr) {
301
303
  context_[i].destroy(context_[i].value);
@@ -329,8 +331,8 @@ void HealthCheckClient::CallState::StartCall() {
329
331
  &call_combiner_,
330
332
  0, // parent_data_size
331
333
  };
332
- grpc_error* error =
333
- health_check_client_->connected_subchannel_->CreateCall(args, &call_);
334
+ grpc_error* error = GRPC_ERROR_NONE;
335
+ call_ = health_check_client_->connected_subchannel_->CreateCall(args, &error);
334
336
  if (error != GRPC_ERROR_NONE) {
335
337
  gpr_log(GPR_ERROR,
336
338
  "HealthCheckClient %p CallState %p: error creating health "
@@ -423,14 +425,14 @@ void HealthCheckClient::CallState::StartBatchInCallCombiner(void* arg,
423
425
  grpc_error* error) {
424
426
  grpc_transport_stream_op_batch* batch =
425
427
  static_cast<grpc_transport_stream_op_batch*>(arg);
426
- grpc_subchannel_call* call =
427
- static_cast<grpc_subchannel_call*>(batch->handler_private.extra_arg);
428
- grpc_subchannel_call_process_op(call, batch);
428
+ SubchannelCall* call =
429
+ static_cast<SubchannelCall*>(batch->handler_private.extra_arg);
430
+ call->StartTransportStreamOpBatch(batch);
429
431
  }
430
432
 
431
433
  void HealthCheckClient::CallState::StartBatch(
432
434
  grpc_transport_stream_op_batch* batch) {
433
- batch->handler_private.extra_arg = call_;
435
+ batch->handler_private.extra_arg = call_.get();
434
436
  GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner,
435
437
  batch, grpc_schedule_on_exec_ctx);
436
438
  GRPC_CALL_COMBINER_START(&call_combiner_, &batch->handler_private.closure,
@@ -452,7 +454,7 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) {
452
454
  GRPC_CLOSURE_CREATE(OnCancelComplete, self, grpc_schedule_on_exec_ctx));
453
455
  batch->cancel_stream = true;
454
456
  batch->payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED;
455
- grpc_subchannel_call_process_op(self->call_, batch);
457
+ self->call_->StartTransportStreamOpBatch(batch);
456
458
  }
457
459
 
458
460
  void HealthCheckClient::CallState::Cancel() {
@@ -99,7 +99,7 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
99
99
  grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {};
100
100
 
101
101
  // The streaming call to the backend. Always non-NULL.
102
- grpc_subchannel_call* call_;
102
+ RefCountedPtr<SubchannelCall> call_;
103
103
 
104
104
  grpc_transport_stream_op_batch_payload payload_;
105
105
  grpc_transport_stream_op_batch batch_;
@@ -33,151 +33,160 @@
33
33
  #include "src/core/lib/channel/handshaker_registry.h"
34
34
  #include "src/core/lib/gpr/env.h"
35
35
  #include "src/core/lib/gpr/string.h"
36
+ #include "src/core/lib/gprpp/mutex_lock.h"
36
37
  #include "src/core/lib/http/format_request.h"
37
38
  #include "src/core/lib/http/parser.h"
38
39
  #include "src/core/lib/slice/slice_internal.h"
39
40
  #include "src/core/lib/uri/uri_parser.h"
40
41
 
41
- typedef struct http_connect_handshaker {
42
- // Base class. Must be first.
43
- grpc_handshaker base;
42
+ namespace grpc_core {
44
43
 
45
- gpr_refcount refcount;
46
- gpr_mu mu;
44
+ namespace {
47
45
 
48
- bool shutdown;
46
+ class HttpConnectHandshaker : public Handshaker {
47
+ public:
48
+ HttpConnectHandshaker();
49
+ void Shutdown(grpc_error* why) override;
50
+ void DoHandshake(grpc_tcp_server_acceptor* acceptor,
51
+ grpc_closure* on_handshake_done,
52
+ HandshakerArgs* args) override;
53
+ const char* name() const override { return "http_connect"; }
54
+
55
+ private:
56
+ virtual ~HttpConnectHandshaker();
57
+ void CleanupArgsForFailureLocked();
58
+ void HandshakeFailedLocked(grpc_error* error);
59
+ static void OnWriteDone(void* arg, grpc_error* error);
60
+ static void OnReadDone(void* arg, grpc_error* error);
61
+
62
+ gpr_mu mu_;
63
+
64
+ bool is_shutdown_ = false;
49
65
  // Endpoint and read buffer to destroy after a shutdown.
50
- grpc_endpoint* endpoint_to_destroy;
51
- grpc_slice_buffer* read_buffer_to_destroy;
66
+ grpc_endpoint* endpoint_to_destroy_ = nullptr;
67
+ grpc_slice_buffer* read_buffer_to_destroy_ = nullptr;
52
68
 
53
69
  // State saved while performing the handshake.
54
- grpc_handshaker_args* args;
55
- grpc_closure* on_handshake_done;
70
+ HandshakerArgs* args_ = nullptr;
71
+ grpc_closure* on_handshake_done_ = nullptr;
56
72
 
57
73
  // Objects for processing the HTTP CONNECT request and response.
58
- grpc_slice_buffer write_buffer;
59
- grpc_closure request_done_closure;
60
- grpc_closure response_read_closure;
61
- grpc_http_parser http_parser;
62
- grpc_http_response http_response;
63
- } http_connect_handshaker;
74
+ grpc_slice_buffer write_buffer_;
75
+ grpc_closure request_done_closure_;
76
+ grpc_closure response_read_closure_;
77
+ grpc_http_parser http_parser_;
78
+ grpc_http_response http_response_;
79
+ };
64
80
 
65
- // Unref and clean up handshaker.
66
- static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) {
67
- if (gpr_unref(&handshaker->refcount)) {
68
- gpr_mu_destroy(&handshaker->mu);
69
- if (handshaker->endpoint_to_destroy != nullptr) {
70
- grpc_endpoint_destroy(handshaker->endpoint_to_destroy);
71
- }
72
- if (handshaker->read_buffer_to_destroy != nullptr) {
73
- grpc_slice_buffer_destroy_internal(handshaker->read_buffer_to_destroy);
74
- gpr_free(handshaker->read_buffer_to_destroy);
75
- }
76
- grpc_slice_buffer_destroy_internal(&handshaker->write_buffer);
77
- grpc_http_parser_destroy(&handshaker->http_parser);
78
- grpc_http_response_destroy(&handshaker->http_response);
79
- gpr_free(handshaker);
81
+ HttpConnectHandshaker::~HttpConnectHandshaker() {
82
+ gpr_mu_destroy(&mu_);
83
+ if (endpoint_to_destroy_ != nullptr) {
84
+ grpc_endpoint_destroy(endpoint_to_destroy_);
85
+ }
86
+ if (read_buffer_to_destroy_ != nullptr) {
87
+ grpc_slice_buffer_destroy_internal(read_buffer_to_destroy_);
88
+ gpr_free(read_buffer_to_destroy_);
80
89
  }
90
+ grpc_slice_buffer_destroy_internal(&write_buffer_);
91
+ grpc_http_parser_destroy(&http_parser_);
92
+ grpc_http_response_destroy(&http_response_);
81
93
  }
82
94
 
83
95
  // Set args fields to nullptr, saving the endpoint and read buffer for
84
96
  // later destruction.
85
- static void cleanup_args_for_failure_locked(
86
- http_connect_handshaker* handshaker) {
87
- handshaker->endpoint_to_destroy = handshaker->args->endpoint;
88
- handshaker->args->endpoint = nullptr;
89
- handshaker->read_buffer_to_destroy = handshaker->args->read_buffer;
90
- handshaker->args->read_buffer = nullptr;
91
- grpc_channel_args_destroy(handshaker->args->args);
92
- handshaker->args->args = nullptr;
97
+ void HttpConnectHandshaker::CleanupArgsForFailureLocked() {
98
+ endpoint_to_destroy_ = args_->endpoint;
99
+ args_->endpoint = nullptr;
100
+ read_buffer_to_destroy_ = args_->read_buffer;
101
+ args_->read_buffer = nullptr;
102
+ grpc_channel_args_destroy(args_->args);
103
+ args_->args = nullptr;
93
104
  }
94
105
 
95
106
  // If the handshake failed or we're shutting down, clean up and invoke the
96
107
  // callback with the error.
97
- static void handshake_failed_locked(http_connect_handshaker* handshaker,
98
- grpc_error* error) {
108
+ void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error* error) {
99
109
  if (error == GRPC_ERROR_NONE) {
100
110
  // If we were shut down after an endpoint operation succeeded but
101
111
  // before the endpoint callback was invoked, we need to generate our
102
112
  // own error.
103
113
  error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown");
104
114
  }
105
- if (!handshaker->shutdown) {
115
+ if (!is_shutdown_) {
106
116
  // TODO(ctiller): It is currently necessary to shutdown endpoints
107
117
  // before destroying them, even if we know that there are no
108
118
  // pending read/write callbacks. This should be fixed, at which
109
119
  // point this can be removed.
110
- grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(error));
120
+ grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(error));
111
121
  // Not shutting down, so the handshake failed. Clean up before
112
122
  // invoking the callback.
113
- cleanup_args_for_failure_locked(handshaker);
123
+ CleanupArgsForFailureLocked();
114
124
  // Set shutdown to true so that subsequent calls to
115
125
  // http_connect_handshaker_shutdown() do nothing.
116
- handshaker->shutdown = true;
126
+ is_shutdown_ = true;
117
127
  }
118
128
  // Invoke callback.
119
- GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error);
129
+ GRPC_CLOSURE_SCHED(on_handshake_done_, error);
120
130
  }
121
131
 
122
132
  // Callback invoked when finished writing HTTP CONNECT request.
123
- static void on_write_done(void* arg, grpc_error* error) {
124
- http_connect_handshaker* handshaker =
125
- static_cast<http_connect_handshaker*>(arg);
126
- gpr_mu_lock(&handshaker->mu);
127
- if (error != GRPC_ERROR_NONE || handshaker->shutdown) {
133
+ void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error* error) {
134
+ auto* handshaker = static_cast<HttpConnectHandshaker*>(arg);
135
+ gpr_mu_lock(&handshaker->mu_);
136
+ if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) {
128
137
  // If the write failed or we're shutting down, clean up and invoke the
129
138
  // callback with the error.
130
- handshake_failed_locked(handshaker, GRPC_ERROR_REF(error));
131
- gpr_mu_unlock(&handshaker->mu);
132
- http_connect_handshaker_unref(handshaker);
139
+ handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error));
140
+ gpr_mu_unlock(&handshaker->mu_);
141
+ handshaker->Unref();
133
142
  } else {
134
143
  // Otherwise, read the response.
135
144
  // The read callback inherits our ref to the handshaker.
136
- grpc_endpoint_read(handshaker->args->endpoint,
137
- handshaker->args->read_buffer,
138
- &handshaker->response_read_closure);
139
- gpr_mu_unlock(&handshaker->mu);
145
+ grpc_endpoint_read(handshaker->args_->endpoint,
146
+ handshaker->args_->read_buffer,
147
+ &handshaker->response_read_closure_);
148
+ gpr_mu_unlock(&handshaker->mu_);
140
149
  }
141
150
  }
142
151
 
143
152
  // Callback invoked for reading HTTP CONNECT response.
144
- static void on_read_done(void* arg, grpc_error* error) {
145
- http_connect_handshaker* handshaker =
146
- static_cast<http_connect_handshaker*>(arg);
147
- gpr_mu_lock(&handshaker->mu);
148
- if (error != GRPC_ERROR_NONE || handshaker->shutdown) {
153
+ void HttpConnectHandshaker::OnReadDone(void* arg, grpc_error* error) {
154
+ auto* handshaker = static_cast<HttpConnectHandshaker*>(arg);
155
+
156
+ gpr_mu_lock(&handshaker->mu_);
157
+ if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) {
149
158
  // If the read failed or we're shutting down, clean up and invoke the
150
159
  // callback with the error.
151
- handshake_failed_locked(handshaker, GRPC_ERROR_REF(error));
160
+ handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error));
152
161
  goto done;
153
162
  }
154
163
  // Add buffer to parser.
155
- for (size_t i = 0; i < handshaker->args->read_buffer->count; ++i) {
156
- if (GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i]) > 0) {
164
+ for (size_t i = 0; i < handshaker->args_->read_buffer->count; ++i) {
165
+ if (GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i]) > 0) {
157
166
  size_t body_start_offset = 0;
158
- error = grpc_http_parser_parse(&handshaker->http_parser,
159
- handshaker->args->read_buffer->slices[i],
167
+ error = grpc_http_parser_parse(&handshaker->http_parser_,
168
+ handshaker->args_->read_buffer->slices[i],
160
169
  &body_start_offset);
161
170
  if (error != GRPC_ERROR_NONE) {
162
- handshake_failed_locked(handshaker, error);
171
+ handshaker->HandshakeFailedLocked(error);
163
172
  goto done;
164
173
  }
165
- if (handshaker->http_parser.state == GRPC_HTTP_BODY) {
174
+ if (handshaker->http_parser_.state == GRPC_HTTP_BODY) {
166
175
  // Remove the data we've already read from the read buffer,
167
176
  // leaving only the leftover bytes (if any).
168
177
  grpc_slice_buffer tmp_buffer;
169
178
  grpc_slice_buffer_init(&tmp_buffer);
170
179
  if (body_start_offset <
171
- GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i])) {
180
+ GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i])) {
172
181
  grpc_slice_buffer_add(
173
182
  &tmp_buffer,
174
- grpc_slice_split_tail(&handshaker->args->read_buffer->slices[i],
183
+ grpc_slice_split_tail(&handshaker->args_->read_buffer->slices[i],
175
184
  body_start_offset));
176
185
  }
177
186
  grpc_slice_buffer_addn(&tmp_buffer,
178
- &handshaker->args->read_buffer->slices[i + 1],
179
- handshaker->args->read_buffer->count - i - 1);
180
- grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer);
187
+ &handshaker->args_->read_buffer->slices[i + 1],
188
+ handshaker->args_->read_buffer->count - i - 1);
189
+ grpc_slice_buffer_swap(handshaker->args_->read_buffer, &tmp_buffer);
181
190
  grpc_slice_buffer_destroy_internal(&tmp_buffer);
182
191
  break;
183
192
  }
@@ -194,64 +203,53 @@ static void on_read_done(void* arg, grpc_error* error) {
194
203
  // need to fix the HTTP parser to understand when the body is
195
204
  // complete (e.g., handling chunked transfer encoding or looking
196
205
  // at the Content-Length: header).
197
- if (handshaker->http_parser.state != GRPC_HTTP_BODY) {
198
- grpc_slice_buffer_reset_and_unref_internal(handshaker->args->read_buffer);
199
- grpc_endpoint_read(handshaker->args->endpoint,
200
- handshaker->args->read_buffer,
201
- &handshaker->response_read_closure);
202
- gpr_mu_unlock(&handshaker->mu);
206
+ if (handshaker->http_parser_.state != GRPC_HTTP_BODY) {
207
+ grpc_slice_buffer_reset_and_unref_internal(handshaker->args_->read_buffer);
208
+ grpc_endpoint_read(handshaker->args_->endpoint,
209
+ handshaker->args_->read_buffer,
210
+ &handshaker->response_read_closure_);
211
+ gpr_mu_unlock(&handshaker->mu_);
203
212
  return;
204
213
  }
205
214
  // Make sure we got a 2xx response.
206
- if (handshaker->http_response.status < 200 ||
207
- handshaker->http_response.status >= 300) {
215
+ if (handshaker->http_response_.status < 200 ||
216
+ handshaker->http_response_.status >= 300) {
208
217
  char* msg;
209
218
  gpr_asprintf(&msg, "HTTP proxy returned response code %d",
210
- handshaker->http_response.status);
219
+ handshaker->http_response_.status);
211
220
  error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
212
221
  gpr_free(msg);
213
- handshake_failed_locked(handshaker, error);
222
+ handshaker->HandshakeFailedLocked(error);
214
223
  goto done;
215
224
  }
216
225
  // Success. Invoke handshake-done callback.
217
- GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error);
226
+ GRPC_CLOSURE_SCHED(handshaker->on_handshake_done_, error);
218
227
  done:
219
228
  // Set shutdown to true so that subsequent calls to
220
229
  // http_connect_handshaker_shutdown() do nothing.
221
- handshaker->shutdown = true;
222
- gpr_mu_unlock(&handshaker->mu);
223
- http_connect_handshaker_unref(handshaker);
230
+ handshaker->is_shutdown_ = true;
231
+ gpr_mu_unlock(&handshaker->mu_);
232
+ handshaker->Unref();
224
233
  }
225
234
 
226
235
  //
227
236
  // Public handshaker methods
228
237
  //
229
238
 
230
- static void http_connect_handshaker_destroy(grpc_handshaker* handshaker_in) {
231
- http_connect_handshaker* handshaker =
232
- reinterpret_cast<http_connect_handshaker*>(handshaker_in);
233
- http_connect_handshaker_unref(handshaker);
234
- }
235
-
236
- static void http_connect_handshaker_shutdown(grpc_handshaker* handshaker_in,
237
- grpc_error* why) {
238
- http_connect_handshaker* handshaker =
239
- reinterpret_cast<http_connect_handshaker*>(handshaker_in);
240
- gpr_mu_lock(&handshaker->mu);
241
- if (!handshaker->shutdown) {
242
- handshaker->shutdown = true;
243
- grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(why));
244
- cleanup_args_for_failure_locked(handshaker);
239
+ void HttpConnectHandshaker::Shutdown(grpc_error* why) {
240
+ gpr_mu_lock(&mu_);
241
+ if (!is_shutdown_) {
242
+ is_shutdown_ = true;
243
+ grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why));
244
+ CleanupArgsForFailureLocked();
245
245
  }
246
- gpr_mu_unlock(&handshaker->mu);
246
+ gpr_mu_unlock(&mu_);
247
247
  GRPC_ERROR_UNREF(why);
248
248
  }
249
249
 
250
- static void http_connect_handshaker_do_handshake(
251
- grpc_handshaker* handshaker_in, grpc_tcp_server_acceptor* acceptor,
252
- grpc_closure* on_handshake_done, grpc_handshaker_args* args) {
253
- http_connect_handshaker* handshaker =
254
- reinterpret_cast<http_connect_handshaker*>(handshaker_in);
250
+ void HttpConnectHandshaker::DoHandshake(grpc_tcp_server_acceptor* acceptor,
251
+ grpc_closure* on_handshake_done,
252
+ HandshakerArgs* args) {
255
253
  // Check for HTTP CONNECT channel arg.
256
254
  // If not found, invoke on_handshake_done without doing anything.
257
255
  const grpc_arg* arg =
@@ -260,9 +258,9 @@ static void http_connect_handshaker_do_handshake(
260
258
  if (server_name == nullptr) {
261
259
  // Set shutdown to true so that subsequent calls to
262
260
  // http_connect_handshaker_shutdown() do nothing.
263
- gpr_mu_lock(&handshaker->mu);
264
- handshaker->shutdown = true;
265
- gpr_mu_unlock(&handshaker->mu);
261
+ gpr_mu_lock(&mu_);
262
+ is_shutdown_ = true;
263
+ gpr_mu_unlock(&mu_);
266
264
  GRPC_CLOSURE_SCHED(on_handshake_done, GRPC_ERROR_NONE);
267
265
  return;
268
266
  }
@@ -280,6 +278,7 @@ static void http_connect_handshaker_do_handshake(
280
278
  gpr_malloc(sizeof(grpc_http_header) * num_header_strings));
281
279
  for (size_t i = 0; i < num_header_strings; ++i) {
282
280
  char* sep = strchr(header_strings[i], ':');
281
+
283
282
  if (sep == nullptr) {
284
283
  gpr_log(GPR_ERROR, "skipping unparseable HTTP CONNECT header: %s",
285
284
  header_strings[i]);
@@ -292,9 +291,9 @@ static void http_connect_handshaker_do_handshake(
292
291
  }
293
292
  }
294
293
  // Save state in the handshaker object.
295
- gpr_mu_lock(&handshaker->mu);
296
- handshaker->args = args;
297
- handshaker->on_handshake_done = on_handshake_done;
294
+ MutexLock lock(&mu_);
295
+ args_ = args;
296
+ on_handshake_done_ = on_handshake_done;
298
297
  // Log connection via proxy.
299
298
  char* proxy_name = grpc_endpoint_get_peer(args->endpoint);
300
299
  gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", server_name,
@@ -302,15 +301,18 @@ static void http_connect_handshaker_do_handshake(
302
301
  gpr_free(proxy_name);
303
302
  // Construct HTTP CONNECT request.
304
303
  grpc_httpcli_request request;
305
- memset(&request, 0, sizeof(request));
306
304
  request.host = server_name;
305
+ request.ssl_host_override = nullptr;
307
306
  request.http.method = (char*)"CONNECT";
308
307
  request.http.path = server_name;
308
+ request.http.version = GRPC_HTTP_HTTP10; // Set by OnReadDone
309
309
  request.http.hdrs = headers;
310
310
  request.http.hdr_count = num_headers;
311
+ request.http.body_length = 0;
312
+ request.http.body = nullptr;
311
313
  request.handshaker = &grpc_httpcli_plaintext;
312
314
  grpc_slice request_slice = grpc_httpcli_format_connect_request(&request);
313
- grpc_slice_buffer_add(&handshaker->write_buffer, request_slice);
315
+ grpc_slice_buffer_add(&write_buffer_, request_slice);
314
316
  // Clean up.
315
317
  gpr_free(headers);
316
318
  for (size_t i = 0; i < num_header_strings; ++i) {
@@ -318,54 +320,42 @@ static void http_connect_handshaker_do_handshake(
318
320
  }
319
321
  gpr_free(header_strings);
320
322
  // Take a new ref to be held by the write callback.
321
- gpr_ref(&handshaker->refcount);
322
- grpc_endpoint_write(args->endpoint, &handshaker->write_buffer,
323
- &handshaker->request_done_closure, nullptr);
324
- gpr_mu_unlock(&handshaker->mu);
323
+ Ref().release();
324
+ grpc_endpoint_write(args->endpoint, &write_buffer_, &request_done_closure_,
325
+ nullptr);
325
326
  }
326
327
 
327
- static const grpc_handshaker_vtable http_connect_handshaker_vtable = {
328
- http_connect_handshaker_destroy, http_connect_handshaker_shutdown,
329
- http_connect_handshaker_do_handshake, "http_connect"};
330
-
331
- static grpc_handshaker* grpc_http_connect_handshaker_create() {
332
- http_connect_handshaker* handshaker =
333
- static_cast<http_connect_handshaker*>(gpr_malloc(sizeof(*handshaker)));
334
- memset(handshaker, 0, sizeof(*handshaker));
335
- grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base);
336
- gpr_mu_init(&handshaker->mu);
337
- gpr_ref_init(&handshaker->refcount, 1);
338
- grpc_slice_buffer_init(&handshaker->write_buffer);
339
- GRPC_CLOSURE_INIT(&handshaker->request_done_closure, on_write_done,
340
- handshaker, grpc_schedule_on_exec_ctx);
341
- GRPC_CLOSURE_INIT(&handshaker->response_read_closure, on_read_done,
342
- handshaker, grpc_schedule_on_exec_ctx);
343
- grpc_http_parser_init(&handshaker->http_parser, GRPC_HTTP_RESPONSE,
344
- &handshaker->http_response);
345
- return &handshaker->base;
328
+ HttpConnectHandshaker::HttpConnectHandshaker() {
329
+ gpr_mu_init(&mu_);
330
+ grpc_slice_buffer_init(&write_buffer_);
331
+ GRPC_CLOSURE_INIT(&request_done_closure_, &HttpConnectHandshaker::OnWriteDone,
332
+ this, grpc_schedule_on_exec_ctx);
333
+ GRPC_CLOSURE_INIT(&response_read_closure_, &HttpConnectHandshaker::OnReadDone,
334
+ this, grpc_schedule_on_exec_ctx);
335
+ grpc_http_parser_init(&http_parser_, GRPC_HTTP_RESPONSE, &http_response_);
346
336
  }
347
337
 
348
338
  //
349
339
  // handshaker factory
350
340
  //
351
341
 
352
- static void handshaker_factory_add_handshakers(
353
- grpc_handshaker_factory* factory, const grpc_channel_args* args,
354
- grpc_pollset_set* interested_parties,
355
- grpc_handshake_manager* handshake_mgr) {
356
- grpc_handshake_manager_add(handshake_mgr,
357
- grpc_http_connect_handshaker_create());
358
- }
359
-
360
- static void handshaker_factory_destroy(grpc_handshaker_factory* factory) {}
342
+ class HttpConnectHandshakerFactory : public HandshakerFactory {
343
+ public:
344
+ void AddHandshakers(const grpc_channel_args* args,
345
+ grpc_pollset_set* interested_parties,
346
+ HandshakeManager* handshake_mgr) override {
347
+ handshake_mgr->Add(MakeRefCounted<HttpConnectHandshaker>());
348
+ }
349
+ ~HttpConnectHandshakerFactory() override = default;
350
+ };
361
351
 
362
- static const grpc_handshaker_factory_vtable handshaker_factory_vtable = {
363
- handshaker_factory_add_handshakers, handshaker_factory_destroy};
352
+ } // namespace
364
353
 
365
- static grpc_handshaker_factory handshaker_factory = {
366
- &handshaker_factory_vtable};
354
+ } // namespace grpc_core
367
355
 
368
356
  void grpc_http_connect_register_handshaker_factory() {
369
- grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_CLIENT,
370
- &handshaker_factory);
357
+ using namespace grpc_core;
358
+ HandshakerRegistry::RegisterHandshakerFactory(
359
+ true /* at_start */, HANDSHAKER_CLIENT,
360
+ UniquePtr<HandshakerFactory>(New<HttpConnectHandshakerFactory>()));
371
361
  }