From 003590672f8f6bd768611f866866c30767bd0449 Mon Sep 17 00:00:00 2001 From: Bron Gondwana Date: Thu, 21 May 2009 13:59:54 +1000 Subject: [PATCH] Rewrite zlib inflate handling Use a single fixed-size buffer, and return to "inflate" again for further data rather than resizing the output buffer. --- lib/prot.c | 119 +++++++++++++++++++++++++++++------------------------------- lib/prot.h | 1 - 2 files changed, 57 insertions(+), 63 deletions(-) diff --git a/lib/prot.c b/lib/prot.c index 5261f75..331b767 100644 --- a/lib/prot.c +++ b/lib/prot.c @@ -94,7 +94,6 @@ int write; newstream = (struct protstream *) xzmalloc(sizeof(struct protstream)); newstream->buf = (unsigned char *) xmalloc(sizeof(char) * (PROT_BUFSIZE)); - newstream->buf_size = PROT_BUFSIZE; newstream->ptr = newstream->buf; newstream->maxplain = PROT_BUFSIZE; newstream->fd = fd; @@ -106,6 +105,10 @@ int write; newstream->bytes_in = 0; newstream->bytes_out = 0; +#ifdef HAVE_ZLIB + newstream->zbuf = 0; + newstream->zbuf_size = 0; +#endif return newstream; } @@ -275,7 +278,7 @@ static void zfree(voidpf opaque __attribute__((unused)), /* * Turn on (de)compression for this connection - * If its an output stream, initialize a compressor, + * If its an output stream, iOnitialize a compressor, * otherwise initialize a decompressor. */ @@ -520,6 +523,32 @@ int prot_fill(struct protstream *s) if (s->eof || s->error) return EOF; do { +#ifdef HAVE_ZLIB + /* check if there's anything in the zlib buffer already */ + if (s->zstrm && s->zstrm->avail_in) { + int zr; + if (!s->zbuf) + s->zbuf = (unsigned char *)xmalloc(sizeof(char) * (PROT_BUFSIZE)); + s->zstrm->next_out = s->zbuf; + s->zstrm->avail_out = PROT_BUFSIZE; + zr = inflate(s->zstrm, Z_SYNC_FLUSH); + if (zr != Z_OK) { + /* Error decompressing */ + syslog(LOG_ERR, "zlib error: %d %s", zr, s->zstrm->msg); + s->error = xstrdup("Error decompressing data"); + return EOF; + } + + if (s->zstrm->avail_out < PROT_BUFSIZE) { + /* inflated some data */ + s->ptr = s->zbuf; + s->cnt = PROT_BUFSIZE - s->zstrm->avail_out; + syslog(LOG_DEBUG, " => decompressed to %d bytes", s->cnt); + break; + } + } +#endif + /* wait until get input */ haveinput = 0; @@ -640,75 +669,41 @@ int prot_fill(struct protstream *s) } #ifdef HAVE_ZLIB - if (s->zstrm && s->cnt > 0) { - /* Decompress the data */ - int zr = Z_OK; + if (s->zstrm) { + /* transfer the stream to the input of the z_stream and loop */ s->zstrm->next_in = s->ptr; s->zstrm->avail_in = s->cnt; - s->zstrm->next_out = s->zbuf; - s->zstrm->avail_out = s->zbuf_size; - - syslog(LOG_DEBUG, "inflate(%d bytes)", s->cnt); + s->cnt = 0; + } +#endif /* HAVE_ZLIB */ + } while (!s->cnt); - do { - if (!s->zstrm->avail_out) { - /* Need more space to decompress */ - syslog(LOG_DEBUG, - "growing decompress buffer from %d to %d bytes", - s->zbuf_size, s->zbuf_size + PROT_BUFSIZE); - - s->zbuf = (unsigned char *) - xrealloc(s->zbuf, s->zbuf_size + PROT_BUFSIZE); - s->zstrm->next_out = s->zbuf + s->zbuf_size; - s->zstrm->avail_out = PROT_BUFSIZE; - s->zbuf_size += PROT_BUFSIZE; - } + if (s->logfd != -1) { + time_t newtime; + char timebuf[20]; - zr = inflate(s->zstrm, Z_SYNC_FLUSH); - } while (zr == Z_OK && !s->zstrm->avail_out); + time(&newtime); + snprintf(timebuf, sizeof(timebuf), "<%ld<", newtime); + write(s->logfd, timebuf, strlen(timebuf)); - if (zr != Z_OK || s->zstrm->avail_in) { - /* Error decompressing */ - s->error = xstrdup("Error decompressing data"); - return EOF; + left = s->cnt; + ptr = s->ptr; + do { + n = write(s->logfd, ptr, left); + if (n == -1 && (errno != EINTR || signals_poll())) { + break; } - - s->ptr = s->zbuf; - s->cnt = s->zbuf_size - s->zstrm->avail_out; - - syslog(LOG_DEBUG, " => decompressed to %d bytes", s->cnt); - } -#endif /* HAVE_ZLIB */ - - if (s->cnt > 0) { - if (s->logfd != -1) { - time_t newtime; - char timebuf[20]; - - time(&newtime); - snprintf(timebuf, sizeof(timebuf), "<%ld<", newtime); - write(s->logfd, timebuf, strlen(timebuf)); - - left = s->cnt; - ptr = s->ptr; - do { - n = write(s->logfd, ptr, left); - if (n == -1 && (errno != EINTR || signals_poll())) { - break; - } - if (n > 0) { - ptr += n; - left -= n; - } - } while (left); + if (n > 0) { + ptr += n; + left -= n; } + } while (left); + } - s->cnt--; /* we return the first char */ - s->bytes_in++; - return *s->ptr++; - } - } while (1); + s->cnt--; /* we return the first char */ + s->bytes_in++; + return *s->ptr++; } /* diff --git a/lib/prot.h b/lib/prot.h index 17109f3..2d9688f 100644 --- a/lib/prot.h +++ b/lib/prot.h @@ -73,7 +73,6 @@ typedef void prot_readcallback_t(struct protstream *s, void *rock); struct protstream { /* The Buffer */ unsigned char *buf; - unsigned buf_size; unsigned char *ptr; /* The end of data in the buffer */ unsigned cnt; /* Space Remaining in buffer */ -- 1.5.6.5