summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-07-01 11:38:25 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-07-01 11:38:25 +0000
commit92c66d24acb2ef0c4324e682d32491bed04cab75 (patch)
tree1123b7d1647b8500c63aa2739befb6ceb68e5ccb /src
parent61bb4bc02e662a33ae0d7a9747d28898ed847276 (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.cc2
-rw-r--r--src/A2STR.h2
-rw-r--r--src/ChunkedDecoder.cc129
-rw-r--r--src/ChunkedDecoder.h (renamed from src/TransferEncoding.h)51
-rw-r--r--src/ChunkedEncoding.cc194
-rw-r--r--src/ChunkedEncoding.h79
-rw-r--r--src/DownloadCommand.cc24
-rw-r--r--src/DownloadCommand.h4
-rw-r--r--src/HttpDownloadCommand.cc6
-rw-r--r--src/HttpResponse.cc47
-rw-r--r--src/HttpResponse.h3
-rw-r--r--src/HttpResponseCommand.cc33
-rw-r--r--src/HttpSkipResponseCommand.cc25
-rw-r--r--src/HttpSkipResponseCommand.h6
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.in55
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@