Fix handling of ZSTREAM_END result from zlib.
Avoid getting stuck when ZSTREAM_END occurs with no more bytes written out.
This commit is contained in:
parent
f983194d7e
commit
45ae3978f6
@ -298,25 +298,51 @@ public:
|
|||||||
zlib.next_out = zlibOutputBuffer;
|
zlib.next_out = zlibOutputBuffer;
|
||||||
zlib.avail_out = ZLIB_DECOMPRESS_BUFFER_SIZE;
|
zlib.avail_out = ZLIB_DECOMPRESS_BUFFER_SIZE;
|
||||||
|
|
||||||
if (contentGZip) {
|
if (contentGZip && !handleGZipHeader()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writtenSize = 0;
|
||||||
|
do {
|
||||||
|
int result = inflate(&zlib, Z_NO_FLUSH);
|
||||||
|
if (result == Z_OK || result == Z_STREAM_END) {
|
||||||
|
// nothing to do
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_IO, SG_WARN, "got Zlib error:" << result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writtenSize = ZLIB_DECOMPRESS_BUFFER_SIZE - zlib.avail_out;
|
||||||
|
if (result == Z_STREAM_END) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((writtenSize == 0) && (zlib.avail_in > 0));
|
||||||
|
|
||||||
|
if (writtenSize > 0) {
|
||||||
|
activeRequest->processBodyBytes((const char*) zlibOutputBuffer, writtenSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleGZipHeader()
|
||||||
|
{
|
||||||
// we clear this down to contentDeflate once the GZip header has been seen
|
// we clear this down to contentDeflate once the GZip header has been seen
|
||||||
if (reqSize < GZIP_HEADER_SIZE) {
|
if (zlib.avail_in < GZIP_HEADER_SIZE) {
|
||||||
return; // need more header bytes
|
return false; // need more header bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((zlibInflateBuffer[0] != GZIP_HEADER_ID1) ||
|
if ((zlibInflateBuffer[0] != GZIP_HEADER_ID1) ||
|
||||||
(zlibInflateBuffer[1] != GZIP_HEADER_ID2) ||
|
(zlibInflateBuffer[1] != GZIP_HEADER_ID2) ||
|
||||||
(zlibInflateBuffer[2] != GZIP_HEADER_METHOD_DEFLATE))
|
(zlibInflateBuffer[2] != GZIP_HEADER_METHOD_DEFLATE))
|
||||||
{
|
{
|
||||||
return; // invalid GZip header
|
return false; // invalid GZip header
|
||||||
}
|
}
|
||||||
|
|
||||||
char flags = zlibInflateBuffer[3];
|
char flags = zlibInflateBuffer[3];
|
||||||
int gzipHeaderSize = GZIP_HEADER_SIZE;
|
int gzipHeaderSize = GZIP_HEADER_SIZE;
|
||||||
if (flags & GZIP_HEADER_FEXTRA) {
|
if (flags & GZIP_HEADER_FEXTRA) {
|
||||||
gzipHeaderSize += 2;
|
gzipHeaderSize += 2;
|
||||||
if (reqSize < gzipHeaderSize) {
|
if (zlib.avail_in < gzipHeaderSize) {
|
||||||
return; // need more header bytes
|
return false; // need more header bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short extraHeaderBytes = *(reinterpret_cast<unsigned short*>(zlibInflateBuffer + GZIP_HEADER_FEXTRA));
|
unsigned short extraHeaderBytes = *(reinterpret_cast<unsigned short*>(zlibInflateBuffer + GZIP_HEADER_FEXTRA));
|
||||||
@ -325,14 +351,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
gzipHeaderSize += extraHeaderBytes;
|
gzipHeaderSize += extraHeaderBytes;
|
||||||
if (reqSize < gzipHeaderSize) {
|
if (zlib.avail_in < gzipHeaderSize) {
|
||||||
return; // need more header bytes
|
return false; // need more header bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & GZIP_HEADER_FNAME) {
|
if (flags & GZIP_HEADER_FNAME) {
|
||||||
gzipHeaderSize++;
|
gzipHeaderSize++;
|
||||||
while (gzipHeaderSize <= reqSize) {
|
while (gzipHeaderSize <= zlib.avail_in) {
|
||||||
if (zlibInflateBuffer[gzipHeaderSize-1] == 0) {
|
if (zlibInflateBuffer[gzipHeaderSize-1] == 0) {
|
||||||
break; // found terminating NULL character
|
break; // found terminating NULL character
|
||||||
}
|
}
|
||||||
@ -341,7 +367,7 @@ public:
|
|||||||
|
|
||||||
if (flags & GZIP_HEADER_COMMENT) {
|
if (flags & GZIP_HEADER_COMMENT) {
|
||||||
gzipHeaderSize++;
|
gzipHeaderSize++;
|
||||||
while (gzipHeaderSize <= reqSize) {
|
while (gzipHeaderSize <= zlib.avail_in) {
|
||||||
if (zlibInflateBuffer[gzipHeaderSize-1] == 0) {
|
if (zlibInflateBuffer[gzipHeaderSize-1] == 0) {
|
||||||
break; // found terminating NULL character
|
break; // found terminating NULL character
|
||||||
}
|
}
|
||||||
@ -352,33 +378,16 @@ public:
|
|||||||
gzipHeaderSize += 2;
|
gzipHeaderSize += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reqSize < gzipHeaderSize) {
|
if (zlib.avail_in < gzipHeaderSize) {
|
||||||
return; // need more header bytes
|
return false; // need more header bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
zlib.next_in += gzipHeaderSize;
|
zlib.next_in += gzipHeaderSize;
|
||||||
zlib.avail_in = reqSize - gzipHeaderSize;
|
zlib.avail_in -= gzipHeaderSize;
|
||||||
// now we've processed the GZip header, can decode as deflate
|
// now we've processed the GZip header, can decode as deflate
|
||||||
contentGZip = false;
|
contentGZip = false;
|
||||||
contentDeflate = true;
|
contentDeflate = true;
|
||||||
}
|
return true;
|
||||||
|
|
||||||
int writtenSize = 0;
|
|
||||||
do {
|
|
||||||
int result = inflate(&zlib, Z_NO_FLUSH);
|
|
||||||
if (result == Z_OK || result == Z_STREAM_END) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
SG_LOG(SG_IO, SG_WARN, "got Zlib error:" << result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
writtenSize = ZLIB_DECOMPRESS_BUFFER_SIZE - zlib.avail_out;
|
|
||||||
} while ((writtenSize == 0) && (zlib.avail_in > 0));
|
|
||||||
|
|
||||||
if (writtenSize > 0) {
|
|
||||||
activeRequest->processBodyBytes((const char*) zlibOutputBuffer, writtenSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void foundTerminator(void)
|
virtual void foundTerminator(void)
|
||||||
@ -405,6 +414,7 @@ public:
|
|||||||
case STATE_GETTING_CHUNKED_BYTES:
|
case STATE_GETTING_CHUNKED_BYTES:
|
||||||
setTerminator("\r\n");
|
setTerminator("\r\n");
|
||||||
state = STATE_GETTING_CHUNKED;
|
state = STATE_GETTING_CHUNKED;
|
||||||
|
buffer.clear();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user