int FetchBody(struct worker *wrk, struct object *obj) { int cls; struct storage *st; int mklen; ssize_t cl; struct http_conn *htc; struct busyobj *bo; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); bo = wrk->busyobj; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AZ(bo->fetch_obj); CHECK_OBJ_NOTNULL(bo->vbc, VBC_MAGIC); CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(obj->http, HTTP_MAGIC); htc = &bo->htc; if (bo->vfp == NULL) bo->vfp = &vfp_nop; AssertObjCorePassOrBusy(obj->objcore); AZ(bo->vgz_rx); AZ(VTAILQ_FIRST(&obj->store)); bo->fetch_obj = obj; bo->fetch_failed = 0; /* XXX: pick up estimate from objdr ? */ cl = 0; switch (bo->body_status) { case BS_NONE: cls = 0; mklen = 0; break; case BS_ZERO: cls = 0; mklen = 1; break; case BS_LENGTH: cl = fetch_number(bo->h_content_length, 10); bo->vfp->begin(wrk, cl > 0 ? cl : 0); cls = fetch_straight(wrk, htc, cl); mklen = 1; if (bo->vfp->end(wrk)) cls = -1; break; case BS_CHUNKED: bo->vfp->begin(wrk, cl); cls = fetch_chunked(wrk, htc); mklen = 1; if (bo->vfp->end(wrk)) cls = -1; break; case BS_EOF: bo->vfp->begin(wrk, cl); cls = fetch_eof(wrk, htc); mklen = 1; if (bo->vfp->end(wrk)) cls = -1; break; case BS_ERROR: cls = 1; mklen = 0; break; default: cls = 0; mklen = 0; INCOMPL(); } AZ(bo->vgz_rx); /* * It is OK for ->end to just leave the last storage segment * sitting on wrk->storage, we will always call vfp_nop_end() * to get it trimmed or thrown out if empty. */ AZ(vfp_nop_end(wrk)); bo->fetch_obj = NULL; WSLB(wrk, SLT_Fetch_Body, "%u(%s) cls %d mklen %d", bo->body_status, body_status(bo->body_status), cls, mklen); if (bo->body_status == BS_ERROR) { VDI_CloseFd(wrk, &bo->vbc); return (__LINE__); } if (cls < 0) { wrk->stats.fetch_failed++; /* XXX: Wouldn't this store automatically be released ? */ while (!VTAILQ_EMPTY(&obj->store)) { st = VTAILQ_FIRST(&obj->store); VTAILQ_REMOVE(&obj->store, st, list); STV_free(st); } VDI_CloseFd(wrk, &bo->vbc); obj->len = 0; return (__LINE__); } AZ(bo->fetch_failed); if (cls == 0 && bo->should_close) cls = 1; WSLB(wrk, SLT_Length, "%zd", obj->len); { /* Sanity check fetch methods accounting */ ssize_t uu; uu = 0; VTAILQ_FOREACH(st, &obj->store, list) uu += st->len; if (bo->do_stream) /* Streaming might have started freeing stuff */ assert (uu <= obj->len); else assert(uu == obj->len); } if (mklen > 0) { http_Unset(obj->http, H_Content_Length); http_PrintfHeader(wrk, bo->vbc->vsl_id, obj->http, "Content-Length: %zd", obj->len); } if (cls) VDI_CloseFd(wrk, &bo->vbc); else VDI_RecycleFd(wrk, &bo->vbc); return (0); }
int FetchBody(struct sess *sp) { int cls; struct storage *st; struct worker *w; int mklen; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); w = sp->wrk; CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(sp->obj->http, HTTP_MAGIC); if (w->vfp == NULL) w->vfp = &vfp_nop; AN(sp->director); AssertObjCorePassOrBusy(sp->obj->objcore); AZ(w->vgz_rx); AZ(VTAILQ_FIRST(&sp->obj->store)); switch (w->body_status) { case BS_NONE: cls = 0; mklen = 0; break; case BS_ZERO: cls = 0; mklen = 1; break; case BS_LENGTH: cls = fetch_straight(sp, w->htc, w->h_content_length); mklen = 1; XXXAZ(w->vfp->end(sp)); break; case BS_CHUNKED: cls = fetch_chunked(sp, w->htc); mklen = 1; XXXAZ(w->vfp->end(sp)); break; case BS_EOF: cls = fetch_eof(sp, w->htc); mklen = 1; XXXAZ(w->vfp->end(sp)); break; case BS_ERROR: cls = 1; mklen = 0; break; default: cls = 0; mklen = 0; INCOMPL(); } AZ(w->vgz_rx); /* * It is OK for ->end to just leave the last storage segment * sitting on w->storage, we will always call vfp_nop_end() * to get it trimmed or thrown out if empty. */ AZ(vfp_nop_end(sp)); WSL(w, SLT_Fetch_Body, sp->vbc->vsl_id, "%u(%s) cls %d mklen %u", w->body_status, body_status(w->body_status), cls, mklen); if (w->body_status == BS_ERROR) { VDI_CloseFd(sp); return (__LINE__); } if (cls < 0) { w->stats.fetch_failed++; /* XXX: Wouldn't this store automatically be released ? */ while (!VTAILQ_EMPTY(&sp->obj->store)) { st = VTAILQ_FIRST(&sp->obj->store); VTAILQ_REMOVE(&sp->obj->store, st, list); STV_free(st); } VDI_CloseFd(sp); sp->obj->len = 0; return (__LINE__); } if (cls == 0 && w->do_close) cls = 1; WSL(w, SLT_Length, sp->vbc->vsl_id, "%u", sp->obj->len); { /* Sanity check fetch methods accounting */ ssize_t uu; uu = 0; VTAILQ_FOREACH(st, &sp->obj->store, list) uu += st->len; if (sp->objcore == NULL || (sp->objcore->flags & OC_F_PASS)) /* Streaming might have started freeing stuff */ assert (uu <= sp->obj->len); else assert(uu == sp->obj->len); } if (mklen > 0) { http_Unset(sp->obj->http, H_Content_Length); http_PrintfHeader(w, sp->vsl_id, sp->obj->http, "Content-Length: %jd", (intmax_t)sp->obj->len); } if (cls) VDI_CloseFd(sp); else VDI_RecycleFd(sp); return (0); }