[master] 2899bb9 And now the going gets ugly: Add code to include a non-gzip'ed ESI-object in a gzip'ed ESI object.

Poul-Henning Kamp phk at project.varnish-software.com
Sat Jan 22 14:55:41 CET 2011


commit 2899bb924ddd4fa45c1b7235a6439acef7abffdf
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Sat Jan 22 13:41:41 2011 +0000

    And now the going gets ugly:  Add code to include a non-gzip'ed ESI-object
    in a gzip'ed ESI object.

diff --git a/bin/varnishd/cache_esi_deliver.c b/bin/varnishd/cache_esi_deliver.c
index e5209e3..ca581f8 100644
--- a/bin/varnishd/cache_esi_deliver.c
+++ b/bin/varnishd/cache_esi_deliver.c
@@ -168,6 +168,57 @@ ved_decode_len(uint8_t **pp)
 	return (l);
 }
 
+/*---------------------------------------------------------------------
+ * If a gzip'ed ESI object includes a ungzip'ed object, we need to make
+ * it looked like a gzip'ed data stream.  The official way to do so would
+ * be to fire up libvgz and gzip it, but we don't, we fake it.
+ *
+ * First, we cannot know if it is ungzip'ed on purpose, the admin may
+ * know something we don't.
+ *
+ * What do you mean "BS ?"
+ *
+ * All right then...
+ *
+ * The matter of the fact is that we simply will not fire up a gzip in
+ * the output path because it costs too much memory and CPU, so we simply
+ * wrap the data in very convenient "gzip copy-blocks" and send it down
+ * the stream with a bit more overhead.
+ */
+
+static void
+ved_pretend_gzip(struct sess *sp, uint8_t *p, ssize_t l)
+{
+	ssize_t ll;
+	uint8_t buf[5];
+	char chunk[20];
+
+	while (l > 0) {
+		ll = l;
+		if (ll > 65535)
+			ll = 65535;
+		buf[0] = 0;
+		vle16enc(buf + 1, ll);
+		vle16enc(buf + 3, ~ll);
+		if (sp->wrk->res_mode & RES_CHUNKED) {
+			bprintf(chunk, "%jx\r\n", (intmax_t)ll + 5);
+			(void)WRW_Write(sp->wrk, chunk, -1);
+		}
+		(void)WRW_Write(sp->wrk, buf, sizeof buf);
+		(void)WRW_Write(sp->wrk, p, ll);
+		if (sp->wrk->res_mode & RES_CHUNKED) 
+			(void)WRW_Write(sp->wrk, "\r\n", -1);
+		(void)WRW_Flush(sp->wrk);
+		sp->wrk->crc = crc32(sp->wrk->crc, p, ll);
+		sp->wrk->l_crc += ll;
+		l -= ll;
+		p += ll;
+	}
+}
+
+/*---------------------------------------------------------------------
+ */
+
 void
 ESI_Deliver(struct sess *sp)
 {
@@ -177,6 +228,7 @@ ESI_Deliver(struct sess *sp)
 	ssize_t l, l_icrc;
 	uint32_t icrc;
 	uint8_t tailbuf[8 + 5];
+	int isgzip;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 	st = sp->obj->esidata;
@@ -184,9 +236,15 @@ ESI_Deliver(struct sess *sp)
 	p = st->ptr;
 	e = st->ptr + st->len;
 
+	if (*p == VEC_GZ) {
+		isgzip = 1;
+		p++;
+	} else {
+		isgzip = 0;
+	}
+
 	if (sp->esi_level == 0) {
-		if (*p == VEC_GZ) {
-			p++;	
+		if (isgzip) {
 			sp->wrk->gzip_resp = 1;
 			sp->wrk->crc = crc32(0L, Z_NULL, 0);
 		} else 
@@ -202,21 +260,36 @@ ESI_Deliver(struct sess *sp)
 		case VEC_V2:
 		case VEC_V8:
 			l = ved_decode_len(&p);
-			if (sp->wrk->gzip_resp) {
-				assert(*p == VEC_C1 || *p == VEC_C2 ||
-				    *p == VEC_C8);
-				l_icrc = ved_decode_len(&p);
-				icrc = vbe32dec(p);
-				p += 4;
-				sp->wrk->crc =
-				    crc32_combine(sp->wrk->crc, icrc, l_icrc);
-				sp->wrk->l_crc += l_icrc;
-			}
+			r = p;
 			q = (void*)strchr((const char*)p, '\0');
-			assert (q > p);
-			ved_sendchunk(sp, p, q - p, st->ptr + off, l);
-			off += l;
 			p = q + 1;
+			if (sp->wrk->gzip_resp) {
+				if (isgzip) {
+					assert(*p == VEC_C1 || *p == VEC_C2 ||
+					    *p == VEC_C8);
+					l_icrc = ved_decode_len(&p);
+					icrc = vbe32dec(p);
+					p += 4;
+					sp->wrk->crc = crc32_combine(
+					    sp->wrk->crc, icrc, l_icrc);
+					sp->wrk->l_crc += l_icrc;
+					ved_sendchunk(sp, r, q - r,
+					    st->ptr + off, l);
+					off += l;
+				} else {
+					ved_pretend_gzip(sp,
+					    st->ptr + off, l);
+					off += l;
+				}
+			} else {
+				if (isgzip) {
+					INCOMPL();
+				} else {
+					ved_sendchunk(sp, r, q - r,
+					    st->ptr + off, l);
+					off += l;
+				}
+			}
 			break;
 		case VEC_S1:
 		case VEC_S2:
diff --git a/bin/varnishd/cache_esi_parse.c b/bin/varnishd/cache_esi_parse.c
index 93522d2..6baeb13 100644
--- a/bin/varnishd/cache_esi_parse.c
+++ b/bin/varnishd/cache_esi_parse.c
@@ -286,13 +286,13 @@ vep_emit_verbatim(const struct vep_state *vep, ssize_t l, ssize_t l_crc)
 		Debug("---> VERBATIM(%jd)\n", (intmax_t)l);
 	}
 	vep_emit_len(vep, l, VEC_V1, VEC_V2, VEC_V8);
+	/* Emit Chunked header */
+	vsb_printf(vep->vsb, "%lx\r\n%c", l, 0);
 	if (vep->dogzip) {
 		vep_emit_len(vep, l_crc, VEC_C1, VEC_C2, VEC_C8);
 		vbe32enc(buf, vep->crc);
 		vsb_bcat(vep->vsb, buf, sizeof buf);
 	}
-	/* Emit Chunked header */
-	vsb_printf(vep->vsb, "%lx\r\n%c", l, 0);
 } 
 
 static void



More information about the varnish-commit mailing list