mirror of https://github.com/grpc/grpc.git
commit
942c264861
59 changed files with 5106 additions and 1563 deletions
@ -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,129 @@ |
||||
/*
|
||||
* |
||||
* 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 "test/core/end2end/end2end_tests.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/host_port.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
#include <grpc/support/sync.h> |
||||
#include <grpc/support/thd.h> |
||||
#include <grpc/support/useful.h> |
||||
#include "src/core/ext/client_config/client_channel.h" |
||||
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" |
||||
#include "src/core/lib/channel/connected_channel.h" |
||||
#include "src/core/lib/channel/http_server_filter.h" |
||||
#include "src/core/lib/support/env.h" |
||||
#include "src/core/lib/surface/channel.h" |
||||
#include "src/core/lib/surface/server.h" |
||||
#include "test/core/end2end/fixtures/http_proxy.h" |
||||
#include "test/core/util/port.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
typedef struct fullstack_fixture_data { |
||||
char *server_addr; |
||||
grpc_end2end_http_proxy *proxy; |
||||
} fullstack_fixture_data; |
||||
|
||||
static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( |
||||
grpc_channel_args *client_args, grpc_channel_args *server_args) { |
||||
grpc_end2end_test_fixture f; |
||||
memset(&f, 0, sizeof(f)); |
||||
|
||||
fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); |
||||
const int server_port = grpc_pick_unused_port_or_die(); |
||||
gpr_join_host_port(&ffd->server_addr, "localhost", server_port); |
||||
ffd->proxy = grpc_end2end_http_proxy_create(); |
||||
|
||||
f.fixture_data = ffd; |
||||
f.cq = grpc_completion_queue_create(NULL); |
||||
|
||||
return f; |
||||
} |
||||
|
||||
void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, |
||||
grpc_channel_args *client_args) { |
||||
fullstack_fixture_data *ffd = f->fixture_data; |
||||
char *proxy_uri; |
||||
gpr_asprintf(&proxy_uri, "http://%s", |
||||
grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); |
||||
gpr_setenv("http_proxy", proxy_uri); |
||||
gpr_free(proxy_uri); |
||||
f->client = grpc_insecure_channel_create(ffd->server_addr, client_args, NULL); |
||||
GPR_ASSERT(f->client); |
||||
} |
||||
|
||||
void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, |
||||
grpc_channel_args *server_args) { |
||||
fullstack_fixture_data *ffd = f->fixture_data; |
||||
if (f->server) { |
||||
grpc_server_destroy(f->server); |
||||
} |
||||
f->server = grpc_server_create(server_args, NULL); |
||||
grpc_server_register_completion_queue(f->server, f->cq, NULL); |
||||
GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->server_addr)); |
||||
grpc_server_start(f->server); |
||||
} |
||||
|
||||
void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { |
||||
fullstack_fixture_data *ffd = f->fixture_data; |
||||
gpr_free(ffd->server_addr); |
||||
grpc_end2end_http_proxy_destroy(ffd->proxy); |
||||
gpr_free(ffd); |
||||
} |
||||
|
||||
/* All test configurations */ |
||||
static grpc_end2end_test_config configs[] = { |
||||
{"chttp2/fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, |
||||
chttp2_create_fixture_fullstack, chttp2_init_client_fullstack, |
||||
chttp2_init_server_fullstack, chttp2_tear_down_fullstack}, |
||||
}; |
||||
|
||||
int main(int argc, char **argv) { |
||||
size_t i; |
||||
|
||||
grpc_test_init(argc, argv); |
||||
grpc_end2end_tests_pre_init(); |
||||
grpc_init(); |
||||
|
||||
for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { |
||||
grpc_end2end_tests(argc, argv, configs[i]); |
||||
} |
||||
|
||||
grpc_shutdown(); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,481 @@ |
||||
/*
|
||||
* |
||||
* 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 "test/core/end2end/fixtures/http_proxy.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/atm.h> |
||||
#include <grpc/support/host_port.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/slice_buffer.h> |
||||
#include <grpc/support/string_util.h> |
||||
#include <grpc/support/sync.h> |
||||
#include <grpc/support/thd.h> |
||||
#include <grpc/support/useful.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/http/parser.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/iomgr/pollset.h" |
||||
#include "src/core/lib/iomgr/pollset_set.h" |
||||
#include "src/core/lib/iomgr/resolve_address.h" |
||||
#include "src/core/lib/iomgr/sockaddr_utils.h" |
||||
#include "src/core/lib/iomgr/tcp_client.h" |
||||
#include "src/core/lib/iomgr/tcp_server.h" |
||||
#include "test/core/util/port.h" |
||||
|
||||
struct grpc_end2end_http_proxy { |
||||
char* proxy_name; |
||||
gpr_thd_id thd; |
||||
grpc_tcp_server* server; |
||||
grpc_channel_args* channel_args; |
||||
gpr_mu* mu; |
||||
grpc_pollset* pollset; |
||||
gpr_atm shutdown; |
||||
}; |
||||
|
||||
//
|
||||
// Connection handling
|
||||
//
|
||||
|
||||
typedef struct proxy_connection { |
||||
grpc_endpoint* client_endpoint; |
||||
grpc_endpoint* server_endpoint; |
||||
|
||||
gpr_refcount refcount; |
||||
|
||||
grpc_pollset_set* pollset_set; |
||||
|
||||
grpc_closure on_read_request_done; |
||||
grpc_closure on_server_connect_done; |
||||
grpc_closure on_write_response_done; |
||||
grpc_closure on_client_read_done; |
||||
grpc_closure on_client_write_done; |
||||
grpc_closure on_server_read_done; |
||||
grpc_closure on_server_write_done; |
||||
|
||||
gpr_slice_buffer client_read_buffer; |
||||
gpr_slice_buffer client_deferred_write_buffer; |
||||
gpr_slice_buffer client_write_buffer; |
||||
gpr_slice_buffer server_read_buffer; |
||||
gpr_slice_buffer server_deferred_write_buffer; |
||||
gpr_slice_buffer server_write_buffer; |
||||
|
||||
grpc_http_parser http_parser; |
||||
grpc_http_request http_request; |
||||
} proxy_connection; |
||||
|
||||
// Helper function to destroy the proxy connection.
|
||||
static void proxy_connection_unref(grpc_exec_ctx* exec_ctx, |
||||
proxy_connection* conn) { |
||||
if (gpr_unref(&conn->refcount)) { |
||||
grpc_endpoint_destroy(exec_ctx, conn->client_endpoint); |
||||
if (conn->server_endpoint != NULL) |
||||
grpc_endpoint_destroy(exec_ctx, conn->server_endpoint); |
||||
grpc_pollset_set_destroy(conn->pollset_set); |
||||
gpr_slice_buffer_destroy(&conn->client_read_buffer); |
||||
gpr_slice_buffer_destroy(&conn->client_deferred_write_buffer); |
||||
gpr_slice_buffer_destroy(&conn->client_write_buffer); |
||||
gpr_slice_buffer_destroy(&conn->server_read_buffer); |
||||
gpr_slice_buffer_destroy(&conn->server_deferred_write_buffer); |
||||
gpr_slice_buffer_destroy(&conn->server_write_buffer); |
||||
grpc_http_parser_destroy(&conn->http_parser); |
||||
grpc_http_request_destroy(&conn->http_request); |
||||
gpr_free(conn); |
||||
} |
||||
} |
||||
|
||||
// Helper function to shut down the proxy connection.
|
||||
// Does NOT take ownership of a reference to error.
|
||||
static void proxy_connection_failed(grpc_exec_ctx* exec_ctx, |
||||
proxy_connection* conn, bool is_client, |
||||
const char* prefix, grpc_error* error) { |
||||
const char* msg = grpc_error_string(error); |
||||
gpr_log(GPR_INFO, "%s: %s", prefix, msg); |
||||
grpc_error_free_string(msg); |
||||
grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint); |
||||
if (conn->server_endpoint != NULL) |
||||
grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint); |
||||
proxy_connection_unref(exec_ctx, conn); |
||||
} |
||||
|
||||
// Callback for writing proxy data to the client.
|
||||
static void on_client_write_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy client write", error); |
||||
return; |
||||
} |
||||
// Clear write buffer (the data we just wrote).
|
||||
gpr_slice_buffer_reset_and_unref(&conn->client_write_buffer); |
||||
// If more data was read from the server since we started this write,
|
||||
// write that data now.
|
||||
if (conn->client_deferred_write_buffer.length > 0) { |
||||
gpr_slice_buffer_move_into(&conn->client_deferred_write_buffer, |
||||
&conn->client_write_buffer); |
||||
grpc_endpoint_write(exec_ctx, conn->client_endpoint, |
||||
&conn->client_write_buffer, |
||||
&conn->on_client_write_done); |
||||
} else { |
||||
// No more writes. Unref the connection.
|
||||
proxy_connection_unref(exec_ctx, conn); |
||||
} |
||||
} |
||||
|
||||
// Callback for writing proxy data to the backend server.
|
||||
static void on_server_write_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, false /* is_client */, |
||||
"HTTP proxy server write", error); |
||||
return; |
||||
} |
||||
// Clear write buffer (the data we just wrote).
|
||||
gpr_slice_buffer_reset_and_unref(&conn->server_write_buffer); |
||||
// If more data was read from the client since we started this write,
|
||||
// write that data now.
|
||||
if (conn->server_deferred_write_buffer.length > 0) { |
||||
gpr_slice_buffer_move_into(&conn->server_deferred_write_buffer, |
||||
&conn->server_write_buffer); |
||||
grpc_endpoint_write(exec_ctx, conn->server_endpoint, |
||||
&conn->server_write_buffer, |
||||
&conn->on_server_write_done); |
||||
} else { |
||||
// No more writes. Unref the connection.
|
||||
proxy_connection_unref(exec_ctx, conn); |
||||
} |
||||
} |
||||
|
||||
// Callback for reading data from the client, which will be proxied to
|
||||
// the backend server.
|
||||
static void on_client_read_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy client read", error); |
||||
return; |
||||
} |
||||
// If there is already a pending write (i.e., server_write_buffer is
|
||||
// not empty), then move the read data into server_deferred_write_buffer,
|
||||
// and the next write will be requested in on_server_write_done(), when
|
||||
// the current write is finished.
|
||||
//
|
||||
// Otherwise, move the read data into the write buffer and write it.
|
||||
if (conn->server_write_buffer.length > 0) { |
||||
gpr_slice_buffer_move_into(&conn->client_read_buffer, |
||||
&conn->server_deferred_write_buffer); |
||||
} else { |
||||
gpr_slice_buffer_move_into(&conn->client_read_buffer, |
||||
&conn->server_write_buffer); |
||||
gpr_ref(&conn->refcount); |
||||
grpc_endpoint_write(exec_ctx, conn->server_endpoint, |
||||
&conn->server_write_buffer, |
||||
&conn->on_server_write_done); |
||||
} |
||||
// Read more data.
|
||||
grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, |
||||
&conn->on_client_read_done); |
||||
} |
||||
|
||||
// Callback for reading data from the backend server, which will be
|
||||
// proxied to the client.
|
||||
static void on_server_read_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, false /* is_client */, |
||||
"HTTP proxy server read", error); |
||||
return; |
||||
} |
||||
// If there is already a pending write (i.e., client_write_buffer is
|
||||
// not empty), then move the read data into client_deferred_write_buffer,
|
||||
// and the next write will be requested in on_client_write_done(), when
|
||||
// the current write is finished.
|
||||
//
|
||||
// Otherwise, move the read data into the write buffer and write it.
|
||||
if (conn->client_write_buffer.length > 0) { |
||||
gpr_slice_buffer_move_into(&conn->server_read_buffer, |
||||
&conn->client_deferred_write_buffer); |
||||
} else { |
||||
gpr_slice_buffer_move_into(&conn->server_read_buffer, |
||||
&conn->client_write_buffer); |
||||
gpr_ref(&conn->refcount); |
||||
grpc_endpoint_write(exec_ctx, conn->client_endpoint, |
||||
&conn->client_write_buffer, |
||||
&conn->on_client_write_done); |
||||
} |
||||
// Read more data.
|
||||
grpc_endpoint_read(exec_ctx, conn->server_endpoint, &conn->server_read_buffer, |
||||
&conn->on_server_read_done); |
||||
} |
||||
|
||||
// Callback to write the HTTP response for the CONNECT request.
|
||||
static void on_write_response_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy write response", error); |
||||
return; |
||||
} |
||||
// Clear write buffer.
|
||||
gpr_slice_buffer_reset_and_unref(&conn->client_write_buffer); |
||||
// Start reading from both client and server. One of the read
|
||||
// requests inherits our ref to conn, but we need to take a new ref
|
||||
// for the other one.
|
||||
gpr_ref(&conn->refcount); |
||||
grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, |
||||
&conn->on_client_read_done); |
||||
grpc_endpoint_read(exec_ctx, conn->server_endpoint, &conn->server_read_buffer, |
||||
&conn->on_server_read_done); |
||||
} |
||||
|
||||
// Callback to connect to the backend server specified by the HTTP
|
||||
// CONNECT request.
|
||||
static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
// TODO(roth): Technically, in this case, we should handle the error
|
||||
// by returning an HTTP response to the client indicating that the
|
||||
// connection failed. However, for the purposes of this test code,
|
||||
// it's fine to pretend this is a client-side error, which will
|
||||
// cause the client connection to be dropped.
|
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy server connect", error); |
||||
return; |
||||
} |
||||
// We've established a connection, so send back a 200 response code to
|
||||
// the client.
|
||||
// The write callback inherits our reference to conn.
|
||||
gpr_slice slice = |
||||
gpr_slice_from_copied_string("HTTP/1.0 200 connected\r\n\r\n"); |
||||
gpr_slice_buffer_add(&conn->client_write_buffer, slice); |
||||
grpc_endpoint_write(exec_ctx, conn->client_endpoint, |
||||
&conn->client_write_buffer, |
||||
&conn->on_write_response_done); |
||||
} |
||||
|
||||
// Callback to read the HTTP CONNECT request.
|
||||
// TODO(roth): Technically, for any of the failure modes handled by this
|
||||
// function, we should handle the error by returning an HTTP response to
|
||||
// the client indicating that the request failed. However, for the purposes
|
||||
// of this test code, it's fine to pretend this is a client-side error,
|
||||
// which will cause the client connection to be dropped.
|
||||
static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
proxy_connection* conn = arg; |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy read request", error); |
||||
return; |
||||
} |
||||
// Read request and feed it to the parser.
|
||||
for (size_t i = 0; i < conn->client_read_buffer.count; ++i) { |
||||
if (GPR_SLICE_LENGTH(conn->client_read_buffer.slices[i]) > 0) { |
||||
error = grpc_http_parser_parse(&conn->http_parser, |
||||
conn->client_read_buffer.slices[i], NULL); |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy request parse", error); |
||||
GRPC_ERROR_UNREF(error); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
gpr_slice_buffer_reset_and_unref(&conn->client_read_buffer); |
||||
// If we're not done reading the request, read more data.
|
||||
if (conn->http_parser.state != GRPC_HTTP_BODY) { |
||||
grpc_endpoint_read(exec_ctx, conn->client_endpoint, |
||||
&conn->client_read_buffer, &conn->on_read_request_done); |
||||
return; |
||||
} |
||||
// Make sure we got a CONNECT request.
|
||||
if (strcmp(conn->http_request.method, "CONNECT") != 0) { |
||||
char* msg; |
||||
gpr_asprintf(&msg, "HTTP proxy got request method %s", |
||||
conn->http_request.method); |
||||
error = GRPC_ERROR_CREATE(msg); |
||||
gpr_free(msg); |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy read request", error); |
||||
GRPC_ERROR_UNREF(error); |
||||
return; |
||||
} |
||||
// Resolve address.
|
||||
grpc_resolved_addresses* resolved_addresses = NULL; |
||||
error = grpc_blocking_resolve_address(conn->http_request.path, "80", |
||||
&resolved_addresses); |
||||
if (error != GRPC_ERROR_NONE) { |
||||
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
||||
"HTTP proxy DNS lookup", error); |
||||
GRPC_ERROR_UNREF(error); |
||||
return; |
||||
} |
||||
GPR_ASSERT(resolved_addresses->naddrs >= 1); |
||||
// Connect to requested address.
|
||||
// The connection callback inherits our reference to conn.
|
||||
const gpr_timespec deadline = gpr_time_add( |
||||
gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(10, GPR_TIMESPAN)); |
||||
grpc_tcp_client_connect(exec_ctx, &conn->on_server_connect_done, |
||||
&conn->server_endpoint, conn->pollset_set, |
||||
(struct sockaddr*)&resolved_addresses->addrs[0].addr, |
||||
resolved_addresses->addrs[0].len, deadline); |
||||
grpc_resolved_addresses_destroy(resolved_addresses); |
||||
} |
||||
|
||||
static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_endpoint* endpoint, grpc_pollset* accepting_pollset, |
||||
grpc_tcp_server_acceptor* acceptor) { |
||||
grpc_end2end_http_proxy* proxy = arg; |
||||
// Instantiate proxy_connection.
|
||||
proxy_connection* conn = gpr_malloc(sizeof(*conn)); |
||||
memset(conn, 0, sizeof(*conn)); |
||||
conn->client_endpoint = endpoint; |
||||
gpr_ref_init(&conn->refcount, 1); |
||||
conn->pollset_set = grpc_pollset_set_create(); |
||||
grpc_pollset_set_add_pollset(exec_ctx, conn->pollset_set, proxy->pollset); |
||||
grpc_closure_init(&conn->on_read_request_done, on_read_request_done, conn); |
||||
grpc_closure_init(&conn->on_server_connect_done, on_server_connect_done, |
||||
conn); |
||||
grpc_closure_init(&conn->on_write_response_done, on_write_response_done, |
||||
conn); |
||||
grpc_closure_init(&conn->on_client_read_done, on_client_read_done, conn); |
||||
grpc_closure_init(&conn->on_client_write_done, on_client_write_done, conn); |
||||
grpc_closure_init(&conn->on_server_read_done, on_server_read_done, conn); |
||||
grpc_closure_init(&conn->on_server_write_done, on_server_write_done, conn); |
||||
gpr_slice_buffer_init(&conn->client_read_buffer); |
||||
gpr_slice_buffer_init(&conn->client_deferred_write_buffer); |
||||
gpr_slice_buffer_init(&conn->client_write_buffer); |
||||
gpr_slice_buffer_init(&conn->server_read_buffer); |
||||
gpr_slice_buffer_init(&conn->server_deferred_write_buffer); |
||||
gpr_slice_buffer_init(&conn->server_write_buffer); |
||||
grpc_http_parser_init(&conn->http_parser, GRPC_HTTP_REQUEST, |
||||
&conn->http_request); |
||||
grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, |
||||
&conn->on_read_request_done); |
||||
} |
||||
|
||||
//
|
||||
// Proxy class
|
||||
//
|
||||
|
||||
static void thread_main(void* arg) { |
||||
grpc_end2end_http_proxy* proxy = arg; |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
do { |
||||
const gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); |
||||
const gpr_timespec deadline = |
||||
gpr_time_add(now, gpr_time_from_seconds(1, GPR_TIMESPAN)); |
||||
grpc_pollset_worker* worker = NULL; |
||||
gpr_mu_lock(proxy->mu); |
||||
GRPC_LOG_IF_ERROR( |
||||
"grpc_pollset_work", |
||||
grpc_pollset_work(&exec_ctx, proxy->pollset, &worker, now, deadline)); |
||||
gpr_mu_unlock(proxy->mu); |
||||
grpc_exec_ctx_flush(&exec_ctx); |
||||
} while (!gpr_atm_acq_load(&proxy->shutdown)); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() { |
||||
grpc_end2end_http_proxy* proxy = gpr_malloc(sizeof(*proxy)); |
||||
memset(proxy, 0, sizeof(*proxy)); |
||||
// Construct proxy address.
|
||||
const int proxy_port = grpc_pick_unused_port_or_die(); |
||||
gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port); |
||||
gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name); |
||||
// Create TCP server.
|
||||
proxy->channel_args = grpc_channel_args_copy(NULL); |
||||
grpc_error* error = |
||||
grpc_tcp_server_create(NULL, proxy->channel_args, &proxy->server); |
||||
GPR_ASSERT(error == GRPC_ERROR_NONE); |
||||
// Bind to port.
|
||||
struct sockaddr_in addr; |
||||
memset(&addr, 0, sizeof(addr)); |
||||
addr.sin_family = AF_INET; |
||||
grpc_sockaddr_set_port((struct sockaddr*)&addr, proxy_port); |
||||
int port; |
||||
error = grpc_tcp_server_add_port(proxy->server, (struct sockaddr*)&addr, |
||||
sizeof(addr), &port); |
||||
GPR_ASSERT(error == GRPC_ERROR_NONE); |
||||
GPR_ASSERT(port == proxy_port); |
||||
// Start server.
|
||||
proxy->pollset = gpr_malloc(grpc_pollset_size()); |
||||
grpc_pollset_init(proxy->pollset, &proxy->mu); |
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept, |
||||
proxy); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
// Start proxy thread.
|
||||
gpr_thd_options opt = gpr_thd_options_default(); |
||||
gpr_thd_options_set_joinable(&opt); |
||||
GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); |
||||
return proxy; |
||||
} |
||||
|
||||
static void destroy_pollset(grpc_exec_ctx* exec_ctx, void* arg, |
||||
grpc_error* error) { |
||||
grpc_pollset* pollset = arg; |
||||
grpc_pollset_destroy(pollset); |
||||
gpr_free(pollset); |
||||
} |
||||
|
||||
void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) { |
||||
gpr_atm_rel_store(&proxy->shutdown, 1); // Signal proxy thread to shutdown.
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
gpr_thd_join(proxy->thd); |
||||
grpc_tcp_server_shutdown_listeners(&exec_ctx, proxy->server); |
||||
grpc_tcp_server_unref(&exec_ctx, proxy->server); |
||||
gpr_free(proxy->proxy_name); |
||||
grpc_channel_args_destroy(proxy->channel_args); |
||||
grpc_closure destroyed; |
||||
grpc_closure_init(&destroyed, destroy_pollset, proxy->pollset); |
||||
grpc_pollset_shutdown(&exec_ctx, proxy->pollset, &destroyed); |
||||
gpr_free(proxy); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
} |
||||
|
||||
const char* grpc_end2end_http_proxy_get_proxy_name( |
||||
grpc_end2end_http_proxy* proxy) { |
||||
return proxy->proxy_name; |
||||
} |
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
typedef struct grpc_end2end_http_proxy grpc_end2end_http_proxy; |
||||
|
||||
grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(); |
||||
|
||||
void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy); |
||||
|
||||
const char* grpc_end2end_http_proxy_get_proxy_name( |
||||
grpc_end2end_http_proxy* proxy); |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,191 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup Label="ProjectConfigurations"> |
||||
<ProjectConfiguration Include="Debug|Win32"> |
||||
<Configuration>Debug</Configuration> |
||||
<Platform>Win32</Platform> |
||||
</ProjectConfiguration> |
||||
<ProjectConfiguration Include="Debug|x64"> |
||||
<Configuration>Debug</Configuration> |
||||
<Platform>x64</Platform> |
||||
</ProjectConfiguration> |
||||
<ProjectConfiguration Include="Release|Win32"> |
||||
<Configuration>Release</Configuration> |
||||
<Platform>Win32</Platform> |
||||
</ProjectConfiguration> |
||||
<ProjectConfiguration Include="Release|x64"> |
||||
<Configuration>Release</Configuration> |
||||
<Platform>x64</Platform> |
||||
</ProjectConfiguration> |
||||
</ItemGroup> |
||||
<PropertyGroup Label="Globals"> |
||||
<ProjectGuid>{58EA8DAE-6E50-45A3-0CCC-5165D824380E}</ProjectGuid> |
||||
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected> |
||||
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir> |
||||
</PropertyGroup> |
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration"> |
||||
<PlatformToolset>v100</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration"> |
||||
<PlatformToolset>v110</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration"> |
||||
<PlatformToolset>v120</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration"> |
||||
<PlatformToolset>v140</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> |
||||
<ConfigurationType>Application</ConfigurationType> |
||||
<UseDebugLibraries>true</UseDebugLibraries> |
||||
<CharacterSet>Unicode</CharacterSet> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> |
||||
<ConfigurationType>Application</ConfigurationType> |
||||
<UseDebugLibraries>false</UseDebugLibraries> |
||||
<WholeProgramOptimization>true</WholeProgramOptimization> |
||||
<CharacterSet>Unicode</CharacterSet> |
||||
</PropertyGroup> |
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
||||
<ImportGroup Label="ExtensionSettings"> |
||||
</ImportGroup> |
||||
<ImportGroup Label="PropertySheets"> |
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\global.props" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" /> |
||||
</ImportGroup> |
||||
<PropertyGroup Label="UserMacros" /> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'"> |
||||
<TargetName>h2_http_proxy_nosec_test</TargetName> |
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib> |
||||
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'"> |
||||
<TargetName>h2_http_proxy_nosec_test</TargetName> |
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib> |
||||
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib> |
||||
</PropertyGroup> |
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>Disabled</Optimization> |
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>Disabled</Optimization> |
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>MaxSpeed</Optimization> |
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<FunctionLevelLinking>true</FunctionLevelLinking> |
||||
<IntrinsicFunctions>true</IntrinsicFunctions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding> |
||||
<OptimizeReferences>true</OptimizeReferences> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>MaxSpeed</Optimization> |
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<FunctionLevelLinking>true</FunctionLevelLinking> |
||||
<IntrinsicFunctions>true</IntrinsicFunctions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding> |
||||
<OptimizeReferences>true</OptimizeReferences> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemGroup> |
||||
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_http_proxy.c"> |
||||
</ClCompile> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_nosec_tests\end2end_nosec_tests.vcxproj"> |
||||
<Project>{47C2CB41-4E9F-58B6-F606-F6FAED5D00ED}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj"> |
||||
<Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj"> |
||||
<Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj"> |
||||
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj"> |
||||
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project> |
||||
</ProjectReference> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<None Include="packages.config" /> |
||||
</ItemGroup> |
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
||||
<ImportGroup Label="ExtensionTargets"> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" /> |
||||
</ImportGroup> |
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
||||
<PropertyGroup> |
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> |
||||
</PropertyGroup> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" /> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" /> |
||||
</Target> |
||||
</Project> |
||||
|
@ -0,0 +1,24 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
||||
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_http_proxy.c"> |
||||
<Filter>test\core\end2end\fixtures</Filter> |
||||
</ClCompile> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<Filter Include="test"> |
||||
<UniqueIdentifier>{318aaada-bfb3-a91b-9ec7-50f91d2553fe}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="test\core"> |
||||
<UniqueIdentifier>{6ac28876-f5a4-067a-c4f3-a40fea67e0d8}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="test\core\end2end"> |
||||
<UniqueIdentifier>{116ee744-756f-b125-d1fa-367f891887c7}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="test\core\end2end\fixtures"> |
||||
<UniqueIdentifier>{48a717b7-dce8-8e65-4a42-cc4396074f3a}</UniqueIdentifier> |
||||
</Filter> |
||||
</ItemGroup> |
||||
</Project> |
||||
|
@ -0,0 +1,202 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" /> |
||||
<ItemGroup Label="ProjectConfigurations"> |
||||
<ProjectConfiguration Include="Debug|Win32"> |
||||
<Configuration>Debug</Configuration> |
||||
<Platform>Win32</Platform> |
||||
</ProjectConfiguration> |
||||
<ProjectConfiguration Include="Debug|x64"> |
||||
<Configuration>Debug</Configuration> |
||||
<Platform>x64</Platform> |
||||
</ProjectConfiguration> |
||||
<ProjectConfiguration Include="Release|Win32"> |
||||
<Configuration>Release</Configuration> |
||||
<Platform>Win32</Platform> |
||||
</ProjectConfiguration> |
||||
<ProjectConfiguration Include="Release|x64"> |
||||
<Configuration>Release</Configuration> |
||||
<Platform>x64</Platform> |
||||
</ProjectConfiguration> |
||||
</ItemGroup> |
||||
<PropertyGroup Label="Globals"> |
||||
<ProjectGuid>{C9076E5F-7297-67C2-F786-3CC4F26D8F8A}</ProjectGuid> |
||||
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected> |
||||
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir> |
||||
</PropertyGroup> |
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration"> |
||||
<PlatformToolset>v100</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration"> |
||||
<PlatformToolset>v110</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration"> |
||||
<PlatformToolset>v120</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration"> |
||||
<PlatformToolset>v140</PlatformToolset> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> |
||||
<ConfigurationType>Application</ConfigurationType> |
||||
<UseDebugLibraries>true</UseDebugLibraries> |
||||
<CharacterSet>Unicode</CharacterSet> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> |
||||
<ConfigurationType>Application</ConfigurationType> |
||||
<UseDebugLibraries>false</UseDebugLibraries> |
||||
<WholeProgramOptimization>true</WholeProgramOptimization> |
||||
<CharacterSet>Unicode</CharacterSet> |
||||
</PropertyGroup> |
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
||||
<ImportGroup Label="ExtensionSettings"> |
||||
</ImportGroup> |
||||
<ImportGroup Label="PropertySheets"> |
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\global.props" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" /> |
||||
</ImportGroup> |
||||
<PropertyGroup Label="UserMacros" /> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'"> |
||||
<TargetName>h2_http_proxy_test</TargetName> |
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib> |
||||
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib> |
||||
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl> |
||||
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'"> |
||||
<TargetName>h2_http_proxy_test</TargetName> |
||||
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib> |
||||
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib> |
||||
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl> |
||||
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl> |
||||
</PropertyGroup> |
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>Disabled</Optimization> |
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>Disabled</Optimization> |
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>MaxSpeed</Optimization> |
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<FunctionLevelLinking>true</FunctionLevelLinking> |
||||
<IntrinsicFunctions>true</IntrinsicFunctions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding> |
||||
<OptimizeReferences>true</OptimizeReferences> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> |
||||
<ClCompile> |
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader> |
||||
<WarningLevel>Level3</WarningLevel> |
||||
<Optimization>MaxSpeed</Optimization> |
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
||||
<FunctionLevelLinking>true</FunctionLevelLinking> |
||||
<IntrinsicFunctions>true</IntrinsicFunctions> |
||||
<SDLCheck>true</SDLCheck> |
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> |
||||
<TreatWarningAsError>true</TreatWarningAsError> |
||||
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> |
||||
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> |
||||
</ClCompile> |
||||
<Link> |
||||
<SubSystem>Console</SubSystem> |
||||
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> |
||||
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> |
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding> |
||||
<OptimizeReferences>true</OptimizeReferences> |
||||
</Link> |
||||
</ItemDefinitionGroup> |
||||
|
||||
<ItemGroup> |
||||
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_http_proxy.c"> |
||||
</ClCompile> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/end2end/tests\end2end_tests\end2end_tests.vcxproj"> |
||||
<Project>{1F1F9084-2A93-B80E-364F-5754894AFAB4}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj"> |
||||
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj"> |
||||
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj"> |
||||
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project> |
||||
</ProjectReference> |
||||
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj"> |
||||
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project> |
||||
</ProjectReference> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<None Include="packages.config" /> |
||||
</ItemGroup> |
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
||||
<ImportGroup Label="ExtensionTargets"> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" /> |
||||
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" /> |
||||
</ImportGroup> |
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
||||
<PropertyGroup> |
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> |
||||
</PropertyGroup> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" /> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" /> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" /> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" /> |
||||
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" /> |
||||
</Target> |
||||
</Project> |
||||
|
@ -0,0 +1,24 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
||||
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\fixtures\h2_http_proxy.c"> |
||||
<Filter>test\core\end2end\fixtures</Filter> |
||||
</ClCompile> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<Filter Include="test"> |
||||
<UniqueIdentifier>{b725acb1-7722-0738-5c04-6b70cf1f75a4}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="test\core"> |
||||
<UniqueIdentifier>{4a10c467-2c7d-9051-e9bf-a24684cfa755}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="test\core\end2end"> |
||||
<UniqueIdentifier>{4837a689-69d2-7fd8-99e6-d7a44dd77a6d}</UniqueIdentifier> |
||||
</Filter> |
||||
<Filter Include="test\core\end2end\fixtures"> |
||||
<UniqueIdentifier>{e7d5a1d8-129c-4b79-0afe-3f453bcd9c49}</UniqueIdentifier> |
||||
</Filter> |
||||
</ItemGroup> |
||||
</Project> |
||||
|
Loading…
Reference in new issue