Commit 1b9e19cb authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

For reasons not understood, last commit missed this file.

Try again:

    Add the necessary code (& a testcase) to pad out an included
    gzip file, no matter which of the 8 bits of a byte the last bit
    lands in.
parent 70dacf26
...@@ -352,15 +352,55 @@ assert(l > 10); ...@@ -352,15 +352,55 @@ assert(l > 10);
* Include an object in a gzip'ed ESI object delivery * Include an object in a gzip'ed ESI object delivery
*/ */
static unsigned
ved_deliver_byterange(struct sess *sp, ssize_t low, ssize_t high)
{
struct storage *st;
ssize_t l, lx;
u_char *p;
//printf("BR %jd %jd\n", low, high);
lx = 0;
VTAILQ_FOREACH(st, &sp->obj->store, list) {
p = st->ptr;
l = st->len;
//printf("[0-] %jd %jd\n", lx, lx + l);
if (lx + l < low) {
lx += l;
continue;
}
if (lx == high)
return (p[0]);
assert(lx < high);
if (lx < low) {
p += (low - lx);
l -= (low - lx);
lx = low;
}
//printf("[1-] %jd %jd\n", lx, lx + l);
if (lx + l >= high)
l = high - lx;
//printf("[2-] %jd %jd\n", lx, lx + l);
assert(lx >= low && lx + l <= high);
if (l != 0)
ved_sendchunk(sp, NULL, 0, p, l);
if (lx + st->len > high)
return(p[l]);
lx += st->len;
}
INCOMPL();
}
void void
ESI_DeliverChild(struct sess *sp) ESI_DeliverChild(struct sess *sp)
{ {
struct storage *st; struct storage *st;
struct object *obj; struct object *obj;
ssize_t start, last, stop, l, lx, dl; ssize_t start, last, stop, lpad;
u_char *p; u_char *p, cc;
uint32_t icrc; uint32_t icrc;
uint32_t ilen; uint32_t ilen;
uint8_t pad[6];
if (!sp->obj->gziped) { if (!sp->obj->gziped) {
VTAILQ_FOREACH(st, &sp->obj->store, list) VTAILQ_FOREACH(st, &sp->obj->store, list)
...@@ -377,61 +417,74 @@ ESI_DeliverChild(struct sess *sp) ...@@ -377,61 +417,74 @@ ESI_DeliverChild(struct sess *sp)
start = obj->gzip_start; start = obj->gzip_start;
last = obj->gzip_last; last = obj->gzip_last;
stop = obj->gzip_stop; stop = obj->gzip_stop;
assert(start > 0 && start < obj->len * 8);
assert(last > 0 && last < obj->len * 8);
assert(stop > 0 && stop < obj->len * 8);
assert(last >= start); assert(last >= start);
assert(last < stop); assert(last < stop);
assert(start > 0 && start <= obj->len * 8); //printf("BITS %jd %jd %jd\n", start, last, stop);
assert(last > 0 && last <= obj->len * 8);
assert(stop > 0 && stop <= obj->len * 8);
printf("BITS %jd %jd %jd\n", start, last, stop);
/* The start bit must be byte aligned. */ /* The start bit must be byte aligned. */
AZ(start & 7); AZ(start & 7);
lx = 0; /*
VTAILQ_FOREACH(st, &sp->obj->store, list) { * XXX: optimize for the case where the 'last'
p = st->ptr; * XXX: bit is in a empty copy block
l = st->len; */
xxxassert(start/8 < l); cc = ved_deliver_byterange(sp, start/8, last/8);
if (start/8 > 0) { //printf("CC_LAST %x\n", cc);
l -= start/8; cc &= ~(1 << (start & 7));
p += start/8; ved_sendchunk(sp, NULL, 0, &cc, 1);
lx += start/8; cc = ved_deliver_byterange(sp, 1 + last/8, stop/8);
start = 0; //printf("CC_STOP %x (%d)\n", cc, (int)(stop & 7));
} switch((int)(stop & 7)) {
assert(l >= 0); case 0: /* xxxxxxxx */
if (l == 0) /* I think we have an off by one here, but that's OK */
continue; lpad = 0;
printf("XXXX: %jd %jd %jd\n", l, lx, last / 8); break;
dl = last/8 - lx; case 1: /* x000.... 00000000 00000000 11111111 11111111 */
if (dl > 0) { case 3: /* xxx000.. 00000000 00000000 11111111 11111111 */
if (dl > l) case 5: /* xxxxx000 00000000 00000000 11111111 11111111 */
dl = l; pad[0] = cc | 0x00;
printf("CH1 %jd\n", dl); pad[1] = 0x00; pad[2] = 0x00; pad[3] = 0xff; pad[4] = 0xff;
ved_sendchunk(sp, NULL, 0, p, dl); lpad = 5;
lx += dl; break;
p += dl; case 2: /* xx010000 00000100 00000001 00000000 */
l -= dl; pad[0] = cc | 0x08;
} pad[1] = 0x20;
assert(l >= 0); pad[2] = 0x80;
if (l == 0) pad[3] = 0x00;
continue; lpad = 4;
printf("XXXX: %jd %jd %jd %02x\n", l, lx, last / 8, *p); break;
/* case 4: /* xxxx0100 00000001 00000000 */
* If we are lucky, the last bit is aligned and in a copy pad[0] = cc | 0x20;
* block, detect and be happy pad[1] = 0x80;
*/ pad[2] = 0x00;
if (l >= 3 && (last & 7) == 0 && lpad = 3;
p[0] == 0x01 && p[1] == 0 && p[2] == 0) break;
break; case 6: /* xxxxxx01 00000000 */
INCOMPL(); pad[0] = cc | 0x80;
pad[1] = 0x00;
lpad = 2;
break;
case 7: /* xxxxxxx0 00...... 00000000 00000000 11111111 11111111 */
pad[0] = cc | 0x00;
pad[1] = 0x00;
pad[2] = 0x00; pad[3] = 0x00; pad[4] = 0xff; pad[5] = 0xff;
lpad = 6;
break;
default:
AZ(stop & 7);
} }
AZ(VTAILQ_NEXT(st, list)); if (lpad > 0)
ved_sendchunk(sp, NULL, 0, pad, lpad);
st = VTAILQ_LAST(&sp->obj->store, objecthead);
assert(st->len > 8); assert(st->len > 8);
p = st->ptr + st->len - 8; p = st->ptr + st->len - 8;
icrc = vle32dec(p); icrc = vle32dec(p);
ilen = vle32dec(p + 4); ilen = vle32dec(p + 4);
printf("CRC %08x LEN %d\n", icrc, ilen); //printf("CRC %08x LEN %d\n", icrc, ilen);
sp->wrk->crc = crc32_combine(sp->wrk->crc, icrc, ilen); sp->wrk->crc = crc32_combine(sp->wrk->crc, icrc, ilen);
sp->wrk->l_crc += ilen; sp->wrk->l_crc += ilen;
} }
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