static void
vca_kev(const struct kevent *kp)
{
    int i, j;
    struct sess *sp;
    struct sess *ss[NKEV];

    AN(kp->udata);
    if (kp->udata == vca_pipes) {
        j = 0;
        i = read(vca_pipes[0], ss, sizeof ss);
        if (i == -1 && errno == EAGAIN)
            return;
        while (i >= sizeof ss[0]) {
            CHECK_OBJ_NOTNULL(ss[j], SESS_MAGIC);
            assert(ss[j]->sp_fd >= 0);
            AZ(ss[j]->obj);
            VTAILQ_INSERT_TAIL(&sesshead, ss[j], list);
            vca_kq_sess(ss[j], EV_ADD | EV_ONESHOT);
            j++;
            i -= sizeof ss[0];
        }
        assert(i == 0);
        return;
    }
    CAST_OBJ_NOTNULL(sp, kp->udata, SESS_MAGIC);
    DSL(0x04, SLT_Debug, sp->id, "KQ: sp %p kev data %lu flags 0x%x%s",
        sp, (unsigned long)kp->data, kp->flags,
        (kp->flags & EV_EOF) ? " EOF" : "");

    assert(sp->id == kp->ident);
    assert(sp->sp_fd == sp->id);
    if (kp->data > 0) {
        i = HTC_Rx(sp->htc);
        if (i == 0) {
            vca_kq_sess(sp, EV_ADD | EV_ONESHOT);
            return;	/* more needed */
        }
        VTAILQ_REMOVE(&sesshead, sp, list);
        vca_handover(sp, i);
        return;
    } else if (kp->flags & EV_EOF) {
        VTAILQ_REMOVE(&sesshead, sp, list);
        vca_close_session(sp, "EOF");
        SES_Delete(sp);
        return;
    } else {
        VSL(SLT_Debug, sp->id, "KQ: sp %p kev data %lu flags 0x%x%s",
            sp, (unsigned long)kp->data, kp->flags,
            (kp->flags & EV_EOF) ? " EOF" : "");
    }
}
static inline void
vca_port_ev(port_event_t *ev) {
	struct sess *sp;
	if(ev->portev_source == PORT_SOURCE_USER) {
		CAST_OBJ_NOTNULL(sp, ev->portev_user, SESS_MAGIC);
		assert(sp->fd >= 0);
		AZ(sp->obj);
		VTAILQ_INSERT_TAIL(&sesshead, sp, list);
		vca_add(sp->fd, sp);
	} else {
		int i;
		assert(ev->portev_source == PORT_SOURCE_FD);
		CAST_OBJ_NOTNULL(sp, ev->portev_user, SESS_MAGIC);
		assert(sp->fd >= 0);
		if(ev->portev_events & POLLERR) {
			vca_del(sp->fd);
			VTAILQ_REMOVE(&sesshead, sp, list);			
			vca_close_session(sp, "EOF");
			SES_Delete(sp);
			return;
		}
		i = HTC_Rx(sp->htc);

		if (i == 0) {
			/* incomplete header, wait for more data */
			vca_add(sp->fd, sp);
			return;
		}

		/* 
		 * note: the original man page for port_associate(3C) states:
		 *
		 *    When an event for a PORT_SOURCE_FD object is retrieved,
		 *    the object no longer has an association with the port.
		 *
		 * This can be read along the lines of sparing the
		 * port_dissociate after port_getn(), but in fact,
		 * port_dissociate should be used
		 *
		 * Ref: http://opensolaris.org/jive/thread.jspa?threadID=129476&tstart=0
		 */
		vca_del(sp->fd);
		VTAILQ_REMOVE(&sesshead, sp, list);

		/* vca_handover will also handle errors */
		vca_handover(sp, i);
	}
	return;
}
static void
vca_eev(const struct epoll_event *ep)
{
	struct sess *ss[NEEV], *sp;
	int i, j;

	AN(ep->data.ptr);
	if (ep->data.ptr == vca_pipes) {
		if (ep->events & EPOLLIN || ep->events & EPOLLPRI) {
			j = 0;
			i = read(vca_pipes[0], ss, sizeof ss);
			if (i == -1 && errno == EAGAIN)
				return;
			while (i >= sizeof ss[0]) {
				CHECK_OBJ_NOTNULL(ss[j], SESS_MAGIC);
				assert(ss[j]->fd >= 0);
				AZ(ss[j]->obj);
				VTAILQ_INSERT_TAIL(&sesshead, ss[j], list);
				vca_cond_modadd(ss[j]->fd, ss[j]);
				j++;
				i -= sizeof ss[0];
			}
			assert(i == 0);
		}
	} else {
		CAST_OBJ_NOTNULL(sp, ep->data.ptr, SESS_MAGIC);
		if (ep->events & EPOLLIN || ep->events & EPOLLPRI) {
			i = HTC_Rx(sp->htc);
			if (i == 0) {
				vca_modadd(sp->fd, sp, EPOLL_CTL_MOD);
				return;	/* more needed */
			}
			VTAILQ_REMOVE(&sesshead, sp, list);
			vca_handover(sp, i);
		} else if (ep->events & EPOLLERR) {
			VTAILQ_REMOVE(&sesshead, sp, list);
			vca_close_session(sp, "ERR");
			SES_Delete(sp);
		} else if (ep->events & EPOLLHUP) {
			VTAILQ_REMOVE(&sesshead, sp, list);
			vca_close_session(sp, "HUP");
			SES_Delete(sp);
		} else if (ep->events & EPOLLRDHUP) {
			VTAILQ_REMOVE(&sesshead, sp, list);
			vca_close_session(sp, "RHUP");
			SES_Delete(sp);
		}
	}
}
Пример #4
0
static int
cnt_wait(struct sess *sp)
{
    int i;
    struct pollfd pfd[1];
    struct worker *wrk;

    CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
    wrk = sp->wrk;
    CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
    AZ(sp->vcl);
    AZ(wrk->obj);
    AZ(sp->esi_level);
    assert(sp->xid == 0);

    i = HTC_Complete(sp->htc);
    if (i == 0 && cache_param->session_linger > 0) {
        pfd[0].fd = sp->fd;
        pfd[0].events = POLLIN;
        pfd[0].revents = 0;
        i = poll(pfd, 1, cache_param->session_linger);
        if (i)
            i = HTC_Rx(sp->htc);
    }
    if (i == 0) {
        WSP(sp, SLT_Debug, "herding");
        wrk->stats.sess_herd++;
        SES_Charge(sp);
        Pool_Wait(sp);
        return (1);
    }
    if (i == 1) {
        sp->step = STP_START;
        return (0);
    }
    if (i == -2) {
        SES_Close(sp, "overflow");
    } else if (i == -1 && Tlen(sp->htc->rxbuf) == 0 &&
               (errno == 0 || errno == ECONNRESET))
        SES_Close(sp, "EOF");
    else
        SES_Close(sp, "error");
    sp->step = STP_DONE;
    return (0);
}
static int
cnt_wait(struct sess *sp)
{
    int i;
    struct pollfd pfd[1];

    CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
    AZ(sp->vcl);
    AZ(sp->obj);
    assert(sp->xid == 0);

    i = HTC_Complete(sp->htc);
    while (i == 0) {
        if (params->session_linger > 0) {
            pfd[0].fd = sp->fd;
            pfd[0].events = POLLIN;
            pfd[0].revents = 0;
            i = poll(pfd, 1, params->session_linger);
            if (i == 0) {
                WSL(sp->wrk, SLT_Debug, sp->fd, "herding");
                VSL_stats->sess_herd++;
                sp->wrk = NULL;
                vca_return_session(sp);
                return (1);
            }
        }
        i = HTC_Rx(sp->htc);
    }
    if (i == 1) {
        sp->step = STP_START;
    } else {
        if (i == -2)
            vca_close_session(sp, "overflow");
        else if (i == -1 && Tlen(sp->htc->rxbuf) == 0 &&
                 (errno == 0 || errno == ECONNRESET))
            vca_close_session(sp, "EOF");
        else
            vca_close_session(sp, "error");
        sp->step = STP_DONE;
    }
    return (0);
}
Пример #6
0
int
FetchHdr(struct sess *sp, int need_host_hdr)
{
	struct vbc *vc;
	struct worker *wrk;
	struct http *hp;
	int retry = -1;
	int i;
	struct http_conn *htc;

	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
	wrk = sp->wrk;
	CHECK_OBJ_NOTNULL(wrk->busyobj, BUSYOBJ_MAGIC);
	htc = &wrk->busyobj->htc;

	AN(sp->req->director);
	AZ(sp->req->obj);

	if (sp->req->objcore != NULL) {		/* pass has no objcore */
		CHECK_OBJ_NOTNULL(sp->req->objcore, OBJCORE_MAGIC);
		AN(sp->req->objcore->flags & OC_F_BUSY);
	}

	hp = wrk->busyobj->bereq;

	sp->wrk->busyobj->vbc = VDI_GetFd(NULL, sp);
	if (sp->wrk->busyobj->vbc == NULL) {
		WSP(sp, SLT_FetchError, "no backend connection");
		return (-1);
	}
	vc = sp->wrk->busyobj->vbc;
	if (vc->recycled)
		retry = 1;

	/*
	 * Now that we know our backend, we can set a default Host:
	 * header if one is necessary.  This cannot be done in the VCL
	 * because the backend may be chosen by a director.
	 */
	if (need_host_hdr)
		VDI_AddHostHeader(sp->wrk, vc);

	(void)VTCP_blocking(vc->fd);	/* XXX: we should timeout instead */
	WRW_Reserve(wrk, &vc->fd);
	(void)http_Write(wrk, vc->vsl_id, hp, 0);	/* XXX: stats ? */

	/* Deal with any message-body the request might have */
	i = FetchReqBody(sp);
	if (WRW_FlushRelease(wrk) || i > 0) {
		WSP(sp, SLT_FetchError, "backend write error: %d (%s)",
		    errno, strerror(errno));
		VDI_CloseFd(sp->wrk, &sp->wrk->busyobj->vbc);
		/* XXX: other cleanup ? */
		return (retry);
	}

	/* Checkpoint the vsl.here */
	WSL_Flush(wrk, 0);

	/* XXX is this the right place? */
	VSC_C_main->backend_req++;

	/* Receive response */

	HTC_Init(htc, wrk->ws, vc->fd, vc->vsl_id,
	    cache_param->http_resp_size,
	    cache_param->http_resp_hdr_len);

	VTCP_set_read_timeout(vc->fd, vc->first_byte_timeout);

	i = HTC_Rx(htc);

	if (i < 0) {
		WSP(sp, SLT_FetchError, "http first read error: %d %d (%s)",
		    i, errno, strerror(errno));
		VDI_CloseFd(sp->wrk, &sp->wrk->busyobj->vbc);
		/* XXX: other cleanup ? */
		/* Retryable if we never received anything */
		return (i == -1 ? retry : -1);
	}

	VTCP_set_read_timeout(vc->fd, vc->between_bytes_timeout);

	while (i == 0) {
		i = HTC_Rx(htc);
		if (i < 0) {
			WSP(sp, SLT_FetchError,
			    "http first read error: %d %d (%s)",
			    i, errno, strerror(errno));
			VDI_CloseFd(sp->wrk, &sp->wrk->busyobj->vbc);
			/* XXX: other cleanup ? */
			return (-1);
		}
	}

	hp = wrk->busyobj->beresp;

	if (http_DissectResponse(wrk, htc, hp)) {
		WSP(sp, SLT_FetchError, "http format error");
		VDI_CloseFd(sp->wrk, &sp->wrk->busyobj->vbc);
		/* XXX: other cleanup ? */
		return (-1);
	}
	return (0);
}