Author: rhuijben
Date: Wed Nov 11 14:36:21 2015
New Revision: 1713852
URL: http://svn.apache.org/viewvc?rev=1713852&view=rev
Log:
In preparation for improving the capabilities of the deflate stream,
split the serf_deflate_read() function in 3 functions that now call
each other. No functional changes yet.
* buckets/deflate_buckets.c
(deflate_read3,
deflate_read2): New functions, extracted from...
(serf_deflate_read): ... here. Call deflate_read2.
Modified:
serf/trunk/buckets/deflate_buckets.c
Modified: serf/trunk/buckets/deflate_buckets.c
URL:
http://svn.apache.org/viewvc/serf/trunk/buckets/deflate_buckets.c?rev=1713852&r1=1713851&r2=1713852&view=diff
==============================================================================
--- serf/trunk/buckets/deflate_buckets.c (original)
+++ serf/trunk/buckets/deflate_buckets.c Wed Nov 11 14:36:21 2015
@@ -146,7 +146,195 @@ static void serf_deflate_destroy_and_dat
serf_default_destroy_and_data(bucket);
}
-static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
+static apr_status_t deflate_read3(serf_bucket_t *bucket,
+ apr_size_t requested,
+ const char **data,
+ apr_size_t *len)
+{
+ deflate_context_t *ctx = bucket->data;
+ apr_status_t status;
+ int zRC;
+
+ /* Do we have anything already uncompressed to read? */
+ status = serf_bucket_read(ctx->inflate_stream, requested, data,
+ len);
+ if (SERF_BUCKET_READ_ERROR(status)) {
+ return status;
+ }
+ /* Hide EOF. */
+ if (APR_STATUS_IS_EOF(status)) {
+ status = ctx->stream_status;
+ if (APR_STATUS_IS_EOF(status)) {
+ /* We've read all of the data from our stream, but we
+ * need to continue to iterate until we flush
+ * out the zlib buffer.
+ */
+ status = APR_SUCCESS;
+ }
+ }
+ if (*len != 0) {
+ return status;
+ }
+
+ /* We tried; but we have nothing buffered. Fetch more. */
+
+ /* It is possible that we maxed out avail_out before
+ * exhausting avail_in; therefore, continue using the
+ * previous buffer. Otherwise, fetch more data from
+ * our stream bucket.
+ */
+ if (ctx->zstream.avail_in == 0) {
+ const char *private_data;
+ apr_size_t private_len;
+
+ /* When we empty our inflated stream, we'll return this
+ * status - this allow us to eventually pass up EAGAINs.
+ */
+ ctx->stream_status = serf_bucket_read(ctx->stream,
+ ctx->bufferSize,
+ &private_data,
+ &private_len);
+
+ if (SERF_BUCKET_READ_ERROR(ctx->stream_status)) {
+ return ctx->stream_status;
+ }
+
+ if (!private_len && APR_STATUS_IS_EAGAIN(ctx->stream_status)) {
+ *len = 0;
+ status = ctx->stream_status;
+ ctx->stream_status = APR_SUCCESS;
+ return status;
+ }
+
+ /* Make valgrind happy and explictly initialize next_in to specific
+ * value for empty buffer. */
+ if (private_len) {
+ ctx->zstream.next_in = (unsigned char*)private_data;
+ ctx->zstream.avail_in = private_len;
+ } else {
+ ctx->zstream.next_in = Z_NULL;
+ ctx->zstream.avail_in = 0;
+ }
+ }
+
+ while (1) {
+
+ zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
+
+ /* We're full or zlib requires more space. Either case, clear
+ out our buffer, reset, and return. */
+ if (zRC == Z_BUF_ERROR || ctx->zstream.avail_out == 0) {
+ apr_size_t private_len;
+ serf_bucket_t *tmp;
+
+ ctx->zstream.next_out = ctx->buffer;
+ private_len = ctx->bufferSize - ctx->zstream.avail_out;
+
+ ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
+ private_len);
+
+ /* FIXME: There probably needs to be a free func. */
+ tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char *)ctx->buffer,
+ private_len,
+ bucket->allocator);
+ serf_bucket_aggregate_append(ctx->inflate_stream, tmp);
+ ctx->zstream.avail_out = ctx->bufferSize;
+ break;
+ }
+
+ if (zRC == Z_STREAM_END) {
+ apr_size_t private_len;
+ serf_bucket_t *tmp;
+
+ private_len = ctx->bufferSize - ctx->zstream.avail_out;
+ ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
+ private_len);
+ /* FIXME: There probably needs to be a free func. */
+ tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char *)ctx->buffer,
+ private_len,
+ bucket->allocator);
+ serf_bucket_aggregate_append(ctx->inflate_stream, tmp);
+
+ ctx->zstream.avail_out = ctx->bufferSize;
+
+ /* Push back the remaining data to be read. */
+ tmp = serf_bucket_aggregate_create(bucket->allocator);
+ serf_bucket_set_config(tmp, ctx->config);
+ serf_bucket_aggregate_prepend(tmp, ctx->stream);
+ ctx->stream = tmp;
+
+ /* We now need to take the remaining avail_in and
+ * throw it in ctx->stream so our next read picks it up.
+ */
+ tmp = SERF_BUCKET_SIMPLE_STRING_LEN(
+ (const char*)ctx->zstream.next_in,
+ ctx->zstream.avail_in,
+ bucket->allocator);
+ serf_bucket_aggregate_prepend(ctx->stream, tmp);
+
+ switch (ctx->format) {
+ case SERF_DEFLATE_GZIP:
+ ctx->stream_left = ctx->stream_size =
+ DEFLATE_VERIFY_SIZE;
+ ctx->state++;
+ break;
+ case SERF_DEFLATE_DEFLATE:
+ /* Deflate does not have a verify footer. */
+ ctx->state = STATE_FINISH;
+ break;
+ default:
+ /* Not reachable */
+ return APR_EGENERAL;
+ }
+
+ break;
+ }
+
+ /* Any other error? */
+ if (zRC != Z_OK) {
+ serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__,
+ ctx->config, "inflate error %d - %s\n",
+ zRC, ctx->zstream.msg);
+ return SERF_ERROR_DECOMPRESSION_FAILED;
+ }
+
+ /* As long as zRC == Z_OK, just keep looping. */
+ }
+ /* Okay, we've inflated. Try to read. */
+ status = serf_bucket_read(ctx->inflate_stream, requested, data,
+ len);
+ /* Hide EOF. */
+ if (APR_STATUS_IS_EOF(status)) {
+ status = ctx->stream_status;
+
+ /* If the inflation wasn't finished, return APR_SUCCESS. */
+ if (zRC != Z_STREAM_END)
+ return APR_SUCCESS;
+
+ /* If our stream is finished too and all data was inflated,
+ * return SUCCESS so we'll iterate one more time.
+ */
+ if (APR_STATUS_IS_EOF(status)) {
+ /* No more data to read from the stream, and everything
+ inflated. If all data was received correctly, state
+ should have been advanced to STATE_READING_VERIFY or
+ STATE_FINISH. If not, then the data was incomplete
+ and we have an error. */
+ if (ctx->state != STATE_INFLATE)
+ return APR_SUCCESS;
+ else {
+ serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__,
+ ctx->config,
+ "Unexpected EOF on input stream\n");
+ return SERF_ERROR_DECOMPRESSION_FAILED;
+ }
+ }
+ }
+
+ return status;
+}
+
+static apr_status_t deflate_read2(serf_bucket_t *bucket,
apr_size_t requested,
const char **data, apr_size_t *len)
{
@@ -252,176 +440,7 @@ static apr_status_t serf_deflate_read(se
ctx->state++;
break;
case STATE_INFLATE:
- /* Do we have anything already uncompressed to read? */
- status = serf_bucket_read(ctx->inflate_stream, requested, data,
- len);
- if (SERF_BUCKET_READ_ERROR(status)) {
- return status;
- }
- /* Hide EOF. */
- if (APR_STATUS_IS_EOF(status)) {
- status = ctx->stream_status;
- if (APR_STATUS_IS_EOF(status)) {
- /* We've read all of the data from our stream, but we
- * need to continue to iterate until we flush
- * out the zlib buffer.
- */
- status = APR_SUCCESS;
- }
- }
- if (*len != 0) {
- return status;
- }
-
- /* We tried; but we have nothing buffered. Fetch more. */
-
- /* It is possible that we maxed out avail_out before
- * exhausting avail_in; therefore, continue using the
- * previous buffer. Otherwise, fetch more data from
- * our stream bucket.
- */
- if (ctx->zstream.avail_in == 0) {
- /* When we empty our inflated stream, we'll return this
- * status - this allow us to eventually pass up EAGAINs.
- */
- ctx->stream_status = serf_bucket_read(ctx->stream,
- ctx->bufferSize,
- &private_data,
- &private_len);
-
- if (SERF_BUCKET_READ_ERROR(ctx->stream_status)) {
- return ctx->stream_status;
- }
-
- if (!private_len && APR_STATUS_IS_EAGAIN(ctx->stream_status)) {
- *len = 0;
- status = ctx->stream_status;
- ctx->stream_status = APR_SUCCESS;
- return status;
- }
-
- /* Make valgrind happy and explictly initialize next_in to
specific
- * value for empty buffer. */
- if (private_len) {
- ctx->zstream.next_in = (unsigned char*)private_data;
- ctx->zstream.avail_in = private_len;
- } else {
- ctx->zstream.next_in = Z_NULL;
- ctx->zstream.avail_in = 0;
- }
- }
-
- while (1) {
-
- zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
-
- /* We're full or zlib requires more space. Either case, clear
- out our buffer, reset, and return. */
- if (zRC == Z_BUF_ERROR || ctx->zstream.avail_out == 0) {
- serf_bucket_t *tmp;
- ctx->zstream.next_out = ctx->buffer;
- private_len = ctx->bufferSize - ctx->zstream.avail_out;
-
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
- private_len);
-
- /* FIXME: There probably needs to be a free func. */
- tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char *)ctx->buffer,
- private_len,
- bucket->allocator);
- serf_bucket_aggregate_append(ctx->inflate_stream, tmp);
- ctx->zstream.avail_out = ctx->bufferSize;
- break;
- }
-
- if (zRC == Z_STREAM_END) {
- serf_bucket_t *tmp;
-
- private_len = ctx->bufferSize - ctx->zstream.avail_out;
- ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
- private_len);
- /* FIXME: There probably needs to be a free func. */
- tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char *)ctx->buffer,
- private_len,
- bucket->allocator);
- serf_bucket_aggregate_append(ctx->inflate_stream, tmp);
-
- ctx->zstream.avail_out = ctx->bufferSize;
-
- /* Push back the remaining data to be read. */
- tmp = serf_bucket_aggregate_create(bucket->allocator);
- serf_bucket_set_config(tmp, ctx->config);
- serf_bucket_aggregate_prepend(tmp, ctx->stream);
- ctx->stream = tmp;
-
- /* We now need to take the remaining avail_in and
- * throw it in ctx->stream so our next read picks it up.
- */
- tmp = SERF_BUCKET_SIMPLE_STRING_LEN(
- (const char*)ctx->zstream.next_in,
- ctx->zstream.avail_in,
- bucket->allocator);
- serf_bucket_aggregate_prepend(ctx->stream, tmp);
-
- switch (ctx->format) {
- case SERF_DEFLATE_GZIP:
- ctx->stream_left = ctx->stream_size =
- DEFLATE_VERIFY_SIZE;
- ctx->state++;
- break;
- case SERF_DEFLATE_DEFLATE:
- /* Deflate does not have a verify footer. */
- ctx->state = STATE_FINISH;
- break;
- default:
- /* Not reachable */
- return APR_EGENERAL;
- }
-
- break;
- }
-
- /* Any other error? */
- if (zRC != Z_OK) {
- serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__,
- ctx->config, "inflate error %d - %s\n",
- zRC, ctx->zstream.msg);
- return SERF_ERROR_DECOMPRESSION_FAILED;
- }
-
- /* As long as zRC == Z_OK, just keep looping. */
- }
- /* Okay, we've inflated. Try to read. */
- status = serf_bucket_read(ctx->inflate_stream, requested, data,
- len);
- /* Hide EOF. */
- if (APR_STATUS_IS_EOF(status)) {
- status = ctx->stream_status;
-
- /* If the inflation wasn't finished, return APR_SUCCESS. */
- if (zRC != Z_STREAM_END)
- return APR_SUCCESS;
-
- /* If our stream is finished too and all data was inflated,
- * return SUCCESS so we'll iterate one more time.
- */
- if (APR_STATUS_IS_EOF(status)) {
- /* No more data to read from the stream, and everything
- inflated. If all data was received correctly, state
- should have been advanced to STATE_READING_VERIFY or
- STATE_FINISH. If not, then the data was incomplete
- and we have an error. */
- if (ctx->state != STATE_INFLATE)
- return APR_SUCCESS;
- else {
- serf__log(LOGLVL_ERROR, LOGCOMP_COMPR, __FILE__,
- ctx->config,
- "Unexpected EOF on input stream\n");
- return SERF_ERROR_DECOMPRESSION_FAILED;
- }
- }
- }
- return status;
+ return deflate_read3(bucket, requested, data, len);
case STATE_DONE:
/* We're done inflating. Use our finished buffer. */
return serf_bucket_read(ctx->stream, requested, data, len);
@@ -434,6 +453,13 @@ static apr_status_t serf_deflate_read(se
/* NOTREACHED */
}
+static apr_status_t serf_deflate_read(serf_bucket_t *bucket,
+ apr_size_t requested,
+ const char **data, apr_size_t *len)
+{
+ return deflate_read2(bucket, requested, data, len);
+}
+
static apr_status_t serf_deflate_set_config(serf_bucket_t *bucket,
serf_config_t *config)
{