lcbio_CTX * lcbio_ctx_new(lcbio_SOCKET *sock, void *data, const lcbio_EASYPROCS *procs) { lcbio_CTX *ctx = calloc(1, sizeof(*ctx)); ctx->sock = sock; sock->ctx = ctx; ctx->io = sock->io; ctx->data = data; ctx->procs = *procs; ctx->state = ES_ACTIVE; ctx->as_err = lcbio_timer_new(ctx->io, ctx, err_handler); ctx->subsys = "unknown"; rdb_init(&ctx->ior, sock->settings->allocator_factory()); lcbio_ref(sock); if (IOT_IS_EVENT(ctx->io)) { ctx->event = IOT_V0EV(ctx->io).create(IOT_ARG(ctx->io)); ctx->fd = sock->u.fd; } else { ctx->sd = sock->u.sd; } ctx->procs = *procs; ctx->state = ES_ACTIVE; lcb_log(LOGARGS(ctx, DEBUG), CTX_LOGFMT "Pairing with SOCK=%p", CTX_LOGID(ctx), (void*)sock); return ctx; }
lcb_error_t lcb_bootstrap_common(lcb_t instance, int options) { struct lcb_BOOTSTRAP *bs = instance->bootstrap; hrtime_t now = gethrtime(); if (!bs) { bs = calloc(1, sizeof(*instance->bootstrap)); if (!bs) { return LCB_CLIENT_ENOMEM; } bs->tm = lcbio_timer_new(instance->iotable, bs, initial_timeout); instance->bootstrap = bs; bs->parent = instance; lcb_confmon_add_listener(instance->confmon, &bs->listener); } if (lcb_confmon_is_refreshing(instance->confmon)) { return LCB_SUCCESS; } if (options & LCB_BS_REFRESH_THROTTLE) { /* Refresh throttle requested. This is not true if options == ALWAYS */ hrtime_t next_ts; unsigned errthresh = LCBT_SETTING(instance, weird_things_threshold); if (options & LCB_BS_REFRESH_INCRERR) { bs->errcounter++; } next_ts = bs->last_refresh; next_ts += LCB_US2NS(LCBT_SETTING(instance, weird_things_delay)); if (now < next_ts && bs->errcounter < errthresh) { lcb_log(LOGARGS(instance, INFO), "Not requesting a config refresh because of throttling parameters. Next refresh possible in %ums or %u errors. " "See LCB_CNTL_CONFDELAY_THRESH and LCB_CNTL_CONFERRTHRESH to modify the throttling settings", LCB_NS2US(next_ts-now)/1000, (unsigned)errthresh-bs->errcounter); return LCB_SUCCESS; } } if (options == LCB_BS_REFRESH_INITIAL) { lcb_confmon_prepare(instance->confmon); bs->listener.callback = config_callback; lcbio_timer_set_target(bs->tm, initial_timeout); lcbio_timer_rearm(bs->tm, LCBT_SETTING(instance, config_timeout)); lcb_aspend_add(&instance->pendops, LCB_PENDTYPE_COUNTER, NULL); } else { /** No initial timer */ bs->listener.callback = async_step_callback; } /* Reset the counters */ bs->errcounter = 0; if (options != LCB_BS_REFRESH_INITIAL) { bs->last_refresh = now; } return lcb_confmon_start(instance->confmon); }
clconfig_provider * lcb_clconfig_create_mcraw(lcb_confmon *parent) { bc_MCRAW *mcr = calloc(1, sizeof(*mcr)); if (!mcr) { return NULL; } mcr->async = lcbio_timer_new(parent->iot, mcr, async_update); mcr->base.parent = parent; mcr->base.type = LCB_CLCONFIG_MCRAW; mcr->base.get_cached = get_cached; mcr->base.refresh = get_refresh; mcr->base.pause = pause_mcr; mcr->base.configure_nodes = configure_nodes; mcr->base.shutdown = mcraw_shutdown; return &mcr->base; }
clconfig_provider * lcb_clconfig_create_file(lcb_confmon *parent) { file_provider *provider = calloc(1, sizeof(*provider)); if (!provider) { return NULL; } provider->base.get_cached = get_cached; provider->base.refresh = refresh_file; provider->base.pause = pause_file; provider->base.shutdown = shutdown_file; provider->base.dump = do_file_dump; provider->base.type = LCB_CLCONFIG_FILE; provider->listener.callback = config_listener; provider->timer = lcbio_timer_new(parent->iot, provider, async_callback); lcb_confmon_add_listener(parent, &provider->listener); return &provider->base; }
mc_pSESSREQ mc_sessreq_start(lcbio_SOCKET *sock, lcb_settings *settings, uint32_t tmo, lcbio_CONNDONE_cb callback, void *data) { lcb_error_t err; cbsasl_error_t saslerr; protocol_binary_request_no_extras req; const lcb_host_t *curhost; struct lcbio_NAMEINFO nistrs; mc_pSESSREQ sreq; mc_pSESSINFO sasl; lcbio_CTXPROCS procs; if ((sreq = calloc(1, sizeof(*sreq))) == NULL) { return NULL; } if ((sasl = calloc(1, sizeof(*sasl))) == NULL) { cleanup_pending(sreq); return NULL; } procs.cb_err = handle_ioerr; procs.cb_read = handle_read; lcbio_get_nameinfo(sock, &nistrs); sreq->cb = callback; sreq->data = data; sreq->inner = sasl; sreq->timer = lcbio_timer_new(sock->io, sreq, timeout_handler); if ((err = lcbio_sslify_if_needed(sock, settings)) != LCB_SUCCESS) { set_error_ex(sreq, err, "Couldn't initialize SSL on socket"); lcbio_async_signal(sreq->timer); return sreq; } sreq->ctx = lcbio_ctx_new(sock, sreq, &procs); sreq->ctx->subsys = "sasl"; if (tmo) { lcbio_timer_rearm(sreq->timer, tmo); } sasl->base.id = LCBIO_PROTOCTX_SESSINFO; sasl->base.dtor = (void (*)(struct lcbio_PROTOCTX *))cleanup_negotiated; sasl->settings = settings; err = setup_sasl_params(sasl); if (err != LCB_SUCCESS) { cleanup_pending(sreq); return NULL; } curhost = lcbio_get_host(sock); saslerr = cbsasl_client_new( "couchbase", curhost->host, nistrs.local, nistrs.remote, sasl->sasl_callbacks, 0, &sasl->sasl); if (saslerr != SASL_OK) { cleanup_pending(sreq); return NULL; } memset(&req, 0, sizeof(req)); req.message.header.request.magic = PROTOCOL_BINARY_REQ; req.message.header.request.opcode = PROTOCOL_BINARY_CMD_SASL_LIST_MECHS; req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES; req.message.header.request.bodylen = 0; req.message.header.request.keylen = 0; req.message.header.request.opaque = 0; lcbio_ctx_put(sreq->ctx, req.bytes, sizeof(req.bytes)); LCBIO_CTX_RSCHEDULE(sreq->ctx, 24); return sreq; }
struct lcbio_CONNSTART * lcbio_connect(lcbio_TABLE *iot, lcb_settings *settings, lcb_host_t *dest, uint32_t timeout, lcbio_CONNDONE_cb handler, void *arg) { lcbio_SOCKET *s; lcbio_CONNSTART *ret; struct addrinfo hints; int rv; s = calloc(1, sizeof(*s)); ret = calloc(1, sizeof(*ret)); /** Initialize the socket first */ s->io = iot; s->settings = settings; s->ctx = ret; s->refcount = 1; s->info = calloc(1, sizeof(*s->info)); s->info->ep = *dest; lcbio_table_ref(s->io); lcb_settings_ref(s->settings); lcb_list_init(&s->protos); if (IOT_IS_EVENT(iot)) { s->u.fd = INVALID_SOCKET; ret->event = IOT_V0EV(iot).create(IOT_ARG(iot)); } /** Initialize the connstart structure */ ret->handler = handler; ret->arg = arg; ret->sock = s; ret->async = lcbio_timer_new(iot, ret, cs_handler); lcbio_timer_rearm(ret->async, timeout); lcb_log(LOGARGS(s, INFO), CSLOGFMT "Starting. Timeout=%uus", CSLOGID(s), timeout); /** Hostname lookup: */ memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; if (settings->ipv6 == LCB_IPV6_DISABLED) { hints.ai_family = AF_INET; } else if (settings->ipv6 == LCB_IPV6_ONLY) { hints.ai_family = AF_INET6; } else { hints.ai_family = AF_UNSPEC; } if ((rv = getaddrinfo(dest->host, dest->port, &hints, &ret->ai_root))) { const char *errstr = rv != EAI_SYSTEM ? gai_strerror(rv) : ""; lcb_log(LOGARGS(s, ERR), CSLOGFMT "Couldn't look up %s (%s) [EAI=%d]", CSLOGID(s), dest->host, errstr, rv); cs_state_signal(ret, CS_ERROR, LCB_UNKNOWN_HOST); } else { ret->ai = ret->ai_root; /** Figure out how to connect */ if (IOT_IS_EVENT(iot)) { E_connect(-1, LCB_WRITE_EVENT, ret); } else { C_connect(ret); } } return ret; }