From efbfe4c006cfb6e0bf3ee4ed57d0657c0cd85c19 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 6 Sep 2010 14:29:36 +0000 Subject: 2010-09-06 Tatsuhiro Tsujikawa Data from remote server in HTTP/FTP download are now written to the disk(or memory) through StreamFilter. Decoding chunked and gziped streams are done cascading StreamFilter. Removed inefficient 1byte read code. * src/ChunkedDecodingStreamFilter.cc * src/ChunkedDecodingStreamFilter.h * src/DownloadCommand.cc * src/DownloadCommand.h * src/GZipDecodingStreamFilter.cc * src/GZipDecodingStreamFilter.h * src/HttpConnection.cc * src/HttpDownloadCommand.cc * src/HttpResponse.cc * src/HttpResponse.h * src/HttpResponseCommand.cc * src/HttpResponseCommand.h * src/HttpSkipResponseCommand.cc * src/HttpSkipResponseCommand.h * src/Makefile.am * src/NullSinkStreamFilter.cc * src/NullSinkStreamFilter.h * src/RequestGroup.cc * src/SinkStreamFilter.cc * src/SinkStreamFilter.h * src/StreamFilter.cc * src/StreamFilter.h * test/ChunkedDecodingStreamFilterTest.cc * test/GZipDecodingStreamFilterTest.cc * test/HttpResponseTest.cc * test/Makefile.am * test/MockSegment.h --- src/GZipDecodingStreamFilter.cc | 131 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/GZipDecodingStreamFilter.cc (limited to 'src/GZipDecodingStreamFilter.cc') diff --git a/src/GZipDecodingStreamFilter.cc b/src/GZipDecodingStreamFilter.cc new file mode 100644 index 00000000..3fa1d05c --- /dev/null +++ b/src/GZipDecodingStreamFilter.cc @@ -0,0 +1,131 @@ +/* */ +#include "GZipDecodingStreamFilter.h" + +#include + +#include "StringFormat.h" +#include "DlAbortEx.h" + +namespace aria2 { + +const std::string GZipDecodingStreamFilter::NAME("GZipDecodingStreamFilter"); + +GZipDecodingStreamFilter::GZipDecodingStreamFilter +(const SharedHandle& delegate): + StreamFilter(delegate), strm_(0), finished_(false), bytesProcessed_(0) {} + +GZipDecodingStreamFilter::~GZipDecodingStreamFilter() +{ + release(); +} + +void GZipDecodingStreamFilter::init() +{ + finished_ = false; + release(); + strm_ = new z_stream(); + strm_->zalloc = Z_NULL; + strm_->zfree = Z_NULL; + strm_->opaque = Z_NULL; + strm_->avail_in = 0; + strm_->next_in = Z_NULL; + + // initalize z_stream with gzip/zlib format auto detection enabled. + if(Z_OK != inflateInit2(strm_, 47)) { + throw DL_ABORT_EX("Initializing z_stream failed."); + } +} + +void GZipDecodingStreamFilter::release() +{ + if(strm_) { + inflateEnd(strm_); + delete strm_; + strm_ = 0; + } +} + +ssize_t GZipDecodingStreamFilter::transform +(const SharedHandle& out, + const SharedHandle& segment, + const unsigned char* inbuf, size_t inlen) +{ + bytesProcessed_ = 0; + ssize_t outlen = 0; + if(inlen == 0) { + return outlen; + } + + strm_->avail_in = inlen; + strm_->next_in = const_cast(inbuf); + + unsigned char outbuf[OUTBUF_LENGTH]; + while(1) { + strm_->avail_out = OUTBUF_LENGTH; + strm_->next_out = outbuf; + + int ret = ::inflate(strm_, Z_NO_FLUSH); + + if(ret == Z_STREAM_END) { + finished_ = true; + } else if(ret != Z_OK) { + throw DL_ABORT_EX(StringFormat("libz::inflate() failed. cause:%s", + strm_->msg).str()); + } + + size_t produced = OUTBUF_LENGTH-strm_->avail_out; + + outlen += getDelegate()->transform(out, segment, outbuf, produced); + if(strm_->avail_out > 0) { + break; + } + } + assert(inlen >= strm_->avail_in); + bytesProcessed_ = inlen-strm_->avail_in; + return outlen; +} + +bool GZipDecodingStreamFilter::finished() +{ + return finished_ && getDelegate()->finished(); +} + +const std::string& GZipDecodingStreamFilter::getName() const +{ + return NAME; +} + +} // namespace aria2 -- cgit