diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2008-07-01 11:38:25 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2008-07-01 11:38:25 +0000 |
| commit | 92c66d24acb2ef0c4324e682d32491bed04cab75 (patch) | |
| tree | 1123b7d1647b8500c63aa2739befb6ceb68e5ccb /src | |
| parent | 61bb4bc02e662a33ae0d7a9747d28898ed847276 (diff) | |
2008-07-01 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Rewritten ChunkedEncoding class as ChunkedDecoder class.
* src/A2STR.cc
* src/A2STR.h
* src/ChunkedDecoder.cc
* src/ChunkedDecoder.h
* src/ChunkedEncoding.cc: Removed
* src/ChunkedEncoding.h: Removed
* src/DownloadCommand.cc
* src/DownloadCommand.h
* src/HttpDownloadCommand.cc
* src/HttpResponse.cc
* src/HttpResponse.h
* src/HttpResponseCommand.cc
* src/HttpSkipResponseCommand.cc
* src/HttpSkipResponseCommand.h
* src/Makefile.am
* src/TransferEncoding.h: Removed
* test/ChunkedDecoderTest.cc
* test/ChunkedEncodingTest.cc: Removed
* test/HttpResponseTest.cc
* test/Makefile.am
Diffstat (limited to 'src')
| -rw-r--r-- | src/A2STR.cc | 2 | ||||
| -rw-r--r-- | src/A2STR.h | 2 | ||||
| -rw-r--r-- | src/ChunkedDecoder.cc | 129 | ||||
| -rw-r--r-- | src/ChunkedDecoder.h (renamed from src/TransferEncoding.h) | 51 | ||||
| -rw-r--r-- | src/ChunkedEncoding.cc | 194 | ||||
| -rw-r--r-- | src/ChunkedEncoding.h | 79 | ||||
| -rw-r--r-- | src/DownloadCommand.cc | 24 | ||||
| -rw-r--r-- | src/DownloadCommand.h | 4 | ||||
| -rw-r--r-- | src/HttpDownloadCommand.cc | 6 | ||||
| -rw-r--r-- | src/HttpResponse.cc | 47 | ||||
| -rw-r--r-- | src/HttpResponse.h | 3 | ||||
| -rw-r--r-- | src/HttpResponseCommand.cc | 33 | ||||
| -rw-r--r-- | src/HttpSkipResponseCommand.cc | 25 | ||||
| -rw-r--r-- | src/HttpSkipResponseCommand.h | 6 | ||||
| -rw-r--r-- | src/Makefile.am | 5 | ||||
| -rw-r--r-- | src/Makefile.in | 55 |
16 files changed, 274 insertions, 391 deletions
diff --git a/src/A2STR.cc b/src/A2STR.cc index 19865046..5f08e7b7 100644 --- a/src/A2STR.cc +++ b/src/A2STR.cc @@ -52,6 +52,8 @@ const std::string A2STR::DOT_C("."); const std::string A2STR::COLON_C(":"); +const std::string A2STR::SEMICOLON_C(";"); + const std::string A2STR::EQUAL_C("="); } // namespace aria2 diff --git a/src/A2STR.h b/src/A2STR.h index b4a8fe4f..d62133c0 100644 --- a/src/A2STR.h +++ b/src/A2STR.h @@ -59,6 +59,8 @@ public: static const std::string COLON_C; + static const std::string SEMICOLON_C; + static const std::string EQUAL_C; }; } // namespace aria2 diff --git a/src/ChunkedDecoder.cc b/src/ChunkedDecoder.cc new file mode 100644 index 00000000..9ec6872a --- /dev/null +++ b/src/ChunkedDecoder.cc @@ -0,0 +1,129 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "ChunkedDecoder.h" +#include "Util.h" +#include "message.h" +#include "DlAbortEx.h" +#include "StringFormat.h" +#include "A2STR.h" + +namespace aria2 { + +const std::string ChunkedDecoder::NAME("ChunkedDecoder"); + +ChunkedDecoder::ChunkedDecoder():_chunkSize(0), _state(READ_SIZE) {} + +ChunkedDecoder::~ChunkedDecoder() {} + +void ChunkedDecoder::init() {} + +static bool readChunkSize(size_t& chunkSize, std::string& in) +{ + std::string::size_type crlfPos = in.find(A2STR::CRLF); + if(crlfPos == std::string::npos) { + return false; + } + std::string::size_type extPos = in.find(A2STR::SEMICOLON_C); + if(extPos == std::string::npos || crlfPos < extPos) { + extPos = crlfPos; + } + chunkSize = Util::parseUInt(in.substr(0, extPos), 16); + in.erase(0, crlfPos+2); + return true; +} + +static bool readData(std::string& out, size_t& chunkSize, std::string& in) +{ + size_t readlen = std::min(chunkSize, in.size()); + out.append(in.begin(), in.begin()+readlen); + in.erase(0, readlen); + chunkSize -= readlen; + if(chunkSize == 0 && in.size() >= 2) { + if(in.find(A2STR::CRLF) == 0) { + in.erase(0, 2); + return true; + } else { + throw DlAbortEx(EX_INVALID_CHUNK_SIZE); + } + } else { + return false; + } +} + +std::string ChunkedDecoder::decode(const unsigned char* inbuf, size_t inlen) +{ + _buf.append(&inbuf[0], &inbuf[inlen]); + + std::string outbuf; + while(1) { + if(_state == READ_SIZE) { + if(readChunkSize(_chunkSize, _buf)) { + if(_chunkSize == 0) { + _state = STREAM_END; + break; + } else { + if(_chunkSize > MAX_CHUNK_SIZE) { + throw DlAbortEx + (StringFormat(EX_TOO_LARGE_CHUNK, _chunkSize).str()); + } + _state = READ_DATA; + } + } else { + break; + } + } else if(_state == READ_DATA) { + if(readData(outbuf, _chunkSize, _buf)) { + _state = READ_SIZE; + } else { + break; + } + } + } + return outbuf; +} + +bool ChunkedDecoder::finished() +{ + return _state == STREAM_END; +} + +void ChunkedDecoder::release() {} + +const std::string& ChunkedDecoder::getName() const +{ + return NAME; +} + +} // namespace aria2 diff --git a/src/TransferEncoding.h b/src/ChunkedDecoder.h index 8f80edd6..e5b58edb 100644 --- a/src/TransferEncoding.h +++ b/src/ChunkedDecoder.h @@ -32,28 +32,47 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#ifndef _D_TRANSFER_ENCODING_H_ -#define _D_TRANSFER_ENCODING_H_ +#ifndef _D_CHUNKED_DECODER_H_ +#define _D_CHUNKED_DECODER_H_ -#include "common.h" -#include "SharedHandle.h" -#include <stdint.h> +#include "Decoder.h" namespace aria2 { -class TransferEncoding { +class ChunkedDecoder : public Decoder { +private: + enum STATE { + READ_SIZE, + READ_DATA, + STREAM_END + }; + + std::string _buf; + + size_t _chunkSize; + + STATE _state; + + static const size_t MAX_CHUNK_SIZE = 1024*1024; + + static const std::string NAME; + public: - virtual ~TransferEncoding() {} - virtual void init() = 0; - virtual void inflate(unsigned char* outbuf, size_t& outlen, - const unsigned char* inbuf, size_t inlen) = 0; - virtual bool finished() = 0; - virtual void end() = 0; -}; + ChunkedDecoder(); -typedef SharedHandle<TransferEncoding> TransferEncodingHandle; + virtual ~ChunkedDecoder(); -} // namespace aria2 + virtual void init(); -#endif // _D_TRANSFER_ENCODING_H_ + virtual std::string decode(const unsigned char* inbuf, size_t inlen); + + virtual bool finished(); + + virtual void release(); + + virtual const std::string& getName() const; +}; + +} // namespace aria2 +#endif // _D_DECODER_H_ diff --git a/src/ChunkedEncoding.cc b/src/ChunkedEncoding.cc deleted file mode 100644 index ea9ea2f2..00000000 --- a/src/ChunkedEncoding.cc +++ /dev/null @@ -1,194 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#include "ChunkedEncoding.h" -#include "DlAbortEx.h" -#include "message.h" -#include "Util.h" -#include "StringFormat.h" -#include <cstring> - -namespace aria2 { - -#define MAX_BUFSIZE (1024*1024) - -ChunkedEncoding::ChunkedEncoding() { - strbufSize = 4096; - strbuf = new unsigned char[strbufSize]; - strbufTail = strbuf; - state = READ_SIZE; - chunkSize = 0; -} - -ChunkedEncoding::~ChunkedEncoding() { - delete [] strbuf; -} - -void ChunkedEncoding::init() { -} - -bool ChunkedEncoding::finished() { - return state == FINISH ? true : false; -} - -void ChunkedEncoding::end() {} - -void ChunkedEncoding::inflate(unsigned char* outbuf, size_t& outlen, - const unsigned char* inbuf, size_t inlen) { - addBuffer(inbuf, inlen); - unsigned char* p = strbuf; - size_t clen = 0; - while(1) { - if(state == READ_SIZE) { - if(readChunkSize(&p) == 0) { - if(chunkSize == 0) { - state = FINISH; - } else { - state = READ_DATA; - } - } else { - // chunk size is not fully received. - break; - } - } else if(state == READ_DATA) { - if(readData(&p, outbuf, clen, outlen) == 0) { - state = READ_SIZE; - } else { - break; - } - } else { - break; - } - // all bytes in strbuf were examined? - if(strbufTail <= p) { - break; - } - } - if(strbufTail <= p) { - strbufTail = strbuf; - } else { - // copy string between [p, strbufTail] - size_t unreadSize = strbufTail-p; - unsigned char* temp = new unsigned char[strbufSize]; - memcpy(temp, p, unreadSize); - delete [] strbuf; - strbuf = temp; - strbufTail = strbuf+unreadSize; - } - outlen = clen; -} - -int ChunkedEncoding::readData(unsigned char** pp, - unsigned char* buf, size_t& len, - size_t maxlen) -{ - if(buf+len == buf+maxlen) { - return -1; - } - if(chunkSize == 0) { - return readDataEOL(pp); - } - size_t wsize; - if((size_t)(strbufTail-*pp) < chunkSize) { - wsize = std::min((size_t)(strbufTail-*pp), maxlen-len); - } else { - wsize = std::min(chunkSize, maxlen-len); - } - memcpy(buf+len, *pp, wsize); - chunkSize -= wsize; - len += wsize; - *pp += wsize; - if(chunkSize == 0) { - return readDataEOL(pp); - } else { - return -1; - } -} - -int ChunkedEncoding::readDataEOL(unsigned char** pp) { - unsigned char* np = reinterpret_cast<unsigned char*>(memchr(*pp, '\n', strbufTail-*pp)); - unsigned char* rp = reinterpret_cast<unsigned char*>(memchr(*pp, '\r', strbufTail-*pp)); - if(np != NULL && rp != NULL && np-rp == 1 && *pp == rp) { - *pp += 2; - return 0; - } else if(strbufTail-*pp < 2) { - return -1; - } else { - throw DlAbortEx(EX_INVALID_CHUNK_SIZE); - } -} - -int ChunkedEncoding::readChunkSize(unsigned char** pp) { - // we read chunk-size from *pp - unsigned char* p; - unsigned char* np = reinterpret_cast<unsigned char*>(memchr(*pp, '\n', strbufTail-*pp)); - unsigned char* rp = reinterpret_cast<unsigned char*>(memchr(*pp, '\r', strbufTail-*pp)); - if(np == NULL || rp == NULL || np-rp != 1) { - // \r\n is not found. Return -1 - return -1; - } - p = rp; - // We ignore chunk-extension - unsigned char* exsp = reinterpret_cast<unsigned char*>(memchr(*pp, ';', strbufTail-*pp)); - if(exsp == 0 || p < exsp) { - exsp = p; - } - std::string temp(*pp, exsp); - chunkSize = Util::parseInt(temp, 16); - if(chunkSize < 0) { - throw DlAbortEx(EX_INVALID_CHUNK_SIZE); - } - *pp = p+2; - return 0; -} - -void ChunkedEncoding::addBuffer(const unsigned char* inbuf, size_t inlen) { - size_t realbufSize = strbufTail-strbuf; - if(realbufSize+inlen >= strbufSize) { - if(realbufSize+inlen > MAX_BUFSIZE) { - throw DlAbortEx - (StringFormat(EX_TOO_LARGE_CHUNK, realbufSize+inlen).str()); - } - strbufSize = realbufSize+inlen; - unsigned char* temp = new unsigned char[strbufSize]; - memcpy(temp, strbuf, realbufSize); - delete [] strbuf; - strbuf = temp; - strbufTail = strbuf+realbufSize; - } - memcpy(strbufTail, inbuf, inlen); - strbufTail += inlen; -} - -} // namespace aria2 diff --git a/src/ChunkedEncoding.h b/src/ChunkedEncoding.h deleted file mode 100644 index 95df857a..00000000 --- a/src/ChunkedEncoding.h +++ /dev/null @@ -1,79 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#ifndef _D_CHUNKED_ENCODING_H_ -#define _D_CHUNKED_ENCODING_H_ - -#include "TransferEncoding.h" - -namespace aria2 { - -class ChunkedEncoding:public TransferEncoding { -private: - enum STATE { - READ_SIZE, - READ_DATA, - FINISH - }; - size_t chunkSize; - STATE state; - unsigned char* strbuf; - size_t strbufSize; - unsigned char* strbufTail; - - /** - * Returns 0 if the size of chunk is retrieved successfully, - * otherwise returns non-zero value. - */ - int readChunkSize(unsigned char** pp); - int readData(unsigned char** pp, unsigned char* buf, size_t& len, - size_t maxlen); - void addBuffer(const unsigned char* inbuf, size_t inlen); - int readDataEOL(unsigned char** pp); - - -public: - ChunkedEncoding(); - ~ChunkedEncoding(); - - void init(); - void inflate(unsigned char* outbuf, size_t& outlen, - const unsigned char* inbuf, size_t inlen); - bool finished(); - void end(); -}; - -} // namespace aria2 - -#endif // _D_CHUNKED_ENCODING_H_ diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index 2b4cfa7b..f7ba463f 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -123,19 +123,18 @@ bool DownloadCommand::executeInternal() { const SharedHandle<DiskAdaptor>& diskAdaptor = _requestGroup->getPieceStorage()->getDiskAdaptor(); - unsigned char* bufFinal; + const unsigned char* bufFinal; size_t bufSizeFinal; - if(transferDecoder.isNull()) { + std::string decoded; + if(_transferEncodingDecoder.isNull()) { bufFinal = buf; bufSizeFinal = bufSize; } else { - size_t infbufSize = 16*1024; - unsigned char infbuf[infbufSize]; - transferDecoder->inflate(infbuf, infbufSize, buf, bufSize); + decoded = _transferEncodingDecoder->decode(buf, bufSize); - bufFinal = infbuf; - bufSizeFinal = infbufSize; + bufFinal = reinterpret_cast<const unsigned char*>(decoded.c_str()); + bufSizeFinal = decoded.size(); } if(_contentEncodingDecoder.isNull()) { @@ -164,10 +163,10 @@ bool DownloadCommand::executeInternal() { if(_requestGroup->getTotalLength() != 0 && bufSize == 0) { throw DlRetryEx(EX_GOT_EOF); } - if((!transferDecoder.isNull() && transferDecoder->finished()) - || (transferDecoder.isNull() && segment->complete()) + if((!_transferEncodingDecoder.isNull() && + _transferEncodingDecoder->finished()) + || (_transferEncodingDecoder.isNull() && segment->complete()) || bufSize == 0) { - if(!transferDecoder.isNull()) transferDecoder->end(); logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid); if(!_contentEncodingDecoder.isNull() && @@ -284,9 +283,10 @@ void DownloadCommand::validatePieceHash(const SharedHandle<Segment>& segment, #endif // ENABLE_MESSAGE_DIGEST -void DownloadCommand::setTransferDecoder(const TransferEncodingHandle& transferDecoder) +void DownloadCommand::setTransferEncodingDecoder +(const SharedHandle<Decoder>& decoder) { - this->transferDecoder = transferDecoder; + this->_transferEncodingDecoder = decoder; } void DownloadCommand::setContentEncodingDecoder diff --git a/src/DownloadCommand.h b/src/DownloadCommand.h index e4388e5a..654824f4 100644 --- a/src/DownloadCommand.h +++ b/src/DownloadCommand.h @@ -67,7 +67,7 @@ private: void checkLowestDownloadSpeed() const; protected: - SharedHandle<TransferEncoding> transferDecoder; + SharedHandle<Decoder> _transferEncodingDecoder; SharedHandle<Decoder> _contentEncodingDecoder; @@ -83,7 +83,7 @@ public: const SharedHandle<SocketCore>& s); virtual ~DownloadCommand(); - void setTransferDecoder(const SharedHandle<TransferEncoding>& transferDecoder); + void setTransferEncodingDecoder(const SharedHandle<Decoder>& decoder); void setContentEncodingDecoder(const SharedHandle<Decoder>& decoder); diff --git a/src/HttpDownloadCommand.cc b/src/HttpDownloadCommand.cc index 4f4cba9d..e5c9ac30 100644 --- a/src/HttpDownloadCommand.cc +++ b/src/HttpDownloadCommand.cc @@ -66,8 +66,10 @@ bool HttpDownloadCommand::prepareForNextSegment() { if(!e->option->getAsBool(PREF_HTTP_PROXY_ENABLED)) { if(req->isPipeliningEnabled() || (req->isKeepAliveEnabled() && - ((!transferDecoder.isNull() && _requestGroup->downloadFinished()) || - (uint64_t)_segments.front()->getPositionToWrite() == _requestGroup->getTotalLength()))) { + ((!_transferEncodingDecoder.isNull() && + _requestGroup->downloadFinished()) || + (uint64_t)_segments.front()->getPositionToWrite() == + _requestGroup->getTotalLength()))) { std::pair<std::string, uint16_t> peerInfo; socket->getPeerInfo(peerInfo); e->poolSocket(peerInfo.first, peerInfo.second, socket); diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc index 5c9c2df4..86a929b2 100644 --- a/src/HttpResponse.cc +++ b/src/HttpResponse.cc @@ -41,13 +41,13 @@ #include "Range.h" #include "LogFactory.h" #include "Logger.h" -#include "ChunkedEncoding.h" #include "Util.h" #include "message.h" #include "DlAbortEx.h" #include "StringFormat.h" #include "A2STR.h" #include "Decoder.h" +#include "ChunkedDecoder.h" #ifdef HAVE_LIBZ # include "GZipDecoder.h" #endif // HAVE_LIBZ @@ -73,21 +73,19 @@ void HttpResponse::validateResponse() const (StringFormat(EX_LOCATION_HEADER_REQUIRED, Util::parseUInt(status)).str()); } - } else { - if(!httpHeader->defined(HttpHeader::TRANSFER_ENCODING)) { - // compare the received range against the requested range - RangeHandle responseRange = httpHeader->getRange(); - if(!httpRequest->isRangeSatisfied(responseRange)) { - throw DlAbortEx - (StringFormat(EX_INVALID_RANGE_HEADER, - Util::itos(httpRequest->getStartByte(), true).c_str(), - Util::itos(httpRequest->getEndByte(), true).c_str(), - Util::uitos(httpRequest->getEntityLength(), true).c_str(), - Util::itos(responseRange->getStartByte(), true).c_str(), - Util::itos(responseRange->getEndByte(), true).c_str(), - Util::uitos(responseRange->getEntityLength(), true).c_str() - ).str()); - } + } else if(!httpHeader->defined(HttpHeader::TRANSFER_ENCODING)) { + // compare the received range against the requested range + RangeHandle responseRange = httpHeader->getRange(); + if(!httpRequest->isRangeSatisfied(responseRange)) { + throw DlAbortEx + (StringFormat + (EX_INVALID_RANGE_HEADER, + Util::itos(httpRequest->getStartByte(), true).c_str(), + Util::itos(httpRequest->getEndByte(), true).c_str(), + Util::uitos(httpRequest->getEntityLength(), true).c_str(), + Util::itos(responseRange->getStartByte(), true).c_str(), + Util::itos(responseRange->getEndByte(), true).c_str(), + Util::uitos(responseRange->getEntityLength(), true).c_str()).str()); } } } @@ -109,10 +107,10 @@ std::string HttpResponse::determinFilename() const void HttpResponse::retrieveCookie() { std::deque<std::string> v = httpHeader->get(HttpHeader::SET_COOKIE); - for(std::deque<std::string>::const_iterator itr = v.begin(); itr != v.end(); itr++) { - std::string domain = httpRequest->getHost(); - std::string path = httpRequest->getDir(); - httpRequest->getRequest()->cookieBox->add(*itr, domain, path); + for(std::deque<std::string>::const_iterator itr = v.begin(); itr != v.end(); + itr++) { + httpRequest->getRequest()->cookieBox->add(*itr, httpRequest->getHost(), + httpRequest->getDir()); } } @@ -141,17 +139,20 @@ bool HttpResponse::isTransferEncodingSpecified() const std::string HttpResponse::getTransferEncoding() const { + // TODO See TODO in getTransferEncodingDecoder() return httpHeader->getFirst(HttpHeader::TRANSFER_ENCODING); } -TransferEncodingHandle HttpResponse::getTransferDecoder() const +SharedHandle<Decoder> HttpResponse::getTransferEncodingDecoder() const { + // TODO Transfer-Encoding header field can contains multiple tokens. We should + // parse the field and retrieve each token. if(isTransferEncodingSpecified()) { if(getTransferEncoding() == HttpHeader::CHUNKED) { - return SharedHandle<TransferEncoding>(new ChunkedEncoding()); + return SharedHandle<Decoder>(new ChunkedDecoder()); } } - return SharedHandle<TransferEncoding>(); + return SharedHandle<Decoder>(); } bool HttpResponse::isContentEncodingSpecified() const diff --git a/src/HttpResponse.h b/src/HttpResponse.h index 71d72c43..aaef9a97 100644 --- a/src/HttpResponse.h +++ b/src/HttpResponse.h @@ -44,7 +44,6 @@ namespace aria2 { class HttpRequest; class HttpHeader; -class TransferEncoding; class Logger; class Decoder; @@ -84,7 +83,7 @@ public: std::string getTransferEncoding() const; - SharedHandle<TransferEncoding> getTransferDecoder() const; + SharedHandle<Decoder> getTransferEncodingDecoder() const; bool isContentEncodingSpecified() const; diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 0cdffcc5..c46014a5 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -180,20 +180,20 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp return true; } -static SharedHandle<TransferEncoding> getTransferEncoding +static SharedHandle<Decoder> getTransferEncodingDecoder (const SharedHandle<HttpResponse>& httpResponse) { - TransferEncodingHandle enc; + SharedHandle<Decoder> decoder; if(httpResponse->isTransferEncodingSpecified()) { - enc = httpResponse->getTransferDecoder(); - if(enc.isNull()) { + decoder = httpResponse->getTransferEncodingDecoder(); + if(decoder.isNull()) { throw DlAbortEx (StringFormat(EX_TRANSFER_ENCODING_NOT_SUPPORTED, httpResponse->getTransferEncoding().c_str()).str()); } - enc->init(); + decoder->init(); } - return enc; + return decoder; } static SharedHandle<Decoder> getContentEncodingDecoder @@ -218,13 +218,13 @@ static SharedHandle<Decoder> getContentEncodingDecoder bool HttpResponseCommand::skipResponseBody (const SharedHandle<HttpResponse>& httpResponse) { - SharedHandle<TransferEncoding> enc(getTransferEncoding(httpResponse)); + SharedHandle<Decoder> decoder = getTransferEncodingDecoder(httpResponse); // We don't use Content-Encoding here because this response body is just // thrown away. HttpSkipResponseCommand* command = new HttpSkipResponseCommand (cuid, req, _requestGroup, httpConnection, httpResponse, e, socket); - command->setTransferDecoder(enc); + command->setTransferEncodingDecoder(decoder); // If the response body is zero-length, set command's status to real time // so that avoid read check blocking @@ -238,18 +238,23 @@ bool HttpResponseCommand::skipResponseBody return true; } -HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpResponseHandle& httpResponse) +HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand +(const HttpResponseHandle& httpResponse) { - TransferEncodingHandle enc = getTransferEncoding(httpResponse); + SharedHandle<Decoder> transferEncodingDecoder = + getTransferEncodingDecoder(httpResponse); SharedHandle<Decoder> contentEncodingDecoder = getContentEncodingDecoder(httpResponse); HttpDownloadCommand* command = - new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e, socket); - command->setMaxDownloadSpeedLimit(e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT)); + new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e, + socket); + command->setMaxDownloadSpeedLimit + (e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT)); command->setStartupIdleTime(e->option->getAsInt(PREF_STARTUP_IDLE_TIME)); - command->setLowestDownloadSpeedLimit(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT)); - command->setTransferDecoder(enc); + command->setLowestDownloadSpeedLimit + (e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT)); + command->setTransferEncodingDecoder(transferEncodingDecoder); if(!contentEncodingDecoder.isNull()) { command->setContentEncodingDecoder(contentEncodingDecoder); diff --git a/src/HttpSkipResponseCommand.cc b/src/HttpSkipResponseCommand.cc index 8e6dafc9..0ed640cd 100644 --- a/src/HttpSkipResponseCommand.cc +++ b/src/HttpSkipResponseCommand.cc @@ -37,7 +37,7 @@ #include "HttpResponse.h" #include "message.h" #include "SocketCore.h" -#include "TransferEncoding.h" +#include "Decoder.h" #include "DlRetryEx.h" #include "Request.h" #include "DownloadEngine.h" @@ -70,15 +70,15 @@ HttpSkipResponseCommand::HttpSkipResponseCommand HttpSkipResponseCommand::~HttpSkipResponseCommand() {} -void HttpSkipResponseCommand::setTransferDecoder -(const SharedHandle<TransferEncoding>& transferDecoder) +void HttpSkipResponseCommand::setTransferEncodingDecoder +(const SharedHandle<Decoder>& decoder) { - _transferDecoder = transferDecoder; + _transferEncodingDecoder = decoder; } bool HttpSkipResponseCommand::executeInternal() { - if(_totalLength == 0 && _transferDecoder.isNull()) { + if(_totalLength == 0 && _transferEncodingDecoder.isNull()) { return processResponse(); } const size_t BUFSIZE = 16*1024; @@ -88,13 +88,12 @@ bool HttpSkipResponseCommand::executeInternal() try { socket->readData(buf, bufSize); - if(_transferDecoder.isNull()) { + if(_transferEncodingDecoder.isNull()) { _receivedBytes += bufSize; } else { // _receivedBytes is not updated if transferEncoding is set. - size_t infbufSize = 16*1024; - unsigned char infbuf[infbufSize]; - _transferDecoder->inflate(infbuf, infbufSize, buf, bufSize); + // The return value is safely ignored here. + _transferEncodingDecoder->decode(buf, bufSize); } if(_totalLength != 0 && bufSize == 0) { throw DlRetryEx(EX_GOT_EOF); @@ -109,10 +108,10 @@ bool HttpSkipResponseCommand::executeInternal() // readable, bufSize == 0 means server shutdown the connection. // So socket cannot be reused in this case. return prepareForRetry(0); - } else if((!_transferDecoder.isNull() && _transferDecoder->finished()) - || (_transferDecoder.isNull() && _totalLength == _receivedBytes)) { - if(!_transferDecoder.isNull()) _transferDecoder->end(); - + } else if((!_transferEncodingDecoder.isNull() && + _transferEncodingDecoder->finished()) + || (_transferEncodingDecoder.isNull() && + _totalLength == _receivedBytes)) { if(!e->option->getAsBool(PREF_HTTP_PROXY_ENABLED) && req->supportsPersistentConnection()) { std::pair<std::string, uint16_t> peerInfo; diff --git a/src/HttpSkipResponseCommand.h b/src/HttpSkipResponseCommand.h index d6c32e5f..f0af1e60 100644 --- a/src/HttpSkipResponseCommand.h +++ b/src/HttpSkipResponseCommand.h @@ -41,7 +41,7 @@ namespace aria2 { class HttpConnection; class HttpResponse; -class TransferEncoding; +class Decoder; class HttpSkipResponseCommand : public AbstractCommand { private: @@ -49,7 +49,7 @@ private: SharedHandle<HttpResponse> _httpResponse; - SharedHandle<TransferEncoding> _transferDecoder; + SharedHandle<Decoder> _transferEncodingDecoder; uint64_t _totalLength; @@ -69,7 +69,7 @@ public: virtual ~HttpSkipResponseCommand(); - void setTransferDecoder(const SharedHandle<TransferEncoding>& transferDecoder); + void setTransferEncodingDecoder(const SharedHandle<Decoder>& decoder); }; } // namespace aria2 diff --git a/src/Makefile.am b/src/Makefile.am index 937424bc..582aae9a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,8 +41,6 @@ SRCS = Socket.h\ DownloadFailureException.h\ Logger.h\ SimpleLogger.cc SimpleLogger.h\ - TransferEncoding.h\ - ChunkedEncoding.cc ChunkedEncoding.h\ DiskWriter.h\ DiskWriterFactory.h\ AbstractDiskWriter.cc AbstractDiskWriter.h\ @@ -189,7 +187,8 @@ SRCS = Socket.h\ FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h\ A2STR.cc A2STR.h\ RarestPieceSelector.cc RarestPieceSelector.h\ - Decoder.h + Decoder.h\ + ChunkedDecoder.cc ChunkedDecoder.h if HAVE_LIBZ SRCS += GZipDecoder.cc GZipDecoder.h diff --git a/src/Makefile.in b/src/Makefile.in index d15845e4..3f07f0c1 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -317,8 +317,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ message.h Exception.cc Exception.h FatalException.h \ RecoverableException.h DlAbortEx.h DlRetryEx.h \ DownloadFailureException.h Logger.h SimpleLogger.cc \ - SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \ - ChunkedEncoding.h DiskWriter.h DiskWriterFactory.h \ + SimpleLogger.h DiskWriter.h DiskWriterFactory.h \ AbstractDiskWriter.cc AbstractDiskWriter.h \ DefaultDiskWriter.cc DefaultDiskWriter.h \ DefaultDiskWriterFactory.cc DefaultDiskWriterFactory.h File.cc \ @@ -407,8 +406,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ InitiateConnectionCommand.cc InitiateConnectionCommand.h \ FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \ A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \ - Decoder.h GZipDecoder.cc GZipDecoder.h AsyncNameResolver.cc \ - AsyncNameResolver.h IteratableChunkChecksumValidator.cc \ + Decoder.h ChunkedDecoder.cc ChunkedDecoder.h GZipDecoder.cc \ + GZipDecoder.h AsyncNameResolver.cc AsyncNameResolver.h \ + IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.h \ IteratableChecksumValidator.cc IteratableChecksumValidator.h \ CheckIntegrityCommand.cc CheckIntegrityCommand.h \ @@ -740,15 +740,14 @@ am__objects_17 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ DownloadEngine.$(OBJEXT) GrowSegment.$(OBJEXT) \ PiecedSegment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \ Request.$(OBJEXT) Exception.$(OBJEXT) SimpleLogger.$(OBJEXT) \ - ChunkedEncoding.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \ - DefaultDiskWriter.$(OBJEXT) DefaultDiskWriterFactory.$(OBJEXT) \ - File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \ - CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \ - FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \ - SpeedCalc.$(OBJEXT) BitfieldMan.$(OBJEXT) \ - BitfieldManFactory.$(OBJEXT) SimpleRandomizer.$(OBJEXT) \ - HttpResponse.$(OBJEXT) HttpRequest.$(OBJEXT) \ - AbstractProxyRequestCommand.$(OBJEXT) \ + AbstractDiskWriter.$(OBJEXT) DefaultDiskWriter.$(OBJEXT) \ + DefaultDiskWriterFactory.$(OBJEXT) File.$(OBJEXT) \ + Option.$(OBJEXT) Base64.$(OBJEXT) CookieBox.$(OBJEXT) \ + LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) FeatureConfig.$(OBJEXT) \ + DownloadEngineFactory.$(OBJEXT) SpeedCalc.$(OBJEXT) \ + BitfieldMan.$(OBJEXT) BitfieldManFactory.$(OBJEXT) \ + SimpleRandomizer.$(OBJEXT) HttpResponse.$(OBJEXT) \ + HttpRequest.$(OBJEXT) AbstractProxyRequestCommand.$(OBJEXT) \ AbstractProxyResponseCommand.$(OBJEXT) Netrc.$(OBJEXT) \ AuthConfig.$(OBJEXT) AbstractAuthResolver.$(OBJEXT) \ DefaultAuthResolver.$(OBJEXT) NetrcAuthResolver.$(OBJEXT) \ @@ -794,12 +793,13 @@ am__objects_17 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ HttpSkipResponseCommand.$(OBJEXT) \ InitiateConnectionCommand.$(OBJEXT) \ FtpFinishDownloadCommand.$(OBJEXT) A2STR.$(OBJEXT) \ - RarestPieceSelector.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_5) $(am__objects_6) $(am__objects_7) \ - $(am__objects_8) $(am__objects_9) $(am__objects_10) \ - $(am__objects_11) $(am__objects_12) $(am__objects_13) \ - $(am__objects_14) $(am__objects_15) $(am__objects_16) + RarestPieceSelector.$(OBJEXT) ChunkedDecoder.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) \ + $(am__objects_7) $(am__objects_8) $(am__objects_9) \ + $(am__objects_10) $(am__objects_11) $(am__objects_12) \ + $(am__objects_13) $(am__objects_14) $(am__objects_15) \ + $(am__objects_16) am_libaria2c_a_OBJECTS = $(am__objects_17) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" @@ -1027,8 +1027,7 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ message.h Exception.cc Exception.h FatalException.h \ RecoverableException.h DlAbortEx.h DlRetryEx.h \ DownloadFailureException.h Logger.h SimpleLogger.cc \ - SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \ - ChunkedEncoding.h DiskWriter.h DiskWriterFactory.h \ + SimpleLogger.h DiskWriter.h DiskWriterFactory.h \ AbstractDiskWriter.cc AbstractDiskWriter.h \ DefaultDiskWriter.cc DefaultDiskWriter.h \ DefaultDiskWriterFactory.cc DefaultDiskWriterFactory.h File.cc \ @@ -1117,12 +1116,12 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ InitiateConnectionCommand.cc InitiateConnectionCommand.h \ FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \ A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \ - Decoder.h $(am__append_1) $(am__append_2) $(am__append_3) \ - $(am__append_4) $(am__append_5) $(am__append_6) \ - $(am__append_7) $(am__append_8) $(am__append_9) \ - $(am__append_10) $(am__append_11) $(am__append_12) \ - $(am__append_13) $(am__append_14) $(am__append_15) \ - $(am__append_16) + Decoder.h ChunkedDecoder.cc ChunkedDecoder.h $(am__append_1) \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) $(am__append_6) $(am__append_7) \ + $(am__append_8) $(am__append_9) $(am__append_10) \ + $(am__append_11) $(am__append_12) $(am__append_13) \ + $(am__append_14) $(am__append_15) $(am__append_16) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -1264,7 +1263,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChecksumCheckIntegrityEntry.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncoding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedDecoder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Command.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompactPeerListProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleStatCalc.Po@am__quote@ |
