Example #1
0
enum htc_status_e
SES_RxReq(const struct worker *wrk, struct req *req, htc_complete_f *func)
{
	double tmo;
	double now, when;
	struct sess *sp;
	enum htc_status_e hs;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	sp = req->sp;
	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);

	AZ(isnan(sp->t_idle));
	assert(isnan(req->t_first));

	when = sp->t_idle + cache_param->timeout_idle;
	tmo = cache_param->timeout_linger;
	while (1) {
		hs = SES_Rx(req->htc, tmo);
		now = VTIM_real();
		if (hs == HTC_S_EOF) {
			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
			return (HTC_S_CLOSE);
		}
		if (hs == HTC_S_OVERFLOW) {
			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
			return (HTC_S_OVERFLOW);
		}
		hs = func(req->htc);
		if (hs == HTC_S_OVERFLOW) {
			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
			return (HTC_S_OVERFLOW);
		}
		if (hs == HTC_S_JUNK) {
			WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b);
			return (HTC_S_JUNK);
		}
		if (hs == HTC_S_COMPLETE) {
			/* Got it, run with it */
			if (isnan(req->t_first))
				req->t_first = now;
			req->t_req = now;
			return (HTC_S_COMPLETE);
		}
		if (when < now)
			return (HTC_S_TIMEOUT);
		if (hs == HTC_S_MORE) {
			/* Working on it */
			if (isnan(req->t_first))
				req->t_first = now;
			tmo = when - now;
			continue;
		}
		assert(hs == HTC_S_EMPTY);
		/* Nothing but whitespace */
		tmo = sp->t_idle + cache_param->timeout_linger - now;
		if (tmo < 0)
			return (HTC_S_IDLE);
	}
}
int
V1F_FetchRespHdr(struct busyobj *bo)
{

	struct http *hp;
	enum htc_status_e hs;
	int first;
	struct http_conn *htc;

	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC);

	htc = bo->htc;

	VSC_C_main->backend_req++;

	/* Receive response */

	SES_RxInit(htc, bo->ws, cache_param->http_resp_size,
	    cache_param->http_resp_hdr_len);
	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);

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

	first = 1;
	do {
		hs = SES_Rx(htc, 0);
		if (hs == HTC_S_MORE)
			hs = HTTP1_Complete(htc);
		if (hs == HTC_S_OVERFLOW) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			bo->acct.beresp_hdrbytes +=
			    htc->rxbuf_e - htc->rxbuf_b;
			VSLb(bo->vsl, SLT_FetchError,
			    "http %sread error: overflow",
			    first ? "first " : "");
			htc->doclose = SC_RX_OVERFLOW;
			return (-1);
		}
		if (hs == HTC_S_EOF) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			bo->acct.beresp_hdrbytes +=
			    htc->rxbuf_e - htc->rxbuf_b;
			VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF",
			    first ? "first " : "");
			htc->doclose = SC_RX_TIMEOUT;
			return (first ? 1 : -1);
		}
		if (first) {
			first = 0;
			VTCP_set_read_timeout(htc->fd,
			    htc->between_bytes_timeout);
		}
	} while (hs != HTC_S_COMPLETE);
	bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b;

	hp = bo->beresp;

	if (HTTP1_DissectResponse(hp, htc)) {
		VSLb(bo->vsl, SLT_FetchError, "http format error");
		htc->doclose = SC_RX_JUNK;
		return (-1);
	}

	htc->doclose = http_DoConnection(hp);

	return (0);
}