29 #include "absl/base/thread_annotations.h"
30 #include "absl/memory/memory.h"
31 #include "absl/strings/str_cat.h"
32 #include "absl/strings/string_view.h"
63 class HttpConnectHandshaker :
public Handshaker {
65 HttpConnectHandshaker();
69 HandshakerArgs*
args)
override;
70 const char*
name()
const override {
return "http_connect"; }
73 ~HttpConnectHandshaker()
override;
90 HandshakerArgs*
args_ =
nullptr;
101 HttpConnectHandshaker::~HttpConnectHandshaker() {
116 void HttpConnectHandshaker::CleanupArgsForFailureLocked() {
118 args_->endpoint =
nullptr;
120 args_->read_buffer =
nullptr;
122 args_->args =
nullptr;
142 CleanupArgsForFailureLocked();
153 void HttpConnectHandshaker::OnWriteDoneScheduler(
void*
arg,
155 auto* handshaker =
static_cast<HttpConnectHandshaker*
>(
arg);
158 &HttpConnectHandshaker::OnWriteDone,
159 handshaker, grpc_schedule_on_exec_ctx),
165 auto* handshaker =
static_cast<HttpConnectHandshaker*
>(
arg);
166 ReleasableMutexLock lock(&handshaker->mu_);
177 handshaker->args_->endpoint, handshaker->args_->read_buffer,
179 &HttpConnectHandshaker::OnReadDoneScheduler,
180 handshaker, grpc_schedule_on_exec_ctx),
187 void HttpConnectHandshaker::OnReadDoneScheduler(
void*
arg,
189 auto* handshaker =
static_cast<HttpConnectHandshaker*
>(
arg);
192 &HttpConnectHandshaker::OnReadDone, handshaker,
193 grpc_schedule_on_exec_ctx),
199 auto* handshaker =
static_cast<HttpConnectHandshaker*
>(
arg);
200 ReleasableMutexLock lock(&handshaker->mu_);
208 for (
size_t i = 0;
i < handshaker->args_->read_buffer->count; ++
i) {
210 size_t body_start_offset = 0;
212 handshaker->args_->read_buffer->slices[i],
215 handshaker->HandshakeFailedLocked(
error);
223 if (body_start_offset <
231 &handshaker->args_->read_buffer->slices[i + 1],
232 handshaker->args_->read_buffer->count - i - 1);
253 handshaker->args_->endpoint, handshaker->args_->read_buffer,
255 &HttpConnectHandshaker::OnReadDoneScheduler,
256 handshaker, grpc_schedule_on_exec_ctx),
261 if (handshaker->http_response_.status < 200 ||
262 handshaker->http_response_.status >= 300) {
265 handshaker->http_response_.status));
266 handshaker->HandshakeFailedLocked(
error);
274 handshaker->is_shutdown_ =
true;
289 CleanupArgsForFailureLocked();
297 HandshakerArgs*
args) {
317 size_t num_headers = 0;
318 char** header_strings =
nullptr;
319 size_t num_header_strings = 0;
320 if (arg_header_string !=
nullptr) {
322 &num_header_strings);
325 for (
size_t i = 0;
i < num_header_strings; ++
i) {
326 char*
sep = strchr(header_strings[i],
':');
328 if (
sep ==
nullptr) {
334 headers[num_headers].
key = header_strings[
i];
335 headers[num_headers].
value =
sep + 1;
349 request.method =
const_cast<char*
>(
"CONNECT");
352 request.hdr_count = num_headers;
360 for (
size_t i = 0;
i < num_header_strings; ++
i) {
367 args->endpoint, &write_buffer_,
369 &HttpConnectHandshaker::OnWriteDoneScheduler,
this,
370 grpc_schedule_on_exec_ctx),
374 HttpConnectHandshaker::HttpConnectHandshaker() {
383 class HttpConnectHandshakerFactory :
public HandshakerFactory {
387 HandshakeManager* handshake_mgr)
override {
388 handshake_mgr->Add(MakeRefCounted<HttpConnectHandshaker>());
390 ~HttpConnectHandshakerFactory()
override =
default;
396 builder->handshaker_registry()->RegisterHandshakerFactory(
398 absl::make_unique<HttpConnectHandshakerFactory>());