static void * exp_timer(struct sess *sp, void *priv) { struct objcore *oc; struct object *o; double t; struct objcore_head *lru; (void)priv; AZ(sleep(10)); /* XXX: Takes time for VCL to arrive */ VCL_Get(&sp->vcl); t = TIM_real(); while (1) { Lck_Lock(&exp_mtx); oc = binheap_root(exp_heap); CHECK_OBJ_ORNULL(oc, OBJCORE_MAGIC); if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */ Lck_Unlock(&exp_mtx); WSL_Flush(sp->wrk, 0); WRK_SumStat(sp->wrk); AZ(sleep(1)); VCL_Refresh(&sp->vcl); t = TIM_real(); continue; } o = oc->obj; CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(o->objhead, OBJHEAD_MAGIC); assert(oc->flags & OC_F_ONLRU); assert(oc->timer_idx != BINHEAP_NOIDX); binheap_delete(exp_heap, oc->timer_idx); assert(oc->timer_idx == BINHEAP_NOIDX); lru = STV_lru(o->objstore); AN(lru); VTAILQ_REMOVE(lru, o->objcore, lru_list); oc->flags &= ~OC_F_ONLRU; { /* Sanity checking */ struct objcore *oc2 = binheap_root(exp_heap); if (oc2 != NULL) { assert(oc2->timer_idx != BINHEAP_NOIDX); assert(oc2->timer_when >= oc->timer_when); } } VSL_stats->n_expired++; Lck_Unlock(&exp_mtx); WSL(sp->wrk, SLT_ExpKill, 0, "%u %d", o->xid, (int)(o->ttl - t)); HSH_Deref(sp->wrk, &o); } }
static int cnt_start(struct sess *sp) { int done; char *p; const char *r = "HTTP/1.1 100 Continue\r\n\r\n"; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); AZ(sp->restarts); AZ(sp->obj); AZ(sp->vcl); /* Update stats of various sorts */ VSL_stats->client_req++; /* XXX not locked */ sp->t_req = TIM_real(); sp->wrk->lastused = sp->t_req; sp->acct_req.req++; /* Assign XID and log */ sp->xid = ++xids; /* XXX not locked */ WSP(sp, SLT_ReqStart, "%s %s %u", sp->addr, sp->port, sp->xid); /* Borrow VCL reference from worker thread */ VCL_Refresh(&sp->wrk->vcl); sp->vcl = sp->wrk->vcl; sp->wrk->vcl = NULL; http_Setup(sp->http, sp->ws); done = http_DissectRequest(sp); /* Catch request snapshot */ sp->ws_req = WS_Snapshot(sp->ws); /* Catch original request, before modification */ *sp->http0 = *sp->http; if (done != 0) { sp->err_code = done; sp->step = STP_ERROR; return (0); } sp->doclose = http_DoConnection(sp->http); /* XXX: Handle TRACE & OPTIONS of Max-Forwards = 0 */ /* * Handle Expect headers */ if (http_GetHdr(sp->http, H_Expect, &p)) { if (strcmp(p, "100-continue")) { sp->err_code = 417; sp->step = STP_ERROR; return (0); } /* XXX: Don't bother with write failures for now */ (void)write(sp->fd, r, strlen(r)); /* XXX: When we do ESI includes, this is not removed * XXX: because we use http0 as our basis. Believed * XXX: safe, but potentially confusing. */ http_Unset(sp->http, H_Expect); } sp->step = STP_RECV; return (0); }
static int http1_dissect(struct worker *wrk, struct req *req) { const char *r_100 = "HTTP/1.1 100 Continue\r\n\r\n"; const char *r_400 = "HTTP/1.1 400 Bad Request\r\n\r\n"; const char *r_417 = "HTTP/1.1 417 Expectation Failed\r\n\r\n"; const char *p; ssize_t r; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); /* Allocate a new vxid now that we know we'll need it. */ AZ(req->vsl->wid); req->vsl->wid = VXID_Get(wrk, VSL_CLIENTMARKER); VSLb(req->vsl, SLT_Begin, "req %u rxreq", VXID(req->sp->vxid)); VSL(SLT_Link, req->sp->vxid, "req %u rxreq", VXID(req->vsl->wid)); AZ(isnan(req->t_first)); /* First byte timestamp set by http1_wait */ AZ(isnan(req->t_req)); /* Complete req rcvd set by http1_wait */ req->t_prev = req->t_first; VSLb_ts_req(req, "Start", req->t_first); VSLb_ts_req(req, "Req", req->t_req); /* Borrow VCL reference from worker thread */ VCL_Refresh(&wrk->vcl); req->vcl = wrk->vcl; wrk->vcl = NULL; HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod); req->err_code = HTTP1_DissectRequest(req->htc, req->http); /* If we could not even parse the request, just close */ if (req->err_code != 0) { VSLb(req->vsl, SLT_HttpGarbage, "%.*s", (int)(req->htc->rxbuf_e - req->htc->rxbuf_b), req->htc->rxbuf_b); wrk->stats->client_req_400++; r = write(req->sp->fd, r_400, strlen(r_400)); if (r > 0) req->acct.resp_hdrbytes += r; req->doclose = SC_RX_JUNK; return (-1); } assert (req->req_body_status == REQ_BODY_INIT); if (req->htc->body_status == BS_CHUNKED) { req->req_body_status = REQ_BODY_WITHOUT_LEN; } else if (req->htc->body_status == BS_LENGTH) { req->req_body_status = REQ_BODY_WITH_LEN; } else if (req->htc->body_status == BS_NONE) { req->req_body_status = REQ_BODY_NONE; } else if (req->htc->body_status == BS_EOF) { req->req_body_status = REQ_BODY_WITHOUT_LEN; } else { WRONG("Unknown req.body_length situation"); } if (http_GetHdr(req->http, H_Expect, &p)) { if (strcasecmp(p, "100-continue")) { wrk->stats->client_req_417++; req->err_code = 417; r = write(req->sp->fd, r_417, strlen(r_417)); if (r > 0) req->acct.resp_hdrbytes += r; req->doclose = SC_RX_JUNK; return (-1); } r = write(req->sp->fd, r_100, strlen(r_100)); if (r > 0) req->acct.resp_hdrbytes += r; if (r != strlen(r_100)) { req->doclose = SC_REM_CLOSE; return (-1); } http_Unset(req->http, H_Expect); } wrk->stats->client_req++; wrk->stats->s_req++; AZ(req->err_code); req->ws_req = WS_Snapshot(req->ws); req->doclose = http_DoConnection(req->http); if (req->doclose == SC_RX_BAD) { r = write(req->sp->fd, r_400, strlen(r_400)); if (r > 0) req->acct.resp_hdrbytes += r; return (-1); } assert(req->req_body_status != REQ_BODY_INIT); HTTP_Copy(req->http0, req->http); // For ESI & restart return (0); }