// 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 (GRPC_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; } } } grpc_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, NULL, &resolved_addresses->addrs[0], deadline); grpc_resolved_addresses_destroy(resolved_addresses); }
void test_succeeds(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int svr_fd; int r; gpr_event ev; gpr_event_init(&ev); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* create a dummy server */ svr_fd = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(svr_fd >= 0); GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len)); GPR_ASSERT(0 == listen(svr_fd, 1)); /* connect to it */ GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0); grpc_tcp_client_connect(must_succeed, &ev, (struct sockaddr *)&addr, addr_len, gpr_inf_future); /* await the connection */ do { addr_len = sizeof(addr); r = accept(svr_fd, (struct sockaddr *)&addr, &addr_len); } while (r == -1 && errno == EINTR); GPR_ASSERT(r >= 0); close(r); /* wait for the connection callback to finish */ GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); }
static void next_address(internal_request *req) { grpc_resolved_address *addr; if (req->next_address == req->addresses->naddrs) { finish(req, 0); return; } addr = &req->addresses->addrs[req->next_address++]; grpc_tcp_client_connect(on_connected, req, (struct sockaddr *)&addr->addr, addr->len, req->deadline); }
void test_succeeds(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int svr_fd; int r; int connections_complete_before; grpc_closure done; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_succeeds"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* create a dummy server */ svr_fd = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(svr_fd >= 0); GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len)); GPR_ASSERT(0 == listen(svr_fd, 1)); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); connections_complete_before = g_connections_complete; gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); /* connect to it */ GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0); grpc_closure_init(&done, must_succeed, NULL); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, &g_pollset_set, (struct sockaddr *)&addr, addr_len, gpr_inf_future(GPR_CLOCK_REALTIME)); /* await the connection */ do { addr_len = sizeof(addr); r = accept(svr_fd, (struct sockaddr *)&addr, &addr_len); } while (r == -1 && errno == EINTR); GPR_ASSERT(r >= 0); close(r); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (g_connections_complete == connections_complete_before) { grpc_pollset_worker *worker = NULL; grpc_pollset_work(&exec_ctx, &g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5)); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); grpc_exec_ctx_finish(&exec_ctx); }
/* attempt to connect to the next available resolved address */ static int maybe_try_next_resolved(request *r) { grpc_resolved_address *addr; if (!r->resolved) return 0; if (r->resolved_index == r->resolved->naddrs) return 0; addr = &r->resolved->addrs[r->resolved_index++]; grpc_tcp_client_connect( on_connect, r, grpc_client_setup_get_interested_parties(r->cs_request), (struct sockaddr *)&addr->addr, addr->len, grpc_client_setup_request_deadline(r->cs_request)); return 1; }
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) { grpc_resolved_address *addr; if (req->next_address == req->addresses->naddrs) { finish(exec_ctx, req, 0); return; } addr = &req->addresses->addrs[req->next_address++]; grpc_closure_init(&req->connected, on_connected, req); grpc_tcp_client_connect( exec_ctx, &req->connected, &req->ep, &req->context->pollset_set, (struct sockaddr *)&addr->addr, addr->len, req->deadline); }
void test_times_out(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int svr_fd; #define NUM_CLIENT_CONNECTS 10 int client_fd[NUM_CLIENT_CONNECTS]; int i; int r; gpr_event ev; gpr_timespec connect_deadline; gpr_event_init(&ev); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* create a dummy server */ svr_fd = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(svr_fd >= 0); GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len)); GPR_ASSERT(0 == listen(svr_fd, 1)); /* Get its address */ GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0); /* tie up the listen buffer, which is somewhat arbitrarily sized. */ for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) { client_fd[i] = socket(AF_INET, SOCK_STREAM, 0); grpc_set_socket_nonblocking(client_fd[i], 1); do { r = connect(client_fd[i], (struct sockaddr *)&addr, addr_len); } while (r == -1 && errno == EINTR); GPR_ASSERT(r < 0); GPR_ASSERT(errno == EWOULDBLOCK || errno == EINPROGRESS); } /* connect to dummy server address */ connect_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1); grpc_tcp_client_connect(must_fail, &ev, (struct sockaddr *)&addr, addr_len, connect_deadline); /* Make sure the event doesn't trigger early */ GPR_ASSERT(!gpr_event_wait(&ev, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(500))); /* Now wait until it should have triggered */ sleep(1); /* wait for the connection callback to finish */ GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); close(svr_fd); for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) { close(client_fd[i]); } }
static void connector_connect(grpc_connector *con, const grpc_connect_in_args *args, grpc_connect_out_args *result, grpc_iomgr_closure *notify) { connector *c = (connector *)con; GPR_ASSERT(c->notify == NULL); GPR_ASSERT(notify->cb); c->notify = notify; c->args = *args; c->result = result; grpc_tcp_client_connect(connected, c, args->interested_parties, args->addr, args->addr_len, args->deadline); }
void test_succeeds(void) { grpc_resolved_address resolved_addr; struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; uv_tcp_t *svr_handle = gpr_malloc(sizeof(uv_tcp_t)); int connections_complete_before; grpc_closure done; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_succeeds"); memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; /* create a dummy server */ GPR_ASSERT(0 == uv_tcp_init(uv_default_loop(), svr_handle)); GPR_ASSERT(0 == uv_tcp_bind(svr_handle, (struct sockaddr *)addr, 0)); GPR_ASSERT(0 == uv_listen((uv_stream_t *)svr_handle, 1, connection_cb)); gpr_mu_lock(g_mu); connections_complete_before = g_connections_complete; gpr_mu_unlock(g_mu); /* connect to it */ GPR_ASSERT(uv_tcp_getsockname(svr_handle, (struct sockaddr *)addr, (int *)&resolved_addr.len) == 0); GRPC_CLOSURE_INIT(&done, must_succeed, NULL, grpc_schedule_on_exec_ctx); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME)); gpr_mu_lock(g_mu); while (g_connections_complete == connections_complete_before) { grpc_pollset_worker *worker = NULL; GPR_ASSERT(GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), grpc_timeout_seconds_to_deadline(5)))); gpr_mu_unlock(g_mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(g_mu); } // This will get cleaned up when the pollset runs again or gets shutdown uv_close((uv_handle_t *)svr_handle, close_cb); gpr_mu_unlock(g_mu); grpc_exec_ctx_finish(&exec_ctx); }
void test_fails(void) { grpc_resolved_address resolved_addr; struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; int connections_complete_before; grpc_closure done; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_fails"); memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; gpr_mu_lock(g_mu); connections_complete_before = g_connections_complete; gpr_mu_unlock(g_mu); /* connect to a broken address */ GRPC_CLOSURE_INIT(&done, must_fail, NULL, grpc_schedule_on_exec_ctx); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, NULL, NULL, &resolved_addr, gpr_inf_future(GPR_CLOCK_REALTIME)); gpr_mu_lock(g_mu); /* wait for the connection callback to finish */ while (g_connections_complete == connections_complete_before) { grpc_pollset_worker *worker = NULL; gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec polling_deadline = test_deadline(); switch (grpc_timer_check(&exec_ctx, now, &polling_deadline)) { case GRPC_TIMERS_FIRED: break; case GRPC_TIMERS_NOT_CHECKED: polling_deadline = now; /* fall through */ case GRPC_TIMERS_CHECKED_AND_EMPTY: GPR_ASSERT(GRPC_LOG_IF_ERROR( "pollset_work", grpc_pollset_work(&exec_ctx, g_pollset, &worker, now, polling_deadline))); break; } gpr_mu_unlock(g_mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(g_mu); } gpr_mu_unlock(g_mu); grpc_exec_ctx_finish(&exec_ctx); }
static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, const grpc_connect_in_args *args, grpc_connect_out_args *result, grpc_closure *notify) { connector *c = (connector *)con; GPR_ASSERT(c->notify == NULL); c->notify = notify; c->args = *args; c->result = result; gpr_mu_lock(&c->mu); GPR_ASSERT(c->connecting_endpoint == NULL); gpr_mu_unlock(&c->mu); grpc_closure_init(&c->connected_closure, connected, c); grpc_tcp_client_connect( exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint, args->interested_parties, args->channel_args, args->addr, args->deadline); }
void test_fails(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); gpr_event ev; gpr_event_init(&ev); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* connect to a broken address */ grpc_tcp_client_connect(must_fail, &ev, (struct sockaddr *)&addr, addr_len, gpr_inf_future); /* wait for the connection callback to finish */ GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); }
static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con, const grpc_connect_in_args *args, grpc_connect_out_args *result, grpc_closure *notify) { chttp2_connector *c = (chttp2_connector *)con; gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == NULL); c->notify = notify; c->args = *args; c->result = result; GPR_ASSERT(c->endpoint == NULL); chttp2_connector_ref(con); // Ref taken for callback. grpc_closure_init(&c->connected, connected, c); GPR_ASSERT(!c->connecting); c->connecting = true; grpc_tcp_client_connect(exec_ctx, &c->connected, &c->endpoint, args->interested_parties, args->channel_args, args->addr, args->deadline); gpr_mu_unlock(&c->mu); }
void test_fails(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int connections_complete_before; grpc_closure done; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_fails"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); connections_complete_before = g_connections_complete; gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); /* connect to a broken address */ grpc_closure_init(&done, must_fail, NULL); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, &g_pollset_set, (struct sockaddr *)&addr, addr_len, gpr_inf_future(GPR_CLOCK_REALTIME)); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); /* wait for the connection callback to finish */ while (g_connections_complete == connections_complete_before) { grpc_pollset_worker *worker = NULL; gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec polling_deadline = test_deadline(); if (!grpc_timer_check(&exec_ctx, now, &polling_deadline)) { grpc_pollset_work(&exec_ctx, &g_pollset, &worker, now, polling_deadline); } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); grpc_exec_ctx_finish(&exec_ctx); }
void test_times_out(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int svr_fd; #define NUM_CLIENT_CONNECTS 100 int client_fd[NUM_CLIENT_CONNECTS]; int i; int r; int connections_complete_before; gpr_timespec connect_deadline; grpc_closure done; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_log(GPR_DEBUG, "test_times_out"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* create a dummy server */ svr_fd = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(svr_fd >= 0); GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len)); GPR_ASSERT(0 == listen(svr_fd, 1)); /* Get its address */ GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0); /* tie up the listen buffer, which is somewhat arbitrarily sized. */ for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) { client_fd[i] = socket(AF_INET, SOCK_STREAM, 0); grpc_set_socket_nonblocking(client_fd[i], 1); do { r = connect(client_fd[i], (struct sockaddr *)&addr, addr_len); } while (r == -1 && errno == EINTR); GPR_ASSERT(r < 0); GPR_ASSERT(errno == EWOULDBLOCK || errno == EINPROGRESS); } /* connect to dummy server address */ connect_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); connections_complete_before = g_connections_complete; gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); grpc_closure_init(&done, must_fail, NULL); grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, &g_pollset_set, (struct sockaddr *)&addr, addr_len, connect_deadline); /* Make sure the event doesn't trigger early */ gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); for (;;) { grpc_pollset_worker worker; gpr_timespec now = gpr_now(connect_deadline.clock_type); gpr_timespec continue_verifying_time = gpr_time_from_seconds(5, GPR_TIMESPAN); gpr_timespec grace_time = gpr_time_from_seconds(3, GPR_TIMESPAN); gpr_timespec finish_time = gpr_time_add(connect_deadline, continue_verifying_time); gpr_timespec restart_verifying_time = gpr_time_add(connect_deadline, grace_time); int is_after_deadline = gpr_time_cmp(now, connect_deadline) > 0; if (gpr_time_cmp(now, finish_time) > 0) { break; } gpr_log(GPR_DEBUG, "now=%lld.%09d connect_deadline=%lld.%09d", (long long)now.tv_sec, (int)now.tv_nsec, (long long)connect_deadline.tv_sec, (int)connect_deadline.tv_nsec); if (is_after_deadline && gpr_time_cmp(now, restart_verifying_time) <= 0) { /* allow some slack before insisting that things be done */ } else { GPR_ASSERT(g_connections_complete == connections_complete_before + is_after_deadline); } grpc_pollset_work(&exec_ctx, &g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10)); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); grpc_exec_ctx_finish(&exec_ctx); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); close(svr_fd); for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) { close(client_fd[i]); } }