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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
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);
}