|
|
|
@ -72,10 +72,21 @@ struct grpc_end2end_http_proxy { |
|
|
|
|
// Connection handling
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
typedef struct connection_data { |
|
|
|
|
typedef struct proxy_connection { |
|
|
|
|
grpc_endpoint* client_endpoint; |
|
|
|
|
grpc_endpoint* server_endpoint; |
|
|
|
|
|
|
|
|
|
gpr_refcount refcount; |
|
|
|
|
bool client_shutdown; |
|
|
|
|
bool server_shutdown; |
|
|
|
|
bool client_write_pending; |
|
|
|
|
bool server_write_pending; |
|
|
|
|
|
|
|
|
|
size_t client_bytes_read; |
|
|
|
|
size_t client_bytes_written; |
|
|
|
|
size_t server_bytes_read; |
|
|
|
|
size_t server_bytes_written; |
|
|
|
|
|
|
|
|
|
grpc_pollset_set* pollset_set; |
|
|
|
|
|
|
|
|
|
grpc_closure on_read_request_done; |
|
|
|
@ -94,229 +105,304 @@ typedef struct connection_data { |
|
|
|
|
grpc_http_parser http_parser; |
|
|
|
|
grpc_http_request http_request; |
|
|
|
|
|
|
|
|
|
grpc_end2end_http_proxy* proxy; |
|
|
|
|
|
|
|
|
|
gpr_refcount refcount; |
|
|
|
|
} connection_data; |
|
|
|
|
grpc_end2end_http_proxy* proxy; // Does not own.
|
|
|
|
|
} proxy_connection; |
|
|
|
|
|
|
|
|
|
// Helper function to destroy the proxy connection.
|
|
|
|
|
static void connection_data_destroy(grpc_exec_ctx* exec_ctx, |
|
|
|
|
connection_data* cd) { |
|
|
|
|
cd->proxy->shutdown = true; |
|
|
|
|
grpc_endpoint_destroy(exec_ctx, cd->client_endpoint); |
|
|
|
|
if (cd->server_endpoint != NULL) |
|
|
|
|
grpc_endpoint_destroy(exec_ctx, cd->server_endpoint); |
|
|
|
|
grpc_pollset_set_destroy(cd->pollset_set); |
|
|
|
|
gpr_slice_buffer_destroy(&cd->client_read_buffer); |
|
|
|
|
gpr_slice_buffer_destroy(&cd->client_write_buffer); |
|
|
|
|
gpr_slice_buffer_destroy(&cd->server_read_buffer); |
|
|
|
|
gpr_slice_buffer_destroy(&cd->server_write_buffer); |
|
|
|
|
grpc_http_parser_destroy(&cd->http_parser); |
|
|
|
|
grpc_http_request_destroy(&cd->http_request); |
|
|
|
|
gpr_free(cd); |
|
|
|
|
static void proxy_connection_destroy(grpc_exec_ctx* exec_ctx, |
|
|
|
|
proxy_connection* conn) { |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
gpr_log(GPR_INFO, "client_bytes_read=%lu", conn->client_bytes_read); |
|
|
|
|
gpr_log(GPR_INFO, "server_bytes_written=%lu", conn->server_bytes_written); |
|
|
|
|
gpr_log(GPR_INFO, "server_bytes_read=%lu", conn->server_bytes_read); |
|
|
|
|
gpr_log(GPR_INFO, "client_bytes_written=%lu", conn->client_bytes_written); |
|
|
|
|
// Tell the server to shut down when this connection is closed.
|
|
|
|
|
conn->proxy->shutdown = true; |
|
|
|
|
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_write_buffer); |
|
|
|
|
gpr_slice_buffer_destroy(&conn->server_read_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 connection_data_failed(grpc_exec_ctx* exec_ctx, |
|
|
|
|
connection_data* cd, const char* prefix, |
|
|
|
|
grpc_error* error) { |
|
|
|
|
static void proxy_connection_failed(grpc_exec_ctx* exec_ctx, |
|
|
|
|
proxy_connection* conn, bool is_client, |
|
|
|
|
const char* prefix, grpc_error* error) { |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
const char* msg = grpc_error_string(error); |
|
|
|
|
gpr_log(GPR_ERROR, "%s: %s", prefix, msg); |
|
|
|
|
grpc_error_free_string(msg); |
|
|
|
|
grpc_endpoint_shutdown(exec_ctx, cd->client_endpoint); |
|
|
|
|
if (cd->server_endpoint != NULL) |
|
|
|
|
grpc_endpoint_shutdown(exec_ctx, cd->server_endpoint); |
|
|
|
|
if (gpr_unref(&cd->refcount)) |
|
|
|
|
connection_data_destroy(exec_ctx, cd); |
|
|
|
|
if (is_client || !conn->client_write_pending) { |
|
|
|
|
grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint); |
|
|
|
|
conn->client_shutdown = true; |
|
|
|
|
} |
|
|
|
|
if (!is_client || !conn->server_write_pending) { |
|
|
|
|
grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint); |
|
|
|
|
conn->server_shutdown = true; |
|
|
|
|
} |
|
|
|
|
if (gpr_unref(&conn->refcount)) |
|
|
|
|
proxy_connection_destroy(exec_ctx, conn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Forward declarations.
|
|
|
|
|
static void do_client_read(grpc_exec_ctx* exec_ctx, proxy_connection* conn); |
|
|
|
|
static void do_server_read(grpc_exec_ctx* exec_ctx, proxy_connection* 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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
conn->client_write_pending = false; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy client write", error); |
|
|
|
|
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
|
|
|
|
"HTTP proxy client write", error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Clear write buffer and release our reference.
|
|
|
|
|
gpr_slice_buffer_reset_and_unref(&cd->client_write_buffer); |
|
|
|
|
gpr_unref(&cd->refcount); |
|
|
|
|
gpr_unref(&conn->refcount); |
|
|
|
|
// Clear write buffer.
|
|
|
|
|
gpr_log(GPR_INFO, "wrote %lu bytes to client", conn->client_write_buffer.length); |
|
|
|
|
conn->client_bytes_written += conn->client_write_buffer.length; |
|
|
|
|
gpr_slice_buffer_reset_and_unref(&conn->client_write_buffer); |
|
|
|
|
// If the server has been shut down, shut down the client now.
|
|
|
|
|
if (conn->server_shutdown) |
|
|
|
|
grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
conn->server_write_pending = false; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy server write", error); |
|
|
|
|
proxy_connection_failed(exec_ctx, conn, false /* is_client */, |
|
|
|
|
"HTTP proxy server write", error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Clear write buffer and release our reference.
|
|
|
|
|
gpr_slice_buffer_reset_and_unref(&cd->server_write_buffer); |
|
|
|
|
gpr_unref(&cd->refcount); |
|
|
|
|
gpr_unref(&conn->refcount); |
|
|
|
|
// Clear write buffer.
|
|
|
|
|
gpr_log(GPR_INFO, "wrote %lu bytes to server", conn->server_write_buffer.length); |
|
|
|
|
conn->server_bytes_written += conn->server_write_buffer.length; |
|
|
|
|
gpr_slice_buffer_reset_and_unref(&conn->server_write_buffer); |
|
|
|
|
// If the client has been shut down, shut down the server now.
|
|
|
|
|
if (conn->client_shutdown) |
|
|
|
|
grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy client read", error); |
|
|
|
|
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
|
|
|
|
"HTTP proxy client read", error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Move read data into write buffer and write it.
|
|
|
|
|
// Take a new ref for the write callback.
|
|
|
|
|
gpr_ref(&cd->refcount); |
|
|
|
|
gpr_slice_buffer_move_into(&cd->client_read_buffer, &cd->server_write_buffer); |
|
|
|
|
grpc_endpoint_write(exec_ctx, cd->server_endpoint, &cd->server_write_buffer, |
|
|
|
|
&cd->on_server_write_done); |
|
|
|
|
// The write operation inherits our reference to conn.
|
|
|
|
|
gpr_log(GPR_INFO, "read %lu bytes from client", conn->client_read_buffer.length); |
|
|
|
|
conn->client_bytes_read += conn->client_read_buffer.length; |
|
|
|
|
gpr_slice_buffer_move_into(&conn->client_read_buffer, |
|
|
|
|
&conn->server_write_buffer); |
|
|
|
|
conn->server_write_pending = true; |
|
|
|
|
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, cd->client_endpoint, &cd->client_read_buffer, |
|
|
|
|
&cd->on_client_read_done); |
|
|
|
|
do_client_read(exec_ctx, conn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy server read", error); |
|
|
|
|
proxy_connection_failed(exec_ctx, conn, false /* is_client */, |
|
|
|
|
"HTTP proxy server read", error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Move read data into write buffer and write it.
|
|
|
|
|
// Take a new ref for the write callback.
|
|
|
|
|
gpr_ref(&cd->refcount); |
|
|
|
|
gpr_slice_buffer_move_into(&cd->server_read_buffer, &cd->client_write_buffer); |
|
|
|
|
grpc_endpoint_write(exec_ctx, cd->client_endpoint, &cd->client_write_buffer, |
|
|
|
|
&cd->on_client_write_done); |
|
|
|
|
// The write operation inherits our reference to conn.
|
|
|
|
|
gpr_log(GPR_INFO, "read %lu bytes from server", conn->server_read_buffer.length); |
|
|
|
|
conn->server_bytes_read += conn->server_read_buffer.length; |
|
|
|
|
gpr_slice_buffer_move_into(&conn->server_read_buffer, |
|
|
|
|
&conn->client_write_buffer); |
|
|
|
|
conn->client_write_pending = true; |
|
|
|
|
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, cd->server_endpoint, &cd->server_read_buffer, |
|
|
|
|
&cd->on_server_read_done); |
|
|
|
|
do_server_read(exec_ctx, conn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy write response", error); |
|
|
|
|
proxy_connection_failed(exec_ctx, conn, true /* is_client */, |
|
|
|
|
"HTTP proxy write response", error); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
gpr_unref(&conn->refcount); |
|
|
|
|
// Clear write buffer.
|
|
|
|
|
gpr_slice_buffer_reset_and_unref(&cd->client_write_buffer); |
|
|
|
|
gpr_slice_buffer_reset_and_unref(&conn->client_write_buffer); |
|
|
|
|
// Start reading from both client and server.
|
|
|
|
|
// We increase the refcount by one, since we already held one reference
|
|
|
|
|
// for ourselves, and there will now be two pending callbacks.
|
|
|
|
|
gpr_ref(&cd->refcount); |
|
|
|
|
grpc_endpoint_read(exec_ctx, cd->client_endpoint, &cd->client_read_buffer, |
|
|
|
|
&cd->on_client_read_done); |
|
|
|
|
grpc_endpoint_read(exec_ctx, cd->server_endpoint, &cd->server_read_buffer, |
|
|
|
|
&cd->on_server_read_done); |
|
|
|
|
do_client_read(exec_ctx, conn); |
|
|
|
|
do_server_read(exec_ctx, conn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Start a read from the client.
|
|
|
|
|
static void do_client_read(grpc_exec_ctx* exec_ctx, proxy_connection* conn) { |
|
|
|
|
gpr_ref(&conn->refcount); |
|
|
|
|
grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, |
|
|
|
|
&conn->on_client_read_done); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Start a read from the server.
|
|
|
|
|
static void do_server_read(grpc_exec_ctx* exec_ctx, proxy_connection* conn) { |
|
|
|
|
gpr_ref(&conn->refcount); |
|
|
|
|
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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy server connect", error); |
|
|
|
|
// 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("200 connected\r\n\r\n"); |
|
|
|
|
gpr_slice_buffer_add(&cd->client_write_buffer, slice); |
|
|
|
|
grpc_endpoint_write(exec_ctx, cd->client_endpoint, &cd->client_write_buffer, |
|
|
|
|
&cd->on_write_response_done); |
|
|
|
|
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) { |
|
|
|
|
connection_data* cd = arg; |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
proxy_connection* conn = arg; |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy read request", error); |
|
|
|
|
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 < cd->client_read_buffer.count; ++i) { |
|
|
|
|
if (GPR_SLICE_LENGTH(cd->client_read_buffer.slices[i]) > 0) { |
|
|
|
|
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( |
|
|
|
|
&cd->http_parser, cd->client_read_buffer.slices[i]); |
|
|
|
|
&conn->http_parser, conn->client_read_buffer.slices[i]); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy request parse", |
|
|
|
|
error); |
|
|
|
|
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(&cd->client_read_buffer); |
|
|
|
|
gpr_slice_buffer_reset_and_unref(&conn->client_read_buffer); |
|
|
|
|
// If we're not done reading the request, read more data.
|
|
|
|
|
if (cd->http_parser.state != GRPC_HTTP_BODY) { |
|
|
|
|
grpc_endpoint_read(exec_ctx, cd->client_endpoint, &cd->client_read_buffer, |
|
|
|
|
&cd->on_read_request_done); |
|
|
|
|
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(cd->http_request.method, "CONNECT") != 0) { |
|
|
|
|
if (strcmp(conn->http_request.method, "CONNECT") != 0) { |
|
|
|
|
char* msg; |
|
|
|
|
gpr_asprintf(&msg, "HTTP proxy got request method %s", |
|
|
|
|
cd->http_request.method); |
|
|
|
|
conn->http_request.method); |
|
|
|
|
error = GRPC_ERROR_CREATE(msg); |
|
|
|
|
gpr_free(msg); |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy read request", error); |
|
|
|
|
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(cd->http_request.path, "80", |
|
|
|
|
error = grpc_blocking_resolve_address(conn->http_request.path, "80", |
|
|
|
|
&resolved_addresses); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
connection_data_failed(exec_ctx, cd, "HTTP proxy DNS lookup", error); |
|
|
|
|
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, &cd->on_server_connect_done, |
|
|
|
|
&cd->server_endpoint, cd->pollset_set, |
|
|
|
|
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* ep, grpc_pollset* accepting_pollset, |
|
|
|
|
grpc_endpoint* endpoint, grpc_pollset* accepting_pollset, |
|
|
|
|
grpc_tcp_server_acceptor* acceptor) { |
|
|
|
|
gpr_log(GPR_INFO, "==> %s()", __func__); |
|
|
|
|
grpc_end2end_http_proxy* proxy = arg; |
|
|
|
|
// Instantiate connection_data.
|
|
|
|
|
connection_data* cd = gpr_malloc(sizeof(*cd)); |
|
|
|
|
memset(cd, 0, sizeof(*cd)); |
|
|
|
|
cd->client_endpoint = ep; |
|
|
|
|
cd->pollset_set = grpc_pollset_set_create(); |
|
|
|
|
grpc_pollset_set_add_pollset(exec_ctx, cd->pollset_set, proxy->pollset); |
|
|
|
|
grpc_closure_init(&cd->on_read_request_done, on_read_request_done, cd); |
|
|
|
|
grpc_closure_init(&cd->on_server_connect_done, on_server_connect_done, cd); |
|
|
|
|
grpc_closure_init(&cd->on_write_response_done, on_write_response_done, cd); |
|
|
|
|
grpc_closure_init(&cd->on_client_read_done, on_client_read_done, cd); |
|
|
|
|
grpc_closure_init(&cd->on_client_write_done, on_client_write_done, cd); |
|
|
|
|
grpc_closure_init(&cd->on_server_read_done, on_server_read_done, cd); |
|
|
|
|
grpc_closure_init(&cd->on_server_write_done, on_server_write_done, cd); |
|
|
|
|
gpr_slice_buffer_init(&cd->client_read_buffer); |
|
|
|
|
gpr_slice_buffer_init(&cd->client_write_buffer); |
|
|
|
|
gpr_slice_buffer_init(&cd->server_read_buffer); |
|
|
|
|
gpr_slice_buffer_init(&cd->server_write_buffer); |
|
|
|
|
grpc_http_parser_init(&cd->http_parser, GRPC_HTTP_REQUEST, |
|
|
|
|
&cd->http_request); |
|
|
|
|
cd->proxy = proxy; |
|
|
|
|
gpr_ref_init(&cd->refcount, 1); |
|
|
|
|
grpc_endpoint_read(exec_ctx, cd->client_endpoint, &cd->client_read_buffer, |
|
|
|
|
&cd->on_read_request_done); |
|
|
|
|
// 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_write_buffer); |
|
|
|
|
gpr_slice_buffer_init(&conn->server_read_buffer); |
|
|
|
|
gpr_slice_buffer_init(&conn->server_write_buffer); |
|
|
|
|
grpc_http_parser_init(&conn->http_parser, GRPC_HTTP_REQUEST, |
|
|
|
|
&conn->http_request); |
|
|
|
|
conn->proxy = proxy; |
|
|
|
|
grpc_endpoint_read(exec_ctx, conn->client_endpoint, &conn->client_read_buffer, |
|
|
|
|
&conn->on_read_request_done); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
@ -329,7 +415,7 @@ static void thread_main(void* arg) { |
|
|
|
|
do { |
|
|
|
|
const gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); |
|
|
|
|
const gpr_timespec deadline = |
|
|
|
|
gpr_time_add(now, gpr_time_from_seconds(5, GPR_TIMESPAN)); |
|
|
|
|
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", |
|
|
|
|