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.
- checksums.yaml +4 -4
- data/Makefile +301 -33
- data/include/grpc/grpc_security.h +195 -0
- data/include/grpc/impl/codegen/grpc_types.h +17 -1
- data/include/grpc/impl/codegen/port_platform.h +36 -0
- data/include/grpc/impl/codegen/slice.h +1 -1
- data/src/core/ext/filters/client_channel/channel_connectivity.cc +2 -0
- data/src/core/ext/filters/client_channel/client_channel.cc +74 -69
- data/src/core/ext/filters/client_channel/client_channel.h +2 -2
- data/src/core/ext/filters/client_channel/client_channel_channelz.cc +5 -6
- data/src/core/ext/filters/client_channel/client_channel_channelz.h +5 -4
- data/src/core/ext/filters/client_channel/client_channel_factory.cc +2 -2
- data/src/core/ext/filters/client_channel/client_channel_factory.h +4 -4
- data/src/core/ext/filters/client_channel/client_channel_plugin.cc +3 -3
- data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +176 -0
- data/src/core/ext/filters/client_channel/global_subchannel_pool.h +68 -0
- data/src/core/ext/filters/client_channel/health/health_check_client.cc +10 -8
- data/src/core/ext/filters/client_channel/health/health_check_client.h +1 -1
- data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +146 -156
- data/src/core/ext/filters/client_channel/lb_policy.cc +30 -1
- data/src/core/ext/filters/client_channel/lb_policy.h +29 -1
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +28 -30
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +5 -8
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +5 -8
- data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +23 -24
- data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +80 -15
- data/src/core/ext/filters/client_channel/lb_policy_factory.h +6 -1
- data/src/core/ext/filters/client_channel/lb_policy_registry.cc +2 -2
- data/src/core/ext/filters/client_channel/lb_policy_registry.h +1 -1
- data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +96 -0
- data/src/core/ext/filters/client_channel/local_subchannel_pool.h +56 -0
- data/src/core/ext/filters/client_channel/parse_address.cc +24 -5
- data/src/core/ext/filters/client_channel/request_routing.cc +13 -3
- data/src/core/ext/filters/client_channel/request_routing.h +5 -1
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +11 -6
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +2 -2
- data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +7 -35
- data/src/core/ext/filters/client_channel/subchannel.cc +698 -791
- data/src/core/ext/filters/client_channel/subchannel.h +213 -123
- data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +97 -0
- data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +94 -0
- data/src/core/ext/filters/http/client_authority_filter.cc +5 -2
- data/src/core/ext/filters/max_age/max_age_filter.cc +1 -1
- data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +13 -12
- data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +5 -7
- data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +19 -27
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +18 -19
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +27 -6
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +3 -2
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/writing.cc +8 -5
- data/src/core/lib/channel/handshaker.cc +141 -214
- data/src/core/lib/channel/handshaker.h +110 -101
- data/src/core/lib/channel/handshaker_factory.h +11 -19
- data/src/core/lib/channel/handshaker_registry.cc +64 -52
- data/src/core/lib/channel/handshaker_registry.h +21 -16
- data/src/core/lib/gpr/log_posix.cc +2 -1
- data/src/core/lib/gpr/time.cc +8 -0
- data/src/core/lib/gpr/time_posix.cc +8 -2
- data/src/core/lib/gprpp/optional.h +47 -0
- data/src/core/lib/http/httpcli_security_connector.cc +13 -14
- data/src/core/lib/iomgr/buffer_list.cc +182 -24
- data/src/core/lib/iomgr/buffer_list.h +70 -8
- data/src/core/lib/iomgr/combiner.cc +11 -3
- data/src/core/lib/iomgr/error.cc +9 -5
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -0
- data/src/core/lib/iomgr/ev_epollex_linux.cc +136 -162
- data/src/core/lib/iomgr/ev_poll_posix.cc +3 -0
- data/src/core/lib/iomgr/ev_posix.cc +4 -0
- data/src/core/lib/iomgr/ev_posix.h +4 -0
- data/src/core/lib/iomgr/exec_ctx.cc +1 -0
- data/src/core/lib/iomgr/exec_ctx.h +137 -8
- data/src/core/lib/iomgr/executor.cc +122 -87
- data/src/core/lib/iomgr/executor.h +53 -48
- data/src/core/lib/iomgr/fork_posix.cc +6 -4
- data/src/core/lib/iomgr/{network_status_tracker.cc → grpc_if_nametoindex.h} +8 -14
- data/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +42 -0
- data/src/core/lib/iomgr/{network_status_tracker.h → grpc_if_nametoindex_unsupported.cc} +15 -9
- data/src/core/lib/iomgr/internal_errqueue.h +105 -3
- data/src/core/lib/iomgr/iomgr.cc +6 -5
- data/src/core/lib/iomgr/iomgr.h +8 -0
- data/src/core/lib/iomgr/iomgr_custom.cc +6 -2
- data/src/core/lib/iomgr/iomgr_internal.cc +4 -0
- data/src/core/lib/iomgr/iomgr_internal.h +4 -0
- data/src/core/lib/iomgr/iomgr_posix.cc +10 -1
- data/src/core/lib/iomgr/iomgr_windows.cc +8 -1
- data/src/core/lib/iomgr/port.h +1 -0
- data/src/core/lib/iomgr/resolve_address_posix.cc +4 -3
- data/src/core/lib/iomgr/resolve_address_windows.cc +2 -1
- data/src/core/lib/iomgr/tcp_custom.cc +0 -4
- data/src/core/lib/iomgr/tcp_posix.cc +58 -44
- data/src/core/lib/iomgr/tcp_uv.cc +0 -1
- data/src/core/lib/iomgr/tcp_windows.cc +0 -4
- data/src/core/lib/iomgr/timer_manager.cc +8 -0
- data/src/core/lib/iomgr/udp_server.cc +6 -4
- data/src/core/lib/json/json.cc +1 -4
- data/src/core/lib/security/credentials/alts/alts_credentials.cc +1 -1
- data/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +2 -2
- data/src/core/lib/security/credentials/composite/composite_credentials.h +4 -0
- data/src/core/lib/security/credentials/credentials.h +9 -1
- data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +15 -2
- data/src/core/lib/security/credentials/google_default/google_default_credentials.h +2 -0
- data/src/core/lib/security/credentials/jwt/json_token.cc +1 -1
- data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -0
- data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +3 -2
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +2 -2
- data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +1 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +192 -0
- data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +213 -0
- data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +10 -8
- data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +6 -10
- data/src/core/lib/security/security_connector/local/local_security_connector.cc +10 -8
- data/src/core/lib/security/security_connector/security_connector.h +2 -2
- data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +4 -6
- data/src/core/lib/security/security_connector/ssl_utils.h +33 -0
- data/src/core/lib/security/transport/security_handshaker.cc +267 -300
- data/src/core/lib/security/transport/security_handshaker.h +11 -2
- data/src/core/lib/security/transport/server_auth_filter.cc +1 -0
- data/src/core/lib/surface/call.cc +5 -1
- data/src/core/lib/surface/channel_init.h +5 -0
- data/src/core/lib/surface/completion_queue.cc +4 -7
- data/src/core/lib/surface/init.cc +5 -3
- data/src/core/lib/surface/init_secure.cc +1 -1
- data/src/core/lib/surface/server.cc +19 -17
- data/src/core/lib/surface/version.cc +1 -1
- data/src/core/lib/transport/service_config.h +1 -0
- data/src/core/lib/transport/static_metadata.cc +279 -279
- data/src/core/lib/transport/transport.cc +5 -3
- data/src/core/tsi/ssl_transport_security.cc +10 -4
- data/src/ruby/ext/grpc/extconf.rb +12 -4
- data/src/ruby/ext/grpc/rb_call_credentials.c +8 -5
- data/src/ruby/ext/grpc/rb_channel.c +14 -10
- data/src/ruby/ext/grpc/rb_channel_credentials.c +8 -4
- data/src/ruby/ext/grpc/rb_compression_options.c +9 -7
- data/src/ruby/ext/grpc/rb_event_thread.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc.c +22 -23
- data/src/ruby/ext/grpc/rb_grpc.h +4 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +18 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +27 -0
- data/src/ruby/ext/grpc/rb_server.c +8 -4
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +46 -39
- data/src/core/ext/filters/client_channel/subchannel_index.cc +0 -248
- data/src/core/ext/filters/client_channel/subchannel_index.h +0 -76
- 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
|
-
|
64
|
-
|
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(
|
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 =
|
132
|
-
|
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 =
|
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(
|
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
|
-
|
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
|
-
|
33
|
-
grpc_client_channel_factory* factory, const
|
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
|
-
|
52
|
-
|
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
|
-
|
64
|
-
grpc_client_channel_factory* factory, const
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
427
|
-
static_cast<
|
428
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
42
|
-
// Base class. Must be first.
|
43
|
-
grpc_handshaker base;
|
42
|
+
namespace grpc_core {
|
44
43
|
|
45
|
-
|
46
|
-
gpr_mu mu;
|
44
|
+
namespace {
|
47
45
|
|
48
|
-
|
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*
|
51
|
-
grpc_slice_buffer*
|
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
|
-
|
55
|
-
grpc_closure*
|
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
|
59
|
-
grpc_closure
|
60
|
-
grpc_closure
|
61
|
-
grpc_http_parser
|
62
|
-
grpc_http_response
|
63
|
-
}
|
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
|
-
|
66
|
-
|
67
|
-
if (
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
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 (!
|
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(
|
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
|
-
|
123
|
+
CleanupArgsForFailureLocked();
|
114
124
|
// Set shutdown to true so that subsequent calls to
|
115
125
|
// http_connect_handshaker_shutdown() do nothing.
|
116
|
-
|
126
|
+
is_shutdown_ = true;
|
117
127
|
}
|
118
128
|
// Invoke callback.
|
119
|
-
GRPC_CLOSURE_SCHED(
|
129
|
+
GRPC_CLOSURE_SCHED(on_handshake_done_, error);
|
120
130
|
}
|
121
131
|
|
122
132
|
// Callback invoked when finished writing HTTP CONNECT request.
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
-
|
131
|
-
gpr_mu_unlock(&handshaker->
|
132
|
-
|
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->
|
137
|
-
handshaker->
|
138
|
-
&handshaker->
|
139
|
-
gpr_mu_unlock(&handshaker->
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
gpr_mu_lock(&handshaker->
|
148
|
-
if (error != GRPC_ERROR_NONE || handshaker->
|
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
|
-
|
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->
|
156
|
-
if (GRPC_SLICE_LENGTH(handshaker->
|
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->
|
159
|
-
handshaker->
|
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
|
-
|
171
|
+
handshaker->HandshakeFailedLocked(error);
|
163
172
|
goto done;
|
164
173
|
}
|
165
|
-
if (handshaker->
|
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->
|
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->
|
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->
|
179
|
-
handshaker->
|
180
|
-
grpc_slice_buffer_swap(handshaker->
|
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->
|
198
|
-
grpc_slice_buffer_reset_and_unref_internal(handshaker->
|
199
|
-
grpc_endpoint_read(handshaker->
|
200
|
-
handshaker->
|
201
|
-
&handshaker->
|
202
|
-
gpr_mu_unlock(&handshaker->
|
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->
|
207
|
-
handshaker->
|
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->
|
219
|
+
handshaker->http_response_.status);
|
211
220
|
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
|
212
221
|
gpr_free(msg);
|
213
|
-
|
222
|
+
handshaker->HandshakeFailedLocked(error);
|
214
223
|
goto done;
|
215
224
|
}
|
216
225
|
// Success. Invoke handshake-done callback.
|
217
|
-
GRPC_CLOSURE_SCHED(handshaker->
|
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->
|
222
|
-
gpr_mu_unlock(&handshaker->
|
223
|
-
|
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
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
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(&
|
246
|
+
gpr_mu_unlock(&mu_);
|
247
247
|
GRPC_ERROR_UNREF(why);
|
248
248
|
}
|
249
249
|
|
250
|
-
|
251
|
-
|
252
|
-
|
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(&
|
264
|
-
|
265
|
-
gpr_mu_unlock(&
|
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
|
-
|
296
|
-
|
297
|
-
|
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(&
|
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
|
-
|
322
|
-
grpc_endpoint_write(args->endpoint, &
|
323
|
-
|
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
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
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
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
}
|
359
|
-
|
360
|
-
|
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
|
-
|
363
|
-
handshaker_factory_add_handshakers, handshaker_factory_destroy};
|
352
|
+
} // namespace
|
364
353
|
|
365
|
-
|
366
|
-
&handshaker_factory_vtable};
|
354
|
+
} // namespace grpc_core
|
367
355
|
|
368
356
|
void grpc_http_connect_register_handshaker_factory() {
|
369
|
-
|
370
|
-
|
357
|
+
using namespace grpc_core;
|
358
|
+
HandshakerRegistry::RegisterHandshakerFactory(
|
359
|
+
true /* at_start */, HANDSHAKER_CLIENT,
|
360
|
+
UniquePtr<HandshakerFactory>(New<HttpConnectHandshakerFactory>()));
|
371
361
|
}
|