Skip to content

Commit

Permalink
mod_deflate:
Browse files Browse the repository at this point in the history
- fix signed/unsigned (int/size_t) comparisons,
- add consume_buffer() to factorize code used multiple times,
- cleanup passed brigade (don't rely on next output filters to do it).


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1619486 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
ylavic committed Aug 21, 2014
1 parent 681606b commit 2b94587
Showing 1 changed file with 55 additions and 90 deletions.
145 changes: 55 additions & 90 deletions modules/filters/mod_deflate.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ typedef struct deflate_filter_config_t
int windowSize;
int memlevel;
int compressionlevel;
apr_size_t bufferSize;
int bufferSize;
char *note_ratio_name;
char *note_input_name;
char *note_output_name;
Expand Down Expand Up @@ -256,7 +256,7 @@ static const char *deflate_set_buffer_size(cmd_parms *cmd, void *dummy,
return "DeflateBufferSize should be positive";
}

c->bufferSize = (apr_size_t)n;
c->bufferSize = n;

return NULL;
}
Expand Down Expand Up @@ -418,35 +418,40 @@ typedef struct deflate_ctx_t
/* Do update ctx->crc, see comment in flush_libz_buffer */
#define UPDATE_CRC 1

static void consume_buffer(deflate_ctx *ctx, deflate_filter_config *c,
int len, int crc, apr_bucket_brigade *bb)
{
apr_bucket *b;

/*
* Do we need to update ctx->crc? Usually this is the case for
* inflate action where we need to do a crc on the output, whereas
* in the deflate case we need to do a crc on the input
*/
if (crc) {
ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
}

b = apr_bucket_heap_create((char *)ctx->buffer, len, NULL,
bb->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);

ctx->stream.next_out = ctx->buffer;
ctx->stream.avail_out = c->bufferSize;
}

static int flush_libz_buffer(deflate_ctx *ctx, deflate_filter_config *c,
struct apr_bucket_alloc_t *bucket_alloc,
int (*libz_func)(z_streamp, int), int flush,
int crc)
{
int zRC = Z_OK;
int done = 0;
unsigned int deflate_len;
apr_bucket *b;
int deflate_len;

for (;;) {
deflate_len = c->bufferSize - ctx->stream.avail_out;

if (deflate_len != 0) {
/*
* Do we need to update ctx->crc? Usually this is the case for
* inflate action where we need to do a crc on the output, whereas
* in the deflate case we need to do a crc on the input
*/
if (crc) {
ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,
deflate_len);
}
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 (deflate_len > 0) {
consume_buffer(ctx, c, deflate_len, crc, ctx->bb);
}

if (done)
Expand Down Expand Up @@ -564,6 +569,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
request_rec *r = f->r;
deflate_ctx *ctx = f->ctx;
int zRC;
apr_status_t rv;
apr_size_t len = 0, blen;
const char *data;
deflate_filter_config *c;
Expand Down Expand Up @@ -874,8 +880,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,

ctx->stream.avail_in = 0; /* should be zero already anyway */
/* flush the remaining data from the zlib buffers */
flush_libz_buffer(ctx, c, f->c->bucket_alloc, deflate, Z_FINISH,
NO_UPDATE_CRC);
flush_libz_buffer(ctx, c, deflate, Z_FINISH, NO_UPDATE_CRC);

buf = apr_palloc(r->pool, VALIDATION_SIZE);
putLong((unsigned char *)&buf[0], ctx->crc);
Expand Down Expand Up @@ -926,15 +931,15 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
/* Okay, we've seen the EOS.
* Time to pass it along down the chain.
*/
return ap_pass_brigade(f->next, ctx->bb);
rv = ap_pass_brigade(f->next, ctx->bb);
apr_brigade_cleanup(ctx->bb);
return rv;
}

if (APR_BUCKET_IS_FLUSH(e)) {
apr_status_t rv;

/* flush the remaining data from the zlib buffers */
zRC = flush_libz_buffer(ctx, c, f->c->bucket_alloc, deflate,
Z_SYNC_FLUSH, NO_UPDATE_CRC);
zRC = flush_libz_buffer(ctx, c, deflate, Z_SYNC_FLUSH,
NO_UPDATE_CRC);
if (zRC != Z_OK) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01385)
"Zlib error %d flushing zlib output buffer (%s)",
Expand All @@ -946,6 +951,7 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
rv = ap_pass_brigade(f->next, ctx->bb);
apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
Expand Down Expand Up @@ -980,21 +986,15 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
ctx->stream.next_in = (unsigned char *)data; /* We just lost const-ness,
* but we'll just have to
* trust zlib */
ctx->stream.avail_in = len;
ctx->stream.avail_in = (int)len;

while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
apr_status_t rv;

ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;
consume_buffer(ctx, c, c->bufferSize, NO_UPDATE_CRC, ctx->bb);

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;
/* Send what we have right now to the next filter. */
rv = ap_pass_brigade(f->next, ctx->bb);
apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
Expand Down Expand Up @@ -1321,14 +1321,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
return APR_EINVAL;
}

len = c->bufferSize - ctx->stream.avail_out;
ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
tmp_b = apr_bucket_heap_create((char *)ctx->buffer, len,
NULL, f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_b);

ctx->stream.next_out = ctx->buffer;
ctx->stream.avail_out = c->bufferSize;
consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
UPDATE_CRC, ctx->proc_bb);

/* Flush everything so far in the returning brigade, but continue
* reading should EOS/more follow (don't lose them).
Expand Down Expand Up @@ -1376,16 +1370,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
if (!ctx->validation_buffer) {
while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
apr_bucket *tmp_heap;

ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;

ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
NULL, f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
ctx->stream.avail_out = c->bufferSize;
consume_buffer(ctx, c, c->bufferSize, UPDATE_CRC,
ctx->proc_bb);
}

ctx->inflate_total += ctx->stream.avail_out;
Expand Down Expand Up @@ -1428,7 +1414,6 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
}

if (ctx->validation_buffer) {
apr_bucket *tmp_heap;
apr_size_t avail, valid;
unsigned char *buf = ctx->validation_buffer;

Expand Down Expand Up @@ -1456,13 +1441,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
ctx->stream.total_in, ctx->stream.total_out,
r->uri);

len = c->bufferSize - ctx->stream.avail_out;

ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
NULL, f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
ctx->stream.avail_out = c->bufferSize;
consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
UPDATE_CRC, ctx->proc_bb);

{
unsigned long compCRC, compLen;
Expand Down Expand Up @@ -1507,16 +1487,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
if (block == APR_BLOCK_READ &&
APR_BRIGADE_EMPTY(ctx->proc_bb) &&
ctx->stream.avail_out < c->bufferSize) {
apr_bucket *tmp_heap;
apr_size_t len;
ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;

ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
NULL, f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
ctx->stream.avail_out = c->bufferSize;
consume_buffer(ctx, c, c->bufferSize - ctx->stream.avail_out,
UPDATE_CRC, ctx->proc_bb);
}

if (!APR_BRIGADE_EMPTY(ctx->proc_bb)) {
Expand Down Expand Up @@ -1629,7 +1601,6 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
while (!APR_BRIGADE_EMPTY(bb))
{
const char *data;
apr_bucket *b;
apr_size_t len;

e = APR_BRIGADE_FIRST(bb);
Expand All @@ -1651,8 +1622,7 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
* fails, whereas in the deflate case you can empty a filled output
* buffer and call it again until no more output can be created.
*/
flush_libz_buffer(ctx, c, f->c->bucket_alloc, inflate, Z_SYNC_FLUSH,
UPDATE_CRC);
flush_libz_buffer(ctx, c, inflate, Z_SYNC_FLUSH, UPDATE_CRC);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01398)
"Zlib: Inflated %ld to %ld : URL %s",
ctx->stream.total_in, ctx->stream.total_out, r->uri);
Expand Down Expand Up @@ -1692,15 +1662,14 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
* Okay, we've seen the EOS.
* Time to pass it along down the chain.
*/
return ap_pass_brigade(f->next, ctx->bb);
rv = ap_pass_brigade(f->next, ctx->bb);
apr_brigade_cleanup(ctx->bb);
return rv;
}

if (APR_BUCKET_IS_FLUSH(e)) {
apr_status_t rv;

/* flush the remaining data from the zlib buffers */
zRC = flush_libz_buffer(ctx, c, f->c->bucket_alloc, inflate,
Z_SYNC_FLUSH, UPDATE_CRC);
zRC = flush_libz_buffer(ctx, c, inflate, Z_SYNC_FLUSH, UPDATE_CRC);
if (zRC == Z_STREAM_END) {
if (ctx->validation_buffer == NULL) {
ctx->validation_buffer = apr_pcalloc(f->r->pool,
Expand All @@ -1718,6 +1687,7 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
rv = ap_pass_brigade(f->next, ctx->bb);
apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
Expand Down Expand Up @@ -1834,16 +1804,11 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,

while (ctx->stream.avail_in != 0) {
if (ctx->stream.avail_out == 0) {
ctx->stream.next_out = ctx->buffer;
len = c->bufferSize - ctx->stream.avail_out;

ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
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;
consume_buffer(ctx, c, c->bufferSize, UPDATE_CRC, ctx->bb);

/* Send what we have right now to the next filter. */
rv = ap_pass_brigade(f->next, ctx->bb);
apr_brigade_cleanup(ctx->bb);
if (rv != APR_SUCCESS) {
return rv;
}
Expand Down

0 comments on commit 2b94587

Please sign in to comment.