Przeglądaj źródła

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
Tatsuhiro Tsujikawa 17 lat temu
rodzic
commit
92c66d24ac

+ 24 - 0
ChangeLog

@@ -1,3 +1,27 @@
+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
+
 2008-07-01  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Use append instead of insert.

+ 2 - 0
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

+ 2 - 0
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

+ 129 - 0
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

+ 35 - 16
src/TransferEncoding.h → 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_

+ 0 - 194
src/ChunkedEncoding.cc

@@ -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

+ 0 - 79
src/ChunkedEncoding.h

@@ -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_

+ 12 - 12
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

+ 2 - 2
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);
 

+ 4 - 2
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);

+ 24 - 23
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

+ 1 - 2
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;
 

+ 19 - 14
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);

+ 12 - 13
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;

+ 3 - 3
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

+ 2 - 3
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

+ 27 - 28
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@

+ 146 - 0
test/ChunkedDecoderTest.cc

@@ -0,0 +1,146 @@
+#include "ChunkedDecoder.h"
+#include "DlAbortEx.h"
+#include <iostream>
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace aria2 {
+
+class ChunkedDecoderTest:public CppUnit::TestFixture {
+
+  CPPUNIT_TEST_SUITE(ChunkedDecoderTest);
+  CPPUNIT_TEST(testDecode);
+  CPPUNIT_TEST(testDecode_tooLargeChunkSize);
+  CPPUNIT_TEST(testDecode_chunkSizeMismatch);
+  CPPUNIT_TEST(testGetName);
+  CPPUNIT_TEST_SUITE_END();
+public:
+  void setUp() {}
+
+  void testDecode();
+  void testDecode_tooLargeChunkSize();
+  void testDecode_chunkSizeMismatch();
+  void testGetName();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( ChunkedDecoderTest );
+
+void ChunkedDecoderTest::testDecode()
+{
+  ChunkedDecoder decoder;
+  decoder.init();
+
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>("a\r\n1234567890\r\n");
+    CPPUNIT_ASSERT_EQUAL(std::string("1234567890"),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // Feed extension; see it is ignored.
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>
+      ("3;extensionIgnored\r\n123\r\n");
+    CPPUNIT_ASSERT_EQUAL(std::string("123"),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // Not all chunk size is available
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>("1");
+    CPPUNIT_ASSERT_EQUAL(std::string(),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>("0\r\n1234567890123456\r\n");
+    CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // Not all chunk data is available
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>("10\r\n1234567890");
+    CPPUNIT_ASSERT_EQUAL(std::string("1234567890"),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>("123456\r\n");
+    CPPUNIT_ASSERT_EQUAL(std::string("123456"),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // no trailing CR LF.
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>
+      ("10\r\n1234567890123456");
+    CPPUNIT_ASSERT_EQUAL(std::string("1234567890123456"),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // feed only CR
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>
+      ("\r");
+    CPPUNIT_ASSERT_EQUAL(std::string(),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // feed next LF
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>
+      ("\n");
+    CPPUNIT_ASSERT_EQUAL(std::string(),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // feed 0 CR LF.
+  {
+    std::basic_string<unsigned char> msg =
+      reinterpret_cast<const unsigned char*>
+      ("0\r\n");
+    CPPUNIT_ASSERT_EQUAL(std::string(),
+			 decoder.decode(msg.c_str(), msg.size()));
+  }
+  // input is over
+  CPPUNIT_ASSERT(decoder.finished());
+
+  decoder.release();
+}
+
+void ChunkedDecoderTest::testDecode_tooLargeChunkSize()
+{
+  // Feed chunkSize == ChunkedDecoder::MAX_CHUNK_SIZE + 1 == 0x100001.
+  std::basic_string<unsigned char> msg =
+    reinterpret_cast<const unsigned char*>("100001\r\n");
+
+  ChunkedDecoder decoder;
+  try {
+    decoder.decode(msg.c_str(), msg.size());
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(DlAbortEx& e) {
+    // success
+  }
+}
+
+void ChunkedDecoderTest::testDecode_chunkSizeMismatch()
+{
+  std::basic_string<unsigned char> msg =
+    reinterpret_cast<const unsigned char*>("3\r\n1234\r\n");
+
+  ChunkedDecoder decoder;
+  try {
+    decoder.decode(msg.c_str(), msg.size());
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(DlAbortEx& e) {
+    // success
+  }
+}
+
+void ChunkedDecoderTest::testGetName()
+{
+  ChunkedDecoder decoder;
+  CPPUNIT_ASSERT_EQUAL(std::string("ChunkedDecoder"), decoder.getName());
+}
+
+} // namespace aria2

+ 0 - 70
test/ChunkedEncodingTest.cc

@@ -1,70 +0,0 @@
-#include "ChunkedEncoding.h"
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <cppunit/extensions/HelperMacros.h>
-
-namespace aria2 {
-
-class ChunkedEncodingTest:public CppUnit::TestFixture {
-
-  CPPUNIT_TEST_SUITE(ChunkedEncodingTest);
-  CPPUNIT_TEST(testInflate1);
-  CPPUNIT_TEST(testInflateLargeChunk);
-  CPPUNIT_TEST_SUITE_END();
-private:
-  ChunkedEncoding* enc;
-public:
-  void setUp() {
-    enc = new ChunkedEncoding();
-    enc->init();
-  }
-
-  void testInflate1();
-  void testInflateLargeChunk();
-
-};
-
-
-CPPUNIT_TEST_SUITE_REGISTRATION( ChunkedEncodingTest );
-
-void ChunkedEncodingTest::testInflate1() {
-  std::string msg = "a\r\n1234567890\r\n";
-  unsigned char buf[100];
-  size_t len = sizeof(buf);
-  enc->inflate(buf, len,
-	       reinterpret_cast<const unsigned char*>(msg.c_str()), msg.size());
-  CPPUNIT_ASSERT_EQUAL(std::string("1234567890"), std::string(&buf[0], &buf[len]));
-  // second pass
-  len = sizeof(buf);
-  msg = "3;extensionIgnored\r\n123\r\n0\r\n";
-  enc->inflate(buf, len,
-	       reinterpret_cast<const unsigned char*>(msg.c_str()), msg.size());
-  CPPUNIT_ASSERT_EQUAL(std::string("123"), std::string(&buf[0], &buf[len]));
-  // input is over
-  CPPUNIT_ASSERT(enc->finished());
-}
-
-void ChunkedEncodingTest::testInflateLargeChunk() {
-  // give over 4096 character chunk
-  std::fstream is("4096chunk.txt", std::ios::in);
-  if(is.fail()) {
-    CPPUNIT_FAIL("cannot open file 4096chunk.txt");
-  }
-  std::string body;
-  is >> body;
-  unsigned char buf[4097];
-  size_t len = sizeof(buf);
-  for(int i = 0; i < 2; i++) {
-    std::string msg = "1000\r\n"+body+"\r\n";
-    len = sizeof(buf);
-    enc->inflate(buf, len,
-		 reinterpret_cast<const unsigned char*>(msg.c_str()), msg.size());
-    CPPUNIT_ASSERT_EQUAL(body, std::string(&buf[0], &buf[len]));
-  }
-  enc->inflate(buf, len, reinterpret_cast<const unsigned char*>("0\r\n"), 3);
-  CPPUNIT_ASSERT_EQUAL((size_t)0, len);
-  CPPUNIT_ASSERT(enc->finished());
-}
-
-} // namespace aria2

+ 14 - 11
test/HttpResponseTest.cc

@@ -2,7 +2,6 @@
 #include "prefs.h"
 #include "PiecedSegment.h"
 #include "Piece.h"
-#include "TransferEncoding.h"
 #include "Request.h"
 #include "HttpHeader.h"
 #include "HttpRequest.h"
@@ -30,7 +29,7 @@ class HttpResponseTest : public CppUnit::TestFixture {
   CPPUNIT_TEST(testIsRedirect);
   CPPUNIT_TEST(testIsTransferEncodingSpecified);
   CPPUNIT_TEST(testGetTransferEncoding);
-  CPPUNIT_TEST(testGetTransferDecoder);
+  CPPUNIT_TEST(testGetTransferEncodingDecoder);
   CPPUNIT_TEST(testIsContentEncodingSpecified);
   CPPUNIT_TEST(testGetContentEncoding);
   CPPUNIT_TEST(testGetContentEncodingDecoder);
@@ -58,7 +57,7 @@ public:
   void testIsRedirect();
   void testIsTransferEncodingSpecified();
   void testGetTransferEncoding();
-  void testGetTransferDecoder();
+  void testGetTransferEncodingDecoder();
   void testIsContentEncodingSpecified();
   void testGetContentEncoding();
   void testGetContentEncodingDecoder();
@@ -134,7 +133,8 @@ void HttpResponseTest::testDeterminFilename_without_ContentDisposition()
 		       httpResponse.determinFilename());
 }
 
-void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length()
+void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length
+()
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
@@ -155,7 +155,8 @@ void HttpResponseTest::testDeterminFilename_with_ContentDisposition()
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpHeader->put("Content-Disposition", "attachment; filename=\"aria2-current.tar.bz2\"");
+  httpHeader->put("Content-Disposition",
+		  "attachment; filename=\"aria2-current.tar.bz2\"");
   SharedHandle<HttpRequest> httpRequest(new HttpRequest());
   SharedHandle<Request> request(new Request());
   request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
@@ -186,8 +187,9 @@ void HttpResponseTest::testGetRedirectURI_with_Location()
   httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
   httpResponse.setHttpHeader(httpHeader);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/download/aria2-1.0.0.tar.bz2"),
-		       httpResponse.getRedirectURI());
+  CPPUNIT_ASSERT_EQUAL
+    (std::string("http://localhost/download/aria2-1.0.0.tar.bz2"),
+     httpResponse.getRedirectURI());
 }
 
 void HttpResponseTest::testIsRedirect()
@@ -231,21 +233,22 @@ void HttpResponseTest::testGetTransferEncoding()
 
   httpHeader->put("Transfer-Encoding", "chunked");
 
-  CPPUNIT_ASSERT_EQUAL(std::string("chunked"), httpResponse.getTransferEncoding());
+  CPPUNIT_ASSERT_EQUAL(std::string("chunked"),
+		       httpResponse.getTransferEncoding());
 }
 
-void HttpResponseTest::testGetTransferDecoder()
+void HttpResponseTest::testGetTransferEncodingDecoder()
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
 
   httpResponse.setHttpHeader(httpHeader);
 
-  CPPUNIT_ASSERT(httpResponse.getTransferDecoder().isNull());  
+  CPPUNIT_ASSERT(httpResponse.getTransferEncodingDecoder().isNull());  
 
   httpHeader->put("Transfer-Encoding", "chunked");
 
-  CPPUNIT_ASSERT(!httpResponse.getTransferDecoder().isNull());
+  CPPUNIT_ASSERT(!httpResponse.getTransferEncodingDecoder().isNull());
 }
 
 void HttpResponseTest::testIsContentEncodingSpecified()

+ 2 - 2
test/Makefile.am

@@ -40,7 +40,6 @@ aria2c_SOURCES = AllTest.cc\
 	HttpHeaderTest.cc\
 	HttpResponseTest.cc\
 	SharedHandleTest.cc\
-	ChunkedEncodingTest.cc\
 	FileTest.cc\
 	OptionTest.cc\
 	DefaultDiskWriterTest.cc\
@@ -52,7 +51,8 @@ aria2c_SOURCES = AllTest.cc\
 	ProtocolDetectorTest.cc\
 	StringFormatTest.cc\
 	ExceptionTest.cc\
-	DownloadHandlerFactoryTest.cc
+	DownloadHandlerFactoryTest.cc\
+	ChunkedDecoderTest.cc
 
 if HAVE_LIBZ
 aria2c_SOURCES += GZipDecoderTest.cc

+ 18 - 17
test/Makefile.in

@@ -182,13 +182,13 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \
 	NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
 	OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
 	NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \
-	HttpResponseTest.cc SharedHandleTest.cc ChunkedEncodingTest.cc \
-	FileTest.cc OptionTest.cc DefaultDiskWriterTest.cc \
-	FeatureConfigTest.cc SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
+	HttpResponseTest.cc SharedHandleTest.cc FileTest.cc \
+	OptionTest.cc DefaultDiskWriterTest.cc FeatureConfigTest.cc \
+	SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
 	MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \
 	ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \
-	DownloadHandlerFactoryTest.cc GZipDecoderTest.cc \
-	MessageDigestHelperTest.cc \
+	DownloadHandlerFactoryTest.cc ChunkedDecoderTest.cc \
+	GZipDecoderTest.cc MessageDigestHelperTest.cc \
 	IteratableChunkChecksumValidatorTest.cc \
 	IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
 	BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
@@ -345,15 +345,15 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) SocketCoreTest.$(OBJEXT) \
 	SegmentManTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \
 	NetrcTest.$(OBJEXT) SingletonHolderTest.$(OBJEXT) \
 	HttpHeaderTest.$(OBJEXT) HttpResponseTest.$(OBJEXT) \
-	SharedHandleTest.$(OBJEXT) ChunkedEncodingTest.$(OBJEXT) \
-	FileTest.$(OBJEXT) OptionTest.$(OBJEXT) \
-	DefaultDiskWriterTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \
-	SpeedCalcTest.$(OBJEXT) MultiDiskAdaptorTest.$(OBJEXT) \
+	SharedHandleTest.$(OBJEXT) FileTest.$(OBJEXT) \
+	OptionTest.$(OBJEXT) DefaultDiskWriterTest.$(OBJEXT) \
+	FeatureConfigTest.$(OBJEXT) SpeedCalcTest.$(OBJEXT) \
+	MultiDiskAdaptorTest.$(OBJEXT) \
 	MultiFileAllocationIteratorTest.$(OBJEXT) \
 	ProtocolDetectorTest.$(OBJEXT) StringFormatTest.$(OBJEXT) \
 	ExceptionTest.$(OBJEXT) DownloadHandlerFactoryTest.$(OBJEXT) \
-	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
-	$(am__objects_4)
+	ChunkedDecoderTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
+	$(am__objects_3) $(am__objects_4)
 aria2c_OBJECTS = $(am_aria2c_OBJECTS)
 am__DEPENDENCIES_1 =
 aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1)
@@ -562,13 +562,14 @@ aria2c_SOURCES = AllTest.cc SocketCoreTest.cc array_funTest.cc \
 	NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
 	OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
 	NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \
-	HttpResponseTest.cc SharedHandleTest.cc ChunkedEncodingTest.cc \
-	FileTest.cc OptionTest.cc DefaultDiskWriterTest.cc \
-	FeatureConfigTest.cc SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
+	HttpResponseTest.cc SharedHandleTest.cc FileTest.cc \
+	OptionTest.cc DefaultDiskWriterTest.cc FeatureConfigTest.cc \
+	SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
 	MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \
 	ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \
-	DownloadHandlerFactoryTest.cc $(am__append_1) $(am__append_2) \
-	$(am__append_3) $(am__append_4)
+	DownloadHandlerFactoryTest.cc ChunkedDecoderTest.cc \
+	$(am__append_1) $(am__append_2) $(am__append_3) \
+	$(am__append_4)
 
 #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
 #aria2c_LDFLAGS = ${CPPUNIT_LIBS}
@@ -683,7 +684,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSuggestPieceMessageTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessageTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ByteArrayDiskWriterTest.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncodingTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedDecoderTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxFactoryTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieParserTest.Po@am__quote@