Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
/* 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]);
  }
}
Beispiel #5
0
/* 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));
}
Beispiel #6
0
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);
}
Beispiel #8
0
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;
}
Beispiel #10
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);
}
Beispiel #11
0
// 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;
}
Beispiel #12
0
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);
}
Beispiel #15
0
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);
}
Beispiel #16
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);
}