int V1F_FetchRespHdr(struct busyobj *bo) { struct http *hp; int i; double t; struct http_conn *htc; enum htc_status_e hs; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC); htc = bo->htc; assert(*htc->rfd > 0); VSC_C_main->backend_req++; /* Receive response */ HTC_RxInit(htc, bo->ws); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); t = VTIM_real() + htc->first_byte_timeout; hs = HTC_RxStuff(htc, HTTP1_Complete, NULL, NULL, t, t + htc->between_bytes_timeout, cache_param->http_resp_size); if (hs != HTC_S_COMPLETE) { bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b; switch (hs) { case HTC_S_JUNK: VSLb(bo->vsl, SLT_FetchError, "Received junk"); htc->doclose = SC_RX_JUNK; break; case HTC_S_CLOSE: VSLb(bo->vsl, SLT_FetchError, "backend closed"); htc->doclose = SC_RESP_CLOSE; break; case HTC_S_TIMEOUT: VSLb(bo->vsl, SLT_FetchError, "timeout"); htc->doclose = SC_RX_TIMEOUT; break; case HTC_S_OVERFLOW: VSLb(bo->vsl, SLT_FetchError, "overflow"); htc->doclose = SC_RX_OVERFLOW; break; default: VSLb(bo->vsl, SLT_FetchError, "HTC %s (%d)", HTC_Status(hs), hs); htc->doclose = SC_RX_BAD; break; } return (htc->rxbuf_e == htc->rxbuf_b ? 1 : -1); } VTCP_set_read_timeout(*htc->rfd, htc->between_bytes_timeout); hp = bo->beresp; i = HTTP1_DissectResponse(htc, hp, bo->bereq); bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b; if (i) { VSLb(bo->vsl, SLT_FetchError, "http format error"); htc->doclose = SC_RX_JUNK; return (-1); } htc->doclose = http_DoConnection(hp); RFC2616_Response_Body(bo->wrk, bo); assert(bo->vfc->resp == bo->beresp); if (bo->htc->body_status != BS_NONE && bo->htc->body_status != BS_ERROR) if (V1F_Setup_Fetch(bo->vfc, bo->htc)) { VSLb(bo->vsl, SLT_FetchError, "overflow"); htc->doclose = SC_RX_OVERFLOW; return (-1); } return (0); }
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); }
int V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req) { struct vbc *vc; struct http *hp; enum htc_status_e hs; int retry = -1; int i, first; struct http_conn *htc; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_ORNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); htc = &bo->htc; AN(bo->director); hp = bo->bereq; bo->vbc = VDI_GetFd(NULL, bo); if (bo->vbc == NULL) { VSLb(bo->vsl, SLT_FetchError, "no backend connection"); return (-1); } vc = bo->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 (!http_GetHdr(bo->bereq, H_Host, NULL)) VDI_AddHostHeader(bo->bereq, vc); (void)VTCP_blocking(vc->fd); /* XXX: we should timeout instead */ WRW_Reserve(wrk, &vc->fd, bo->vsl, bo->t_fetch); bo->t_send = VTIM_mono(); (void)HTTP1_Write(wrk, hp, 0); /* XXX: stats ? */ /* Deal with any message-body the request might (still) have */ i = 0; if (req != NULL) { i = HTTP1_IterateReqBody(req, vbf_iter_req_body, wrk); if (req->req_body_status == REQ_BODY_DONE) retry = -1; if (req->req_body_status == REQ_BODY_FAIL) { VSLb(bo->vsl, SLT_FetchError, "req.body read error: %d (%s)", errno, strerror(errno)); req->doclose = SC_RX_BODY; retry = -1; } } if (WRW_FlushRelease(wrk) || i != 0) { VSLb(bo->vsl, SLT_FetchError, "backend write error: %d (%s)", errno, strerror(errno)); VDI_CloseFd(&bo->vbc); /* XXX: other cleanup ? */ return (retry); } VSC_C_main->backend_req++; bo->t_sent = VTIM_mono(); /* Receive response */ HTTP1_Init(htc, bo->ws, vc->fd, vc->vsl, cache_param->http_resp_size, cache_param->http_resp_hdr_len); VTCP_set_read_timeout(vc->fd, vc->first_byte_timeout); first = 1; do { hs = HTTP1_Rx(htc); if (hs == HTTP1_OVERFLOW) { VSLb(bo->vsl, SLT_FetchError, "http %sread error: overflow", first ? "first " : ""); VDI_CloseFd(&bo->vbc); /* XXX: other cleanup ? */ return (-1); } if (hs == HTTP1_ERROR_EOF) { VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF", first ? "first " : ""); VDI_CloseFd(&bo->vbc); /* XXX: other cleanup ? */ return (retry); } if (first) { retry = -1; first = 0; VTCP_set_read_timeout(vc->fd, vc->between_bytes_timeout); } } while (hs != HTTP1_COMPLETE); bo->t_hdr = VTIM_mono(); hp = bo->beresp; if (HTTP1_DissectResponse(hp, htc)) { VSLb(bo->vsl, SLT_FetchError, "http format error"); VDI_CloseFd(&bo->vbc); /* XXX: other cleanup ? */ return (-1); } return (0); }
int V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host) { struct http *hp; enum http1_status_e hs; int retry = 1; int j, first; ssize_t i; struct http_conn *htc; int do_chunked = 0; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC); htc = bo->htc; hp = bo->bereq; /* * 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) && def_host != NULL) http_PrintfHeader(hp, "Host: %s", def_host); if (bo->req != NULL && bo->req->req_body_status == REQ_BODY_WITHOUT_LEN) { http_PrintfHeader(hp, "Transfer-Encoding: chunked"); do_chunked = 1; } (void)VTCP_blocking(htc->fd); /* XXX: we should timeout instead */ V1L_Reserve(wrk, wrk->aws, &htc->fd, bo->vsl, bo->t_prev); bo->acct.bereq_hdrbytes = HTTP1_Write(wrk, hp, HTTP1_Req); /* Deal with any message-body the request might (still) have */ i = 0; if (bo->req != NULL) { if (do_chunked) V1L_Chunked(wrk); i = VRB_Iterate(bo->req, vbf_iter_req_body, bo); if (bo->req->req_body_status == REQ_BODY_TAKEN) { retry = -1; } else if (bo->req->req_body_status == REQ_BODY_FAIL) { VSLb(bo->vsl, SLT_FetchError, "req.body read error: %d (%s)", errno, strerror(errno)); bo->req->doclose = SC_RX_BODY; retry = -1; } if (do_chunked) V1L_EndChunk(wrk); } j = V1L_FlushRelease(wrk); if (j != 0 || i < 0) { VSLb(bo->vsl, SLT_FetchError, "backend write error: %d (%s)", errno, strerror(errno)); VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk)); bo->doclose = SC_TX_ERROR; return (retry); } VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk)); VSC_C_main->backend_req++; /* Receive response */ HTTP1_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 = HTTP1_Rx(htc); if (hs == HTTP1_OVERFLOW) { bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b; VSLb(bo->vsl, SLT_FetchError, "http %sread error: overflow", first ? "first " : ""); bo->doclose = SC_RX_OVERFLOW; return (-1); } if (hs == HTTP1_ERROR_EOF) { bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b; VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF", first ? "first " : ""); bo->doclose = SC_RX_TIMEOUT; return (retry); } if (first) { retry = -1; first = 0; VTCP_set_read_timeout(htc->fd, htc->between_bytes_timeout); } } while (hs != HTTP1_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"); bo->doclose = SC_RX_JUNK; return (-1); } bo->doclose = http_DoConnection(hp); return (0); }