Esempio n. 1
0
File: iomgr.c Progetto: Abioy/kythe
void grpc_iomgr_shutdown(void) {
  delayed_callback *cb;
  gpr_timespec shutdown_deadline =
      gpr_time_add(gpr_now(), gpr_time_from_seconds(10));


  gpr_mu_lock(&g_mu);
  g_shutdown = 1;
  while (g_cbs_head || g_refs) {
    gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs,
            g_cbs_head ? " and executing final callbacks" : "");
    while (g_cbs_head) {
      cb = g_cbs_head;
      g_cbs_head = cb->next;
      if (!g_cbs_head) g_cbs_tail = NULL;
      gpr_mu_unlock(&g_mu);

      cb->cb(cb->cb_arg, 0);
      gpr_free(cb);
      gpr_mu_lock(&g_mu);
    }
    if (g_refs) {
      int timeout = 0;
      gpr_timespec short_deadline = gpr_time_add(gpr_now(),
                                                 gpr_time_from_millis(100));
      while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) {
        if (gpr_time_cmp(gpr_now(), shutdown_deadline) > 0) {
          timeout = 1;
          break;
        }
      }
      if (timeout) {
        gpr_log(GPR_DEBUG,
                "Failed to free %d iomgr objects before shutdown deadline: "
                "memory leaks are likely",
                g_refs);
        break;
      }
    }
  }
  gpr_mu_unlock(&g_mu);

  grpc_kick_poller();
  gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future);

  grpc_iomgr_platform_shutdown();
  grpc_alarm_list_shutdown();
  gpr_mu_destroy(&g_mu);
  gpr_cv_destroy(&g_cv);
  gpr_cv_destroy(&g_rcv);
}
Esempio n. 2
0
static void oauth2_token_fetcher_get_request_metadata(
    grpc_credentials *creds, const char *service_url,
    grpc_credentials_metadata_cb cb, void *user_data) {
  grpc_oauth2_token_fetcher_credentials *c =
      (grpc_oauth2_token_fetcher_credentials *)creds;
  gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
                                    0};
  grpc_mdelem *cached_access_token_md = NULL;
  {
    gpr_mu_lock(&c->mu);
    if (c->access_token_md != NULL &&
        (gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()),
                      refresh_threshold) > 0)) {
      cached_access_token_md = grpc_mdelem_ref(c->access_token_md);
    }
    gpr_mu_unlock(&c->mu);
  }
  if (cached_access_token_md != NULL) {
    cb(user_data, &cached_access_token_md, 1, GRPC_CREDENTIALS_OK);
    grpc_mdelem_unref(cached_access_token_md);
  } else {
    c->fetch_func(
        grpc_credentials_metadata_request_create(creds, cb, user_data),
        on_oauth2_token_fetcher_http_response,
        gpr_time_add(gpr_now(), refresh_threshold));
  }
}
Esempio n. 3
0
/* Convert a timespec to milliseconds:
   - Very small or negative poll times are clamped to zero to do a non-blocking
     poll (which becomes spin polling)
   - Other small values are rounded up to one millisecond
   - Longer than a millisecond polls are rounded up to the next nearest
     millisecond to avoid spinning
   - Infinite timeouts are converted to -1 */
static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
                                           gpr_timespec now) {
  gpr_timespec timeout;
  if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
    return -1;
  }

  if (gpr_time_cmp(deadline, now) <= 0) {
    return 0;
  }

  static const gpr_timespec round_up = {
      .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1};
  timeout = gpr_time_sub(deadline, now);
  int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up));
  return millis >= 1 ? millis : 1;
}

static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_pollset *notifier) {
  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);

  /* Note, it is possible that fd_become_readable might be called twice with
     different 'notifier's when an fd becomes readable and it is in two epoll
     sets (This can happen briefly during polling island merges). In such cases
     it does not really matter which notifer is set as the read_notifier_pollset
     (They would both point to the same polling island anyway) */
  /* Use release store to match with acquire load in fd_get_read_notifier */
  gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
}
Esempio n. 4
0
/* Shuts down and drains the completion queue if necessary.
 *
 * This is done when the ruby completion queue object is about to be GCed.
 */
static void grpc_rb_completion_queue_shutdown_drain(grpc_completion_queue *cq) {
  next_call_stack next_call;
  grpc_completion_type type;
  int drained = 0;
  MEMZERO(&next_call, next_call_stack, 1);

  grpc_completion_queue_shutdown(cq);
  next_call.cq = cq;
  next_call.event.type = GRPC_QUEUE_TIMEOUT;
  /* TODO: the timeout should be a module level constant that defaults
   * to gpr_inf_future(GPR_CLOCK_REALTIME).
   *
   * - at the moment this does not work, it stalls.  Using a small timeout like
   *   this one works, and leads to fast test run times; a longer timeout was
   *   causing unnecessary delays in the test runs.
   *
   * - investigate further, this is probably another example of C-level cleanup
   * not working consistently in all cases.
   */
  next_call.timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                   gpr_time_from_micros(5e3, GPR_TIMESPAN));
  do {
    rb_thread_call_without_gvl(grpc_rb_completion_queue_next_no_gil,
                               (void *)&next_call, NULL, NULL);
    type = next_call.event.type;
    if (type == GRPC_QUEUE_TIMEOUT) break;
    if (type != GRPC_QUEUE_SHUTDOWN) {
      ++drained;
      rb_warning("completion queue shutdown: %d undrained events", drained);
    }
  } while (type != GRPC_QUEUE_SHUTDOWN);
}
Esempio n. 5
0
static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
                      grpc_pollset *accepting_pollset,
                      grpc_tcp_server_acceptor *acceptor) {
  server_state *state = arg;
  gpr_mu_lock(&state->mu);
  if (state->shutdown) {
    gpr_mu_unlock(&state->mu);
    grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_NONE);
    grpc_endpoint_destroy(exec_ctx, tcp);
    gpr_free(acceptor);
    return;
  }
  grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
  grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
                                          handshake_mgr);
  gpr_mu_unlock(&state->mu);
  grpc_tcp_server_ref(state->tcp_server);
  server_connection_state *connection_state =
      gpr_malloc(sizeof(*connection_state));
  connection_state->server_state = state;
  connection_state->accepting_pollset = accepting_pollset;
  connection_state->acceptor = acceptor;
  connection_state->handshake_mgr = handshake_mgr;
  grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args,
                       connection_state->handshake_mgr);
  // TODO(roth): We should really get this timeout value from channel
  // args instead of hard-coding it.
  const gpr_timespec deadline = gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
  grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr,
                                      tcp, state->args, deadline, acceptor,
                                      on_handshake_done, connection_state);
}
Esempio n. 6
0
static void on_oauth2_token_fetcher_http_response(
    grpc_exec_ctx *exec_ctx, void *user_data,
    const grpc_httpcli_response *response) {
  grpc_credentials_metadata_request *r =
      (grpc_credentials_metadata_request *)user_data;
  grpc_oauth2_token_fetcher_credentials *c =
      (grpc_oauth2_token_fetcher_credentials *)r->creds;
  gpr_timespec token_lifetime;
  grpc_credentials_status status;

  gpr_mu_lock(&c->mu);
  status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
      response, &c->access_token_md, &token_lifetime);
  if (status == GRPC_CREDENTIALS_OK) {
    c->token_expiration =
        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
    r->cb(exec_ctx, r->user_data, c->access_token_md->entries,
          c->access_token_md->num_entries, status);
  } else {
    c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
    r->cb(exec_ctx, r->user_data, NULL, 0, status);
  }
  gpr_mu_unlock(&c->mu);
  grpc_credentials_metadata_request_destroy(r);
}
Esempio n. 7
0
static int is_stack_running_on_compute_engine(void) {
  compute_engine_detector detector;
  grpc_httpcli_request request;

  /* The http call is local. If it takes more than one sec, it is for sure not
     on compute engine. */
  gpr_timespec max_detection_delay = {1, 0};

  gpr_mu_init(&detector.mu);
  gpr_cv_init(&detector.cv);
  detector.is_done = 0;
  detector.success = 0;

  memset(&request, 0, sizeof(grpc_httpcli_request));
  request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST;
  request.path = "/";

  grpc_httpcli_get(&request, gpr_time_add(gpr_now(), max_detection_delay),
                   on_compute_engine_detection_http_response, &detector);

  /* Block until we get the response. This is not ideal but this should only be
     called once for the lifetime of the process by the default credentials. */
  gpr_mu_lock(&detector.mu);
  while (!detector.is_done) {
    gpr_cv_wait(&detector.cv, &detector.mu, gpr_inf_future);
  }
  gpr_mu_unlock(&detector.mu);

  gpr_mu_destroy(&detector.mu);
  gpr_cv_destroy(&detector.cv);
  return detector.success;
}
Esempio n. 8
0
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) {
  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
  grpc_pollset_kick(&cc->pollset);
  grpc_pollset_work(&cc->pollset,
                    gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
  gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}
Esempio n. 9
0
// 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);
}
Esempio n. 10
0
static void test_add_sub(void) {
    int i;
    int j;
    int k;
    /* Basic addition and subtraction. */
    for (i = -100; i <= 100; i++) {
        for (j = -100; j <= 100; j++) {
            for (k = 1; k <= 10000000; k *= 10) {
                int sum = i + j;
                int diff = i - j;
                gpr_timespec it = gpr_time_from_micros(i * k, GPR_TIMESPAN);
                gpr_timespec jt = gpr_time_from_micros(j * k, GPR_TIMESPAN);
                gpr_timespec sumt = gpr_time_add(it, jt);
                gpr_timespec difft = gpr_time_sub(it, jt);
                if (gpr_time_cmp(gpr_time_from_micros(sum * k, GPR_TIMESPAN), sumt) !=
                        0) {
                    fprintf(stderr, "i %d  j %d  sum %d    sumt ", i, j, sum);
                    ts_to_s(sumt, &to_fp, stderr);
                    fprintf(stderr, "\n");
                    GPR_ASSERT(0);
                }
                if (gpr_time_cmp(gpr_time_from_micros(diff * k, GPR_TIMESPAN), difft) !=
                        0) {
                    fprintf(stderr, "i %d  j %d  diff %d    diff ", i, j, diff);
                    ts_to_s(sumt, &to_fp, stderr);
                    fprintf(stderr, "\n");
                    GPR_ASSERT(0);
                }
            }
        }
    }
}
Esempio n. 11
0
// Mocks posix poll() function
int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
  int res = 0;
  gpr_timespec poll_time;
  gpr_mu_lock(&poll_mu);
  GPR_ASSERT(nfds == 3);
  GPR_ASSERT(fds[0].fd == 20);
  GPR_ASSERT(fds[1].fd == 30);
  GPR_ASSERT(fds[2].fd == 50);
  GPR_ASSERT(fds[0].events == (POLLIN | POLLHUP));
  GPR_ASSERT(fds[1].events == (POLLIN | POLLHUP));
  GPR_ASSERT(fds[2].events == POLLIN);

  if (timeout < 0) {
    poll_time = gpr_inf_future(GPR_CLOCK_REALTIME);
  } else {
    poll_time = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                             gpr_time_from_millis(timeout, GPR_TIMESPAN));
  }

  if (socket_event || !gpr_cv_wait(&poll_cv, &poll_mu, poll_time)) {
    fds[0].revents = POLLIN;
    res = 1;
  }
  gpr_mu_unlock(&poll_mu);
  return res;
}
Esempio n. 12
0
static void oauth2_token_fetcher_get_request_metadata(
    grpc_credentials *creds, grpc_pollset *pollset, const char *service_url,
    grpc_credentials_metadata_cb cb, void *user_data) {
  grpc_oauth2_token_fetcher_credentials *c =
      (grpc_oauth2_token_fetcher_credentials *)creds;
  gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
                                    0};
  grpc_credentials_md_store *cached_access_token_md = NULL;
  {
    gpr_mu_lock(&c->mu);
    if (c->access_token_md != NULL &&
        (gpr_time_cmp(
             gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
             refresh_threshold) > 0)) {
      cached_access_token_md =
          grpc_credentials_md_store_ref(c->access_token_md);
    }
    gpr_mu_unlock(&c->mu);
  }
  if (cached_access_token_md != NULL) {
    cb(user_data, cached_access_token_md->entries,
       cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK);
    grpc_credentials_md_store_unref(cached_access_token_md);
  } else {
    c->fetch_func(
        grpc_credentials_metadata_request_create(creds, cb, user_data),
        &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
        gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
  }
}
Esempio n. 13
0
grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
                                               const char *audience) {
  gpr_timespec skewed_now;
  int audience_ok;

  GPR_ASSERT(claims != NULL);

  skewed_now =
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
  if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
    gpr_log(GPR_ERROR, "JWT is not valid yet.");
    return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
  }
  skewed_now =
      gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
  if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
    gpr_log(GPR_ERROR, "JWT is expired.");
    return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
  }

  if (audience == NULL) {
    audience_ok = claims->aud == NULL;
  } else {
    audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0;
  }
  if (!audience_ok) {
    gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.",
            audience == NULL ? "NULL" : audience,
            claims->aud == NULL ? "NULL" : claims->aud);
    return GRPC_JWT_VERIFIER_BAD_AUDIENCE;
  }
  return GRPC_JWT_VERIFIER_OK;
}
Esempio n. 14
0
int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
        gpr_timespec now) {
    gpr_timespec timeout;
    static const int64_t max_spin_polling_us = 10;
    if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
        return -1;
    }
    if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros(
            max_spin_polling_us,
            GPR_TIMESPAN))) <= 0) {
        return 0;
    }
    timeout = gpr_time_sub(deadline, now);
    return gpr_time_to_millis(gpr_time_add(
                                  timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
}
Esempio n. 15
0
static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
                              grpc_mdelem *md) {
  grpc_chttp2_transport *t = tp;
  grpc_chttp2_stream *s = t->incoming_stream;

  GPR_TIMER_BEGIN("on_initial_header", 0);

  GPR_ASSERT(s != NULL);

  GRPC_CHTTP2_IF_TRACING(gpr_log(
      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR",
      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));

  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
    /* TODO(ctiller): check for a status like " 0" */
    s->seen_error = true;
  }

  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
    gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
    if (!cached_timeout) {
      /* not already parsed: parse it now, and store the result away */
      cached_timeout = gpr_malloc(sizeof(gpr_timespec));
      if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value),
                                     cached_timeout)) {
        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
                grpc_mdstr_as_c_string(md->value));
        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
      }
      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
    }
    grpc_chttp2_incoming_metadata_buffer_set_deadline(
        &s->metadata_buffer[0],
        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
    GRPC_MDELEM_UNREF(md);
  } else {
    const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
    const size_t metadata_size_limit =
        t->settings[GRPC_ACKED_SETTINGS]
                   [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
    if (new_size > metadata_size_limit) {
      gpr_log(GPR_DEBUG,
              "received initial metadata size exceeds limit (%" PRIuPTR
              " vs. %" PRIuPTR ")",
              new_size, metadata_size_limit);
      grpc_chttp2_cancel_stream(
          exec_ctx, t, s,
          grpc_error_set_int(
              GRPC_ERROR_CREATE("received initial metadata size exceeds limit"),
              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
      grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
      s->seen_error = true;
      GRPC_MDELEM_UNREF(md);
    } else {
      grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
    }
  }

  GPR_TIMER_END("on_initial_header", 0);
}
Esempio n. 16
0
// Either start polling channel connection state or signal that it's free to
// destroy.
// Not safe to call while a channel's connection state is polled.
static void grpc_rb_channel_try_register_connection_polling(
  grpc_rb_channel *wrapper) {
  grpc_connectivity_state conn_state;
  gpr_timespec sleep_time = gpr_time_add(
      gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN));

  GPR_ASSERT(wrapper);
  GPR_ASSERT(wrapper->wrapped);
  gpr_mu_lock(&wrapper->channel_mu);
  if (wrapper->request_safe_destroy) {
    wrapper->safe_to_destroy = 1;
    gpr_cv_broadcast(&wrapper->channel_cv);
    gpr_mu_unlock(&wrapper->channel_mu);
    return;
  }
  gpr_mu_lock(&global_connection_polling_mu);

  conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0);
  if (conn_state != wrapper->current_connectivity_state) {
    wrapper->current_connectivity_state = conn_state;
    gpr_cv_broadcast(&wrapper->channel_cv);
  }
  // avoid posting work to the channel polling cq if it's been shutdown
  if (!abort_channel_polling && conn_state != GRPC_CHANNEL_SHUTDOWN) {
    grpc_channel_watch_connectivity_state(
        wrapper->wrapped, conn_state, sleep_time, channel_polling_cq, wrapper);
  } else {
    wrapper->safe_to_destroy = 1;
    gpr_cv_broadcast(&wrapper->channel_cv);
  }
  gpr_mu_unlock(&global_connection_polling_mu);
  gpr_mu_unlock(&wrapper->channel_mu);
}
Esempio n. 17
0
/* initiate handshaking */
static void setup_initiate(grpc_transport_setup *sp) {
  grpc_client_setup *s = (grpc_client_setup *)sp;
  grpc_client_setup_request *r = gpr_malloc(sizeof(grpc_client_setup_request));
  int in_alarm = 0;

  r->setup = s;
  r->deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(60));

  gpr_mu_lock(&s->mu);
  GPR_ASSERT(s->refs > 0);
  /* there might be more than one request outstanding if the caller calls
     initiate in some kind of rapid-fire way: we try to connect each time,
     and keep track of the latest request (which is the only one that gets
     to finish) */
  if (!s->in_alarm) {
    s->active_request = r;
    s->refs++;
  } else {
    /* TODO(klempner): Maybe do something more clever here */
    in_alarm = 1;
  }
  gpr_mu_unlock(&s->mu);

  if (!in_alarm) {
    s->initiate(s->user_data, r);
  } else {
    destroy_request(r);
  }
}
Esempio n. 18
0
/* Test several threads running (*body)(struct test *m) for increasing settings
   of m->iterations, until about timeout_s to 2*timeout_s seconds have elapsed.
   If extra!=NULL, run (*extra)(m) in an additional thread.  */
static void test(const char *name, void (*body)(void *m),
                 void (*extra)(void *m), int timeout_s) {
  gpr_int64 iterations = 1024;
  struct test *m;
  gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
  gpr_timespec time_taken;
  gpr_timespec deadline = gpr_time_add(
      start, gpr_time_from_micros(timeout_s * 1000000, GPR_TIMESPAN));
  fprintf(stderr, "%s:", name);
  while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
    iterations <<= 1;
    fprintf(stderr, " %ld", (long)iterations);
    m = test_new(10, iterations);
    if (extra != NULL) {
      gpr_thd_id id;
      GPR_ASSERT(gpr_thd_new(&id, extra, m, NULL));
      m->done++; /* one more thread to wait for */
    }
    test_create_threads(m, body);
    test_wait(m);
    if (m->counter != m->threads * m->iterations) {
      fprintf(stderr, "counter %ld  threads %d  iterations %ld\n",
              (long)m->counter, m->threads, (long)m->iterations);
      GPR_ASSERT(0);
    }
    test_destroy(m);
  }
  time_taken = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start);
  fprintf(stderr, " done %ld.%09d s\n", (long)time_taken.tv_sec,
          (int)time_taken.tv_nsec);
}
Esempio n. 19
0
static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
                      grpc_pollset *accepting_pollset,
                      grpc_tcp_server_acceptor *acceptor) {
  server_secure_state *server_state = statep;
  server_secure_connect *connection_state = NULL;
  gpr_mu_lock(&server_state->mu);
  if (server_state->is_shutdown) {
    gpr_mu_unlock(&server_state->mu);
    grpc_endpoint_destroy(exec_ctx, tcp);
    return;
  }
  gpr_mu_unlock(&server_state->mu);
  grpc_tcp_server_ref(server_state->tcp);
  connection_state = gpr_malloc(sizeof(*connection_state));
  connection_state->server_state = server_state;
  connection_state->accepting_pollset = accepting_pollset;
  connection_state->acceptor = acceptor;
  connection_state->handshake_mgr = grpc_handshake_manager_create();
  // TODO(roth): We should really get this timeout value from channel
  // args instead of hard-coding it.
  connection_state->deadline = gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
  grpc_handshake_manager_do_handshake(
      exec_ctx, connection_state->handshake_mgr, tcp,
      grpc_server_get_channel_args(connection_state->server_state->server),
      connection_state->deadline, acceptor, on_handshake_done,
      connection_state);
}
Esempio n. 20
0
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
                            grpc_resolved_addresses *addresses) {
    dns_resolver *r = arg;
    grpc_client_config *config = NULL;
    grpc_subchannel **subchannels;
    grpc_subchannel_args args;
    grpc_lb_policy *lb_policy;
    size_t i;
    gpr_mu_lock(&r->mu);
    GPR_ASSERT(r->resolving);
    r->resolving = 0;
    if (addresses != NULL) {
        grpc_lb_policy_args lb_policy_args;
        config = grpc_client_config_create();
        subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
        size_t naddrs = 0;
        for (i = 0; i < addresses->naddrs; i++) {
            memset(&args, 0, sizeof(args));
            args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
            args.addr_len = (size_t)addresses->addrs[i].len;
            grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
                                              exec_ctx, r->subchannel_factory, &args);
            if (subchannel != NULL) {
                subchannels[naddrs++] = subchannel;
            }
        }
        memset(&lb_policy_args, 0, sizeof(lb_policy_args));
        lb_policy_args.subchannels = subchannels;
        lb_policy_args.num_subchannels = naddrs;
        lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
        if (lb_policy != NULL) {
            grpc_client_config_set_lb_policy(config, lb_policy);
            GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
        }
        grpc_resolved_addresses_destroy(addresses);
        gpr_free(subchannels);
    } else {
        int retry_seconds = 15;
        gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d seconds",
                retry_seconds);
        GPR_ASSERT(!r->have_retry_timer);
        r->have_retry_timer = true;
        gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
        GRPC_RESOLVER_REF(&r->base, "retry-timer");
        grpc_timer_init(
            exec_ctx, &r->retry_timer,
            gpr_time_add(now, gpr_time_from_seconds(retry_seconds, GPR_TIMESPAN)),
            dns_on_retry_timer, r, now);
    }
    if (r->resolved_config) {
        grpc_client_config_unref(exec_ctx, r->resolved_config);
    }
    r->resolved_config = config;
    r->resolved_version++;
    dns_maybe_finish_next_locked(exec_ctx, r);
    gpr_mu_unlock(&r->mu);

    GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
}
Esempio n. 21
0
gpr_timespec tunnel_get_shutdown_timeout(grpc_tunnel* tunnel) {
  int timeout_ms = grpc_channel_arg_get_int_value(
      tunnel->tunnel_args, GRPC_ARG_TUNNEL_SHUTDOWN_TIMEOUT_MS,
      TUNNEL_DEFAULT_SHUTDOWN_TIMEOUT_MS);
  return gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                      gpr_time_from_micros((int64_t)(1e3 * (timeout_ms)),
                                           GPR_TIMESPAN));
}
static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
                                     grpc_call_credentials *creds,
                                     grpc_polling_entity *pollent,
                                     grpc_auth_metadata_context context,
                                     grpc_credentials_metadata_cb cb,
                                     void *user_data) {
  grpc_service_account_jwt_access_credentials *c =
      (grpc_service_account_jwt_access_credentials *)creds;
  gpr_timespec refresh_threshold = gpr_time_from_seconds(
      GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);

  /* See if we can return a cached jwt. */
  grpc_credentials_md_store *jwt_md = NULL;
  {
    gpr_mu_lock(&c->cache_mu);
    if (c->cached.service_url != NULL &&
        strcmp(c->cached.service_url, context.service_url) == 0 &&
        c->cached.jwt_md != NULL &&
        (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
                                   gpr_now(GPR_CLOCK_REALTIME)),
                      refresh_threshold) > 0)) {
      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
    }
    gpr_mu_unlock(&c->cache_mu);
  }

  if (jwt_md == NULL) {
    char *jwt = NULL;
    /* Generate a new jwt. */
    gpr_mu_lock(&c->cache_mu);
    jwt_reset_cache(exec_ctx, c);
    jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url,
                                   c->jwt_lifetime, NULL);
    if (jwt != NULL) {
      char *md_value;
      gpr_asprintf(&md_value, "Bearer %s", jwt);
      gpr_free(jwt);
      c->cached.jwt_expiration =
          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
      c->cached.service_url = gpr_strdup(context.service_url);
      c->cached.jwt_md = grpc_credentials_md_store_create(1);
      grpc_credentials_md_store_add_cstrings(
          c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
      gpr_free(md_value);
      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
    }
    gpr_mu_unlock(&c->cache_mu);
  }

  if (jwt_md != NULL) {
    cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries,
       GRPC_CREDENTIALS_OK, NULL);
    grpc_credentials_md_store_unref(exec_ctx, jwt_md);
  } else {
    cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
       "Could not generate JWT.");
  }
}
Esempio n. 23
0
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
                                 grpc_error *error) {
  size_t i;
  int port = 0;
  portreq *pr = arg;
  int failed = 0;
  grpc_httpcli_response *response = &pr->response;

  if (error != GRPC_ERROR_NONE) {
    failed = 1;
    const char *msg = grpc_error_string(error);
    gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
    grpc_error_free_string(msg);
  } else if (response->status != 200) {
    failed = 1;
    gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
            response->status);
  }

  if (failed) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    GPR_ASSERT(pr->retries < 10);
    gpr_sleep_until(gpr_time_add(
        gpr_now(GPR_CLOCK_REALTIME),
        gpr_time_from_millis(
            (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
            GPR_TIMESPAN)));
    pr->retries++;
    req.host = pr->server;
    req.http.path = "/get";
    grpc_http_response_destroy(&pr->response);
    memset(&pr->response, 0, sizeof(pr->response));
    grpc_resource_quota *resource_quota =
        grpc_resource_quota_create("port_server_client/pick_retry");
    grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req,
                     GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
                     grpc_closure_create(got_port_from_server, pr),
                     &pr->response);
    grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(pr->mu);
  pr->port = port;
  GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
  gpr_mu_unlock(pr->mu);
}
Esempio n. 24
0
int main(int argc, char **argv) {
  grpc_closure destroyed;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  gpr_subprocess *server;
  char *me = argv[0];
  char *lslash = strrchr(me, '/');
  char *args[5];
  int port = grpc_pick_unused_port_or_die();

  GPR_ASSERT(argc <= 2);
  if (argc == 2) {
    args[0] = gpr_strdup(argv[1]);
  } else {
    /* figure out where we are */
    char *root;
    if (lslash) {
      root = gpr_malloc((size_t)(lslash - me + 1));
      memcpy(root, me, (size_t)(lslash - me));
      root[lslash - me] = 0;
    } else {
      root = gpr_strdup(".");
    }
    gpr_asprintf(&args[0], "%s/../../test/core/httpcli/test_server.py", root);
    gpr_free(root);
  }

  /* start the server */
  args[1] = "--port";
  gpr_asprintf(&args[2], "%d", port);
  args[3] = "--ssl";
  server = gpr_subprocess_create(4, (const char **)args);
  GPR_ASSERT(server);
  gpr_free(args[0]);
  gpr_free(args[2]);

  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                               gpr_time_from_seconds(5, GPR_TIMESPAN)));

  grpc_test_init(argc, argv);
  grpc_init();
  grpc_httpcli_context_init(&g_context);
  grpc_pollset_init(&g_pollset);

  test_get(port);
  test_post(port);

  grpc_httpcli_context_destroy(&g_context);
  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
  grpc_exec_ctx_finish(&exec_ctx);
  grpc_shutdown();

  gpr_subprocess_destroy(server);

  return 0;
}
Esempio n. 25
0
void bad_ssl_run(grpc_server *server) {
  int shutdown_started = 0;
  int shutdown_finished = 0;
  grpc_event ev;
  grpc_call_error error;
  grpc_call *s = NULL;
  grpc_call_details call_details;
  grpc_metadata_array request_metadata_recv;
  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);

  grpc_call_details_init(&call_details);
  grpc_metadata_array_init(&request_metadata_recv);

  grpc_server_register_completion_queue(server, cq, NULL);
  grpc_server_start(server);

  error = grpc_server_request_call(server, &s, &call_details,
                                   &request_metadata_recv, cq, cq, (void *)1);
  GPR_ASSERT(GRPC_CALL_OK == error);

  signal(SIGINT, sigint_handler);
  while (!shutdown_finished) {
    if (got_sigint && !shutdown_started) {
      gpr_log(GPR_INFO, "Shutting down due to SIGINT");
      grpc_server_shutdown_and_notify(server, cq, NULL);
      GPR_ASSERT(grpc_completion_queue_pluck(
                     cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
                     .type == GRPC_OP_COMPLETE);
      grpc_completion_queue_shutdown(cq);
      shutdown_started = 1;
    }
    ev = grpc_completion_queue_next(
        cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                         gpr_time_from_micros(1000000, GPR_TIMESPAN)),
        NULL);
    switch (ev.type) {
      case GRPC_OP_COMPLETE:
        GPR_ASSERT(ev.tag == (void *)1);
        GPR_ASSERT(ev.success == 0);
        break;
      case GRPC_QUEUE_SHUTDOWN:
        GPR_ASSERT(shutdown_started);
        shutdown_finished = 1;
        break;
      case GRPC_QUEUE_TIMEOUT:
        break;
    }
  }

  GPR_ASSERT(s == NULL);
  grpc_call_details_destroy(&call_details);
  grpc_metadata_array_destroy(&request_metadata_recv);
}
Esempio n. 26
0
void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
                        const char *default_port, grpc_resolve_cb cb,
                        void *arg) {
  addr_req *r = gpr_malloc(sizeof(*r));
  r->addr = gpr_strdup(addr);
  r->cb = cb;
  r->arg = arg;
  grpc_timer_init(exec_ctx, &r->timer,
                  gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                               gpr_time_from_seconds(1, GPR_TIMESPAN)),
                  finish_resolve, r, gpr_now(GPR_CLOCK_MONOTONIC));
}
Esempio n. 27
0
static void jwt_get_request_metadata(grpc_credentials *creds,
                                     grpc_pollset *pollset,
                                     const char *service_url,
                                     grpc_credentials_metadata_cb cb,
                                     void *user_data) {
  grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
  gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
                                    0};

  /* See if we can return a cached jwt. */
  grpc_credentials_md_store *jwt_md = NULL;
  {
    gpr_mu_lock(&c->cache_mu);
    if (c->cached.service_url != NULL &&
        strcmp(c->cached.service_url, service_url) == 0 &&
        c->cached.jwt_md != NULL &&
        (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
                                   gpr_now(GPR_CLOCK_REALTIME)),
                      refresh_threshold) > 0)) {
      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
    }
    gpr_mu_unlock(&c->cache_mu);
  }

  if (jwt_md == NULL) {
    char *jwt = NULL;
    /* Generate a new jwt. */
    gpr_mu_lock(&c->cache_mu);
    jwt_reset_cache(c);
    jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
    if (jwt != NULL) {
      char *md_value;
      gpr_asprintf(&md_value, "Bearer %s", jwt);
      gpr_free(jwt);
      c->cached.jwt_expiration =
          gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
      c->cached.service_url = gpr_strdup(service_url);
      c->cached.jwt_md = grpc_credentials_md_store_create(1);
      grpc_credentials_md_store_add_cstrings(
          c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
      gpr_free(md_value);
      jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
    }
    gpr_mu_unlock(&c->cache_mu);
  }

  if (jwt_md != NULL) {
    cb(user_data, jwt_md->entries, jwt_md->num_entries, GRPC_CREDENTIALS_OK);
    grpc_credentials_md_store_unref(jwt_md);
  } else {
    cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
  }
}
Esempio n. 28
0
void test_tcp_server_poll(test_tcp_server *server, int seconds) {
  grpc_pollset_worker *worker = NULL;
  gpr_timespec deadline =
      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                   gpr_time_from_seconds(seconds, GPR_TIMESPAN));
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset));
  grpc_pollset_work(&exec_ctx, &server->pollset, &worker,
                    gpr_now(GPR_CLOCK_MONOTONIC), deadline);
  gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset));
  grpc_exec_ctx_finish(&exec_ctx);
}
Esempio n. 29
0
static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
                                       grpc_error *error) {
  const grpc_json *cur;
  verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
  const grpc_http_response *response = &ctx->responses[HTTP_RESPONSE_OPENID];
  grpc_json *json = json_from_http(response);
  grpc_httpcli_request req;
  const char *jwks_uri;

  /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */
  if (json == NULL) goto error;
  cur = find_property_by_name(json, "jwks_uri");
  if (cur == NULL) {
    gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
    goto error;
  }
  jwks_uri = validate_string_field(cur, "jwks_uri");
  if (jwks_uri == NULL) goto error;
  if (strstr(jwks_uri, "https://") != jwks_uri) {
    gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
    goto error;
  }
  jwks_uri += 8;
  req.handshaker = &grpc_httpcli_ssl;
  req.host = gpr_strdup(jwks_uri);
  req.http.path = strchr(jwks_uri, '/');
  if (req.http.path == NULL) {
    req.http.path = "";
  } else {
    *(req.host + (req.http.path - jwks_uri)) = '\0';
  }

  /* TODO(ctiller): Carry the resource_quota in ctx and share it with the host
     channel. This would allow us to cancel an authentication query when under
     extreme memory pressure. */
  grpc_resource_quota *resource_quota =
      grpc_resource_quota_create("jwt_verifier");
  grpc_httpcli_get(
      exec_ctx, &ctx->verifier->http_ctx, &ctx->pollent, resource_quota, &req,
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
      grpc_closure_create(on_keys_retrieved, ctx),
      &ctx->responses[HTTP_RESPONSE_KEYS]);
  grpc_resource_quota_internal_unref(exec_ctx, resource_quota);
  grpc_json_destroy(json);
  gpr_free(req.host);
  return;

error:
  if (json != NULL) grpc_json_destroy(json);
  ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
  verifier_cb_ctx_destroy(ctx);
}
Esempio n. 30
0
static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
                      grpc_pollset *accepting_pollset,
                      grpc_tcp_server_acceptor *acceptor) {
  server_secure_connect *state = gpr_malloc(sizeof(*state));
  state->state = statep;
  state_ref(state->state);
  state->accepting_pollset = accepting_pollset;
  grpc_server_security_connector_do_handshake(
      exec_ctx, state->state->sc, acceptor, tcp,
      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                   gpr_time_from_seconds(120, GPR_TIMESPAN)),
      on_secure_handshake_done, state);
}