/** * Handler invoked to deliver final status for a connection. This will invoke * the user supplied callback with the relevant status (if it has not been * cancelled) and then free the CONNSTART object. */ static void cs_handler(void *cookie) { lcbio_CONNSTART *cs = cookie; lcb_error_t err; lcbio_SOCKET *s = cs->sock; if (s && cs->event) { cs_unwatch(cs); IOT_V0EV(s->io).destroy(IOT_ARG(s->io), cs->event); } if (cs->state == CS_PENDING) { /* state was not changed since initial scheduling */ err = LCB_ETIMEDOUT; } else if (cs->state == CS_CONNECTED) { /* clear pending error */ err = LCB_SUCCESS; } else { if (s != NULL && cs->pending == LCB_CONNECT_ERROR) { err = lcbio_mklcberr(cs->syserr, s->settings); } else { err = cs->pending; } } if (cs->state == CS_CANCELLED) { /* ignore everything. Clean up resources */ goto GT_DTOR; } if (s) { lcbio__load_socknames(s); if (err == LCB_SUCCESS) { lcb_log(LOGARGS(s, INFO), CSLOGFMT "Connected ", CSLOGID(s)); } else { lcb_log(LOGARGS(s, ERR), CSLOGFMT "Failed: lcb_err=0x%x, os_errno=%u", CSLOGID(s), err, cs->syserr); } } /** Handler section */ cs->in_uhandler = 1; cs->handler(err == LCB_SUCCESS ? s : NULL, cs->arg, err, cs->syserr); GT_DTOR: if (cs->async) { lcbio_timer_destroy(cs->async); } if (cs->sock) { lcbio_unref(cs->sock); } if (cs->ai_root) { freeaddrinfo(cs->ai_root); } free(cs); }
static void free_ctx(lcbio_CTX *ctx) { rdb_cleanup(&ctx->ior); lcbio_unref(ctx->sock); if (ctx->output) { ringbuffer_destruct(&ctx->output->rb); free(ctx->output); } if (ctx->procs.cb_flush_ready) { /* dtor */ ctx->procs.cb_flush_ready(ctx); } free(ctx); }
static void negotiation_success(mc_pSESSREQ sreq) { /** Dislodge the connection, and return it back to the caller */ lcbio_SOCKET *s; lcbio_ctx_close(sreq->ctx, close_cb, &s); sreq->ctx = NULL; lcbio_protoctx_add(s, &sreq->inner->base); sreq->inner = NULL; /** Invoke the callback, marking it a success */ sreq->cb(s, sreq->data, LCB_SUCCESS, 0); lcbio_unref(s); cleanup_pending(sreq); }