From: Ruediger Pluem Date: Mon, 17 Jul 2006 14:32:50 +0000 (+0000) Subject: * Fix wrong FLUSH bucket handling in deflate_out_filter: Actually the internal X-Git-Tag: 2.3.0~2245 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54c1b9749e262a4c54e081d6ecb09b94a357989b;p=thirdparty%2Fapache%2Fhttpd.git * Fix wrong FLUSH bucket handling in deflate_out_filter: Actually the internal structures of libz never got flushed as ctx->stream.avail_in is always zero here. As the EOS and the FLUSH bucket case use the same code for flushing libz's internal buffers move this code to the new function flush_zlib_buffer. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@422731 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c index ecd4d1d16c1..58ea9a5dbb5 100644 --- a/modules/filters/mod_deflate.c +++ b/modules/filters/mod_deflate.c @@ -214,6 +214,43 @@ typedef struct deflate_ctx_t apr_bucket_brigade *bb, *proc_bb; } deflate_ctx; +static int flush_zlib_buffer(deflate_ctx *ctx, deflate_filter_config *c, + struct apr_bucket_alloc_t *bucket_alloc, + int flush) +{ + int zRC; + int done = 0; + unsigned int deflate_len; + apr_bucket *b; + + for (;;) { + deflate_len = c->bufferSize - ctx->stream.avail_out; + + if (deflate_len != 0) { + b = apr_bucket_heap_create((char *)ctx->buffer, + deflate_len, NULL, + bucket_alloc); + APR_BRIGADE_INSERT_TAIL(ctx->bb, b); + ctx->stream.next_out = ctx->buffer; + ctx->stream.avail_out = c->bufferSize; + } + + if (done) + break; + + zRC = deflate(&ctx->stream, flush); + + if (deflate_len == 0 && zRC == Z_BUF_ERROR) + zRC = Z_OK; + + done = (ctx->stream.avail_out != 0 || zRC == Z_STREAM_END); + + if (zRC != Z_OK && zRC != Z_STREAM_END) + break; + } + return zRC; +} + static apr_status_t deflate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) { @@ -400,43 +437,15 @@ static apr_status_t deflate_out_filter(ap_filter_t *f, const char *data; apr_bucket *b; apr_size_t len; - int done = 0; e = APR_BRIGADE_FIRST(bb); if (APR_BUCKET_IS_EOS(e)) { char *buf; - unsigned int deflate_len; ctx->stream.avail_in = 0; /* should be zero already anyway */ - for (;;) { - deflate_len = c->bufferSize - ctx->stream.avail_out; - - if (deflate_len != 0) { - b = apr_bucket_heap_create((char *)ctx->buffer, - deflate_len, NULL, - f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctx->bb, b); - ctx->stream.next_out = ctx->buffer; - ctx->stream.avail_out = c->bufferSize; - } - - if (done) { - break; - } - - zRC = deflate(&ctx->stream, Z_FINISH); - - if (deflate_len == 0 && zRC == Z_BUF_ERROR) { - zRC = Z_OK; - } - - done = (ctx->stream.avail_out != 0 || zRC == Z_STREAM_END); - - if (zRC != Z_OK && zRC != Z_STREAM_END) { - break; - } - } + /* flush the remaining data from the zlib buffers */ + flush_zlib_buffer(ctx, c, f->c->bucket_alloc, Z_FINISH); buf = apr_palloc(r->pool, 8); putLong((unsigned char *)&buf[0], ctx->crc); @@ -488,28 +497,17 @@ static apr_status_t deflate_out_filter(ap_filter_t *f, } if (APR_BUCKET_IS_FLUSH(e)) { - apr_bucket *bkt; apr_status_t rv; - apr_bucket_delete(e); - - if (ctx->stream.avail_in > 0) { - zRC = deflate(&(ctx->stream), Z_SYNC_FLUSH); - if (zRC != Z_OK) { - return APR_EGENERAL; - } + /* flush the remaining data from the zlib buffers */ + zRC = flush_zlib_buffer(ctx, c, f->c->bucket_alloc, Z_SYNC_FLUSH); + if (zRC != Z_OK) { + return APR_EGENERAL; } - ctx->stream.next_out = ctx->buffer; - len = c->bufferSize - ctx->stream.avail_out; - - b = apr_bucket_heap_create((char *)ctx->buffer, len, - NULL, f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctx->bb, b); - ctx->stream.avail_out = c->bufferSize; - - bkt = apr_bucket_flush_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctx->bb, bkt); + /* Remove flush bucket from old brigade anf insert into the new. */ + APR_BUCKET_REMOVE(e); + APR_BRIGADE_INSERT_TAIL(ctx->bb, e); rv = ap_pass_brigade(f->next, ctx->bb); if (rv != APR_SUCCESS) { return rv;