static void destroy_cursock(lcbio_CONNSTART *cs) { lcbio_SOCKET *s = cs->sock; lcbio_TABLE *iot = s->io; if (cs->ai) { cs->ai = cs->ai->ai_next; } if (!cs->ai) { return; } if (IOT_IS_EVENT(iot)) { if (cs->ev_active) { lcb_assert(s->u.fd != INVALID_SOCKET); IOT_V0EV(iot).cancel(IOT_ARG(iot), s->u.fd, cs->event); cs->ev_active = 0; } IOT_V0IO(iot).close(IOT_ARG(iot), s->u.fd); s->u.fd = INVALID_SOCKET; } else { if (s->u.sd) { IOT_V1(iot).close(IOT_ARG(iot), s->u.sd); s->u.sd = NULL; } } }
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; }
void lcbio_ctx_wwant(lcbio_CTX *ctx) { if ((IOT_IS_EVENT(ctx->io)) == 0 && ctx->entered == 0) { ctx->procs.cb_flush_ready(ctx); } else { ctx->wwant = 1; } }
int lcbio_ctx_put_ex(lcbio_CTX *ctx, lcb_IOV *iov, unsigned niov, unsigned nb) { lcbio_TABLE *iot = ctx->io; if (IOT_IS_EVENT(iot)) { return E_put_ex(ctx, iov, niov, nb); } else { return C_put_ex(ctx, iov, niov, nb); } }
int lcbio_is_netclosed(lcbio_SOCKET *sock, int flags) { lcbio_pTABLE iot = sock->io; if (IOT_IS_EVENT(iot)) { return IOT_V0IO(iot).is_closed(IOT_ARG(iot), sock->u.fd, flags); } else { return IOT_V1(iot).is_closed(IOT_ARG(iot), sock->u.sd, flags); } }
void lcbio_ctx_schedule(lcbio_CTX *ctx) { if (ctx->entered || ctx->err || ctx->state != ES_ACTIVE) { /* don't schedule events on i/o errors or on entered state */ return; } if (IOT_IS_EVENT(ctx->io)) { E_schedule(ctx); } else { C_schedule(ctx); } }
void lcbio_shutdown(lcbio_SOCKET *s) { lcbio_TABLE *io = s->io; lcbio__protoctx_delall(s); if (IOT_IS_EVENT(io)) { if (s->u.fd != INVALID_SOCKET) { IOT_V0IO(io).close(IOT_ARG(io), s->u.fd); s->u.fd = INVALID_SOCKET; } } else { if (s->u.sd) { IOT_V1(io).close(IOT_ARG(io), s->u.sd); s->u.sd = NULL; } } }
static int ensure_sock(lcbio_CONNSTART *cs) { lcbio_SOCKET *s = cs->sock; lcbio_TABLE *io = s->io; int errtmp = 0; if (cs->ai == NULL) { return -1; } if (IOT_IS_EVENT(io)) { if (s->u.fd != INVALID_SOCKET) { /* already have one? */ return 0; } while (s->u.fd == INVALID_SOCKET && cs->ai != NULL) { s->u.fd = lcbio_E_ai2sock(io, &cs->ai, &errtmp); if (s->u.fd != INVALID_SOCKET) { return 0; } } } else { if (s->u.sd) { return 0; } while (s->u.sd == NULL && cs->ai != NULL) { s->u.sd = lcbio_C_ai2sock(io, &cs->ai, &errtmp); if (s->u.sd) { s->u.sd->lcbconn = (void *) cs->sock; s->u.sd->parent = IOT_ARG(io); return 0; } } } if (cs->ai == NULL) { lcbio_mksyserr(IOT_ERRNO(io), &cs->syserr); return -1; } return 0; }
void lcbio__load_socknames(lcbio_SOCKET *sock) { int n_salocal, n_saremote, rv; struct lcb_nameinfo_st ni; lcbio_CONNINFO *info = sock->info; n_salocal = sizeof(info->sa_local); n_saremote = sizeof(info->sa_remote); ni.local.name = (struct sockaddr *)&info->sa_local; ni.local.len = &n_salocal; ni.remote.name = (struct sockaddr *)&info->sa_remote; ni.remote.len = &n_saremote; if (!IOT_IS_EVENT(sock->io)) { if (!sock->u.sd) { return; } rv = IOT_V1(sock->io).nameinfo(IOT_ARG(sock->io), sock->u.sd, &ni); if (ni.local.len == 0 || ni.remote.len == 0 || rv < 0) { return; } } else { socklen_t sl_tmp = sizeof(info->sa_local); if (sock->u.fd == INVALID_SOCKET) { return; } rv = getsockname(sock->u.fd, ni.local.name, &sl_tmp); n_salocal = sl_tmp; if (rv < 0) { return; } rv = getpeername(sock->u.fd, ni.remote.name, &sl_tmp); n_saremote = sl_tmp; if (rv < 0) { return; } } info->naddr = n_salocal; }
void lcbio_ctx_dump(lcbio_CTX *ctx) { printf("IOCTX=%p. SUBSYS=%s\n", (void*)ctx, ctx->subsys); printf(" Pending=%d\n", ctx->npending); printf(" ReqRead=%d\n", ctx->rdwant); printf(" WantWrite=%d\n", ctx->wwant); printf(" Entered=%d\n", ctx->entered); printf(" Active=%d\n", ctx->state == ES_ACTIVE); printf(" SOCKET=%p\n", (void*)ctx->sock); printf(" Model=%s\n", ctx->io->model == LCB_IOMODEL_EVENT ? "Event" : "Completion"); if (IOT_IS_EVENT(ctx->io)) { printf(" FD=%d\n", ctx->sock->u.fd); printf(" Watcher Active=%d\n", ctx->evactive); } else { printf(" SD=%p\n", (void *)ctx->sock->u.sd); printf(" Reading=%d\n", ctx->sock->u.sd->is_reading); } }
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; }