grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; 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( &exec_ctx, NULL, proxy->channel_args, &proxy->server); GPR_ASSERT(error == GRPC_ERROR_NONE); // Bind to port. grpc_resolved_address resolved_addr; struct sockaddr_in* addr = (struct sockaddr_in*)resolved_addr.addr; memset(&resolved_addr, 0, sizeof(resolved_addr)); addr->sin_family = AF_INET; grpc_sockaddr_set_port(&resolved_addr, proxy_port); int port; error = grpc_tcp_server_add_port(proxy->server, &resolved_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_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 test_mt_sized(int size, int nth) { gpr_stack_lockfree *stack; struct test_arg args[MAX_THREADS]; gpr_thd_id thds[MAX_THREADS]; int sum; int i; gpr_thd_options options = gpr_thd_options_default(); stack = gpr_stack_lockfree_create(size); for (i = 0; i < nth; i++) { args[i].stack = stack; args[i].stack_size = size; args[i].nthreads = nth; args[i].rank = i; args[i].sum = 0; } gpr_thd_options_set_joinable(&options); for (i = 0; i < nth; i++) { GPR_ASSERT(gpr_thd_new(&thds[i], test_mt_body, &args[i], &options)); } sum = 0; for (i = 0; i < nth; i++) { gpr_thd_join(thds[i]); sum = sum + args[i].sum; } GPR_ASSERT((unsigned)sum == ((unsigned)size * (size - 1)) / 2); gpr_stack_lockfree_destroy(stack); }
grpc_end2end_proxy *grpc_end2end_proxy_create( const grpc_end2end_proxy_def *def) { gpr_thd_options opt = gpr_thd_options_default(); int proxy_port = grpc_pick_unused_port_or_die(); int server_port = grpc_pick_unused_port_or_die(); grpc_end2end_proxy *proxy = gpr_malloc(sizeof(*proxy)); memset(proxy, 0, sizeof(*proxy)); gpr_join_host_port(&proxy->proxy_port, "localhost", proxy_port); gpr_join_host_port(&proxy->server_port, "localhost", server_port); gpr_log(GPR_DEBUG, "PROXY ADDR:%s BACKEND:%s", proxy->proxy_port, proxy->server_port); proxy->cq = grpc_completion_queue_create(NULL); proxy->server = def->create_server(proxy->proxy_port); proxy->client = def->create_client(proxy->server_port); grpc_server_register_completion_queue(proxy->server, proxy->cq, NULL); grpc_server_start(proxy->server); gpr_thd_options_set_joinable(&opt); GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); request_call(proxy); return proxy; }
/* Test that we can create a number of threads and wait for them. */ static void test(void) { int i; gpr_thd_id thd; gpr_thd_id thds[1000]; struct test t; int n = 1000; gpr_thd_options options = gpr_thd_options_default(); gpr_mu_init(&t.mu); gpr_cv_init(&t.done_cv); t.n = n; t.is_done = 0; for (i = 0; i != n; i++) { GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, NULL)); } gpr_mu_lock(&t.mu); while (!t.is_done) { gpr_cv_wait(&t.done_cv, &t.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } gpr_mu_unlock(&t.mu); GPR_ASSERT(t.n == 0); gpr_thd_options_set_joinable(&options); for (i = 0; i < n; i++) { GPR_ASSERT(gpr_thd_new(&thds[i], &thd_body_joinable, NULL, &options)); } for (i = 0; i < n; i++) { gpr_thd_join(thds[i]); } }
/* Test thread options work as expected */ static void test_options(void) { gpr_thd_options options = gpr_thd_options_default(); GPR_ASSERT(!gpr_thd_options_is_joinable(&options)); GPR_ASSERT(gpr_thd_options_is_detached(&options)); gpr_thd_options_set_joinable(&options); GPR_ASSERT(gpr_thd_options_is_joinable(&options)); GPR_ASSERT(!gpr_thd_options_is_detached(&options)); gpr_thd_options_set_detached(&options); GPR_ASSERT(!gpr_thd_options_is_joinable(&options)); GPR_ASSERT(gpr_thd_options_is_detached(&options)); }
static void test_mt_multipop(void) { gpr_log(GPR_DEBUG, "test_mt_multipop"); gpr_event start; gpr_event_init(&start); gpr_thd_id thds[100]; gpr_thd_id pull_thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; gpr_mpscq q; gpr_mpscq_init(&q); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); ta[i].ctr = 0; ta[i].q = &q; ta[i].start = &start; GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); } pull_args pa; pa.ta = ta; pa.num_thds = GPR_ARRAY_SIZE(thds); pa.spins = 0; pa.num_done = 0; pa.q = &q; pa.start = &start; gpr_mu_init(&pa.mu); for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options)); } gpr_event_set(&start, (void *)1); for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { gpr_thd_join(pull_thds[i]); } gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } gpr_mpscq_destroy(&q); }
static void test_too_many_plucks(void) { grpc_event ev; grpc_completion_queue *cc; void *tags[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS]; grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)]; gpr_thd_id thread_ids[GPR_ARRAY_SIZE(tags)]; struct thread_state thread_states[GPR_ARRAY_SIZE(tags)]; gpr_thd_options thread_options = gpr_thd_options_default(); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; unsigned i, j; LOG_TEST("test_too_many_plucks"); cc = grpc_completion_queue_create(NULL); gpr_thd_options_set_joinable(&thread_options); for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { tags[i] = create_test_tag(); for (j = 0; j < i; j++) { GPR_ASSERT(tags[i] != tags[j]); } thread_states[i].cc = cc; thread_states[i].tag = tags[i]; gpr_thd_new(thread_ids + i, pluck_one, thread_states + i, &thread_options); } /* wait until all other threads are plucking */ gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1000)); ev = grpc_completion_queue_pluck(cc, create_test_tag(), gpr_inf_future(GPR_CLOCK_REALTIME), NULL); GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { grpc_cq_begin_op(cc, tags[i]); grpc_cq_end_op(&exec_ctx, cc, tags[i], GRPC_ERROR_NONE, do_nothing_end_completion, NULL, &completions[i]); } for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { gpr_thd_join(thread_ids[i]); } shutdown_and_destroy(cc); grpc_exec_ctx_finish(&exec_ctx); }
static void test_threading(void) { threading_shared shared; shared.pollset = gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(shared.pollset, &shared.mu); gpr_thd_id thds[10]; for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options opt = gpr_thd_options_default(); gpr_thd_options_set_joinable(&opt); gpr_thd_new(&thds[i], test_threading_loop, &shared, &opt); } grpc_wakeup_fd fd; GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd))); shared.wakeup_fd = &fd; shared.wakeup_desc = grpc_fd_create(fd.read_fd, "wakeup"); shared.wakeups = 0; { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_pollset_add_fd(&exec_ctx, shared.pollset, shared.wakeup_desc); grpc_fd_notify_on_read( &exec_ctx, shared.wakeup_desc, GRPC_CLOSURE_INIT(&shared.on_wakeup, test_threading_wakeup, &shared, grpc_schedule_on_exec_ctx)); grpc_exec_ctx_finish(&exec_ctx); } GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_first", grpc_wakeup_fd_wakeup(shared.wakeup_fd))); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } fd.read_fd = 0; grpc_wakeup_fd_destroy(&fd); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_fd_shutdown(&exec_ctx, shared.wakeup_desc, GRPC_ERROR_CANCELLED); grpc_fd_orphan(&exec_ctx, shared.wakeup_desc, NULL, NULL, false /* already_closed */, "done"); grpc_pollset_shutdown(&exec_ctx, shared.pollset, GRPC_CLOSURE_CREATE(destroy_pollset, shared.pollset, grpc_schedule_on_exec_ctx)); grpc_exec_ctx_finish(&exec_ctx); } gpr_free(shared.pollset); }
// This test tries to catch deadlock situations. // With short timeouts on "watches" and long timeouts on cq next calls, // so that a QUEUE_TIMEOUT likely means that something is stuck. int run_concurrent_watches_with_short_timeouts_test() { grpc_init(); gpr_thd_id threads[NUM_THREADS]; char *localhost = gpr_strdup("localhost:54321"); gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], watches_with_short_timeouts, localhost, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } gpr_free(localhost); grpc_shutdown(); return 0; }
static void test_mt(void) { gpr_log(GPR_DEBUG, "test_mt"); gpr_event start; gpr_event_init(&start); gpr_thd_id thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; gpr_mpscq q; gpr_mpscq_init(&q); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); ta[i].ctr = 0; ta[i].q = &q; ta[i].start = &start; GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); } size_t num_done = 0; size_t spins = 0; gpr_event_set(&start, (void *)1); while (num_done != GPR_ARRAY_SIZE(thds)) { gpr_mpscq_node *n; while ((n = gpr_mpscq_pop(&q)) == NULL) { spins++; } test_node *tn = (test_node *)n; GPR_ASSERT(*tn->ctr == tn->i - 1); *tn->ctr = tn->i; if (tn->i == THREAD_ITERATIONS) num_done++; gpr_free(tn); } gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } gpr_mpscq_destroy(&q); }
// This test launches a gRPC server on a separate thread and then establishes a // TLS handshake via a minimal TLS client. The TLS client has configurable (via // alpn_list) ALPN settings and can probe at the supported ALPN preferences // using this (via alpn_expected). static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, const char *alpn_expected) { bool success = true; grpc_init(); int port = grpc_pick_unused_port_or_die(); gpr_event_init(&client_handshake_complete); // Launch the gRPC server thread. gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; gpr_thd_options_set_joinable(&thdopt); GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); const SSL_METHOD *method = TLSv1_2_client_method(); SSL_CTX *ctx = SSL_CTX_new(method); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); abort(); } // Load key pair. if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } // Set the cipher list to match the one expressed in // src/core/lib/tsi/ssl_transport_security.c. const char *cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Couldn't set server cipher list."); abort(); } // Configure ALPN list the client will send to the server. This must match the // wire format, see documentation for SSL_CTX_set_alpn_protos. unsigned int alpn_protos_len = alpn_list_len; for (unsigned int i = 0; i < alpn_list_len; ++i) { alpn_protos_len += (unsigned int)strlen(alpn_list[i]); } unsigned char *alpn_protos = gpr_malloc(alpn_protos_len); unsigned char *p = alpn_protos; for (unsigned int i = 0; i < alpn_list_len; ++i) { const uint8_t len = (uint8_t)strlen(alpn_list[i]); *p++ = len; memcpy(p, alpn_list[i], len); p += len; } GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); // Try and connect to server. We allow a bounded number of retries as we might // be racing with the server setup on its separate thread. int retries = 10; int sock = -1; while (sock == -1 && retries-- > 0) { sock = create_socket(port); if (sock < 0) { sleep(1); } } GPR_ASSERT(sock > 0); gpr_log(GPR_INFO, "Connected to server on port %d", port); // Establish a SSL* and connect at SSL layer. SSL *ssl = SSL_new(ctx); GPR_ASSERT(ssl); SSL_set_fd(ssl, sock); if (SSL_connect(ssl) <= 0) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Handshake failed."); success = false; } else { gpr_log(GPR_INFO, "Handshake successful."); // Validate ALPN preferred by server matches alpn_expected. const unsigned char *alpn_selected; unsigned int alpn_selected_len; SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); if (strlen(alpn_expected) != alpn_selected_len || strncmp((const char *)alpn_selected, alpn_expected, alpn_selected_len) != 0) { gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); success = false; } } gpr_event_set(&client_handshake_complete, &client_handshake_complete); SSL_free(ssl); gpr_free(alpn_protos); SSL_CTX_free(ctx); EVP_cleanup(); close(sock); gpr_thd_join(thdid); grpc_shutdown(); return success; }
void grpc_executor_init() { memset(&g_executor, 0, sizeof(grpc_executor)); gpr_mu_init(&g_executor.mu); g_executor.options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&g_executor.options); }
int run_concurrent_connectivity_test() { struct server_thread_args args; memset(&args, 0, sizeof(args)); grpc_init(); gpr_thd_id threads[NUM_THREADS]; gpr_thd_id server; char *localhost = gpr_strdup("localhost:54321"); gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); /* First round, no server */ gpr_log(GPR_DEBUG, "Wave 1"); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } gpr_free(localhost); /* Second round, actual grpc server */ gpr_log(GPR_DEBUG, "Wave 2"); int port = grpc_pick_unused_port_or_die(); gpr_asprintf(&args.addr, "localhost:%d", port); args.server = grpc_server_create(NULL, NULL); grpc_server_add_insecure_http2_port(args.server, args.addr); args.cq = grpc_completion_queue_create_for_next(NULL); grpc_server_register_completion_queue(args.server, args.cq, NULL); grpc_server_start(args.server); gpr_thd_new(&server, server_thread, &args, &options); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } grpc_server_shutdown_and_notify(args.server, args.cq, tag(0xd1e)); gpr_thd_join(server); grpc_server_destroy(args.server); grpc_completion_queue_destroy(args.cq); gpr_free(args.addr); /* Third round, bogus tcp server */ gpr_log(GPR_DEBUG, "Wave 3"); args.pollset = gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(args.pollset, &args.mu); gpr_event_init(&args.ready); gpr_thd_new(&server, bad_server_thread, &args, &options); gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC)); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } gpr_atm_rel_store(&args.stop, 1); gpr_thd_join(server); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_pollset_shutdown(&exec_ctx, args.pollset, GRPC_CLOSURE_CREATE(done_pollset_shutdown, args.pollset, grpc_schedule_on_exec_ctx)); grpc_exec_ctx_finish(&exec_ctx); grpc_shutdown(); return 0; }
static void test_connectivity(grpc_end2end_test_config config) { grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); grpc_connectivity_state state; cq_verifier *cqv = cq_verifier_create(f.cq); child_events ce; gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; config.init_client(&f, NULL); ce.channel = f.client; ce.cq = f.cq; gpr_event_init(&ce.started); gpr_thd_options_set_joinable(&thdopt); GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt)); gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC)); /* channels should start life in IDLE, and stay there */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == GRPC_CHANNEL_IDLE); gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == GRPC_CHANNEL_IDLE); /* start watching for a change */ gpr_log(GPR_DEBUG, "watching"); grpc_channel_watch_connectivity_state( f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1)); /* eventually the child thread completion should trigger */ gpr_thd_join(thdid); /* check that we're still in idle, and start connecting */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == GRPC_CHANNEL_IDLE); /* start watching for a change */ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(2)); /* and now the watch should trigger */ cq_expect_completion(cqv, tag(2), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING); /* quickly followed by a transition to TRANSIENT_FAILURE */ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(3)); cq_expect_completion(cqv, tag(3), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING); gpr_log(GPR_DEBUG, "*** STARTING SERVER ***"); /* now let's bring up a server to connect to */ config.init_server(&f, NULL); gpr_log(GPR_DEBUG, "*** STARTED SERVER ***"); /* we'll go through some set of transitions (some might be missed), until READY is reached */ while (state != GRPC_CHANNEL_READY) { grpc_channel_watch_connectivity_state( f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(4)); cq_expect_completion(cqv, tag(4), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_TRANSIENT_FAILURE); } /* bring down the server again */ /* we should go immediately to TRANSIENT_FAILURE */ gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(5)); grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); cq_expect_completion(cqv, tag(5), 1); cq_expect_completion(cqv, tag(0xdead), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); /* cleanup server */ grpc_server_destroy(f.server); gpr_log(GPR_DEBUG, "*** SHUTDOWN SERVER ***"); grpc_channel_destroy(f.client); grpc_completion_queue_shutdown(f.cq); grpc_completion_queue_destroy(f.cq); config.tear_down_data(&f); cq_verifier_destroy(cqv); }
void test_poll_cv_trigger(void) { grpc_wakeup_fd cvfd1, cvfd2, cvfd3; struct pollfd pfds[6]; poll_args pargs; gpr_thd_id t_id; gpr_thd_options opt; GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE); GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE); GPR_ASSERT(grpc_wakeup_fd_init(&cvfd3) == GRPC_ERROR_NONE); GPR_ASSERT(cvfd1.read_fd < 0); GPR_ASSERT(cvfd2.read_fd < 0); GPR_ASSERT(cvfd3.read_fd < 0); GPR_ASSERT(cvfd1.read_fd != cvfd2.read_fd); GPR_ASSERT(cvfd2.read_fd != cvfd3.read_fd); GPR_ASSERT(cvfd1.read_fd != cvfd3.read_fd); pfds[0].fd = cvfd1.read_fd; pfds[1].fd = cvfd2.read_fd; pfds[2].fd = 20; pfds[3].fd = 30; pfds[4].fd = cvfd3.read_fd; pfds[5].fd = 50; pfds[0].events = 0; pfds[1].events = POLLIN; pfds[2].events = POLLIN | POLLHUP; pfds[3].events = POLLIN | POLLHUP; pfds[4].events = POLLIN; pfds[5].events = POLLIN; pargs.fds = pfds; pargs.nfds = 6; pargs.timeout = 1000; pargs.result = -2; opt = gpr_thd_options_default(); gpr_thd_options_set_joinable(&opt); gpr_thd_new(&t_id, &background_poll, &pargs, &opt); // Wakeup wakeup_fd not listening for events GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE); gpr_thd_join(t_id); GPR_ASSERT(pargs.result == 0); GPR_ASSERT(pfds[0].revents == 0); GPR_ASSERT(pfds[1].revents == 0); GPR_ASSERT(pfds[2].revents == 0); GPR_ASSERT(pfds[3].revents == 0); GPR_ASSERT(pfds[4].revents == 0); GPR_ASSERT(pfds[5].revents == 0); // Pollin on socket fd pargs.timeout = -1; pargs.result = -2; gpr_thd_new(&t_id, &background_poll, &pargs, &opt); trigger_socket_event(); gpr_thd_join(t_id); GPR_ASSERT(pargs.result == 1); GPR_ASSERT(pfds[0].revents == 0); GPR_ASSERT(pfds[1].revents == 0); GPR_ASSERT(pfds[2].revents == POLLIN); GPR_ASSERT(pfds[3].revents == 0); GPR_ASSERT(pfds[4].revents == 0); GPR_ASSERT(pfds[5].revents == 0); // Pollin on wakeup fd reset_socket_event(); pargs.result = -2; gpr_thd_new(&t_id, &background_poll, &pargs, &opt); GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE); gpr_thd_join(t_id); GPR_ASSERT(pargs.result == 1); GPR_ASSERT(pfds[0].revents == 0); GPR_ASSERT(pfds[1].revents == POLLIN); GPR_ASSERT(pfds[2].revents == 0); GPR_ASSERT(pfds[3].revents == 0); GPR_ASSERT(pfds[4].revents == 0); GPR_ASSERT(pfds[5].revents == 0); // Pollin on wakeupfd before poll() pargs.result = -2; gpr_thd_new(&t_id, &background_poll, &pargs, &opt); gpr_thd_join(t_id); GPR_ASSERT(pargs.result == 1); GPR_ASSERT(pfds[0].revents == 0); GPR_ASSERT(pfds[1].revents == POLLIN); GPR_ASSERT(pfds[2].revents == 0); GPR_ASSERT(pfds[3].revents == 0); GPR_ASSERT(pfds[4].revents == 0); GPR_ASSERT(pfds[5].revents == 0); // No Events pargs.result = -2; pargs.timeout = 1000; reset_socket_event(); GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE); GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE); gpr_thd_new(&t_id, &background_poll, &pargs, &opt); gpr_thd_join(t_id); GPR_ASSERT(pargs.result == 0); GPR_ASSERT(pfds[0].revents == 0); GPR_ASSERT(pfds[1].revents == 0); GPR_ASSERT(pfds[2].revents == 0); GPR_ASSERT(pfds[3].revents == 0); GPR_ASSERT(pfds[4].revents == 0); GPR_ASSERT(pfds[5].revents == 0); }
// This test launches a minimal TLS server on a separate thread and then // establishes a TLS handshake via the core library to the server. The TLS // server validates ALPN aspects of the handshake and supplies the protocol // specified in the server_alpn_preferred argument to the client. static bool client_ssl_test(char *server_alpn_preferred) { bool success = true; grpc_init(); // Find a port we can bind to. Retries added to handle flakes in port server // and port picking. int port = -1; int server_socket = -1; int socket_retries = 10; while (server_socket == -1 && socket_retries-- > 0) { port = grpc_pick_unused_port_or_die(); server_socket = create_socket(port); if (server_socket == -1) { sleep(1); } } GPR_ASSERT(server_socket > 0); // Launch the TLS server thread. gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; gpr_thd_options_set_joinable(&thdopt); server_args args = {.socket = server_socket, .alpn_preferred = server_alpn_preferred}; GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &args, &thdopt)); // Load key pair and establish client SSL credentials. grpc_ssl_pem_key_cert_pair pem_key_cert_pair; gpr_slice ca_slice, cert_slice, key_slice; GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); const char *ca_cert = (const char *)GPR_SLICE_START_PTR(ca_slice); pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice); pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice); grpc_channel_credentials *ssl_creds = grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, NULL); // Establish a channel pointing at the TLS server. Since the gRPC runtime is // lazy, this won't necessarily establish a connection yet. char *target; gpr_asprintf(&target, "127.0.0.1:%d", port); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; grpc_channel_args grpc_args; grpc_args.num_args = 1; grpc_args.args = &ssl_name_override; grpc_channel *channel = grpc_secure_channel_create(ssl_creds, target, &grpc_args, NULL); GPR_ASSERT(channel); gpr_free(target); // Initially the channel will be idle, the // grpc_channel_check_connectivity_state triggers an attempt to connect. GPR_ASSERT(grpc_channel_check_connectivity_state( channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE); // Wait a bounded number of times for the channel to be ready. When the // channel is ready, the initial TLS handshake will have successfully // completed and we know that the client's ALPN list satisfied the server. int retries = 10; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_completion_queue *cq = grpc_completion_queue_create(NULL); while (state != GRPC_CHANNEL_READY && retries-- > 0) { grpc_channel_watch_connectivity_state( channel, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), cq, NULL); gpr_timespec cq_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); state = grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */); } grpc_completion_queue_destroy(cq); if (retries < 0) { success = false; } grpc_channel_destroy(channel); grpc_channel_credentials_release(ssl_creds); gpr_slice_unref(cert_slice); gpr_slice_unref(key_slice); gpr_slice_unref(ca_slice); gpr_thd_join(thdid); grpc_shutdown(); return success; }
static void init_output() { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); GPR_ASSERT(gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options)); atexit(finish_writing); }