Ejemplo n.º 1
0
Archivo: httpcli.c Proyecto: sihai/grpc
static void on_connected(void *arg, grpc_endpoint *tcp) {
  internal_request *req = arg;

  if (!tcp) {
    next_address(req);
    return;
  }
  req->ep = tcp;
  if (req->use_ssl) {
    grpc_channel_security_connector *sc = NULL;
    const unsigned char *pem_root_certs = NULL;
    size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
    if (pem_root_certs == NULL || pem_root_certs_size == 0) {
      gpr_log(GPR_ERROR, "Could not get default pem root certs.");
      finish(req, 0);
      return;
    }
    GPR_ASSERT(grpc_httpcli_ssl_channel_security_connector_create(
                   pem_root_certs, pem_root_certs_size, req->host, &sc) ==
               GRPC_SECURITY_OK);
    grpc_setup_secure_transport(&sc->base, tcp, on_secure_transport_setup_done,
                                req);
    GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
  } else {
    start_write(req);
  }
}
Ejemplo n.º 2
0
static grpc_channel *client_channel_factory_create_channel(
    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
    const char *target, grpc_client_channel_type type,
    grpc_channel_args *args) {
  client_channel_factory *f = (client_channel_factory *)cc_factory;

  grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
  grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
                                              GRPC_CLIENT_CHANNEL, NULL);
  grpc_channel_args_destroy(final_args);

  grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
  if (resolver != NULL) {
    grpc_client_channel_set_resolver(
        exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
    GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create");
  } else {
    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
                                "client_channel_factory_create_channel");
    channel = NULL;
  }

  GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                "client_channel_factory_create_channel");
  return channel;
}
Ejemplo n.º 3
0
/* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
                                 grpc_channel_element *elem) {
  /* grab pointers to our data from the channel element */
  channel_data *chand = elem->channel_data;
  GRPC_SECURITY_CONNECTOR_UNREF(chand->security_connector,
                                "server_auth_filter");
}
Ejemplo n.º 4
0
static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
                          grpc_endpoint *tcp, const char *host,
                          gpr_timespec deadline,
                          void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
                                          grpc_endpoint *endpoint)) {
  grpc_channel_security_connector *sc = NULL;
  const unsigned char *pem_root_certs = NULL;
  on_done_closure *c = gpr_malloc(sizeof(*c));
  size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
  if (pem_root_certs == NULL || pem_root_certs_size == 0) {
    gpr_log(GPR_ERROR, "Could not get default pem root certs.");
    on_done(exec_ctx, arg, NULL);
    gpr_free(c);
    return;
  }
  c->func = on_done;
  c->arg = arg;
  c->handshake_mgr = grpc_handshake_manager_create();
  GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
                 pem_root_certs, pem_root_certs_size, host, &sc) ==
             GRPC_SECURITY_OK);
  grpc_channel_security_connector_add_handshakers(exec_ctx, sc,
                                                  c->handshake_mgr);
  grpc_handshake_manager_do_handshake(
      exec_ctx, c->handshake_mgr, tcp, NULL /* channel_args */, deadline,
      NULL /* acceptor */, on_handshake_done, c /* user_data */);
  GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
}
Ejemplo n.º 5
0
static void client_channel_factory_unref(
    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
    client_channel_factory *f = (client_channel_factory *)cc_factory;
    if (gpr_unref(&f->refs)) {
        GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                      "client_channel_factory");
        gpr_free(f);
    }
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
                                 grpc_channel_element *elem) {
  /* grab pointers to our data from the channel element */
  channel_data *chand = elem->channel_data;
  grpc_channel_security_connector *sc = chand->security_connector;
  if (sc != NULL) {
    GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter");
  }
  GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter");
}
Ejemplo n.º 7
0
static void subchannel_factory_unref(grpc_subchannel_factory *scf) {
  subchannel_factory *f = (subchannel_factory *)scf;
  if (gpr_unref(&f->refs)) {
    GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                  "subchannel_factory");
    grpc_channel_args_destroy(f->merge_args);
    grpc_mdctx_unref(f->mdctx);
    gpr_free(f);
  }
}
Ejemplo n.º 8
0
/* Create a secure client channel:
   Asynchronously: - resolve target
                   - connect to it (trying alternatives as presented)
                   - perform handshakes */
grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
        const char *target,
        const grpc_channel_args *args,
        void *reserved) {
    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
    GRPC_API_TRACE(
        "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
        "reserved=%p)",
        4, (creds, target, args, reserved));
    GPR_ASSERT(reserved == NULL);
    // Make sure security connector does not already exist in args.
    if (grpc_find_security_connector_in_args(args) != NULL) {
        gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
        grpc_exec_ctx_finish(&exec_ctx);
        return grpc_lame_client_channel_create(
                   target, GRPC_STATUS_INTERNAL,
                   "Security connector exists in channel args.");
    }
    // Create security connector and construct new channel args.
    grpc_channel_security_connector *security_connector;
    grpc_channel_args *new_args_from_connector;
    if (grpc_channel_credentials_create_security_connector(
                creds, target, args, &security_connector, &new_args_from_connector) !=
            GRPC_SECURITY_OK) {
        grpc_exec_ctx_finish(&exec_ctx);
        return grpc_lame_client_channel_create(
                   target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
    }
    grpc_arg connector_arg =
        grpc_security_connector_to_arg(&security_connector->base);
    grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
                                      new_args_from_connector != NULL ? new_args_from_connector : args,
                                      &connector_arg, 1);
    if (new_args_from_connector != NULL) {
        grpc_channel_args_destroy(new_args_from_connector);
    }
    // Create client channel factory.
    client_channel_factory *f = gpr_malloc(sizeof(*f));
    memset(f, 0, sizeof(*f));
    f->base.vtable = &client_channel_factory_vtable;
    gpr_ref_init(&f->refs, 1);
    GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
                                "grpc_secure_channel_create");
    f->security_connector = security_connector;
    // Create channel.
    grpc_channel *channel = client_channel_factory_create_channel(
                                &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
    // Clean up.
    GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                  "secure_client_channel_factory_create_channel");
    grpc_channel_args_destroy(new_args);
    grpc_client_channel_factory_unref(&exec_ctx, &f->base);
    grpc_exec_ctx_finish(&exec_ctx);
    return channel; /* may be NULL */
}
Ejemplo n.º 9
0
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
                                     grpc_subchannel_factory *scf) {
  subchannel_factory *f = (subchannel_factory *)scf;
  if (gpr_unref(&f->refs)) {
    GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                  "subchannel_factory");
    GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
    grpc_channel_args_destroy(f->merge_args);
    gpr_free(f);
  }
}
Ejemplo n.º 10
0
static void state_unref(server_secure_state *state) {
  if (gpr_unref(&state->refcount)) {
    /* ensure all threads have unlocked */
    gpr_mu_lock(&state->mu);
    gpr_mu_unlock(&state->mu);
    /* clean up */
    GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server");
    grpc_server_credentials_unref(state->creds);
    gpr_free(state);
  }
}
Ejemplo n.º 11
0
static void unref_handshake(grpc_security_handshake *h) {
    if (gpr_unref(&h->refs)) {
        if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
        if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
        gpr_slice_buffer_destroy(&h->left_overs);
        gpr_slice_buffer_destroy(&h->outgoing);
        gpr_slice_buffer_destroy(&h->incoming);
        GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
        GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
        gpr_free(h);
    }
}
Ejemplo n.º 12
0
grpc_security_connector *grpc_security_connector_ref(
    grpc_security_connector *sc, const char *file, int line,
    const char *reason) {
  if (sc == NULL) return NULL;
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
          "SECURITY_CONNECTOR:%p   ref %d -> %d %s", sc,
          (int)sc->refcount.count, (int)sc->refcount.count + 1, reason);
#else
grpc_security_connector *grpc_security_connector_ref(
    grpc_security_connector *sc) {
  if (sc == NULL) return NULL;
#endif
  gpr_ref(&sc->refcount);
  return sc;
}

#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG
void grpc_security_connector_unref(grpc_security_connector *sc,
                                   const char *file, int line,
                                   const char *reason) {
  if (sc == NULL) return;
  gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
          "SECURITY_CONNECTOR:%p unref %d -> %d %s", sc,
          (int)sc->refcount.count, (int)sc->refcount.count - 1, reason);
#else
void grpc_security_connector_unref(grpc_security_connector *sc) {
  if (sc == NULL) return;
#endif
  if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc);
}

static void connector_pointer_arg_destroy(void *p) {
  GRPC_SECURITY_CONNECTOR_UNREF(p, "connector_pointer_arg");
}

static void *connector_pointer_arg_copy(void *p) {
  return GRPC_SECURITY_CONNECTOR_REF(p, "connector_pointer_arg");
}

static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); }

static const grpc_arg_pointer_vtable connector_pointer_vtable = {
    connector_pointer_arg_copy, connector_pointer_arg_destroy,
    connector_pointer_cmp};

grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) {
  grpc_arg result;
  result.type = GRPC_ARG_POINTER;
  result.key = GRPC_SECURITY_CONNECTOR_ARG;
  result.value.pointer.vtable = &connector_pointer_vtable;
  result.value.pointer.p = sc;
  return result;
}
Ejemplo n.º 13
0
static void client_channel_factory_unref(
    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
  client_channel_factory *f = (client_channel_factory *)cc_factory;
  if (gpr_unref(&f->refs)) {
    GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                  "client_channel_factory");
    if (f->master != NULL) {
      GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
                                  "client_channel_factory");
    }
    grpc_channel_args_destroy(f->merge_args);
    gpr_free(f);
  }
}
Ejemplo n.º 14
0
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
                                      grpc_server_credentials *creds) {
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_error *err = GRPC_ERROR_NONE;
  grpc_server_security_connector *sc = NULL;
  int port_num = 0;
  GRPC_API_TRACE(
      "grpc_server_add_secure_http2_port("
      "server=%p, addr=%s, creds=%p)",
      3, (server, addr, creds));
  // Create security context.
  if (creds == NULL) {
    err = GRPC_ERROR_CREATE(
        "No credentials specified for secure server port (creds==NULL)");
    goto done;
  }
  grpc_security_status status =
      grpc_server_credentials_create_security_connector(&exec_ctx, creds, &sc);
  if (status != GRPC_SECURITY_OK) {
    char *msg;
    gpr_asprintf(&msg,
                 "Unable to create secure server with credentials of type %s.",
                 creds->type);
    err = grpc_error_set_int(GRPC_ERROR_CREATE(msg),
                             GRPC_ERROR_INT_SECURITY_STATUS, status);
    gpr_free(msg);
    goto done;
  }
  // Create channel args.
  grpc_arg args_to_add[2];
  args_to_add[0] = grpc_server_credentials_to_arg(creds);
  args_to_add[1] = grpc_security_connector_to_arg(&sc->base);
  grpc_channel_args *args =
      grpc_channel_args_copy_and_add(grpc_server_get_channel_args(server),
                                     args_to_add, GPR_ARRAY_SIZE(args_to_add));
  // Add server port.
  err = grpc_chttp2_server_add_port(&exec_ctx, server, addr, args, &port_num);
done:
  if (sc != NULL) {
    GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "server");
  }
  grpc_exec_ctx_finish(&exec_ctx);
  if (err != GRPC_ERROR_NONE) {
    const char *msg = grpc_error_string(err);
    gpr_log(GPR_ERROR, "%s", msg);
    grpc_error_free_string(msg);
    GRPC_ERROR_UNREF(err);
  }
  return port_num;
}
Ejemplo n.º 15
0
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) {
  /* grab pointers to our data from the channel element */
  channel_data *chand = elem->channel_data;
  grpc_channel_security_connector *ctx = chand->security_connector;
  if (ctx != NULL)
    GRPC_SECURITY_CONNECTOR_UNREF(&ctx->base, "client_auth_filter");
  if (chand->authority_string != NULL) {
    GRPC_MDSTR_UNREF(chand->authority_string);
  }
  if (chand->error_msg_key != NULL) {
    GRPC_MDSTR_UNREF(chand->error_msg_key);
  }
  if (chand->status_key != NULL) {
    GRPC_MDSTR_UNREF(chand->status_key);
  }
  if (chand->path_string != NULL) {
    GRPC_MDSTR_UNREF(chand->path_string);
  }
}
Ejemplo n.º 16
0
static void security_handshaker_unref(grpc_exec_ctx *exec_ctx,
                                      security_handshaker *h) {
  if (gpr_unref(&h->refs)) {
    gpr_mu_destroy(&h->mu);
    tsi_handshaker_destroy(h->handshaker);
    tsi_handshaker_result_destroy(h->handshaker_result);
    if (h->endpoint_to_destroy != NULL) {
      grpc_endpoint_destroy(exec_ctx, h->endpoint_to_destroy);
    }
    if (h->read_buffer_to_destroy != NULL) {
      grpc_slice_buffer_destroy_internal(exec_ctx, h->read_buffer_to_destroy);
      gpr_free(h->read_buffer_to_destroy);
    }
    gpr_free(h->handshake_buffer);
    grpc_slice_buffer_destroy_internal(exec_ctx, &h->outgoing);
    GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
    GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, h->connector, "handshake");
    gpr_free(h);
  }
}
Ejemplo n.º 17
0
static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *statep,
                                         grpc_error *error) {
  server_secure_state *server_state = statep;
  /* ensure all threads have unlocked */
  gpr_mu_lock(&server_state->mu);
  grpc_closure *destroy_done = server_state->server_destroy_listener_done;
  GPR_ASSERT(server_state->is_shutdown);
  gpr_mu_unlock(&server_state->mu);
  /* clean up */
  grpc_server_security_connector_shutdown(exec_ctx, server_state->sc);

  /* Flush queued work before a synchronous unref. */
  grpc_exec_ctx_flush(exec_ctx);
  GRPC_SECURITY_CONNECTOR_UNREF(&server_state->sc->base, "server");
  grpc_server_credentials_unref(server_state->creds);

  if (destroy_done != NULL) {
    destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error));
    grpc_exec_ctx_flush(exec_ctx);
  }
  gpr_free(server_state);
}
Ejemplo n.º 18
0
static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
                          grpc_endpoint *tcp, const char *host,
                          void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
                                          grpc_endpoint *endpoint)) {
  grpc_channel_security_connector *sc = NULL;
  const unsigned char *pem_root_certs = NULL;
  on_done_closure *c = gpr_malloc(sizeof(*c));
  size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
  if (pem_root_certs == NULL || pem_root_certs_size == 0) {
    gpr_log(GPR_ERROR, "Could not get default pem root certs.");
    on_done(exec_ctx, arg, NULL);
    gpr_free(c);
    return;
  }
  c->func = on_done;
  c->arg = arg;
  GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
                 pem_root_certs, pem_root_certs_size, host, &sc) ==
             GRPC_SECURITY_OK);
  grpc_channel_security_connector_do_handshake(
      exec_ctx, sc, tcp, on_secure_transport_setup_done, c);
  GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
}
Ejemplo n.º 19
0
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
                                      grpc_server_credentials *creds) {
  grpc_resolved_addresses *resolved = NULL;
  grpc_tcp_server *tcp = NULL;
  grpc_server_secure_state *state = NULL;
  size_t i;
  unsigned count = 0;
  int port_num = -1;
  int port_temp;
  grpc_security_status status = GRPC_SECURITY_ERROR;
  grpc_security_connector *sc = NULL;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  GRPC_API_TRACE(
      "grpc_server_add_secure_http2_port("
      "server=%p, addr=%s, creds=%p)",
      3, (server, addr, creds));

  /* create security context */
  if (creds == NULL) goto error;
  status = grpc_server_credentials_create_security_connector(creds, &sc);
  if (status != GRPC_SECURITY_OK) {
    gpr_log(GPR_ERROR,
            "Unable to create secure server with credentials of type %s.",
            creds->type);
    goto error;
  }
  sc->channel_args = grpc_server_get_channel_args(server);

  /* resolve address */
  resolved = grpc_blocking_resolve_address(addr, "https");
  if (!resolved) {
    goto error;
  }

  tcp = grpc_tcp_server_create();
  if (!tcp) {
    goto error;
  }

  for (i = 0; i < resolved->naddrs; i++) {
    grpc_tcp_listener *listener;
    listener = grpc_tcp_server_add_port(
        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
        resolved->addrs[i].len);
    port_temp = grpc_tcp_listener_get_port(listener);
    if (port_temp > 0) {
      if (port_num == -1) {
        port_num = port_temp;
      } else {
        GPR_ASSERT(port_num == port_temp);
      }
      count++;
    }
  }
  if (count == 0) {
    gpr_log(GPR_ERROR, "No address added out of total %d resolved",
            resolved->naddrs);
    goto error;
  }
  if (count != resolved->naddrs) {
    gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
            count, resolved->naddrs);
    /* if it's an error, don't we want to goto error; here ? */
  }
  grpc_resolved_addresses_destroy(resolved);

  state = gpr_malloc(sizeof(*state));
  memset(state, 0, sizeof(*state));
  state->server = server;
  state->tcp = tcp;
  state->sc = sc;
  state->creds = grpc_server_credentials_ref(creds);

  state->is_shutdown = 0;
  gpr_mu_init(&state->mu);
  gpr_ref_init(&state->refcount, 1);

  /* Register with the server only upon success */
  grpc_server_add_listener(&exec_ctx, server, state, start, destroy);

  grpc_exec_ctx_finish(&exec_ctx);
  return port_num;

/* Error path: cleanup and return */
error:
  if (sc) {
    GRPC_SECURITY_CONNECTOR_UNREF(sc, "server");
  }
  if (resolved) {
    grpc_resolved_addresses_destroy(resolved);
  }
  if (tcp) {
    grpc_tcp_server_destroy(&exec_ctx, tcp, NULL);
  }
  if (state) {
    gpr_free(state);
  }
  grpc_exec_ctx_finish(&exec_ctx);
  return 0;
}
Ejemplo n.º 20
0
/* Create a secure client channel:
   Asynchronously: - resolve target
                   - connect to it (trying alternatives as presented)
                   - perform handshakes */
grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
                                         const char *target,
                                         const grpc_channel_args *args,
                                         void *reserved) {
  grpc_channel *channel;
  grpc_arg connector_arg;
  grpc_channel_args *args_copy;
  grpc_channel_args *new_args_from_connector;
  grpc_channel_security_connector *security_connector;
  grpc_mdctx *mdctx;
  grpc_resolver *resolver;
  subchannel_factory *f;
#define MAX_FILTERS 3
  const grpc_channel_filter *filters[MAX_FILTERS];
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  size_t n = 0;

  GRPC_API_TRACE(
      "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
      "reserved=%p)",
      4, (creds, target, args, reserved));
  GPR_ASSERT(reserved == NULL);

  if (grpc_find_security_connector_in_args(args) != NULL) {
    gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
    grpc_exec_ctx_finish(&exec_ctx);
    return grpc_lame_client_channel_create(
        target, GRPC_STATUS_INVALID_ARGUMENT,
        "Security connector exists in channel args.");
  }

  if (grpc_channel_credentials_create_security_connector(
          creds, target, args, &security_connector, &new_args_from_connector) !=
      GRPC_SECURITY_OK) {
    grpc_exec_ctx_finish(&exec_ctx);
    return grpc_lame_client_channel_create(
        target, GRPC_STATUS_INVALID_ARGUMENT,
        "Failed to create security connector.");
  }
  mdctx = grpc_mdctx_create();

  connector_arg = grpc_security_connector_to_arg(&security_connector->base);
  args_copy = grpc_channel_args_copy_and_add(
      new_args_from_connector != NULL ? new_args_from_connector : args,
      &connector_arg, 1);
  if (grpc_channel_args_is_census_enabled(args)) {
    filters[n++] = &grpc_client_census_filter;
  }
  filters[n++] = &grpc_compress_filter;
  filters[n++] = &grpc_client_channel_filter;
  GPR_ASSERT(n <= MAX_FILTERS);

  channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, n,
                                             args_copy, mdctx, 1);

  f = gpr_malloc(sizeof(*f));
  f->base.vtable = &subchannel_factory_vtable;
  gpr_ref_init(&f->refs, 1);
  grpc_mdctx_ref(mdctx);
  f->mdctx = mdctx;
  GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
  f->security_connector = security_connector;
  f->merge_args = grpc_channel_args_copy(args_copy);
  f->master = channel;
  GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
  resolver = grpc_resolver_create(target, &f->base);
  if (!resolver) {
    grpc_exec_ctx_finish(&exec_ctx);
    return NULL;
  }

  grpc_client_channel_set_resolver(
      &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
  GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
  grpc_subchannel_factory_unref(&exec_ctx, &f->base);
  GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");

  grpc_channel_args_destroy(args_copy);
  if (new_args_from_connector != NULL) {
    grpc_channel_args_destroy(new_args_from_connector);
  }

  grpc_exec_ctx_finish(&exec_ctx);

  return channel;
}
Ejemplo n.º 21
0
/* Create a secure client channel:
   Asynchronously: - resolve target
                   - connect to it (trying alternatives as presented)
                   - perform handshakes */
grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
                                         const char *target,
                                         const grpc_channel_args *args) {
  grpc_channel *channel;
  grpc_arg connector_arg;
  grpc_channel_args *args_copy;
  grpc_channel_args *new_args_from_connector;
  grpc_channel_security_connector *connector;
  grpc_mdctx *mdctx;
  grpc_resolver *resolver;
  subchannel_factory *f;
#define MAX_FILTERS 3
  const grpc_channel_filter *filters[MAX_FILTERS];
  int n = 0;

  if (grpc_find_security_connector_in_args(args) != NULL) {
    gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
    return grpc_lame_client_channel_create(target);
  }

  if (grpc_credentials_create_security_connector(
          creds, target, args, NULL, &connector, &new_args_from_connector) !=
      GRPC_SECURITY_OK) {
    return grpc_lame_client_channel_create(target);
  }
  mdctx = grpc_mdctx_create();

  connector_arg = grpc_security_connector_to_arg(&connector->base);
  args_copy = grpc_channel_args_copy_and_add(
      new_args_from_connector != NULL ? new_args_from_connector : args,
      &connector_arg, 1);
  /* TODO(census)
  if (grpc_channel_args_is_census_enabled(args)) {
    filters[n++] = &grpc_client_census_filter;
    } */
  filters[n++] = &grpc_compress_filter;
  filters[n++] = &grpc_client_channel_filter;
  GPR_ASSERT(n <= MAX_FILTERS);

  f = gpr_malloc(sizeof(*f));
  f->base.vtable = &subchannel_factory_vtable;
  gpr_ref_init(&f->refs, 1);
  grpc_mdctx_ref(mdctx);
  f->mdctx = mdctx;
  GRPC_SECURITY_CONNECTOR_REF(&connector->base, "subchannel_factory");
  f->security_connector = connector;
  f->merge_args = grpc_channel_args_copy(args_copy);
  resolver = grpc_resolver_create(target, &f->base);
  if (!resolver) {
    return NULL;
  }

  channel =
      grpc_channel_create_from_filters(target, filters, n, args_copy, mdctx, 1);
  grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
                                   resolver);
  GRPC_RESOLVER_UNREF(resolver, "create");
  grpc_subchannel_factory_unref(&f->base);
  GRPC_SECURITY_CONNECTOR_UNREF(&connector->base, "channel_create");

  grpc_channel_args_destroy(args_copy);
  if (new_args_from_connector != NULL) {
    grpc_channel_args_destroy(new_args_from_connector);
  }

  return channel;
}
Ejemplo n.º 22
0
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
                                      grpc_server_credentials *creds) {
  grpc_resolved_addresses *resolved = NULL;
  grpc_tcp_server *tcp = NULL;
  server_secure_state *state = NULL;
  size_t i;
  size_t count = 0;
  int port_num = -1;
  int port_temp;
  grpc_security_status status = GRPC_SECURITY_ERROR;
  grpc_server_security_connector *sc = NULL;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_error *err = GRPC_ERROR_NONE;
  grpc_error **errors = NULL;

  GRPC_API_TRACE(
      "grpc_server_add_secure_http2_port("
      "server=%p, addr=%s, creds=%p)",
      3, (server, addr, creds));

  /* create security context */
  if (creds == NULL) {
    err = GRPC_ERROR_CREATE(
        "No credentials specified for secure server port (creds==NULL)");
    goto error;
  }
  status = grpc_server_credentials_create_security_connector(creds, &sc);
  if (status != GRPC_SECURITY_OK) {
    char *msg;
    gpr_asprintf(&msg,
                 "Unable to create secure server with credentials of type %s.",
                 creds->type);
    err = grpc_error_set_int(GRPC_ERROR_CREATE(msg),
                             GRPC_ERROR_INT_SECURITY_STATUS, status);
    gpr_free(msg);
    goto error;
  }
  sc->channel_args = grpc_server_get_channel_args(server);

  /* resolve address */
  err = grpc_blocking_resolve_address(addr, "https", &resolved);
  if (err != GRPC_ERROR_NONE) {
    goto error;
  }
  state = gpr_malloc(sizeof(*state));
  memset(state, 0, sizeof(*state));
  grpc_closure_init(&state->destroy_closure, destroy_done, state);
  err = grpc_tcp_server_create(&state->destroy_closure,
                               grpc_server_get_channel_args(server), &tcp);
  if (err != GRPC_ERROR_NONE) {
    goto error;
  }

  state->server = server;
  state->tcp = tcp;
  state->sc = sc;
  state->creds = grpc_server_credentials_ref(creds);
  state->is_shutdown = false;
  gpr_mu_init(&state->mu);
  gpr_ref_init(&state->refcount, 1);

  errors = gpr_malloc(sizeof(*errors) * resolved->naddrs);
  for (i = 0; i < resolved->naddrs; i++) {
    errors[i] = grpc_tcp_server_add_port(
        tcp, (struct sockaddr *)&resolved->addrs[i].addr,
        resolved->addrs[i].len, &port_temp);
    if (errors[i] == GRPC_ERROR_NONE) {
      if (port_num == -1) {
        port_num = port_temp;
      } else {
        GPR_ASSERT(port_num == port_temp);
      }
      count++;
    }
  }
  if (count == 0) {
    char *msg;
    gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
                 resolved->naddrs);
    err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
    gpr_free(msg);
    goto error;
  } else if (count != resolved->naddrs) {
    char *msg;
    gpr_asprintf(&msg, "Only %" PRIuPTR
                       " addresses added out of total %" PRIuPTR " resolved",
                 count, resolved->naddrs);
    err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
    gpr_free(msg);

    const char *warning_message = grpc_error_string(err);
    gpr_log(GPR_INFO, "WARNING: %s", warning_message);
    grpc_error_free_string(warning_message);
    /* we managed to bind some addresses: continue */
  } else {
    for (i = 0; i < resolved->naddrs; i++) {
      GRPC_ERROR_UNREF(errors[i]);
    }
  }
  gpr_free(errors);
  errors = NULL;
  grpc_resolved_addresses_destroy(resolved);

  /* Register with the server only upon success */
  grpc_server_add_listener(&exec_ctx, server, state, start, destroy);

  grpc_exec_ctx_finish(&exec_ctx);
  return port_num;

/* Error path: cleanup and return */
error:
  GPR_ASSERT(err != GRPC_ERROR_NONE);
  if (errors != NULL) {
    for (i = 0; i < resolved->naddrs; i++) {
      GRPC_ERROR_UNREF(errors[i]);
    }
    gpr_free(errors);
  }
  if (resolved) {
    grpc_resolved_addresses_destroy(resolved);
  }
  if (tcp) {
    grpc_tcp_server_unref(&exec_ctx, tcp);
  } else {
    if (sc) {
      GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
    }
    if (state) {
      gpr_free(state);
    }
  }
  grpc_exec_ctx_finish(&exec_ctx);
  const char *msg = grpc_error_string(err);
  GRPC_ERROR_UNREF(err);
  gpr_log(GPR_ERROR, "%s", msg);
  grpc_error_free_string(msg);
  return 0;
}