static unsigned VRY_Validate(const uint8_t *vary) { unsigned retval = 0; while (vary[2] != 0) { assert(strlen((const char*)vary+3) == vary[2]); retval += VRY_Len(vary); vary += VRY_Len(vary); } return (retval + 3); }
/* * Compare two vary entries */ static int vry_cmp(const uint8_t *v1, const uint8_t *v2) { unsigned retval = 0; if (!memcmp(v1, v2, VRY_Len(v1))) { /* Same same */ retval = 0; } else if (memcmp(v1 + 2, v2 + 2, v1[2] + 2)) { /* Different header */ retval = 1; } else if (cache_param->http_gzip_support && !strcasecmp(H_Accept_Encoding, (const char*) v1 + 2)) { /* * If we do gzip processing, we do not vary on Accept-Encoding, * because we want everybody to get the gzip'ed object, and * varnish will gunzip as necessary. We implement the skip at * check time, rather than create time, so that object in * persistent storage can be used with either setting of * http_gzip_support. */ retval = 0; } else { /* Same header, different content */ retval = 2; } return (retval); }
int VRY_Match(struct req *req, const uint8_t *vary) { uint8_t *vsp = req->vary_b; char *h, *e; unsigned lh, ln; int i, oflo = 0; AN(vsp); while (vary[2]) { if (vsp + 2 >= req->vary_e) { /* * Too little workspace to find out */ oflo = 1; break; } i = vry_cmp(vary, vsp); if (i == 1) { /* * Different header, build a new entry, * then compare again with that new entry. */ ln = 2 + vary[2] + 2; i = http_GetHdr(req->http, (const char*)(vary+2), &h); if (i) { /* Trim trailing space */ e = strchr(h, '\0'); while (e > h && vct_issp(e[-1])) e--; lh = e - h; assert(lh < 0xffff); ln += lh; } else { e = h = NULL; lh = 0xffff; } if (vsp + ln + 2 >= req->vary_e) { /* * Not enough space to build new entry * and put terminator behind it. */ oflo = 1; break; } vbe16enc(vsp, (uint16_t)lh); memcpy(vsp + 2, vary + 2, vary[2] + 2); if (h != NULL) memcpy(vsp + 2 + vsp[2] + 2, h, lh); vsp[ln + 0] = 0xff; vsp[ln + 1] = 0xff; vsp[ln + 2] = 0; (void)VRY_Validate(vsp); req->vary_l = vsp + ln + 3; i = vry_cmp(vary, vsp); assert(i == 0 || i == 2); } if (i == 0) { /* Same header, same contents */ vsp += VRY_Len(vsp); vary += VRY_Len(vary); } else if (i == 2) { /* Same header, different contents, cannot match */ return (0); } } if (oflo) { vsp = req->vary_b; req->vary_l = NULL; if (vsp + 2 < req->vary_e) { vsp[0] = 0xff; vsp[1] = 0xff; vsp[2] = 0; } return (0); } else { return (1); } }
static enum fetch_step vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo) { unsigned l; uint16_t nhttp; struct object *obj; struct objiter *oi; void *sp; ssize_t sl, al, tl; struct storage *st; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); l = 0; if (bo->ims_obj->vary != NULL) l += VRY_Len(bo->ims_obj->vary); l += http_EstimateWS(bo->ims_obj->http, 0, &nhttp); bo->stats = &wrk->stats; obj = STV_NewObject(bo, bo->storage_hint, l, nhttp); if (obj == NULL) { (void)VFP_Error(bo, "Could not get storage"); VDI_CloseFd(&bo->vbc); return (F_STP_DONE); } bo->stats = NULL; AZ(bo->fetch_obj); bo->fetch_obj = obj; obj->gziped = bo->ims_obj->gziped; obj->gzip_start = bo->ims_obj->gzip_start; obj->gzip_last = bo->ims_obj->gzip_last; obj->gzip_stop = bo->ims_obj->gzip_stop; /* XXX: ESI */ if (bo->ims_obj->vary != NULL) obj->vary = (void *)WS_Copy(obj->http->ws, bo->ims_obj->vary, VRY_Len(bo->ims_obj->vary)); obj->vxid = bo->vsl->wid; obj->http->logtag = HTTP_Obj; /* XXX: we should have our own HTTP_A_CONDFETCH */ http_FilterResp(bo->ims_obj->http, obj->http, HTTPH_A_INS); http_CopyHome(obj->http); if (!(bo->fetch_obj->objcore->flags & OC_F_PRIVATE)) { EXP_Insert(obj); AN(obj->objcore->ban); } AZ(bo->ws_o->overflow); VBO_setstate(bo, BOS_FETCHING); HSH_Unbusy(&wrk->stats, obj->objcore); st = NULL; al = 0; oi = ObjIterBegin(wrk, bo->ims_obj); while (1 == ObjIter(oi, &sp, &sl)) { while (sl > 0) { if (st == NULL) { st = VFP_GetStorage(bo, bo->ims_obj->len - al); XXXAN(st); } tl = sl; if (tl > st->space - st->len) tl = st->space - st->len; memcpy(st->ptr + st->len, sp, tl); st->len += tl; al += tl; sp = (char *)sp + tl; sl -= tl; VBO_extend(bo, al); if (st->len == st->space) st = NULL; } } assert(al == bo->ims_obj->len); assert(obj->len == al); if (bo->state != BOS_FAILED) VBO_setstate(bo, BOS_FINISHED); HSH_Complete(obj->objcore); return (F_STP_DONE); }