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); }
static void test_no_op_with_port_and_start(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; struct sockaddr_in addr; grpc_tcp_server *s = grpc_tcp_server_create(NULL); LOG_TEST("test_no_op_with_port_and_start"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; GPR_ASSERT( grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr)) > 0); grpc_tcp_server_start(&exec_ctx, s, NULL, 0, on_connect, NULL); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); }
static void test_no_op_with_port(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; struct sockaddr_in addr; grpc_tcp_server *s; GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(NULL, NULL, &s)); LOG_TEST("test_no_op_with_port"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; int port; GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr), &port) == GRPC_ERROR_NONE && port > 0); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); }
void test_tcp_server_destroy(test_tcp_server *server) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_timespec shutdown_deadline; grpc_closure do_nothing_cb; grpc_tcp_server_unref(&exec_ctx, server->tcp_server); grpc_closure_init(&do_nothing_cb, do_nothing, NULL); shutdown_deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(5, GPR_TIMESPAN)); while (!server->shutdown && gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), shutdown_deadline) < 0) { test_tcp_server_poll(server, 1); } grpc_pollset_shutdown(&exec_ctx, &server->pollset, &do_nothing_cb); grpc_exec_ctx_finish(&exec_ctx); grpc_pollset_destroy(&server->pollset); grpc_shutdown(); }
static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_handshaker_args *args = arg; server_connection_state *connection_state = args->user_data; gpr_mu_lock(&connection_state->server_state->mu); if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) { const char *error_str = grpc_error_string(error); gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str); if (error == GRPC_ERROR_NONE && args->endpoint != NULL) { // We were shut down after handshaking completed successfully, so // destroy the endpoint here. // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE); grpc_endpoint_destroy(exec_ctx, args->endpoint); grpc_channel_args_destroy(exec_ctx, args->args); grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); gpr_free(args->read_buffer); } } else { // If the handshaking succeeded but there is no endpoint, then the // handshaker may have handed off the connection to some external // code, so we can just clean up here without creating a transport. if (args->endpoint != NULL) { grpc_transport *transport = grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0); grpc_server_setup_transport( exec_ctx, connection_state->server_state->server, transport, connection_state->accepting_pollset, args->args); grpc_chttp2_transport_start_reading(exec_ctx, transport, args->read_buffer); grpc_channel_args_destroy(exec_ctx, args->args); } } grpc_handshake_manager_pending_list_remove( &connection_state->server_state->pending_handshake_mgrs, connection_state->handshake_mgr); gpr_mu_unlock(&connection_state->server_state->mu); grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server); gpr_free(connection_state->acceptor); gpr_free(connection_state); }
void bad_server_thread(void *vargs) { struct server_thread_args *args = (struct server_thread_args *)vargs; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resolved_address resolved_addr; struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; int port; grpc_tcp_server *s; grpc_error *error = grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s); GPR_ASSERT(error == GRPC_ERROR_NONE); memset(&resolved_addr, 0, sizeof(resolved_addr)); addr->ss_family = AF_INET; error = grpc_tcp_server_add_port(s, &resolved_addr, &port); GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error)); GPR_ASSERT(port > 0); gpr_asprintf(&args->addr, "localhost:%d", port); grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args); gpr_event_set(&args->ready, (void *)1); gpr_mu_lock(args->mu); while (gpr_atm_acq_load(&args->stop) == 0) { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec deadline = gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN)); grpc_pollset_worker *worker = NULL; if (!GRPC_LOG_IF_ERROR("pollset_work", grpc_pollset_work(&exec_ctx, args->pollset, &worker, now, deadline))) { gpr_atm_rel_store(&args->stop, 1); } gpr_mu_unlock(args->mu); grpc_exec_ctx_finish(&exec_ctx); gpr_mu_lock(args->mu); } gpr_mu_unlock(args->mu); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); gpr_free(args->addr); }
static void test_no_op_with_port(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resolved_address resolved_addr; struct sockaddr_in *addr = (struct sockaddr_in *)resolved_addr.addr; grpc_tcp_server *s; GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s)); LOG_TEST("test_no_op_with_port"); memset(&resolved_addr, 0, sizeof(resolved_addr)); resolved_addr.len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; int port; GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr, &port) == GRPC_ERROR_NONE && port > 0); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); }
static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, grpc_security_status status, grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context) { server_secure_connect *connection_state = statep; if (status == GRPC_SECURITY_OK) { if (secure_endpoint) { gpr_mu_lock(&connection_state->server_state->mu); if (!connection_state->server_state->is_shutdown) { grpc_transport *transport = grpc_create_chttp2_transport( exec_ctx, grpc_server_get_channel_args( connection_state->server_state->server), secure_endpoint, 0); grpc_arg args_to_add[2]; args_to_add[0] = grpc_server_credentials_to_arg( connection_state->server_state->creds); args_to_add[1] = grpc_auth_context_to_arg(auth_context); grpc_channel_args *args_copy = grpc_channel_args_copy_and_add( connection_state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); grpc_server_setup_transport( exec_ctx, connection_state->server_state->server, transport, connection_state->accepting_pollset, args_copy); grpc_channel_args_destroy(args_copy); grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL); } else { /* We need to consume this here, because the server may already have * gone away. */ grpc_endpoint_destroy(exec_ctx, secure_endpoint); } gpr_mu_unlock(&connection_state->server_state->mu); } } else { gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); } grpc_channel_args_destroy(connection_state->args); grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp); gpr_free(connection_state); }
void bad_server_thread(void *vargs) { struct server_thread_args *args = (struct server_thread_args *)vargs; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); int port; grpc_tcp_server *s = grpc_tcp_server_create(NULL); memset(&addr, 0, sizeof(addr)); addr.ss_family = AF_INET; port = grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len); GPR_ASSERT(port > 0); gpr_asprintf(&args->addr, "localhost:%d", port); grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args); gpr_event_set(&args->ready, (void *)1); gpr_mu_lock(args->mu); while (gpr_atm_acq_load(&args->stop) == 0) { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec deadline = gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN)); grpc_pollset_worker *worker = NULL; grpc_pollset_work(&exec_ctx, args->pollset, &worker, now, deadline); gpr_mu_unlock(args->mu); grpc_exec_ctx_finish(&exec_ctx); gpr_mu_lock(args->mu); } gpr_mu_unlock(args->mu); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); gpr_free(args->addr); }
grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr, grpc_channel_args *args, int *port_num) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp_server = NULL; size_t i; size_t count = 0; int port_temp; grpc_error *err = GRPC_ERROR_NONE; server_state *state = NULL; grpc_error **errors = NULL; *port_num = -1; /* resolve address */ err = grpc_blocking_resolve_address(addr, "https", &resolved); if (err != GRPC_ERROR_NONE) { goto error; } state = gpr_zalloc(sizeof(*state)); GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete, tcp_server_shutdown_complete, state, grpc_schedule_on_exec_ctx); err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete, args, &tcp_server); if (err != GRPC_ERROR_NONE) { goto error; } state->server = server; state->tcp_server = tcp_server; state->args = args; state->shutdown = true; gpr_mu_init(&state->mu); const size_t naddrs = resolved->naddrs; errors = gpr_malloc(sizeof(*errors) * naddrs); for (i = 0; i < naddrs; i++) { errors[i] = grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp); if (errors[i] == GRPC_ERROR_NONE) { if (*port_num == -1) { *port_num = port_temp; } else { GPR_ASSERT(*port_num == port_temp); } count++; } } if (count == 0) { char *msg; gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", naddrs); err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs); gpr_free(msg); goto error; } else if (count != naddrs) { char *msg; gpr_asprintf(&msg, "Only %" PRIuPTR " addresses added out of total %" PRIuPTR " resolved", count, naddrs); err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs); gpr_free(msg); const char *warning_message = grpc_error_string(err); gpr_log(GPR_INFO, "WARNING: %s", warning_message); /* we managed to bind some addresses: continue */ } grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ grpc_server_add_listener(exec_ctx, server, state, server_start_listener, server_destroy_listener); goto done; /* Error path: cleanup and return */ error: GPR_ASSERT(err != GRPC_ERROR_NONE); if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp_server) { grpc_tcp_server_unref(exec_ctx, tcp_server); } else { grpc_channel_args_destroy(exec_ctx, args); gpr_free(state); } *port_num = 0; done: if (errors != NULL) { for (i = 0; i < naddrs; i++) { GRPC_ERROR_UNREF(errors[i]); } gpr_free(errors); } return err; }
/* Tests a tcp server on "::" listeners with multiple ports. If channel_args is non-NULL, pass them to the server. If dst_addrs is non-NULL, use valid addrs as destination addrs (port is not set). If dst_addrs is NULL, use listener addrs as destination addrs. If test_dst_addrs is true, test connectivity with each destination address, set grpc_resolved_address::len=0 for failures, but don't fail the overall unitest. */ static void test_connect(size_t num_connects, const grpc_channel_args *channel_args, test_addrs *dst_addrs, bool test_dst_addrs) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resolved_address resolved_addr; grpc_resolved_address resolved_addr1; struct sockaddr_storage *const addr = (struct sockaddr_storage *)resolved_addr.addr; struct sockaddr_storage *const addr1 = (struct sockaddr_storage *)resolved_addr1.addr; unsigned svr_fd_count; int port; int svr_port; unsigned svr1_fd_count; int svr1_port; grpc_tcp_server *s; const unsigned num_ports = 2; GPR_ASSERT(GRPC_ERROR_NONE == grpc_tcp_server_create(&exec_ctx, NULL, channel_args, &s)); unsigned port_num; server_weak_ref weak_ref; server_weak_ref_init(&weak_ref); server_weak_ref_set(&weak_ref, s); LOG_TEST("test_connect"); gpr_log(GPR_INFO, "clients=%lu, num chan args=%lu, remote IP=%s, test_dst_addrs=%d", (unsigned long)num_connects, (unsigned long)(channel_args != NULL ? channel_args->num_args : 0), dst_addrs != NULL ? "<specific>" : "::", test_dst_addrs); memset(&resolved_addr, 0, sizeof(resolved_addr)); memset(&resolved_addr1, 0, sizeof(resolved_addr1)); resolved_addr.len = sizeof(struct sockaddr_storage); resolved_addr1.len = sizeof(struct sockaddr_storage); addr->ss_family = addr1->ss_family = AF_INET; GPR_ASSERT(GRPC_LOG_IF_ERROR( "grpc_tcp_server_add_port", grpc_tcp_server_add_port(s, &resolved_addr, &svr_port))); gpr_log(GPR_INFO, "Allocated port %d", svr_port); GPR_ASSERT(svr_port > 0); /* Cannot use wildcard (port==0), because add_port() will try to reuse the same port as a previous add_port(). */ svr1_port = grpc_pick_unused_port_or_die(); GPR_ASSERT(svr1_port > 0); gpr_log(GPR_INFO, "Picked unused port %d", svr1_port); grpc_sockaddr_set_port(&resolved_addr1, svr1_port); GPR_ASSERT(grpc_tcp_server_add_port(s, &resolved_addr1, &port) == GRPC_ERROR_NONE && port == svr1_port); /* Bad port_index. */ GPR_ASSERT(grpc_tcp_server_port_fd_count(s, 2) == 0); GPR_ASSERT(grpc_tcp_server_port_fd(s, 2, 0) < 0); /* Bad fd_index. */ GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 100) < 0); GPR_ASSERT(grpc_tcp_server_port_fd(s, 1, 100) < 0); /* Got at least one fd per port. */ svr_fd_count = grpc_tcp_server_port_fd_count(s, 0); GPR_ASSERT(svr_fd_count >= 1); svr1_fd_count = grpc_tcp_server_port_fd_count(s, 1); GPR_ASSERT(svr1_fd_count >= 1); grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); if (dst_addrs != NULL) { int ports[] = {svr_port, svr1_port}; for (port_num = 0; port_num < num_ports; ++port_num) { size_t dst_idx; size_t num_tested = 0; for (dst_idx = 0; dst_idx < dst_addrs->naddrs; ++dst_idx) { test_addr dst = dst_addrs->addrs[dst_idx]; on_connect_result result; grpc_error *err; if (dst.addr.len == 0) { gpr_log(GPR_DEBUG, "Skipping test of non-functional local IP %s", dst.str); continue; } GPR_ASSERT(grpc_sockaddr_set_port(&dst.addr, ports[port_num])); test_addr_init_str(&dst); ++num_tested; on_connect_result_init(&result); if ((err = tcp_connect(&exec_ctx, &dst, &result)) == GRPC_ERROR_NONE && result.server_fd >= 0 && result.server == s) { continue; } gpr_log(GPR_ERROR, "Failed to connect to %s: %s", dst.str, grpc_error_string(err)); GPR_ASSERT(test_dst_addrs); dst_addrs->addrs[dst_idx].addr.len = 0; GRPC_ERROR_UNREF(err); } GPR_ASSERT(num_tested > 0); } } else { for (port_num = 0; port_num < num_ports; ++port_num) { const unsigned num_fds = grpc_tcp_server_port_fd_count(s, port_num); unsigned fd_num; for (fd_num = 0; fd_num < num_fds; ++fd_num) { int fd = grpc_tcp_server_port_fd(s, port_num, fd_num); size_t connect_num; test_addr dst; GPR_ASSERT(fd >= 0); dst.addr.len = sizeof(dst.addr.addr); GPR_ASSERT(getsockname(fd, (struct sockaddr *)dst.addr.addr, (socklen_t *)&dst.addr.len) == 0); GPR_ASSERT(dst.addr.len <= sizeof(dst.addr.addr)); test_addr_init_str(&dst); gpr_log(GPR_INFO, "(%d, %d) fd %d family %s listening on %s", port_num, fd_num, fd, sock_family_name(addr->ss_family), dst.str); for (connect_num = 0; connect_num < num_connects; ++connect_num) { on_connect_result result; on_connect_result_init(&result); GPR_ASSERT(GRPC_LOG_IF_ERROR("tcp_connect", tcp_connect(&exec_ctx, &dst, &result))); GPR_ASSERT(result.server_fd == fd); GPR_ASSERT(result.port_index == port_num); GPR_ASSERT(result.fd_index == fd_num); GPR_ASSERT(result.server == s); GPR_ASSERT( grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) == result.server_fd); } } } } /* Weak ref to server valid until final unref. */ GPR_ASSERT(weak_ref.server != NULL); GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 0) >= 0); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); /* Weak ref lost. */ GPR_ASSERT(weak_ref.server == NULL); }
/* Tests a tcp server with multiple ports. TODO(daniel-j-born): Multiple fds for the same port should be tested. */ static void test_connect(unsigned n) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; struct sockaddr_storage addr; struct sockaddr_storage addr1; socklen_t addr_len = sizeof(addr); unsigned svr_fd_count; int svr_port; unsigned svr1_fd_count; int svr1_port; grpc_tcp_server *s = grpc_tcp_server_create(NULL); unsigned i; server_weak_ref weak_ref; server_weak_ref_init(&weak_ref); LOG_TEST("test_connect"); gpr_log(GPR_INFO, "clients=%d", n); memset(&addr, 0, sizeof(addr)); memset(&addr1, 0, sizeof(addr1)); addr.ss_family = addr1.ss_family = AF_INET; svr_port = grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len); GPR_ASSERT(svr_port > 0); /* Cannot use wildcard (port==0), because add_port() will try to reuse the same port as a previous add_port(). */ svr1_port = grpc_pick_unused_port_or_die(); grpc_sockaddr_set_port((struct sockaddr *)&addr1, svr1_port); GPR_ASSERT(grpc_tcp_server_add_port(s, (struct sockaddr *)&addr1, addr_len) == svr1_port); /* Bad port_index. */ GPR_ASSERT(grpc_tcp_server_port_fd_count(s, 2) == 0); GPR_ASSERT(grpc_tcp_server_port_fd(s, 2, 0) < 0); /* Bad fd_index. */ GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 100) < 0); GPR_ASSERT(grpc_tcp_server_port_fd(s, 1, 100) < 0); /* Got at least one fd per port. */ svr_fd_count = grpc_tcp_server_port_fd_count(s, 0); GPR_ASSERT(svr_fd_count >= 1); svr1_fd_count = grpc_tcp_server_port_fd_count(s, 1); GPR_ASSERT(svr1_fd_count >= 1); for (i = 0; i < svr_fd_count; ++i) { int fd = grpc_tcp_server_port_fd(s, 0, i); GPR_ASSERT(fd >= 0); if (i == 0) { GPR_ASSERT(getsockname(fd, (struct sockaddr *)&addr, &addr_len) == 0); GPR_ASSERT(addr_len <= sizeof(addr)); } } for (i = 0; i < svr1_fd_count; ++i) { int fd = grpc_tcp_server_port_fd(s, 1, i); GPR_ASSERT(fd >= 0); if (i == 0) { GPR_ASSERT(getsockname(fd, (struct sockaddr *)&addr1, &addr_len) == 0); GPR_ASSERT(addr_len <= sizeof(addr1)); } } grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL); for (i = 0; i < n; i++) { on_connect_result result; int svr_fd; on_connect_result_init(&result); tcp_connect(&exec_ctx, (struct sockaddr *)&addr, addr_len, &result); GPR_ASSERT(result.server_fd >= 0); svr_fd = result.server_fd; GPR_ASSERT(grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) == result.server_fd); GPR_ASSERT(result.port_index == 0); GPR_ASSERT(result.fd_index < svr_fd_count); GPR_ASSERT(result.server == s); if (weak_ref.server == NULL) { server_weak_ref_set(&weak_ref, result.server); } grpc_tcp_server_unref(&exec_ctx, result.server); on_connect_result_init(&result); tcp_connect(&exec_ctx, (struct sockaddr *)&addr1, addr_len, &result); GPR_ASSERT(result.server_fd >= 0); GPR_ASSERT(result.server_fd != svr_fd); GPR_ASSERT(grpc_tcp_server_port_fd(s, result.port_index, result.fd_index) == result.server_fd); GPR_ASSERT(result.port_index == 1); GPR_ASSERT(result.fd_index < svr_fd_count); GPR_ASSERT(result.server == s); grpc_tcp_server_unref(&exec_ctx, result.server); } /* Weak ref to server valid until final unref. */ GPR_ASSERT(weak_ref.server != NULL); GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 0) >= 0); grpc_tcp_server_unref(&exec_ctx, s); /* Weak ref lost. */ GPR_ASSERT(weak_ref.server == NULL); grpc_exec_ctx_finish(&exec_ctx); }
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp = NULL; grpc_server_secure_state *state = NULL; size_t i; unsigned count = 0; int port_num = -1; int port_temp; grpc_security_status status = GRPC_SECURITY_ERROR; grpc_server_security_connector *sc = NULL; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_server_add_secure_http2_port(" "server=%p, addr=%s, creds=%p)", 3, (server, addr, creds)); /* create security context */ if (creds == NULL) goto error; status = grpc_server_credentials_create_security_connector(creds, &sc); if (status != GRPC_SECURITY_OK) { gpr_log(GPR_ERROR, "Unable to create secure server with credentials of type %s.", creds->type); goto error; } sc->channel_args = grpc_server_get_channel_args(server); /* resolve address */ resolved = grpc_blocking_resolve_address(addr, "https"); if (!resolved) { goto error; } state = gpr_malloc(sizeof(*state)); memset(state, 0, sizeof(*state)); grpc_closure_init(&state->destroy_closure, destroy_done, state); tcp = grpc_tcp_server_create(&state->destroy_closure); if (!tcp) { goto error; } state->server = server; state->tcp = tcp; state->sc = sc; state->creds = grpc_server_credentials_ref(creds); state->is_shutdown = 0; gpr_mu_init(&state->mu); gpr_ref_init(&state->refcount, 1); for (i = 0; i < resolved->naddrs; i++) { port_temp = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len); if (port_temp > 0) { if (port_num == -1) { port_num = port_temp; } else { GPR_ASSERT(port_num == port_temp); } count++; } } if (count == 0) { gpr_log(GPR_ERROR, "No address added out of total %d resolved", resolved->naddrs); goto error; } if (count != resolved->naddrs) { gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved", count, resolved->naddrs); /* if it's an error, don't we want to goto error; here ? */ } grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ grpc_server_add_listener(&exec_ctx, server, state, start, destroy); grpc_exec_ctx_finish(&exec_ctx); return port_num; /* Error path: cleanup and return */ error: if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp) { grpc_tcp_server_unref(&exec_ctx, tcp); } else { if (sc) { GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); } if (state) { gpr_free(state); } } grpc_exec_ctx_finish(&exec_ctx); return 0; }
static void test_no_op(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_tcp_server *s = grpc_tcp_server_create(NULL); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); }
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp = NULL; server_secure_state *state = NULL; size_t i; size_t count = 0; int port_num = -1; int port_temp; grpc_security_status status = GRPC_SECURITY_ERROR; grpc_server_security_connector *sc = NULL; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *err = GRPC_ERROR_NONE; grpc_error **errors = NULL; GRPC_API_TRACE( "grpc_server_add_secure_http2_port(" "server=%p, addr=%s, creds=%p)", 3, (server, addr, creds)); /* create security context */ if (creds == NULL) { err = GRPC_ERROR_CREATE( "No credentials specified for secure server port (creds==NULL)"); goto error; } status = grpc_server_credentials_create_security_connector(creds, &sc); if (status != GRPC_SECURITY_OK) { char *msg; gpr_asprintf(&msg, "Unable to create secure server with credentials of type %s.", creds->type); err = grpc_error_set_int(GRPC_ERROR_CREATE(msg), GRPC_ERROR_INT_SECURITY_STATUS, status); gpr_free(msg); goto error; } sc->channel_args = grpc_server_get_channel_args(server); /* resolve address */ err = grpc_blocking_resolve_address(addr, "https", &resolved); if (err != GRPC_ERROR_NONE) { goto error; } state = gpr_malloc(sizeof(*state)); memset(state, 0, sizeof(*state)); grpc_closure_init(&state->destroy_closure, destroy_done, state); err = grpc_tcp_server_create(&state->destroy_closure, grpc_server_get_channel_args(server), &tcp); if (err != GRPC_ERROR_NONE) { goto error; } state->server = server; state->tcp = tcp; state->sc = sc; state->creds = grpc_server_credentials_ref(creds); state->is_shutdown = false; gpr_mu_init(&state->mu); gpr_ref_init(&state->refcount, 1); errors = gpr_malloc(sizeof(*errors) * resolved->naddrs); for (i = 0; i < resolved->naddrs; i++) { errors[i] = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len, &port_temp); if (errors[i] == GRPC_ERROR_NONE) { if (port_num == -1) { port_num = port_temp; } else { GPR_ASSERT(port_num == port_temp); } count++; } } if (count == 0) { char *msg; gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", resolved->naddrs); err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs); gpr_free(msg); goto error; } else if (count != resolved->naddrs) { char *msg; gpr_asprintf(&msg, "Only %" PRIuPTR " addresses added out of total %" PRIuPTR " resolved", count, resolved->naddrs); err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs); gpr_free(msg); const char *warning_message = grpc_error_string(err); gpr_log(GPR_INFO, "WARNING: %s", warning_message); grpc_error_free_string(warning_message); /* we managed to bind some addresses: continue */ } else { for (i = 0; i < resolved->naddrs; i++) { GRPC_ERROR_UNREF(errors[i]); } } gpr_free(errors); errors = NULL; grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ grpc_server_add_listener(&exec_ctx, server, state, start, destroy); grpc_exec_ctx_finish(&exec_ctx); return port_num; /* Error path: cleanup and return */ error: GPR_ASSERT(err != GRPC_ERROR_NONE); if (errors != NULL) { for (i = 0; i < resolved->naddrs; i++) { GRPC_ERROR_UNREF(errors[i]); } gpr_free(errors); } if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp) { grpc_tcp_server_unref(&exec_ctx, tcp); } else { if (sc) { GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); } if (state) { gpr_free(state); } } grpc_exec_ctx_finish(&exec_ctx); const char *msg = grpc_error_string(err); GRPC_ERROR_UNREF(err); gpr_log(GPR_ERROR, "%s", msg); grpc_error_free_string(msg); return 0; }
/* Server callback: destroy the tcp listener (so we don't generate further callbacks) */ static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp, grpc_closure *destroy_done) { grpc_tcp_server *tcp = tcpp; grpc_tcp_server_unref(exec_ctx, tcp); grpc_exec_ctx_sched(exec_ctx, destroy_done, GRPC_ERROR_NONE, NULL); }
int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp = NULL; size_t i; size_t count = 0; int port_num = -1; int port_temp; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_error *err = GRPC_ERROR_NONE; GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2, (server, addr)); grpc_error **errors = NULL; err = grpc_blocking_resolve_address(addr, "https", &resolved); if (err != GRPC_ERROR_NONE) { goto error; } err = grpc_tcp_server_create(NULL, &tcp); if (err != GRPC_ERROR_NONE) { goto error; } const size_t naddrs = resolved->naddrs; errors = gpr_malloc(sizeof(*errors) * naddrs); for (i = 0; i < naddrs; i++) { errors[i] = grpc_tcp_server_add_port( tcp, (struct sockaddr *)&resolved->addrs[i].addr, resolved->addrs[i].len, &port_temp); if (errors[i] == GRPC_ERROR_NONE) { if (port_num == -1) { port_num = port_temp; } else { GPR_ASSERT(port_num == port_temp); } count++; } } if (count == 0) { char *msg; gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved", naddrs); err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs); gpr_free(msg); goto error; } else if (count != naddrs) { char *msg; gpr_asprintf(&msg, "Only %" PRIuPTR " addresses added out of total %" PRIuPTR " resolved", count, naddrs); err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs); gpr_free(msg); const char *warning_message = grpc_error_string(err); gpr_log(GPR_INFO, "WARNING: %s", warning_message); grpc_error_free_string(warning_message); /* we managed to bind some addresses: continue */ } grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ grpc_server_add_listener(&exec_ctx, server, tcp, start, destroy); goto done; /* Error path: cleanup and return */ error: GPR_ASSERT(err != GRPC_ERROR_NONE); if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp) { grpc_tcp_server_unref(&exec_ctx, tcp); } port_num = 0; const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); grpc_error_free_string(msg); GRPC_ERROR_UNREF(err); done: grpc_exec_ctx_finish(&exec_ctx); if (errors != NULL) { for (i = 0; i < naddrs; i++) { GRPC_ERROR_UNREF(errors[i]); } } gpr_free(errors); return port_num; }