in buckets/deflate_buckets.c [415:566]
static apr_status_t serf_deflate_wait_for_data(serf_bucket_t *bucket)
{
deflate_context_t *ctx = bucket->data;
apr_status_t status;
const char *private_data;
apr_size_t private_len;
int zRC;
while (1) {
switch (ctx->state) {
case STATE_READING_HEADER:
case STATE_READING_VERIFY:
status = serf_bucket_read(ctx->stream, ctx->stream_left,
&private_data, &private_len);
if (SERF_BUCKET_READ_ERROR(status)) {
return status;
}
/* The C99 standard (7.21.1/2) requires valid data pointer
* even for zero length array for all functions unless explicitly
* stated otherwise. So don't copy data even most mempy()
* implementations have special handling for zero length copy. */
if (private_len) {
memcpy(ctx->hdr_buffer + (ctx->stream_size - ctx->stream_left),
private_data, private_len);
ctx->stream_left -= private_len;
}
if (ctx->stream_left == 0) {
ctx->state++;
if (APR_STATUS_IS_EAGAIN(status)) {
return status;
}
}
else if (status) {
return status;
}
break;
case STATE_HEADER:
if (ctx->hdr_buffer[0] != deflate_magic[0] ||
ctx->hdr_buffer[1] != deflate_magic[1]) {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__, ctx->config,
"Incorrect magic number. Actual:%hhx%hhx.\n",
ctx->hdr_buffer[0], ctx->hdr_buffer[1]);
return SERF_ERROR_DECOMPRESSION_FAILED;
}
if (ctx->hdr_buffer[3] != 0) {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__, ctx->config,
"Incorrect magic number (at offset 3). Actual: "
"%x\n", ctx->hdr_buffer[3]);
return SERF_ERROR_DECOMPRESSION_FAILED;
}
ctx->state++;
break;
case STATE_VERIFY:
{
unsigned long compCRC, compLen, actualLen;
/* Do the checksum computation. */
compCRC = getLong((unsigned char*)ctx->hdr_buffer);
if (ctx->crc != compCRC) {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__, ctx->config,
"Incorrect crc. Expected: %ld, Actual:%ld\n",
compCRC, ctx->crc);
return SERF_ERROR_DECOMPRESSION_FAILED;
}
compLen = getLong((unsigned char*)ctx->hdr_buffer + 4);
/* The length in the trailer is module 2^32, so do the same for
the actual length. */
actualLen = ctx->zstream.total_out;
actualLen &= 0xFFFFFFFF;
if (actualLen != compLen) {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__, ctx->config,
"Incorrect length. Expected: %ld, Actual:%ld\n",
compLen, ctx->zstream.total_out);
return SERF_ERROR_DECOMPRESSION_FAILED;
}
ctx->state++;
break;
}
case STATE_INIT:
zRC = inflateInit2(&ctx->zstream, ctx->windowSize);
if (zRC != Z_OK) {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__, ctx->config,
"inflateInit2 error %d - %s\n",
zRC, ctx->zstream.msg);
return SERF_ERROR_DECOMPRESSION_FAILED;
}
ctx->zstream.next_out = ctx->buffer;
ctx->zstream.avail_out = ctx->bufferSize;
ctx->state++;
break;
case STATE_FINISH:
inflateEnd(&ctx->zstream);
serf_bucket_aggregate_append(ctx->inflate_stream,
ctx->stream);
ctx->stream = NULL;
ctx->state = STATE_DONE;
break;
case STATE_INFLATE:
return APR_SUCCESS;
case STATE_DONE:
/* We're done inflating. Use our finished buffer. */
return ctx->inflate_stream ? APR_SUCCESS : APR_EOF;
case STATE_WRITING_HEADER:
{
char *header = serf_bucket_mem_calloc(bucket->allocator,
DEFLATE_MAGIC_SIZE);
memcpy(header, deflate_magic, sizeof(deflate_magic));
header[2] = Z_DEFLATED;
/* No mtime. DOS/Default OS */
serf_bucket_aggregate_append(
ctx->inflate_stream,
serf_bucket_simple_own_create(header, DEFLATE_MAGIC_SIZE,
bucket->allocator));
ctx->state++;
break;
}
case STATE_COMPRESS_INIT:
zRC = deflateInit2(&ctx->zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
ctx->windowSize, ctx->memLevel, Z_DEFAULT_STRATEGY);
if (zRC != Z_OK) {
serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__, ctx->config,
"deflateInit2 error %d - %s\n",
zRC, ctx->zstream.msg);
return SERF_ERROR_DECOMPRESSION_FAILED;
}
ctx->zstream.next_out = ctx->buffer;
ctx->zstream.avail_out = ctx->bufferSize;
ctx->state = STATE_INFLATE;
break;
case STATE_COMPRESS_FINISH:
deflateEnd(&ctx->zstream);
serf_bucket_aggregate_append(ctx->inflate_stream,
ctx->stream);
ctx->stream = NULL;
ctx->state = STATE_DONE;
break;
default:
/* Not reachable */
return APR_EGENERAL;
}
}
/* NOTREACHED */
}