Beispiel #1
0
static enum sess_close
vbe_dir_http1pipe(const struct director *d, struct req *req, struct busyobj *bo)
{
	int i;
	enum sess_close retval;
	struct backend *bp;
	struct v1p_acct v1a;
	struct vbc *vbc;

	CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	CAST_OBJ_NOTNULL(bp, d->priv, BACKEND_MAGIC);

	memset(&v1a, 0, sizeof v1a);

	/* This is hackish... */
	v1a.req = req->acct.req_hdrbytes;
	req->acct.req_hdrbytes = 0;

	req->res_mode = RES_PIPE;

	vbc = vbe_dir_getfd(req->wrk, bp, bo);

	if (vbc == NULL) {
		VSLb(bo->vsl, SLT_FetchError, "no backend connection");
		retval = SC_TX_ERROR;
	} else {
		i = V1F_SendReq(req->wrk, bo, &v1a.bereq, 1);
		VSLb_ts_req(req, "Pipe", W_TIM_real(req->wrk));
		if (vbc->state == VBC_STATE_STOLEN)
			VBT_Wait(req->wrk, vbc);
		if (i == 0)
			V1P_Process(req, vbc->fd, &v1a);
		VSLb_ts_req(req, "PipeSess", W_TIM_real(req->wrk));
		bo->htc->doclose = SC_TX_PIPE;
		vbe_dir_finish(d, req->wrk, bo);
		retval = SC_TX_PIPE;
	}
	V1P_Charge(req, &v1a, bp->vsc);
	return (retval);
}
Beispiel #2
0
vbe_dir_gethdrs(const struct director *d, struct worker *wrk,
    struct busyobj *bo)
{
	int i, extrachance = 1;
	struct backend *bp;
	struct vbc *vbc;

	CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	CAST_OBJ_NOTNULL(bp, d->priv, BACKEND_MAGIC);

	/*
	 * 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 (!http_GetHdr(bo->bereq, H_Host, NULL) && bp->hosthdr != NULL)
		http_PrintfHeader(bo->bereq, "Host: %s", bp->hosthdr);

	do {
		vbc = vbe_dir_getfd(wrk, bp, bo);
		if (vbc == NULL) {
			VSLb(bo->vsl, SLT_FetchError, "no backend connection");
			return (-1);
		}
		AN(bo->htc);
		if (vbc->state != VBC_STATE_STOLEN)
			extrachance = 0;

		i = V1F_SendReq(wrk, bo, &bo->acct.bereq_hdrbytes, 0);

		if (vbc->state != VBC_STATE_USED)
			VBT_Wait(wrk, vbc);

		assert(vbc->state == VBC_STATE_USED);

		if (i == 0)
			i = V1F_FetchRespHdr(bo);
		if (i == 0) {
			AN(bo->htc->priv);
			return (0);
		}

		/*
		 * If we recycled a backend connection, there is a finite chance
		 * that the backend closed it before we got the bereq to it.
		 * In that case do a single automatic retry if req.body allows.
		 */
		vbe_dir_finish(d, wrk, bo);
		AZ(bo->htc);
		if (i < 0)
			break;
		if (bo->req != NULL &&
		    bo->req->req_body_status != REQ_BODY_NONE &&
		    bo->req->req_body_status != REQ_BODY_CACHED)
			break;
		VSC_C_main->backend_retry++;
	} while (extrachance);
	return (-1);
}