Commit 2899bb92 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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

in a gzip'ed ESI object.
parent 49965920
...@@ -168,6 +168,57 @@ ved_decode_len(uint8_t **pp) ...@@ -168,6 +168,57 @@ ved_decode_len(uint8_t **pp)
return (l); 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 void
ESI_Deliver(struct sess *sp) ESI_Deliver(struct sess *sp)
{ {
...@@ -177,6 +228,7 @@ ESI_Deliver(struct sess *sp) ...@@ -177,6 +228,7 @@ ESI_Deliver(struct sess *sp)
ssize_t l, l_icrc; ssize_t l, l_icrc;
uint32_t icrc; uint32_t icrc;
uint8_t tailbuf[8 + 5]; uint8_t tailbuf[8 + 5];
int isgzip;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
st = sp->obj->esidata; st = sp->obj->esidata;
...@@ -184,9 +236,15 @@ ESI_Deliver(struct sess *sp) ...@@ -184,9 +236,15 @@ ESI_Deliver(struct sess *sp)
p = st->ptr; p = st->ptr;
e = st->ptr + st->len; e = st->ptr + st->len;
if (sp->esi_level == 0) {
if (*p == VEC_GZ) { if (*p == VEC_GZ) {
isgzip = 1;
p++; p++;
} else {
isgzip = 0;
}
if (sp->esi_level == 0) {
if (isgzip) {
sp->wrk->gzip_resp = 1; sp->wrk->gzip_resp = 1;
sp->wrk->crc = crc32(0L, Z_NULL, 0); sp->wrk->crc = crc32(0L, Z_NULL, 0);
} else } else
...@@ -202,21 +260,36 @@ ESI_Deliver(struct sess *sp) ...@@ -202,21 +260,36 @@ ESI_Deliver(struct sess *sp)
case VEC_V2: case VEC_V2:
case VEC_V8: case VEC_V8:
l = ved_decode_len(&p); l = ved_decode_len(&p);
r = p;
q = (void*)strchr((const char*)p, '\0');
p = q + 1;
if (sp->wrk->gzip_resp) { if (sp->wrk->gzip_resp) {
if (isgzip) {
assert(*p == VEC_C1 || *p == VEC_C2 || assert(*p == VEC_C1 || *p == VEC_C2 ||
*p == VEC_C8); *p == VEC_C8);
l_icrc = ved_decode_len(&p); l_icrc = ved_decode_len(&p);
icrc = vbe32dec(p); icrc = vbe32dec(p);
p += 4; p += 4;
sp->wrk->crc = sp->wrk->crc = crc32_combine(
crc32_combine(sp->wrk->crc, icrc, l_icrc); sp->wrk->crc, icrc, l_icrc);
sp->wrk->l_crc += 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;
} }
q = (void*)strchr((const char*)p, '\0'); } else {
assert (q > p); if (isgzip) {
ved_sendchunk(sp, p, q - p, st->ptr + off, l); INCOMPL();
} else {
ved_sendchunk(sp, r, q - r,
st->ptr + off, l);
off += l; off += l;
p = q + 1; }
}
break; break;
case VEC_S1: case VEC_S1:
case VEC_S2: case VEC_S2:
......
...@@ -286,13 +286,13 @@ vep_emit_verbatim(const struct vep_state *vep, ssize_t l, ssize_t l_crc) ...@@ -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); Debug("---> VERBATIM(%jd)\n", (intmax_t)l);
} }
vep_emit_len(vep, l, VEC_V1, VEC_V2, VEC_V8); 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) { if (vep->dogzip) {
vep_emit_len(vep, l_crc, VEC_C1, VEC_C2, VEC_C8); vep_emit_len(vep, l_crc, VEC_C1, VEC_C2, VEC_C8);
vbe32enc(buf, vep->crc); vbe32enc(buf, vep->crc);
vsb_bcat(vep->vsb, buf, sizeof buf); vsb_bcat(vep->vsb, buf, sizeof buf);
} }
/* Emit Chunked header */
vsb_printf(vep->vsb, "%lx\r\n%c", l, 0);
} }
static void static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment