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); }
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); }