Пример #1
0
static ssize_t
vrb_pull(struct req *req, ssize_t maxsize, objiterate_f *func, void *priv)
{
	ssize_t l, r = 0, yet;
	struct vfp_ctx *vfc;
	uint8_t *ptr;
	enum vfp_status vfps = VFP_ERROR;

	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);

	CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(req->htc->vfc, VFP_CTX_MAGIC);
	vfc = req->htc->vfc;

	req->body_oc = HSH_Private(req->wrk);
	AN(req->body_oc);
	XXXAN(STV_NewObject(req->wrk, req->body_oc, TRANSIENT_STORAGE, 8));

	vfc->oc = req->body_oc;

	if (VFP_Open(vfc) < 0) {
		req->req_body_status = REQ_BODY_FAIL;
		HSH_DerefBoc(req->wrk, req->body_oc);
		AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
		return (-1);
	}

	AZ(req->req_bodybytes);
	AN(req->htc);
	yet = req->htc->content_length;
	if (yet < 0)
		yet = 0;
	do {
		AZ(vfc->failed);
		if (maxsize >= 0 && req->req_bodybytes > maxsize) {
			(void)VFP_Error(vfc, "Request body too big to cache");
			break;
		}
		l = yet;
		if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK)
			break;
		AZ(vfc->failed);
		AN(ptr);
		AN(l);
		vfps = VFP_Suck(vfc, ptr, &l);
		if (l > 0 && vfps != VFP_ERROR) {
			req->req_bodybytes += l;
			req->acct.req_bodybytes += l;
			if (yet >= l)
				yet -= l;
			if (func != NULL) {
				r = func(priv, 1, ptr, l);
				if (r)
					break;
			} else {
				ObjExtend(req->wrk, req->body_oc, l);
			}
		}

	} while (vfps == VFP_OK);
	VFP_Close(vfc);
	VSLb_ts_req(req, "ReqBody", VTIM_real());
	if (func != NULL) {
		HSH_DerefBoc(req->wrk, req->body_oc);
		AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
		if (vfps != VFP_END) {
			req->req_body_status = REQ_BODY_FAIL;
			if (r == 0)
				r = -1;
		}
		return (r);
	}

	ObjTrimStore(req->wrk, req->body_oc);
	AZ(ObjSetU64(req->wrk, req->body_oc, OA_LEN, req->req_bodybytes));
	HSH_DerefBoc(req->wrk, req->body_oc);

	if (vfps != VFP_END) {
		req->req_body_status = REQ_BODY_FAIL;
		AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
		return (-1);
	}

	assert(req->req_bodybytes >= 0);
	if (req->req_bodybytes != req->htc->content_length) {
		/* We must update also the "pristine" req.* copy */
		http_Unset(req->http0, H_Content_Length);
		http_Unset(req->http0, H_Transfer_Encoding);
		http_PrintfHeader(req->http0, "Content-Length: %ju",
		    (uintmax_t)req->req_bodybytes);

		http_Unset(req->http, H_Content_Length);
		http_Unset(req->http, H_Transfer_Encoding);
		http_PrintfHeader(req->http, "Content-Length: %ju",
		    (uintmax_t)req->req_bodybytes);
	}

	req->req_body_status = REQ_BODY_CACHED;
	return (req->req_bodybytes);
}
Пример #2
0
static enum req_fsm_nxt
cnt_synth(struct worker *wrk, struct req *req)
{
	struct http *h;
	double now;
	struct vsb *synth_body;
	ssize_t sz, szl;
	uint8_t *ptr;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);

	wrk->stats->s_synth++;

	now = W_TIM_real(wrk);
	VSLb_ts_req(req, "Process", now);

	if (req->err_code < 100 || req->err_code > 999)
		req->err_code = 501;

	HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
	h = req->resp;
	http_TimeHeader(h, "Date: ", now);
	http_SetHeader(h, "Server: Varnish");
	http_PrintfHeader(req->resp, "X-Varnish: %u", VXID(req->vsl->wid));
	http_PutResponse(h, "HTTP/1.1", req->err_code, req->err_reason);

	synth_body = VSB_new_auto();
	AN(synth_body);

	VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);

	AZ(VSB_finish(synth_body));

	http_Unset(h, H_Content_Length);
	http_PrintfHeader(req->resp, "Content-Length: %zd",
	    VSB_len(synth_body));

	/* Discard any lingering request body before delivery */
	(void)VRB_Ignore(req);

	if (wrk->handling == VCL_RET_RESTART) {
		HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
		VSB_destroy(&synth_body);
		req->req_step = R_STP_RESTART;
		return (REQ_FSM_MORE);
	}
	assert(wrk->handling == VCL_RET_DELIVER);

	req->objcore = HSH_Private(wrk);
	CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
	szl = -1;
	if (STV_NewObject(wrk, req->objcore, TRANSIENT_STORAGE, 1024)) {
		szl = VSB_len(synth_body);
		assert(szl >= 0);
		sz = szl;
		if (sz > 0 &&
		    ObjGetSpace(wrk, req->objcore, &sz, &ptr) && sz >= szl) {
			memcpy(ptr, VSB_data(synth_body), szl);
			ObjExtend(wrk, req->objcore, szl);
		} else if (sz > 0) {
			szl = -1;
		}
	}

	if (szl >= 0)
		AZ(ObjSetU64(wrk, req->objcore, OA_LEN, szl));
	HSH_DerefBoc(wrk, req->objcore);
	VSB_destroy(&synth_body);

	if (szl < 0) {
		VSLb(req->vsl, SLT_Error, "Could not get storage");
		req->doclose = SC_OVERLOAD;
		VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
		(void)HSH_DerefObjCore(wrk, &req->objcore);
		http_Teardown(req->resp);
		return (REQ_FSM_DONE);
	}

	req->req_step = R_STP_TRANSMIT;
	return (REQ_FSM_MORE);
}
Пример #3
0
ssize_t
VRB_Cache(struct req *req, ssize_t maxsize)
{
	ssize_t l, yet;
	struct vfp_ctx *vfc;
	uint8_t *ptr;
	enum vfp_status vfps = VFP_ERROR;

	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);

	assert (req->req_step == R_STP_RECV);
	switch(req->req_body_status) {
	case REQ_BODY_CACHED:
		return (req->req_bodybytes);
	case REQ_BODY_FAIL:
		return (-1);
	case REQ_BODY_NONE:
		return (0);
	case REQ_BODY_WITHOUT_LEN:
	case REQ_BODY_WITH_LEN:
		break;
	default:
		WRONG("Wrong req_body_status in VRB_Cache()");
	}

	CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC);
	vfc = req->htc->vfc;
	VFP_Setup(vfc);
	vfc->wrk = req->wrk;

	if (req->htc->content_length > maxsize) {
		req->req_body_status = REQ_BODY_FAIL;
		(void)VFP_Error(vfc, "Request body too big to cache");
		return (-1);
	}

	req->body_oc = HSH_Private(req->wrk);
	AN(req->body_oc);
	XXXAN(STV_NewObject(req->wrk, req->body_oc, TRANSIENT_STORAGE, 8));

	vfc->http = req->http;
	vfc->oc = req->body_oc;
	V1F_Setup_Fetch(vfc, req->htc);

	if (VFP_Open(vfc) < 0) {
		req->req_body_status = REQ_BODY_FAIL;
		return (-1);
	}

	AZ(req->req_bodybytes);
	AN(req->htc);
	yet = req->htc->content_length;
	if (yet < 0)
		yet = 0;
	do {
		AZ(vfc->failed);
		if (req->req_bodybytes > maxsize) {
			req->req_body_status = REQ_BODY_FAIL;
			(void)VFP_Error(vfc, "Request body too big to cache");
			VFP_Close(vfc);
			return(-1);
		}
		l = yet;
		if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK)
			break;
		AZ(vfc->failed);
		AN(ptr);
		AN(l);
		vfps = VFP_Suck(vfc, ptr, &l);
		if (l > 0 && vfps != VFP_ERROR) {
			req->req_bodybytes += l;
			req->acct.req_bodybytes += l;
			if (yet >= l)
				yet -= l;
			ObjExtend(req->wrk, req->body_oc, l);
		}

	} while (vfps == VFP_OK);
	VFP_Close(vfc);
	ObjTrimStore(req->wrk, req->body_oc);

	/* XXX: check missing:
	    if (req->htc->content_length >= 0)
		MUSTBE (req->req_bodybytes == req->htc->content_length);
	*/

	if (vfps == VFP_END) {
		assert(req->req_bodybytes >= 0);
		if (req->req_bodybytes != req->htc->content_length) {
			/* We must update also the "pristine" req.* copy */
			http_Unset(req->http0, H_Content_Length);
			http_Unset(req->http0, H_Transfer_Encoding);
			http_PrintfHeader(req->http0, "Content-Length: %ju",
			    (uintmax_t)req->req_bodybytes);

			http_Unset(req->http, H_Content_Length);
			http_Unset(req->http, H_Transfer_Encoding);
			http_PrintfHeader(req->http, "Content-Length: %ju",
			    (uintmax_t)req->req_bodybytes);
		}

		req->req_body_status = REQ_BODY_CACHED;
	} else {
		req->req_body_status = REQ_BODY_FAIL;
	}
	VSLb_ts_req(req, "ReqBody", VTIM_real());
	return (vfps == VFP_END ? req->req_bodybytes : -1);
}