void CNT_Session(struct sess *sp) { int done; struct worker *w; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); w = sp->wrk; CHECK_OBJ_NOTNULL(w, WORKER_MAGIC); /* * Possible entrance states */ assert( sp->step == STP_FIRST || sp->step == STP_START || sp->step == STP_LOOKUP || sp->step == STP_RECV); /* * Whenever we come in from the acceptor we need to set blocking * mode, but there is no point in setting it when we come from * ESI or when a parked sessions returns. * It would be simpler to do this in the acceptor, but we'd rather * do the syscall in the worker thread. */ if (sp->step == STP_FIRST || sp->step == STP_START) TCP_blocking(sp->fd); for (done = 0; !done; ) { assert(sp->wrk == w); /* * This is a good place to be paranoid about the various * pointers still pointing to the things we expect. */ CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_ORNULL(sp->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); CHECK_OBJ_ORNULL(w->nobjhead, OBJHEAD_MAGIC); WS_Assert(w->ws); switch (sp->step) { #define STEP(l,u) \ case STP_##u: \ if (params->diag_bitmap & 0x01) \ cnt_diag(sp, #u); \ done = cnt_##l(sp); \ break; #include "steps.h" #undef STEP default: WRONG("State engine misfire"); } WS_Assert(w->ws); CHECK_OBJ_ORNULL(w->nobjhead, OBJHEAD_MAGIC); } WSL_Flush(w, 0); AZ(w->wfd); }
int TCP_connect(int s, const struct sockaddr *name, socklen_t namelen, int msec) { int i, k; socklen_t l; struct pollfd fds[1]; assert(s >= 0); /* Set the socket non-blocking */ TCP_nonblocking(s); /* Attempt the connect */ i = connect(s, name, namelen); if (i == 0 || errno != EINPROGRESS) return (i); /* Exercise our patience, polling for write */ fds[0].fd = s; fds[0].events = POLLWRNORM; fds[0].revents = 0; i = poll(fds, 1, msec); if (i == 0) { /* Timeout, close and give up */ errno = ETIMEDOUT; return (-1); } /* Find out if we got a connection */ l = sizeof k; AZ(getsockopt(s, SOL_SOCKET, SO_ERROR, &k, &l)); /* An error means no connection established */ errno = k; if (k) return (-1); TCP_blocking(s); return (0); }
void PipeSession(struct sess *sp) { struct vbe_conn *vc; struct worker *w; struct pollfd fds[2]; int i; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); w = sp->wrk; sp->vbe = VBE_GetFd(NULL, sp); if (sp->vbe == NULL) return; vc = sp->vbe; (void)TCP_blocking(vc->fd); WRW_Reserve(w, &vc->fd); sp->acct_req.hdrbytes += http_Write(w, sp->wrk->bereq, 0); if (sp->htc->pipeline.b != NULL) sp->acct_req.bodybytes += WRW_Write(w, sp->htc->pipeline.b, Tlen(sp->htc->pipeline)); i = WRW_FlushRelease(w); if (i) { vca_close_session(sp, "pipe"); VBE_ClosedFd(sp); return; } sp->t_resp = TIM_real(); memset(fds, 0, sizeof fds); // XXX: not yet (void)TCP_linger(vc->fd, 0); fds[0].fd = vc->fd; fds[0].events = POLLIN | POLLERR; // XXX: not yet (void)TCP_linger(sp->fd, 0); fds[1].fd = sp->fd; fds[1].events = POLLIN | POLLERR; while (fds[0].fd > -1 || fds[1].fd > -1) { fds[0].revents = 0; fds[1].revents = 0; i = poll(fds, 2, params->pipe_timeout * 1000); if (i < 1) break; if (fds[0].revents && rdf(vc->fd, sp->fd)) { (void)shutdown(vc->fd, SHUT_RD); (void)shutdown(sp->fd, SHUT_WR); fds[0].events = 0; fds[0].fd = -1; } if (fds[1].revents && rdf(sp->fd, vc->fd)) { (void)shutdown(sp->fd, SHUT_RD); (void)shutdown(vc->fd, SHUT_WR); fds[1].events = 0; fds[1].fd = -1; } } if (fds[0].fd >= 0) { (void)shutdown(vc->fd, SHUT_RD); (void)shutdown(sp->fd, SHUT_WR); } if (fds[1].fd >= 0) { (void)shutdown(sp->fd, SHUT_RD); (void)shutdown(vc->fd, SHUT_WR); } vca_close_session(sp, "pipe"); VBE_ClosedFd(sp); }