http_connect_handshaker.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2016 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 
20 
22 
23 #include <limits.h>
24 #include <string.h>
25 
26 #include <memory>
27 #include <string>
28 
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"
33 
35 #include <grpc/slice.h>
36 #include <grpc/slice_buffer.h>
37 #include <grpc/support/alloc.h>
38 #include <grpc/support/log.h>
39 
58 
59 namespace grpc_core {
60 
61 namespace {
62 
63 class HttpConnectHandshaker : public Handshaker {
64  public:
65  HttpConnectHandshaker();
66  void Shutdown(grpc_error_handle why) override;
67  void DoHandshake(grpc_tcp_server_acceptor* acceptor,
69  HandshakerArgs* args) override;
70  const char* name() const override { return "http_connect"; }
71 
72  private:
73  ~HttpConnectHandshaker() override;
74  void CleanupArgsForFailureLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
75  void HandshakeFailedLocked(grpc_error_handle error)
77  static void OnWriteDone(void* arg, grpc_error_handle error);
78  static void OnReadDone(void* arg, grpc_error_handle error);
79  static void OnWriteDoneScheduler(void* arg, grpc_error_handle error);
80  static void OnReadDoneScheduler(void* arg, grpc_error_handle error);
81 
83 
85  // Endpoint and read buffer to destroy after a shutdown.
88 
89  // State saved while performing the handshake.
90  HandshakerArgs* args_ = nullptr;
92 
93  // Objects for processing the HTTP CONNECT request and response.
94  grpc_slice_buffer write_buffer_ ABSL_GUARDED_BY(mu_);
95  grpc_closure request_done_closure_ ABSL_GUARDED_BY(mu_);
96  grpc_closure response_read_closure_ ABSL_GUARDED_BY(mu_);
97  grpc_http_parser http_parser_ ABSL_GUARDED_BY(mu_);
98  grpc_http_response http_response_ ABSL_GUARDED_BY(mu_);
99 };
100 
101 HttpConnectHandshaker::~HttpConnectHandshaker() {
102  if (endpoint_to_destroy_ != nullptr) {
104  }
105  if (read_buffer_to_destroy_ != nullptr) {
108  }
109  grpc_slice_buffer_destroy_internal(&write_buffer_);
110  grpc_http_parser_destroy(&http_parser_);
111  grpc_http_response_destroy(&http_response_);
112 }
113 
114 // Set args fields to nullptr, saving the endpoint and read buffer for
115 // later destruction.
116 void HttpConnectHandshaker::CleanupArgsForFailureLocked() {
117  endpoint_to_destroy_ = args_->endpoint;
118  args_->endpoint = nullptr;
119  read_buffer_to_destroy_ = args_->read_buffer;
120  args_->read_buffer = nullptr;
122  args_->args = nullptr;
123 }
124 
125 // If the handshake failed or we're shutting down, clean up and invoke the
126 // callback with the error.
127 void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error_handle error) {
128  if (GRPC_ERROR_IS_NONE(error)) {
129  // If we were shut down after an endpoint operation succeeded but
130  // before the endpoint callback was invoked, we need to generate our
131  // own error.
132  error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown");
133  }
134  if (!is_shutdown_) {
135  // TODO(ctiller): It is currently necessary to shutdown endpoints
136  // before destroying them, even if we know that there are no
137  // pending read/write callbacks. This should be fixed, at which
138  // point this can be removed.
140  // Not shutting down, so the handshake failed. Clean up before
141  // invoking the callback.
142  CleanupArgsForFailureLocked();
143  // Set shutdown to true so that subsequent calls to
144  // http_connect_handshaker_shutdown() do nothing.
145  is_shutdown_ = true;
146  }
147  // Invoke callback.
149 }
150 
151 // This callback can be invoked inline while already holding onto the mutex. To
152 // avoid deadlocks, schedule OnWriteDone on ExecCtx.
153 void HttpConnectHandshaker::OnWriteDoneScheduler(void* arg,
155  auto* handshaker = static_cast<HttpConnectHandshaker*>(arg);
157  GRPC_CLOSURE_INIT(&handshaker->request_done_closure_,
158  &HttpConnectHandshaker::OnWriteDone,
159  handshaker, grpc_schedule_on_exec_ctx),
161 }
162 
163 // Callback invoked when finished writing HTTP CONNECT request.
164 void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error_handle error) {
165  auto* handshaker = static_cast<HttpConnectHandshaker*>(arg);
166  ReleasableMutexLock lock(&handshaker->mu_);
167  if (!GRPC_ERROR_IS_NONE(error) || handshaker->is_shutdown_) {
168  // If the write failed or we're shutting down, clean up and invoke the
169  // callback with the error.
170  handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error));
171  lock.Release();
172  handshaker->Unref();
173  } else {
174  // Otherwise, read the response.
175  // The read callback inherits our ref to the handshaker.
177  handshaker->args_->endpoint, handshaker->args_->read_buffer,
178  GRPC_CLOSURE_INIT(&handshaker->response_read_closure_,
179  &HttpConnectHandshaker::OnReadDoneScheduler,
180  handshaker, grpc_schedule_on_exec_ctx),
181  /*urgent=*/true, /*min_progress_size=*/1);
182  }
183 }
184 
185 // This callback can be invoked inline while already holding onto the mutex. To
186 // avoid deadlocks, schedule OnReadDone on ExecCtx.
187 void HttpConnectHandshaker::OnReadDoneScheduler(void* arg,
189  auto* handshaker = static_cast<HttpConnectHandshaker*>(arg);
191  GRPC_CLOSURE_INIT(&handshaker->response_read_closure_,
192  &HttpConnectHandshaker::OnReadDone, handshaker,
193  grpc_schedule_on_exec_ctx),
195 }
196 
197 // Callback invoked for reading HTTP CONNECT response.
198 void HttpConnectHandshaker::OnReadDone(void* arg, grpc_error_handle error) {
199  auto* handshaker = static_cast<HttpConnectHandshaker*>(arg);
200  ReleasableMutexLock lock(&handshaker->mu_);
201  if (!GRPC_ERROR_IS_NONE(error) || handshaker->is_shutdown_) {
202  // If the read failed or we're shutting down, clean up and invoke the
203  // callback with the error.
204  handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error));
205  goto done;
206  }
207  // Add buffer to parser.
208  for (size_t i = 0; i < handshaker->args_->read_buffer->count; ++i) {
209  if (GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i]) > 0) {
210  size_t body_start_offset = 0;
211  error = grpc_http_parser_parse(&handshaker->http_parser_,
212  handshaker->args_->read_buffer->slices[i],
213  &body_start_offset);
214  if (!GRPC_ERROR_IS_NONE(error)) {
215  handshaker->HandshakeFailedLocked(error);
216  goto done;
217  }
218  if (handshaker->http_parser_.state == GRPC_HTTP_BODY) {
219  // Remove the data we've already read from the read buffer,
220  // leaving only the leftover bytes (if any).
221  grpc_slice_buffer tmp_buffer;
222  grpc_slice_buffer_init(&tmp_buffer);
223  if (body_start_offset <
224  GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i])) {
226  &tmp_buffer,
227  grpc_slice_split_tail(&handshaker->args_->read_buffer->slices[i],
228  body_start_offset));
229  }
230  grpc_slice_buffer_addn(&tmp_buffer,
231  &handshaker->args_->read_buffer->slices[i + 1],
232  handshaker->args_->read_buffer->count - i - 1);
233  grpc_slice_buffer_swap(handshaker->args_->read_buffer, &tmp_buffer);
235  break;
236  }
237  }
238  }
239  // If we're not done reading the response, read more data.
240  // TODO(roth): In practice, I suspect that the response to a CONNECT
241  // request will never include a body, in which case this check is
242  // sufficient. However, the language of RFC-2817 doesn't explicitly
243  // forbid the response from including a body. If there is a body,
244  // it's possible that we might have parsed part but not all of the
245  // body, in which case this check will cause us to fail to parse the
246  // remainder of the body. If that ever becomes an issue, we may
247  // need to fix the HTTP parser to understand when the body is
248  // complete (e.g., handling chunked transfer encoding or looking
249  // at the Content-Length: header).
250  if (handshaker->http_parser_.state != GRPC_HTTP_BODY) {
251  grpc_slice_buffer_reset_and_unref_internal(handshaker->args_->read_buffer);
253  handshaker->args_->endpoint, handshaker->args_->read_buffer,
254  GRPC_CLOSURE_INIT(&handshaker->response_read_closure_,
255  &HttpConnectHandshaker::OnReadDoneScheduler,
256  handshaker, grpc_schedule_on_exec_ctx),
257  /*urgent=*/true, /*min_progress_size=*/1);
258  return;
259  }
260  // Make sure we got a 2xx response.
261  if (handshaker->http_response_.status < 200 ||
262  handshaker->http_response_.status >= 300) {
264  absl::StrCat("HTTP proxy returned response code ",
265  handshaker->http_response_.status));
266  handshaker->HandshakeFailedLocked(error);
267  goto done;
268  }
269  // Success. Invoke handshake-done callback.
270  ExecCtx::Run(DEBUG_LOCATION, handshaker->on_handshake_done_, error);
271 done:
272  // Set shutdown to true so that subsequent calls to
273  // http_connect_handshaker_shutdown() do nothing.
274  handshaker->is_shutdown_ = true;
275  lock.Release();
276  handshaker->Unref();
277 }
278 
279 //
280 // Public handshaker methods
281 //
282 
284  {
285  MutexLock lock(&mu_);
286  if (!is_shutdown_) {
287  is_shutdown_ = true;
289  CleanupArgsForFailureLocked();
290  }
291  }
292  GRPC_ERROR_UNREF(why);
293 }
294 
295 void HttpConnectHandshaker::DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/,
297  HandshakerArgs* args) {
298  // Check for HTTP CONNECT channel arg.
299  // If not found, invoke on_handshake_done without doing anything.
300  const grpc_arg* arg =
303  if (server_name == nullptr) {
304  // Set shutdown to true so that subsequent calls to
305  // http_connect_handshaker_shutdown() do nothing.
306  {
307  MutexLock lock(&mu_);
308  is_shutdown_ = true;
309  }
311  return;
312  }
313  // Get headers from channel args.
315  char* arg_header_string = grpc_channel_arg_get_string(arg);
316  grpc_http_header* headers = nullptr;
317  size_t num_headers = 0;
318  char** header_strings = nullptr;
319  size_t num_header_strings = 0;
320  if (arg_header_string != nullptr) {
321  gpr_string_split(arg_header_string, "\n", &header_strings,
322  &num_header_strings);
323  headers = static_cast<grpc_http_header*>(
324  gpr_malloc(sizeof(grpc_http_header) * num_header_strings));
325  for (size_t i = 0; i < num_header_strings; ++i) {
326  char* sep = strchr(header_strings[i], ':');
327 
328  if (sep == nullptr) {
329  gpr_log(GPR_ERROR, "skipping unparseable HTTP CONNECT header: %s",
330  header_strings[i]);
331  continue;
332  }
333  *sep = '\0';
334  headers[num_headers].key = header_strings[i];
335  headers[num_headers].value = sep + 1;
336  ++num_headers;
337  }
338  }
339  // Save state in the handshaker object.
340  MutexLock lock(&mu_);
341  args_ = args;
343  // Log connection via proxy.
344  std::string proxy_name(grpc_endpoint_get_peer(args->endpoint));
345  gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", server_name,
346  proxy_name.c_str());
347  // Construct HTTP CONNECT request.
349  request.method = const_cast<char*>("CONNECT");
350  request.version = GRPC_HTTP_HTTP10; // Set by OnReadDone
351  request.hdrs = headers;
352  request.hdr_count = num_headers;
353  request.body_length = 0;
354  request.body = nullptr;
355  grpc_slice request_slice =
357  grpc_slice_buffer_add(&write_buffer_, request_slice);
358  // Clean up.
359  gpr_free(headers);
360  for (size_t i = 0; i < num_header_strings; ++i) {
361  gpr_free(header_strings[i]);
362  }
363  gpr_free(header_strings);
364  // Take a new ref to be held by the write callback.
365  Ref().release();
367  args->endpoint, &write_buffer_,
368  GRPC_CLOSURE_INIT(&request_done_closure_,
369  &HttpConnectHandshaker::OnWriteDoneScheduler, this,
370  grpc_schedule_on_exec_ctx),
371  nullptr, /*max_frame_size=*/INT_MAX);
372 }
373 
374 HttpConnectHandshaker::HttpConnectHandshaker() {
375  grpc_slice_buffer_init(&write_buffer_);
376  grpc_http_parser_init(&http_parser_, GRPC_HTTP_RESPONSE, &http_response_);
377 }
378 
379 //
380 // handshaker factory
381 //
382 
383 class HttpConnectHandshakerFactory : public HandshakerFactory {
384  public:
385  void AddHandshakers(const grpc_channel_args* /*args*/,
386  grpc_pollset_set* /*interested_parties*/,
387  HandshakeManager* handshake_mgr) override {
388  handshake_mgr->Add(MakeRefCounted<HttpConnectHandshaker>());
389  }
390  ~HttpConnectHandshakerFactory() override = default;
391 };
392 
393 } // namespace
394 
396  builder->handshaker_registry()->RegisterHandshakerFactory(
397  true /* at_start */, HANDSHAKER_CLIENT,
398  absl::make_unique<HttpConnectHandshakerFactory>());
399 }
400 
401 } // namespace grpc_core
GRPC_CLOSURE_INIT
#define GRPC_CLOSURE_INIT(closure, cb, cb_arg, scheduler)
Definition: closure.h:115
grpc_arg
Definition: grpc_types.h:103
is_shutdown_
bool is_shutdown_
Definition: rls.cc:344
grpc_channel_arg_get_string
char * grpc_channel_arg_get_string(const grpc_arg *arg)
Definition: channel_args.cc:432
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
format_request.h
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
grpc_slice_buffer_addn
GPRAPI void grpc_slice_buffer_addn(grpc_slice_buffer *sb, grpc_slice *slices, size_t n)
Definition: slice/slice_buffer.cc:224
core_configuration.h
gpr_string_split
void gpr_string_split(const char *input, const char *sep, char ***strs, size_t *nstrs)
Definition: string.cc:300
MutexLock
#define MutexLock(x)
Definition: bloaty/third_party/re2/util/mutex.h:125
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
read_buffer_to_destroy_
grpc_slice_buffer * read_buffer_to_destroy_
Definition: security_handshaker.cc:120
slice.h
false
#define false
Definition: setup_once.h:323
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::CoreConfiguration::Builder
Definition: core_configuration.h:41
grpc_pollset_set
struct grpc_pollset_set grpc_pollset_set
Definition: iomgr_fwd.h:23
string.h
benchmark.request
request
Definition: benchmark.py:77
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
grpc_endpoint_read
void grpc_endpoint_read(grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb, bool urgent, int min_progress_size)
Definition: endpoint.cc:25
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
grpc_endpoint_get_peer
absl::string_view grpc_endpoint_get_peer(grpc_endpoint *ep)
Definition: endpoint.cc:55
gpr_malloc
GPRAPI void * gpr_malloc(size_t size)
Definition: alloc.cc:29
closure.h
ABSL_GUARDED_BY
#define ABSL_GUARDED_BY(x)
Definition: abseil-cpp/absl/base/thread_annotations.h:62
GRPC_ARG_HTTP_CONNECT_HEADERS
#define GRPC_ARG_HTTP_CONNECT_HEADERS
Definition: http_connect_handshaker.h:33
setup.name
name
Definition: setup.py:542
grpc_channel_args
Definition: grpc_types.h:132
grpc_core::RegisterHttpConnectHandshaker
void RegisterHttpConnectHandshaker(CoreConfiguration::Builder *builder)
Definition: http_connect_handshaker.cc:395
grpc_types.h
DEBUG_LOCATION
#define DEBUG_LOCATION
Definition: debug_location.h:41
grpc_http_response
Definition: src/core/lib/http/parser.h:85
profile_analyzer.builder
builder
Definition: profile_analyzer.py:159
grpc_core::HANDSHAKER_CLIENT
@ HANDSHAKER_CLIENT
Definition: handshaker_registry.h:35
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
grpc_http_header::key
char * key
Definition: src/core/lib/http/parser.h:37
GRPC_HTTP_HTTP10
@ GRPC_HTTP_HTTP10
Definition: src/core/lib/http/parser.h:58
grpc_http_header
Definition: src/core/lib/http/parser.h:36
text_format_test_wrapper.sep
sep
Definition: text_format_test_wrapper.py:34
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
ABSL_EXCLUSIVE_LOCKS_REQUIRED
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: abseil-cpp/absl/base/thread_annotations.h:145
handshaker_registry.h
done
struct tab * done
Definition: bloaty/third_party/zlib/examples/enough.c:176
slice_buffer.h
grpc_channel_args_destroy
void grpc_channel_args_destroy(grpc_channel_args *a)
Definition: channel_args.cc:360
arg
Definition: cmdline.cc:40
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
endpoint_to_destroy_
grpc_endpoint * endpoint_to_destroy_
Definition: security_handshaker.cc:119
grpc_http_response_destroy
void grpc_http_response_destroy(grpc_http_response *response)
Definition: src/core/lib/http/parser.cc:434
grpc_slice_buffer_swap
GPRAPI void grpc_slice_buffer_swap(grpc_slice_buffer *a, grpc_slice_buffer *b)
Definition: slice/slice_buffer.cc:249
error.h
grpc_endpoint_shutdown
void grpc_endpoint_shutdown(grpc_endpoint *ep, grpc_error_handle why)
Definition: endpoint.cc:49
benchmark::Shutdown
void Shutdown()
Definition: benchmark/src/benchmark.cc:607
grpc_http_parser_destroy
void grpc_http_parser_destroy(grpc_http_parser *)
Definition: src/core/lib/http/parser.cc:420
slice_internal.h
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_endpoint_destroy
void grpc_endpoint_destroy(grpc_endpoint *ep)
Definition: endpoint.cc:53
grpc_slice_buffer_init
GPRAPI void grpc_slice_buffer_init(grpc_slice_buffer *sb)
Definition: slice/slice_buffer.cc:116
GRPC_ERROR_CREATE_FROM_STATIC_STRING
#define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc)
Definition: error.h:291
GRPC_HTTP_BODY
@ GRPC_HTTP_BODY
Definition: src/core/lib/http/parser.h:44
GRPC_SLICE_LENGTH
#define GRPC_SLICE_LENGTH(slice)
Definition: include/grpc/impl/codegen/slice.h:104
grpc_slice_buffer_add
GPRAPI void grpc_slice_buffer_add(grpc_slice_buffer *sb, grpc_slice slice)
Definition: slice/slice_buffer.cc:170
parser.h
GRPC_ERROR_REF
#define GRPC_ERROR_REF(err)
Definition: error.h:261
debug_location.h
args_
HandshakerArgs * args_
Definition: http_connect_handshaker.cc:90
grpc_tcp_server_acceptor
Definition: tcp_server.h:36
GRPC_ERROR_CREATE_FROM_CPP_STRING
#define GRPC_ERROR_CREATE_FROM_CPP_STRING(desc)
Definition: error.h:297
handshaker_factory.h
alloc.h
http_connect_handshaker.h
google::protobuf.internal::Mutex
WrappedMutex Mutex
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/mutex.h:113
grpc_http_parser_parse
grpc_error_handle grpc_http_parser_parse(grpc_http_parser *parser, const grpc_slice &slice, size_t *start_of_body)
Definition: src/core/lib/http/parser.cc:444
grpc_http_parser_init
void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type, void *request_or_response)
Definition: src/core/lib/http/parser.cc:411
grpc_http_header::value
char * value
Definition: src/core/lib/http/parser.h:38
arg
struct arg arg
exec_ctx.h
handshaker.h
GRPC_ERROR_UNREF
#define GRPC_ERROR_UNREF(err)
Definition: error.h:262
grpc_core::ExecCtx::Run
static void Run(const DebugLocation &location, grpc_closure *closure, grpc_error_handle error)
Definition: exec_ctx.cc:98
ref_counted_ptr.h
mu_
Mutex mu_
Definition: http_connect_handshaker.cc:82
channel_args.h
grpc_slice_buffer_destroy_internal
void grpc_slice_buffer_destroy_internal(grpc_slice_buffer *sb)
Definition: slice/slice_buffer.cc:123
grpc_endpoint_write
void grpc_endpoint_write(grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb, void *arg, int max_frame_size)
Definition: endpoint.cc:30
grpc_httpcli_format_connect_request
grpc_slice grpc_httpcli_format_connect_request(const grpc_http_request *request, const char *host, const char *path)
Definition: format_request.cc:128
grpc_slice_buffer
Definition: include/grpc/impl/codegen/slice.h:83
iomgr_fwd.h
GRPC_HTTP_RESPONSE
@ GRPC_HTTP_RESPONSE
Definition: src/core/lib/http/parser.h:64
endpoint.h
grpc_error
Definition: error_internal.h:42
testing::Ref
internal::RefMatcher< T & > Ref(T &x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8628
tcp_server.h
grpc_http_parser
Definition: src/core/lib/http/parser.h:99
grpc_closure
Definition: closure.h:56
grpc_channel_args_find
const grpc_arg * grpc_channel_args_find(const grpc_channel_args *args, const char *name)
Definition: channel_args.cc:393
grpc_endpoint
Definition: endpoint.h:105
grpc_slice_buffer_reset_and_unref_internal
void grpc_slice_buffer_reset_and_unref_internal(grpc_slice_buffer *sb)
Definition: slice/slice_buffer.cc:238
on_handshake_done
static void on_handshake_done(void *arg, grpc_error_handle error)
Definition: ssl_server_fuzzer.cc:45
sync.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
grpc_slice_split_tail
GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split)
Definition: slice/slice.cc:343
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
grpc_http_request
Definition: src/core/lib/http/parser.h:69
run_interop_tests.server_name
server_name
Definition: run_interop_tests.py:1510
GRPC_ARG_HTTP_CONNECT_SERVER
#define GRPC_ARG_HTTP_CONNECT_SERVER
Definition: http_connect_handshaker.h:28
port_platform.h
on_handshake_done_
grpc_closure * on_handshake_done_
Definition: http_connect_handshaker.cc:91


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:02