enum htc_status_e HTTP1_Rx(struct http_conn *htc) { int i; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); AN(htc->ws->r); AZ(htc->pipeline.b); AZ(htc->pipeline.e); i = (htc->ws->r - htc->rxbuf.e) - 1; /* space for NUL */ if (i <= 0) { WS_ReleaseP(htc->ws, htc->rxbuf.b); return (HTTP1_OVERFLOW); } i = read(htc->fd, htc->rxbuf.e, i); if (i <= 0) { /* * We wouldn't come here if we had a complete HTTP header * so consequently an EOF can not be OK */ WS_ReleaseP(htc->ws, htc->rxbuf.b); return (HTTP1_ERROR_EOF); } htc->rxbuf.e += i; *htc->rxbuf.e = '\0'; return (HTTP1_Complete(htc)); }
enum htc_status_e HTTP1_Reinit(struct http_conn *htc) { unsigned l; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); (void)WS_Reserve(htc->ws, htc->maxbytes); htc->rxbuf.b = htc->ws->f; htc->rxbuf.e = htc->ws->f; if (htc->pipeline.b != NULL) { l = Tlen(htc->pipeline); memmove(htc->rxbuf.b, htc->pipeline.b, l); htc->rxbuf.e += l; htc->pipeline.b = NULL; htc->pipeline.e = NULL; } *htc->rxbuf.e = '\0'; return (HTTP1_Complete(htc)); }
enum http1_status_e HTTP1_Reinit(struct http_conn *htc) { ssize_t l; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); (void)WS_Reserve(htc->ws, htc->maxbytes); htc->rxbuf_b = htc->ws->f; htc->rxbuf_e = htc->ws->f; if (htc->pipeline_b != NULL) { l = htc->pipeline_e - htc->pipeline_b; assert(l > 0); memmove(htc->rxbuf_b, htc->pipeline_b, l); htc->rxbuf_e += l; htc->pipeline_b = NULL; htc->pipeline_e = NULL; } *htc->rxbuf_e = '\0'; return (HTTP1_Complete(htc)); }
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); }
static enum req_fsm_nxt http1_wait(struct sess *sp, struct worker *wrk, struct req *req) { int j, tmo; struct pollfd pfd[1]; double now, when; enum sess_close why = SC_NULL; enum http1_status_e hs; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); assert(req->sp == sp); AZ(req->vcl); AZ(req->esi_level); AZ(isnan(sp->t_idle)); assert(isnan(req->t_first)); assert(isnan(req->t_prev)); assert(isnan(req->t_req)); tmo = (int)(1e3 * cache_param->timeout_linger); while (1) { pfd[0].fd = sp->fd; pfd[0].events = POLLIN; pfd[0].revents = 0; j = poll(pfd, 1, tmo); assert(j >= 0); now = VTIM_real(); if (j != 0) hs = HTTP1_Rx(req->htc); else hs = HTTP1_Complete(req->htc); if (hs == HTTP1_COMPLETE) { /* Got it, run with it */ if (isnan(req->t_first)) req->t_first = now; if (isnan(req->t_req)) req->t_req = now; req->acct.req_hdrbytes += Tlen(req->htc->rxbuf); return (REQ_FSM_MORE); } else if (hs == HTTP1_ERROR_EOF) { why = SC_REM_CLOSE; break; } else if (hs == HTTP1_OVERFLOW) { why = SC_RX_OVERFLOW; break; } else if (hs == HTTP1_ALL_WHITESPACE) { /* Nothing but whitespace */ when = sp->t_idle + cache_param->timeout_idle; if (when < now) { why = SC_RX_TIMEOUT; break; } when = sp->t_idle + cache_param->timeout_linger; tmo = (int)(1e3 * (when - now)); if (when < now || tmo == 0) { wrk->stats->sess_herd++; SES_ReleaseReq(req); WAIT_Enter(sp); return (REQ_FSM_DONE); } } else { /* Working on it */ if (isnan(req->t_first)) /* Record first byte received time stamp */ req->t_first = now; when = sp->t_idle + cache_param->timeout_req; tmo = (int)(1e3 * (when - now)); if (when < now || tmo == 0) { why = SC_RX_TIMEOUT; break; } } } req->acct.req_hdrbytes += Tlen(req->htc->rxbuf); CNT_AcctLogCharge(wrk->stats, req); SES_ReleaseReq(req); assert(why != SC_NULL); SES_Delete(sp, why, now); return (REQ_FSM_DONE); }