예제 #1
0
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);
}
예제 #2
0
/*
 * 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);
}
예제 #3
0
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);
	}
}
예제 #4
0
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);
}