mirror of https://github.com/grpc/grpc.git
commit
e76d36d138
570 changed files with 35489 additions and 10587 deletions
@ -0,0 +1,15 @@ |
||||
There are times when we make changes that include a temporary shim for |
||||
backward-compatibility (e.g., a macro or some other function to preserve |
||||
the original API) to avoid having to bump the major version number in |
||||
the next release. However, when we do eventually want to release a |
||||
feature that does change the API in a non-backward-compatible way, we |
||||
will wind up bumping the major version number anyway, at which point we |
||||
can take the opportunity to clean up any pending backward-compatibility |
||||
shims. |
||||
|
||||
This file lists all pending backward-compatibility changes that should |
||||
be cleaned up the next time we are going to bump the major version |
||||
number: |
||||
|
||||
- remove `ClientContext::set_fail_fast()` method from |
||||
`include/grpc++/impl/codegen/client_context.h` (commit `9477724`) |
@ -0,0 +1,67 @@ |
||||
gRPC environment variables |
||||
-------------------------- |
||||
|
||||
gRPC C core based implementations (those contained in this repository) expose |
||||
some configuration as environment variables that can be set. |
||||
|
||||
* GRPC_ABORT_ON_LEAKS |
||||
A debugging aid to cause a call to abort() when gRPC objects are leaked past |
||||
grpc_shutdown(). Set to 1 to cause the abort, if unset or 0 it does not |
||||
abort the process. |
||||
|
||||
* GOOGLE_APPLICATION_CREDENTIALS |
||||
The path to find the credentials to use when Google credentials are created |
||||
|
||||
* GRPC_SSL_CIPHER_SUITES |
||||
A colon separated list of cipher suites to use with OpenSSL |
||||
Defaults to: |
||||
ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-GCM-SHA384 |
||||
|
||||
* GRPC_DEFAULT_SSL_ROOTS_FILE_PATH |
||||
PEM file to load SSL roots from |
||||
|
||||
* GRPC_POLL_STRATEGY [posix-style environments only] |
||||
Declares which polling engines to try when starting gRPC. |
||||
This is a comma-separated list of engines, which are tried in priority order |
||||
first -> last. |
||||
Available polling engines include: |
||||
- epoll (linux-only) - a polling engine based around the epoll family of |
||||
system calls |
||||
- poll - a portable polling engine based around poll(), intended to be a |
||||
fallback engine when nothing better exists |
||||
- legacy - the (deprecated) original polling engine for gRPC |
||||
|
||||
* GRPC_TRACE |
||||
A comma separated list of tracers that provide additional insight into how |
||||
gRPC C core is processing requests via debug logs. Available tracers include: |
||||
- api - traces api calls to the C core |
||||
- channel - traces operations on the C core channel stack |
||||
- combiner - traces combiner lock state |
||||
- compression - traces compression operations |
||||
- connectivity_state - traces connectivity state changes to channels |
||||
- channel_stack_builder - traces information about channel stacks being built |
||||
- http - traces state in the http2 transport engine |
||||
- http1 - traces HTTP/1.x operations performed by gRPC |
||||
- flowctl - traces http2 flow control |
||||
- op_failure - traces error information when failure is pushed onto a |
||||
completion queue |
||||
- pending_tags - [debug builds only] traces still-in-progress tags on |
||||
completion queues |
||||
- round_robin - traces the round_robin load balancing policy |
||||
- glb - traces the grpclb load balancer |
||||
- queue_pluck |
||||
- queue_timeout |
||||
- secure_endpoint - traces bytes flowing through encrypted channels |
||||
- transport_security - traces metadata about secure channel establishment |
||||
- tcp - traces bytes in and out of a channel |
||||
'all' can additionally be used to turn all traces on. |
||||
Individual traces can be disabled by prefixing them with '-'. |
||||
Example: |
||||
export GRPC_TRACE=all,-pending_tags |
||||
|
||||
* GRPC_VERBOSITY |
||||
Default gRPC logging verbosity - one of: |
||||
- DEBUG - log all gRPC messages |
||||
- INFO - log INFO and ERROR message |
||||
- ERROR - log only errors |
||||
|
@ -0,0 +1,4 @@ |
||||
#Overview |
||||
|
||||
This directory contains source code for gRPC protocol buffer compiler (*protoc*) plugins. Along with `protoc`, |
||||
these plugins are used to generate gRPC client and server stubs from `.proto` files. |
@ -0,0 +1,174 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <map> |
||||
|
||||
#include "src/compiler/config.h" |
||||
#include "src/compiler/generator_helpers.h" |
||||
#include "src/compiler/php_generator_helpers.h" |
||||
|
||||
using grpc::protobuf::FileDescriptor; |
||||
using grpc::protobuf::ServiceDescriptor; |
||||
using grpc::protobuf::MethodDescriptor; |
||||
using grpc::protobuf::Descriptor; |
||||
using grpc::protobuf::io::Printer; |
||||
using grpc::protobuf::io::StringOutputStream; |
||||
using std::map; |
||||
|
||||
namespace grpc_php_generator { |
||||
namespace { |
||||
|
||||
grpc::string MessageIdentifierName(const grpc::string &name) { |
||||
std::vector<grpc::string> tokens = grpc_generator::tokenize(name, "."); |
||||
std::ostringstream oss; |
||||
for (unsigned int i = 0; i < tokens.size(); i++) { |
||||
oss << (i == 0 ? "" : "\\") |
||||
<< grpc_generator::CapitalizeFirstLetter(tokens[i]); |
||||
} |
||||
return oss.str(); |
||||
} |
||||
|
||||
void PrintMethod(const MethodDescriptor *method, Printer *out) { |
||||
const Descriptor *input_type = method->input_type(); |
||||
const Descriptor *output_type = method->output_type(); |
||||
map<grpc::string, grpc::string> vars; |
||||
vars["service_name"] = method->service()->full_name(); |
||||
vars["name"] = method->name(); |
||||
vars["input_type_id"] = MessageIdentifierName(input_type->full_name()); |
||||
vars["output_type_id"] = MessageIdentifierName(output_type->full_name()); |
||||
|
||||
out->Print("/**\n"); |
||||
out->Print(GetPHPComments(method, " *").c_str()); |
||||
if (method->client_streaming()) { |
||||
out->Print(vars, |
||||
" * @param array $$metadata metadata\n" |
||||
" * @param array $$options call options\n */\n" |
||||
"public function $name$($$metadata = [], " |
||||
"$$options = []) {\n"); |
||||
out->Indent(); |
||||
if (method->server_streaming()) { |
||||
out->Print("return $$this->_bidiRequest("); |
||||
} else { |
||||
out->Print("return $$this->_clientStreamRequest("); |
||||
} |
||||
out->Print(vars, |
||||
"'/$service_name$/$name$',\n" |
||||
"['\\$output_type_id$','decode'],\n" |
||||
"$$metadata, $$options);\n"); |
||||
} else { |
||||
out->Print(vars, |
||||
" * @param \\$input_type_id$ $$argument input argument\n" |
||||
" * @param array $$metadata metadata\n" |
||||
" * @param array $$options call options\n */\n" |
||||
"public function $name$(\\$input_type_id$ $$argument,\n" |
||||
" $$metadata = [], $$options = []) {\n"); |
||||
out->Indent(); |
||||
if (method->server_streaming()) { |
||||
out->Print("return $$this->_serverStreamRequest("); |
||||
} else { |
||||
out->Print("return $$this->_simpleRequest("); |
||||
} |
||||
out->Print(vars, |
||||
"'/$service_name$/$name$',\n" |
||||
"$$argument,\n" |
||||
"['\\$output_type_id$', 'decode'],\n" |
||||
"$$metadata, $$options);\n"); |
||||
} |
||||
out->Outdent(); |
||||
out->Print("}\n\n"); |
||||
} |
||||
|
||||
// Prints out the service descriptor object
|
||||
void PrintService(const ServiceDescriptor *service, Printer *out) { |
||||
map<grpc::string, grpc::string> vars; |
||||
out->Print(GetPHPComments(service, "//").c_str()); |
||||
vars["name"] = service->name(); |
||||
out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n"); |
||||
out->Indent(); |
||||
out->Print( |
||||
"/**\n * @param string $$hostname hostname\n" |
||||
" * @param array $$opts channel options\n" |
||||
" * @param Grpc\\Channel $$channel (optional) re-use channel " |
||||
"object\n */\n" |
||||
"public function __construct($$hostname, $$opts, " |
||||
"$$channel = null) {\n"); |
||||
out->Indent(); |
||||
out->Print("parent::__construct($$hostname, $$opts, $$channel);\n"); |
||||
out->Outdent(); |
||||
out->Print("}\n\n"); |
||||
for (int i = 0; i < service->method_count(); i++) { |
||||
grpc::string method_name = |
||||
grpc_generator::LowercaseFirstLetter(service->method(i)->name()); |
||||
PrintMethod(service->method(i), out); |
||||
} |
||||
out->Outdent(); |
||||
out->Print("}\n\n"); |
||||
} |
||||
|
||||
void PrintServices(const FileDescriptor *file, Printer *out) { |
||||
map<grpc::string, grpc::string> vars; |
||||
vars["package"] = MessageIdentifierName(file->package()); |
||||
out->Print(vars, "namespace $package$ {\n\n"); |
||||
out->Indent(); |
||||
for (int i = 0; i < file->service_count(); i++) { |
||||
PrintService(file->service(i), out); |
||||
} |
||||
out->Outdent(); |
||||
out->Print("}\n"); |
||||
} |
||||
} |
||||
|
||||
grpc::string GenerateFile(const FileDescriptor *file) { |
||||
grpc::string output; |
||||
{ |
||||
StringOutputStream output_stream(&output); |
||||
Printer out(&output_stream, '$'); |
||||
|
||||
if (file->service_count() == 0) { |
||||
return output; |
||||
} |
||||
out.Print("<?php\n"); |
||||
out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n"); |
||||
|
||||
grpc::string leading_comments = GetPHPComments(file, "//"); |
||||
if (!leading_comments.empty()) { |
||||
out.Print("// Original file comments:\n"); |
||||
out.Print(leading_comments.c_str()); |
||||
} |
||||
|
||||
PrintServices(file, &out); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
} // namespace grpc_php_generator
|
@ -0,0 +1,58 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_PHP_GENERATOR_HELPERS_H |
||||
#define GRPC_INTERNAL_COMPILER_PHP_GENERATOR_HELPERS_H |
||||
|
||||
#include <algorithm> |
||||
|
||||
#include "src/compiler/config.h" |
||||
#include "src/compiler/generator_helpers.h" |
||||
|
||||
namespace grpc_php_generator { |
||||
|
||||
inline grpc::string GetPHPServiceFilename(const grpc::string& filename) { |
||||
return grpc_generator::StripProto(filename) + "_grpc_pb.php"; |
||||
} |
||||
|
||||
// Get leading or trailing comments in a string. Comment lines start with "// ".
|
||||
// Leading detached comments are put in in front of leading comments.
|
||||
template <typename DescriptorType> |
||||
inline grpc::string GetPHPComments(const DescriptorType* desc, |
||||
grpc::string prefix) { |
||||
return grpc_generator::GetPrefixedComments(desc, true, prefix); |
||||
} |
||||
|
||||
} // namespace grpc_php_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PHP_GENERATOR_HELPERS_H
|
@ -0,0 +1,275 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/ext/client_config/http_connect_handshaker.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/slice_buffer.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/ext/client_config/uri_parser.h" |
||||
#include "src/core/lib/http/format_request.h" |
||||
#include "src/core/lib/http/parser.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
#include "src/core/lib/support/env.h" |
||||
|
||||
typedef struct http_connect_handshaker { |
||||
// Base class. Must be first.
|
||||
grpc_handshaker base; |
||||
|
||||
char* proxy_server; |
||||
char* server_name; |
||||
|
||||
// State saved while performing the handshake.
|
||||
grpc_endpoint* endpoint; |
||||
grpc_channel_args* args; |
||||
grpc_handshaker_done_cb cb; |
||||
void* user_data; |
||||
|
||||
// Objects for processing the HTTP CONNECT request and response.
|
||||
gpr_slice_buffer write_buffer; |
||||
gpr_slice_buffer* read_buffer; // Ownership passes through this object.
|
||||
grpc_closure request_done_closure; |
||||
grpc_closure response_read_closure; |
||||
grpc_http_parser http_parser; |
||||
grpc_http_response http_response; |
||||
grpc_timer timeout_timer; |
||||
|
||||
gpr_refcount refcount; |
||||
} http_connect_handshaker; |
||||
|
||||
// Unref and clean up handshaker.
|
||||
static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) { |
||||
if (gpr_unref(&handshaker->refcount)) { |
||||
gpr_free(handshaker->proxy_server); |
||||
gpr_free(handshaker->server_name); |
||||
gpr_slice_buffer_destroy(&handshaker->write_buffer); |
||||
grpc_http_parser_destroy(&handshaker->http_parser); |
||||
grpc_http_response_destroy(&handshaker->http_response); |
||||
gpr_free(handshaker); |
||||
} |
||||
} |
||||
|
||||
// Callback invoked when deadline is exceeded.
|
||||
static void on_timeout(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { |
||||
http_connect_handshaker* handshaker = arg; |
||||
if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled.
|
||||
grpc_endpoint_shutdown(exec_ctx, handshaker->endpoint); |
||||
} |
||||
http_connect_handshaker_unref(handshaker); |
||||
} |
||||
|
||||
// Callback invoked when finished writing HTTP CONNECT request.
|
||||
static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
http_connect_handshaker* handshaker = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
// If the write failed, invoke the callback immediately with the error.
|
||||
handshaker->cb(exec_ctx, handshaker->endpoint, handshaker->args, |
||||
handshaker->read_buffer, handshaker->user_data, |
||||
GRPC_ERROR_REF(error)); |
||||
} else { |
||||
// Otherwise, read the response.
|
||||
grpc_endpoint_read(exec_ctx, handshaker->endpoint, handshaker->read_buffer, |
||||
&handshaker->response_read_closure); |
||||
} |
||||
} |
||||
|
||||
// Callback invoked for reading HTTP CONNECT response.
|
||||
static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
http_connect_handshaker* handshaker = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
GRPC_ERROR_REF(error); // Take ref to pass to the handshake-done callback.
|
||||
goto done; |
||||
} |
||||
// Add buffer to parser.
|
||||
for (size_t i = 0; i < handshaker->read_buffer->count; ++i) { |
||||
if (GPR_SLICE_LENGTH(handshaker->read_buffer->slices[i]) > 0) { |
||||
size_t body_start_offset = 0; |
||||
error = grpc_http_parser_parse(&handshaker->http_parser, |
||||
handshaker->read_buffer->slices[i], |
||||
&body_start_offset); |
||||
if (error != GRPC_ERROR_NONE) goto done; |
||||
if (handshaker->http_parser.state == GRPC_HTTP_BODY) { |
||||
// We've gotten back a successul response, so stop the timeout timer.
|
||||
grpc_timer_cancel(exec_ctx, &handshaker->timeout_timer); |
||||
// Remove the data we've already read from the read buffer,
|
||||
// leaving only the leftover bytes (if any).
|
||||
gpr_slice_buffer tmp_buffer; |
||||
gpr_slice_buffer_init(&tmp_buffer); |
||||
if (body_start_offset < |
||||
GPR_SLICE_LENGTH(handshaker->read_buffer->slices[i])) { |
||||
gpr_slice_buffer_add( |
||||
&tmp_buffer, |
||||
gpr_slice_split_tail(&handshaker->read_buffer->slices[i], |
||||
body_start_offset)); |
||||
} |
||||
gpr_slice_buffer_addn(&tmp_buffer, |
||||
&handshaker->read_buffer->slices[i + 1], |
||||
handshaker->read_buffer->count - i - 1); |
||||
gpr_slice_buffer_swap(handshaker->read_buffer, &tmp_buffer); |
||||
gpr_slice_buffer_destroy(&tmp_buffer); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
// If we're not done reading the response, read more data.
|
||||
// TODO(roth): In practice, I suspect that the response to a CONNECT
|
||||
// request will never include a body, in which case this check is
|
||||
// sufficient. However, the language of RFC-2817 doesn't explicitly
|
||||
// forbid the response from including a body. If there is a body,
|
||||
// it's possible that we might have parsed part but not all of the
|
||||
// body, in which case this check will cause us to fail to parse the
|
||||
// remainder of the body. If that ever becomes an issue, we may
|
||||
// need to fix the HTTP parser to understand when the body is
|
||||
// complete (e.g., handling chunked transfer encoding or looking
|
||||
// at the Content-Length: header).
|
||||
if (handshaker->http_parser.state != GRPC_HTTP_BODY) { |
||||
gpr_slice_buffer_reset_and_unref(handshaker->read_buffer); |
||||
grpc_endpoint_read(exec_ctx, handshaker->endpoint, handshaker->read_buffer, |
||||
&handshaker->response_read_closure); |
||||
return; |
||||
} |
||||
// Make sure we got a 2xx response.
|
||||
if (handshaker->http_response.status < 200 || |
||||
handshaker->http_response.status >= 300) { |
||||
char* msg; |
||||
gpr_asprintf(&msg, "HTTP proxy returned response code %d", |
||||
handshaker->http_response.status); |
||||
error = GRPC_ERROR_CREATE(msg); |
||||
gpr_free(msg); |
||||
} |
||||
done: |
||||
// Invoke handshake-done callback.
|
||||
handshaker->cb(exec_ctx, handshaker->endpoint, handshaker->args, |
||||
handshaker->read_buffer, handshaker->user_data, error); |
||||
} |
||||
|
||||
//
|
||||
// Public handshaker methods
|
||||
//
|
||||
|
||||
static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, |
||||
grpc_handshaker* handshaker_in) { |
||||
http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; |
||||
http_connect_handshaker_unref(handshaker); |
||||
} |
||||
|
||||
static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, |
||||
grpc_handshaker* handshaker) {} |
||||
|
||||
static void http_connect_handshaker_do_handshake( |
||||
grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker_in, |
||||
grpc_endpoint* endpoint, grpc_channel_args* args, |
||||
gpr_slice_buffer* read_buffer, gpr_timespec deadline, |
||||
grpc_tcp_server_acceptor* acceptor, grpc_handshaker_done_cb cb, |
||||
void* user_data) { |
||||
http_connect_handshaker* handshaker = (http_connect_handshaker*)handshaker_in; |
||||
// Save state in the handshaker object.
|
||||
handshaker->endpoint = endpoint; |
||||
handshaker->args = args; |
||||
handshaker->cb = cb; |
||||
handshaker->user_data = user_data; |
||||
handshaker->read_buffer = read_buffer; |
||||
// Send HTTP CONNECT request.
|
||||
gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", |
||||
handshaker->server_name, handshaker->proxy_server); |
||||
grpc_httpcli_request request; |
||||
memset(&request, 0, sizeof(request)); |
||||
request.host = handshaker->proxy_server; |
||||
request.http.method = "CONNECT"; |
||||
request.http.path = handshaker->server_name; |
||||
request.handshaker = &grpc_httpcli_plaintext; |
||||
gpr_slice request_slice = grpc_httpcli_format_connect_request(&request); |
||||
gpr_slice_buffer_add(&handshaker->write_buffer, request_slice); |
||||
grpc_endpoint_write(exec_ctx, endpoint, &handshaker->write_buffer, |
||||
&handshaker->request_done_closure); |
||||
// Set timeout timer. The timer gets a reference to the handshaker.
|
||||
gpr_ref(&handshaker->refcount); |
||||
grpc_timer_init(exec_ctx, &handshaker->timeout_timer, |
||||
gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), |
||||
on_timeout, handshaker, gpr_now(GPR_CLOCK_MONOTONIC)); |
||||
} |
||||
|
||||
static const struct grpc_handshaker_vtable http_connect_handshaker_vtable = { |
||||
http_connect_handshaker_destroy, http_connect_handshaker_shutdown, |
||||
http_connect_handshaker_do_handshake}; |
||||
|
||||
grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server, |
||||
const char* server_name) { |
||||
GPR_ASSERT(proxy_server != NULL); |
||||
GPR_ASSERT(server_name != NULL); |
||||
http_connect_handshaker* handshaker = |
||||
gpr_malloc(sizeof(http_connect_handshaker)); |
||||
memset(handshaker, 0, sizeof(*handshaker)); |
||||
grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base); |
||||
handshaker->proxy_server = gpr_strdup(proxy_server); |
||||
handshaker->server_name = gpr_strdup(server_name); |
||||
gpr_slice_buffer_init(&handshaker->write_buffer); |
||||
grpc_closure_init(&handshaker->request_done_closure, on_write_done, |
||||
handshaker); |
||||
grpc_closure_init(&handshaker->response_read_closure, on_read_done, |
||||
handshaker); |
||||
grpc_http_parser_init(&handshaker->http_parser, GRPC_HTTP_RESPONSE, |
||||
&handshaker->http_response); |
||||
gpr_ref_init(&handshaker->refcount, 1); |
||||
return &handshaker->base; |
||||
} |
||||
|
||||
char* grpc_get_http_proxy_server() { |
||||
char* uri_str = gpr_getenv("http_proxy"); |
||||
if (uri_str == NULL) return NULL; |
||||
grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */); |
||||
char* proxy_name = NULL; |
||||
if (uri == NULL || uri->authority == NULL) { |
||||
gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var"); |
||||
goto done; |
||||
} |
||||
if (strcmp(uri->scheme, "http") != 0) { |
||||
gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI", uri->scheme); |
||||
goto done; |
||||
} |
||||
if (strchr(uri->authority, '@') != NULL) { |
||||
gpr_log(GPR_ERROR, "userinfo not supported in proxy URI"); |
||||
goto done; |
||||
} |
||||
proxy_name = gpr_strdup(uri->authority); |
||||
done: |
||||
gpr_free(uri_str); |
||||
grpc_uri_destroy(uri); |
||||
return proxy_name; |
||||
} |
@ -0,0 +1,47 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H |
||||
#define GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H |
||||
|
||||
#include "src/core/lib/channel/handshaker.h" |
||||
|
||||
/// Does NOT take ownership of \a proxy_server or \a server_name.
|
||||
grpc_handshaker* grpc_http_connect_handshaker_create(const char* proxy_server, |
||||
const char* server_name); |
||||
|
||||
/// Returns the name of the proxy to use, or NULL if no proxy is configured.
|
||||
/// Caller takes ownership of result.
|
||||
char* grpc_get_http_proxy_server(); |
||||
|
||||
#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H */ |
@ -0,0 +1,302 @@ |
||||
//
|
||||
// Copyright 2016, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include "src/core/lib/channel/deadline_filter.h" |
||||
|
||||
#include <stdbool.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/sync.h> |
||||
#include <grpc/support/time.h> |
||||
|
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
|
||||
//
|
||||
// grpc_deadline_state
|
||||
//
|
||||
|
||||
// Timer callback.
|
||||
static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = arg; |
||||
grpc_deadline_state* deadline_state = elem->call_data; |
||||
gpr_mu_lock(&deadline_state->timer_mu); |
||||
deadline_state->timer_pending = false; |
||||
gpr_mu_unlock(&deadline_state->timer_mu); |
||||
if (error != GRPC_ERROR_CANCELLED) { |
||||
gpr_slice msg = gpr_slice_from_static_string("Deadline Exceeded"); |
||||
grpc_call_element_send_cancel_with_message( |
||||
exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &msg); |
||||
gpr_slice_unref(msg); |
||||
} |
||||
GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); |
||||
} |
||||
|
||||
// Starts the deadline timer.
|
||||
static void start_timer_if_needed(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem, |
||||
gpr_timespec deadline) { |
||||
grpc_deadline_state* deadline_state = elem->call_data; |
||||
deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); |
||||
if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { |
||||
// Take a reference to the call stack, to be owned by the timer.
|
||||
GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer"); |
||||
gpr_mu_lock(&deadline_state->timer_mu); |
||||
deadline_state->timer_pending = true; |
||||
grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, timer_callback, |
||||
elem, gpr_now(GPR_CLOCK_MONOTONIC)); |
||||
gpr_mu_unlock(&deadline_state->timer_mu); |
||||
} |
||||
} |
||||
|
||||
// Cancels the deadline timer.
|
||||
static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, |
||||
grpc_deadline_state* deadline_state) { |
||||
gpr_mu_lock(&deadline_state->timer_mu); |
||||
if (deadline_state->timer_pending) { |
||||
grpc_timer_cancel(exec_ctx, &deadline_state->timer); |
||||
deadline_state->timer_pending = false; |
||||
} |
||||
gpr_mu_unlock(&deadline_state->timer_mu); |
||||
} |
||||
|
||||
// Callback run when the call is complete.
|
||||
static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { |
||||
grpc_deadline_state* deadline_state = arg; |
||||
cancel_timer_if_needed(exec_ctx, deadline_state); |
||||
// Invoke the next callback.
|
||||
deadline_state->next_on_complete->cb( |
||||
exec_ctx, deadline_state->next_on_complete->cb_arg, error); |
||||
} |
||||
|
||||
// Inject our own on_complete callback into op.
|
||||
static void inject_on_complete_cb(grpc_deadline_state* deadline_state, |
||||
grpc_transport_stream_op* op) { |
||||
deadline_state->next_on_complete = op->on_complete; |
||||
grpc_closure_init(&deadline_state->on_complete, on_complete, deadline_state); |
||||
op->on_complete = &deadline_state->on_complete; |
||||
} |
||||
|
||||
// Callback and associated state for starting the timer after call stack
|
||||
// initialization has been completed.
|
||||
struct start_timer_after_init_state { |
||||
grpc_call_element* elem; |
||||
gpr_timespec deadline; |
||||
grpc_closure closure; |
||||
}; |
||||
static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
struct start_timer_after_init_state* state = arg; |
||||
start_timer_if_needed(exec_ctx, state->elem, state->deadline); |
||||
gpr_free(state); |
||||
} |
||||
|
||||
void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||
grpc_call_element_args* args) { |
||||
grpc_deadline_state* deadline_state = elem->call_data; |
||||
memset(deadline_state, 0, sizeof(*deadline_state)); |
||||
deadline_state->call_stack = args->call_stack; |
||||
gpr_mu_init(&deadline_state->timer_mu); |
||||
// Deadline will always be infinite on servers, so the timer will only be
|
||||
// set on clients with a finite deadline.
|
||||
const gpr_timespec deadline = |
||||
gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC); |
||||
if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { |
||||
// When the deadline passes, we indicate the failure by sending down
|
||||
// an op with cancel_error set. However, we can't send down any ops
|
||||
// until after the call stack is fully initialized. If we start the
|
||||
// timer here, we have no guarantee that the timer won't pop before
|
||||
// call stack initialization is finished. To avoid that problem, we
|
||||
// create a closure to start the timer, and we schedule that closure
|
||||
// to be run after call stack initialization is done.
|
||||
struct start_timer_after_init_state* state = gpr_malloc(sizeof(*state)); |
||||
state->elem = elem; |
||||
state->deadline = deadline; |
||||
grpc_closure_init(&state->closure, start_timer_after_init, state); |
||||
grpc_exec_ctx_sched(exec_ctx, &state->closure, GRPC_ERROR_NONE, NULL); |
||||
} |
||||
} |
||||
|
||||
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem) { |
||||
grpc_deadline_state* deadline_state = elem->call_data; |
||||
cancel_timer_if_needed(exec_ctx, deadline_state); |
||||
gpr_mu_destroy(&deadline_state->timer_mu); |
||||
} |
||||
|
||||
void grpc_deadline_state_client_start_transport_stream_op( |
||||
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||
grpc_transport_stream_op* op) { |
||||
grpc_deadline_state* deadline_state = elem->call_data; |
||||
if (op->cancel_error != GRPC_ERROR_NONE || |
||||
op->close_error != GRPC_ERROR_NONE) { |
||||
cancel_timer_if_needed(exec_ctx, deadline_state); |
||||
} else { |
||||
// Make sure we know when the call is complete, so that we can cancel
|
||||
// the timer.
|
||||
if (op->recv_trailing_metadata != NULL) { |
||||
inject_on_complete_cb(deadline_state, op); |
||||
} |
||||
} |
||||
} |
||||
|
||||
//
|
||||
// filter code
|
||||
//
|
||||
|
||||
// Constructor for channel_data. Used for both client and server filters.
|
||||
static void init_channel_elem(grpc_exec_ctx* exec_ctx, |
||||
grpc_channel_element* elem, |
||||
grpc_channel_element_args* args) { |
||||
GPR_ASSERT(!args->is_last); |
||||
} |
||||
|
||||
// Destructor for channel_data. Used for both client and server filters.
|
||||
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, |
||||
grpc_channel_element* elem) {} |
||||
|
||||
// Call data used for both client and server filter.
|
||||
typedef struct base_call_data { |
||||
grpc_deadline_state deadline_state; |
||||
} base_call_data; |
||||
|
||||
// Additional call data used only for the server filter.
|
||||
typedef struct server_call_data { |
||||
base_call_data base; // Must be first.
|
||||
// The closure for receiving initial metadata.
|
||||
grpc_closure recv_initial_metadata_ready; |
||||
// Received initial metadata batch.
|
||||
grpc_metadata_batch* recv_initial_metadata; |
||||
// The original recv_initial_metadata_ready closure, which we chain to
|
||||
// after our own closure is invoked.
|
||||
grpc_closure* next_recv_initial_metadata_ready; |
||||
} server_call_data; |
||||
|
||||
// Constructor for call_data. Used for both client and server filters.
|
||||
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem, |
||||
grpc_call_element_args* args) { |
||||
// Note: size of call data is different between client and server.
|
||||
memset(elem->call_data, 0, elem->filter->sizeof_call_data); |
||||
grpc_deadline_state_init(exec_ctx, elem, args); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
// Destructor for call_data. Used for both client and server filters.
|
||||
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||
const grpc_call_final_info* final_info, |
||||
void* and_free_memory) { |
||||
grpc_deadline_state_destroy(exec_ctx, elem); |
||||
} |
||||
|
||||
// Method for starting a call op for client filter.
|
||||
static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem, |
||||
grpc_transport_stream_op* op) { |
||||
grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op); |
||||
// Chain to next filter.
|
||||
grpc_call_next_op(exec_ctx, elem, op); |
||||
} |
||||
|
||||
// Callback for receiving initial metadata on the server.
|
||||
static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = arg; |
||||
server_call_data* calld = elem->call_data; |
||||
// Get deadline from metadata and start the timer if needed.
|
||||
start_timer_if_needed(exec_ctx, elem, calld->recv_initial_metadata->deadline); |
||||
// Invoke the next callback.
|
||||
calld->next_recv_initial_metadata_ready->cb( |
||||
exec_ctx, calld->next_recv_initial_metadata_ready->cb_arg, error); |
||||
} |
||||
|
||||
// Method for starting a call op for server filter.
|
||||
static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem, |
||||
grpc_transport_stream_op* op) { |
||||
server_call_data* calld = elem->call_data; |
||||
if (op->cancel_error != GRPC_ERROR_NONE || |
||||
op->close_error != GRPC_ERROR_NONE) { |
||||
cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state); |
||||
} else { |
||||
// If we're receiving initial metadata, we need to get the deadline
|
||||
// from the recv_initial_metadata_ready callback. So we inject our
|
||||
// own callback into that hook.
|
||||
if (op->recv_initial_metadata_ready != NULL) { |
||||
calld->next_recv_initial_metadata_ready = op->recv_initial_metadata_ready; |
||||
calld->recv_initial_metadata = op->recv_initial_metadata; |
||||
grpc_closure_init(&calld->recv_initial_metadata_ready, |
||||
recv_initial_metadata_ready, elem); |
||||
op->recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; |
||||
} |
||||
// Make sure we know when the call is complete, so that we can cancel
|
||||
// the timer.
|
||||
// Note that we trigger this on recv_trailing_metadata, even though
|
||||
// the client never sends trailing metadata, because this is the
|
||||
// hook that tells us when the call is complete on the server side.
|
||||
if (op->recv_trailing_metadata != NULL) { |
||||
inject_on_complete_cb(&calld->base.deadline_state, op); |
||||
} |
||||
} |
||||
// Chain to next filter.
|
||||
grpc_call_next_op(exec_ctx, elem, op); |
||||
} |
||||
|
||||
const grpc_channel_filter grpc_client_deadline_filter = { |
||||
client_start_transport_stream_op, |
||||
grpc_channel_next_op, |
||||
sizeof(base_call_data), |
||||
init_call_elem, |
||||
grpc_call_stack_ignore_set_pollset_or_pollset_set, |
||||
destroy_call_elem, |
||||
0, // sizeof(channel_data)
|
||||
init_channel_elem, |
||||
destroy_channel_elem, |
||||
grpc_call_next_get_peer, |
||||
"deadline", |
||||
}; |
||||
|
||||
const grpc_channel_filter grpc_server_deadline_filter = { |
||||
server_start_transport_stream_op, |
||||
grpc_channel_next_op, |
||||
sizeof(server_call_data), |
||||
init_call_elem, |
||||
grpc_call_stack_ignore_set_pollset_or_pollset_set, |
||||
destroy_call_elem, |
||||
0, // sizeof(channel_data)
|
||||
init_channel_elem, |
||||
destroy_channel_elem, |
||||
grpc_call_next_get_peer, |
||||
"deadline", |
||||
}; |
@ -0,0 +1,79 @@ |
||||
//
|
||||
// Copyright 2016, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H |
||||
#define GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H |
||||
|
||||
#include "src/core/lib/channel/channel_stack.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
|
||||
// State used for filters that enforce call deadlines.
|
||||
// Must be the first field in the filter's call_data.
|
||||
typedef struct grpc_deadline_state { |
||||
// We take a reference to the call stack for the timer callback.
|
||||
grpc_call_stack* call_stack; |
||||
// Guards access to timer_pending and timer.
|
||||
gpr_mu timer_mu; |
||||
// True if the timer callback is currently pending.
|
||||
bool timer_pending; |
||||
// The deadline timer.
|
||||
grpc_timer timer; |
||||
// Closure to invoke when the call is complete.
|
||||
// We use this to cancel the timer.
|
||||
grpc_closure on_complete; |
||||
// The original on_complete closure, which we chain to after our own
|
||||
// closure is invoked.
|
||||
grpc_closure* next_on_complete; |
||||
} grpc_deadline_state; |
||||
|
||||
// To be used in a filter's init_call_elem(), destroy_call_elem(), and
|
||||
// start_transport_stream_op() methods to enforce call deadlines.
|
||||
//
|
||||
// REQUIRES: The first field in elem->call_data is a grpc_deadline_state.
|
||||
//
|
||||
// For grpc_deadline_state_client_start_transport_stream_op(), it is the
|
||||
// caller's responsibility to chain to the next filter if necessary
|
||||
// after the function returns.
|
||||
void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||
grpc_call_element_args* args); |
||||
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, |
||||
grpc_call_element* elem); |
||||
void grpc_deadline_state_client_start_transport_stream_op( |
||||
grpc_exec_ctx* exec_ctx, grpc_call_element* elem, |
||||
grpc_transport_stream_op* op); |
||||
|
||||
// Deadline filters for direct client channels and server channels.
|
||||
// Note: Deadlines for non-direct client channels are handled by the
|
||||
// client_channel filter.
|
||||
extern const grpc_channel_filter grpc_client_deadline_filter; |
||||
extern const grpc_channel_filter grpc_server_deadline_filter; |
||||
|
||||
#endif /* GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue