mirror of https://github.com/aria2/aria2
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.ampull/1/head
parent
61bb4bc02e
commit
92c66d24ac
24
ChangeLog
24
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>
|
2008-07-01 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
Use append instead of insert.
|
Use append instead of insert.
|
||||||
|
|
|
@ -52,6 +52,8 @@ const std::string A2STR::DOT_C(".");
|
||||||
|
|
||||||
const std::string A2STR::COLON_C(":");
|
const std::string A2STR::COLON_C(":");
|
||||||
|
|
||||||
|
const std::string A2STR::SEMICOLON_C(";");
|
||||||
|
|
||||||
const std::string A2STR::EQUAL_C("=");
|
const std::string A2STR::EQUAL_C("=");
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -59,6 +59,8 @@ public:
|
||||||
|
|
||||||
static const std::string COLON_C;
|
static const std::string COLON_C;
|
||||||
|
|
||||||
|
static const std::string SEMICOLON_C;
|
||||||
|
|
||||||
static const std::string EQUAL_C;
|
static const std::string EQUAL_C;
|
||||||
};
|
};
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -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
|
|
@ -32,28 +32,47 @@
|
||||||
* files in the program, then also delete it here.
|
* files in the program, then also delete it here.
|
||||||
*/
|
*/
|
||||||
/* copyright --> */
|
/* copyright --> */
|
||||||
#ifndef _D_TRANSFER_ENCODING_H_
|
#ifndef _D_CHUNKED_DECODER_H_
|
||||||
#define _D_TRANSFER_ENCODING_H_
|
#define _D_CHUNKED_DECODER_H_
|
||||||
|
|
||||||
#include "common.h"
|
#include "Decoder.h"
|
||||||
#include "SharedHandle.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
class TransferEncoding {
|
class ChunkedDecoder : public Decoder {
|
||||||
public:
|
private:
|
||||||
virtual ~TransferEncoding() {}
|
enum STATE {
|
||||||
virtual void init() = 0;
|
READ_SIZE,
|
||||||
virtual void inflate(unsigned char* outbuf, size_t& outlen,
|
READ_DATA,
|
||||||
const unsigned char* inbuf, size_t inlen) = 0;
|
STREAM_END
|
||||||
virtual bool finished() = 0;
|
};
|
||||||
virtual void end() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SharedHandle<TransferEncoding> TransferEncodingHandle;
|
std::string _buf;
|
||||||
|
|
||||||
|
size_t _chunkSize;
|
||||||
|
|
||||||
|
STATE _state;
|
||||||
|
|
||||||
|
static const size_t MAX_CHUNK_SIZE = 1024*1024;
|
||||||
|
|
||||||
|
static const std::string NAME;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChunkedDecoder();
|
||||||
|
|
||||||
|
virtual ~ChunkedDecoder();
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
|
||||||
|
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
|
} // namespace aria2
|
||||||
|
|
||||||
#endif // _D_TRANSFER_ENCODING_H_
|
#endif // _D_DECODER_H_
|
||||||
|
|
|
@ -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
|
|
|
@ -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_
|
|
|
@ -123,19 +123,18 @@ bool DownloadCommand::executeInternal() {
|
||||||
const SharedHandle<DiskAdaptor>& diskAdaptor =
|
const SharedHandle<DiskAdaptor>& diskAdaptor =
|
||||||
_requestGroup->getPieceStorage()->getDiskAdaptor();
|
_requestGroup->getPieceStorage()->getDiskAdaptor();
|
||||||
|
|
||||||
unsigned char* bufFinal;
|
const unsigned char* bufFinal;
|
||||||
size_t bufSizeFinal;
|
size_t bufSizeFinal;
|
||||||
|
|
||||||
if(transferDecoder.isNull()) {
|
std::string decoded;
|
||||||
|
if(_transferEncodingDecoder.isNull()) {
|
||||||
bufFinal = buf;
|
bufFinal = buf;
|
||||||
bufSizeFinal = bufSize;
|
bufSizeFinal = bufSize;
|
||||||
} else {
|
} else {
|
||||||
size_t infbufSize = 16*1024;
|
decoded = _transferEncodingDecoder->decode(buf, bufSize);
|
||||||
unsigned char infbuf[infbufSize];
|
|
||||||
transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
|
|
||||||
|
|
||||||
bufFinal = infbuf;
|
bufFinal = reinterpret_cast<const unsigned char*>(decoded.c_str());
|
||||||
bufSizeFinal = infbufSize;
|
bufSizeFinal = decoded.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_contentEncodingDecoder.isNull()) {
|
if(_contentEncodingDecoder.isNull()) {
|
||||||
|
@ -164,10 +163,10 @@ bool DownloadCommand::executeInternal() {
|
||||||
if(_requestGroup->getTotalLength() != 0 && bufSize == 0) {
|
if(_requestGroup->getTotalLength() != 0 && bufSize == 0) {
|
||||||
throw DlRetryEx(EX_GOT_EOF);
|
throw DlRetryEx(EX_GOT_EOF);
|
||||||
}
|
}
|
||||||
if((!transferDecoder.isNull() && transferDecoder->finished())
|
if((!_transferEncodingDecoder.isNull() &&
|
||||||
|| (transferDecoder.isNull() && segment->complete())
|
_transferEncodingDecoder->finished())
|
||||||
|
|| (_transferEncodingDecoder.isNull() && segment->complete())
|
||||||
|| bufSize == 0) {
|
|| bufSize == 0) {
|
||||||
if(!transferDecoder.isNull()) transferDecoder->end();
|
|
||||||
logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
|
logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
|
||||||
|
|
||||||
if(!_contentEncodingDecoder.isNull() &&
|
if(!_contentEncodingDecoder.isNull() &&
|
||||||
|
@ -284,9 +283,10 @@ void DownloadCommand::validatePieceHash(const SharedHandle<Segment>& segment,
|
||||||
|
|
||||||
#endif // ENABLE_MESSAGE_DIGEST
|
#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
|
void DownloadCommand::setContentEncodingDecoder
|
||||||
|
|
|
@ -67,7 +67,7 @@ private:
|
||||||
|
|
||||||
void checkLowestDownloadSpeed() const;
|
void checkLowestDownloadSpeed() const;
|
||||||
protected:
|
protected:
|
||||||
SharedHandle<TransferEncoding> transferDecoder;
|
SharedHandle<Decoder> _transferEncodingDecoder;
|
||||||
|
|
||||||
SharedHandle<Decoder> _contentEncodingDecoder;
|
SharedHandle<Decoder> _contentEncodingDecoder;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ public:
|
||||||
const SharedHandle<SocketCore>& s);
|
const SharedHandle<SocketCore>& s);
|
||||||
virtual ~DownloadCommand();
|
virtual ~DownloadCommand();
|
||||||
|
|
||||||
void setTransferDecoder(const SharedHandle<TransferEncoding>& transferDecoder);
|
void setTransferEncodingDecoder(const SharedHandle<Decoder>& decoder);
|
||||||
|
|
||||||
void setContentEncodingDecoder(const SharedHandle<Decoder>& decoder);
|
void setContentEncodingDecoder(const SharedHandle<Decoder>& decoder);
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,10 @@ bool HttpDownloadCommand::prepareForNextSegment() {
|
||||||
if(!e->option->getAsBool(PREF_HTTP_PROXY_ENABLED)) {
|
if(!e->option->getAsBool(PREF_HTTP_PROXY_ENABLED)) {
|
||||||
if(req->isPipeliningEnabled() ||
|
if(req->isPipeliningEnabled() ||
|
||||||
(req->isKeepAliveEnabled() &&
|
(req->isKeepAliveEnabled() &&
|
||||||
((!transferDecoder.isNull() && _requestGroup->downloadFinished()) ||
|
((!_transferEncodingDecoder.isNull() &&
|
||||||
(uint64_t)_segments.front()->getPositionToWrite() == _requestGroup->getTotalLength()))) {
|
_requestGroup->downloadFinished()) ||
|
||||||
|
(uint64_t)_segments.front()->getPositionToWrite() ==
|
||||||
|
_requestGroup->getTotalLength()))) {
|
||||||
std::pair<std::string, uint16_t> peerInfo;
|
std::pair<std::string, uint16_t> peerInfo;
|
||||||
socket->getPeerInfo(peerInfo);
|
socket->getPeerInfo(peerInfo);
|
||||||
e->poolSocket(peerInfo.first, peerInfo.second, socket);
|
e->poolSocket(peerInfo.first, peerInfo.second, socket);
|
||||||
|
|
|
@ -41,13 +41,13 @@
|
||||||
#include "Range.h"
|
#include "Range.h"
|
||||||
#include "LogFactory.h"
|
#include "LogFactory.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "ChunkedEncoding.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
#include "StringFormat.h"
|
#include "StringFormat.h"
|
||||||
#include "A2STR.h"
|
#include "A2STR.h"
|
||||||
#include "Decoder.h"
|
#include "Decoder.h"
|
||||||
|
#include "ChunkedDecoder.h"
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
# include "GZipDecoder.h"
|
# include "GZipDecoder.h"
|
||||||
#endif // HAVE_LIBZ
|
#endif // HAVE_LIBZ
|
||||||
|
@ -73,21 +73,19 @@ void HttpResponse::validateResponse() const
|
||||||
(StringFormat(EX_LOCATION_HEADER_REQUIRED,
|
(StringFormat(EX_LOCATION_HEADER_REQUIRED,
|
||||||
Util::parseUInt(status)).str());
|
Util::parseUInt(status)).str());
|
||||||
}
|
}
|
||||||
} else {
|
} else if(!httpHeader->defined(HttpHeader::TRANSFER_ENCODING)) {
|
||||||
if(!httpHeader->defined(HttpHeader::TRANSFER_ENCODING)) {
|
// compare the received range against the requested range
|
||||||
// compare the received range against the requested range
|
RangeHandle responseRange = httpHeader->getRange();
|
||||||
RangeHandle responseRange = httpHeader->getRange();
|
if(!httpRequest->isRangeSatisfied(responseRange)) {
|
||||||
if(!httpRequest->isRangeSatisfied(responseRange)) {
|
throw DlAbortEx
|
||||||
throw DlAbortEx
|
(StringFormat
|
||||||
(StringFormat(EX_INVALID_RANGE_HEADER,
|
(EX_INVALID_RANGE_HEADER,
|
||||||
Util::itos(httpRequest->getStartByte(), true).c_str(),
|
Util::itos(httpRequest->getStartByte(), true).c_str(),
|
||||||
Util::itos(httpRequest->getEndByte(), true).c_str(),
|
Util::itos(httpRequest->getEndByte(), true).c_str(),
|
||||||
Util::uitos(httpRequest->getEntityLength(), true).c_str(),
|
Util::uitos(httpRequest->getEntityLength(), true).c_str(),
|
||||||
Util::itos(responseRange->getStartByte(), true).c_str(),
|
Util::itos(responseRange->getStartByte(), true).c_str(),
|
||||||
Util::itos(responseRange->getEndByte(), true).c_str(),
|
Util::itos(responseRange->getEndByte(), true).c_str(),
|
||||||
Util::uitos(responseRange->getEntityLength(), true).c_str()
|
Util::uitos(responseRange->getEntityLength(), true).c_str()).str());
|
||||||
).str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,10 +107,10 @@ std::string HttpResponse::determinFilename() const
|
||||||
void HttpResponse::retrieveCookie()
|
void HttpResponse::retrieveCookie()
|
||||||
{
|
{
|
||||||
std::deque<std::string> v = httpHeader->get(HttpHeader::SET_COOKIE);
|
std::deque<std::string> v = httpHeader->get(HttpHeader::SET_COOKIE);
|
||||||
for(std::deque<std::string>::const_iterator itr = v.begin(); itr != v.end(); itr++) {
|
for(std::deque<std::string>::const_iterator itr = v.begin(); itr != v.end();
|
||||||
std::string domain = httpRequest->getHost();
|
itr++) {
|
||||||
std::string path = httpRequest->getDir();
|
httpRequest->getRequest()->cookieBox->add(*itr, httpRequest->getHost(),
|
||||||
httpRequest->getRequest()->cookieBox->add(*itr, domain, path);
|
httpRequest->getDir());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,17 +139,20 @@ bool HttpResponse::isTransferEncodingSpecified() const
|
||||||
|
|
||||||
std::string HttpResponse::getTransferEncoding() const
|
std::string HttpResponse::getTransferEncoding() const
|
||||||
{
|
{
|
||||||
|
// TODO See TODO in getTransferEncodingDecoder()
|
||||||
return httpHeader->getFirst(HttpHeader::TRANSFER_ENCODING);
|
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(isTransferEncodingSpecified()) {
|
||||||
if(getTransferEncoding() == HttpHeader::CHUNKED) {
|
if(getTransferEncoding() == HttpHeader::CHUNKED) {
|
||||||
return SharedHandle<TransferEncoding>(new ChunkedEncoding());
|
return SharedHandle<Decoder>(new ChunkedDecoder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SharedHandle<TransferEncoding>();
|
return SharedHandle<Decoder>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpResponse::isContentEncodingSpecified() const
|
bool HttpResponse::isContentEncodingSpecified() const
|
||||||
|
|
|
@ -44,7 +44,6 @@ namespace aria2 {
|
||||||
|
|
||||||
class HttpRequest;
|
class HttpRequest;
|
||||||
class HttpHeader;
|
class HttpHeader;
|
||||||
class TransferEncoding;
|
|
||||||
class Logger;
|
class Logger;
|
||||||
class Decoder;
|
class Decoder;
|
||||||
|
|
||||||
|
@ -84,7 +83,7 @@ public:
|
||||||
|
|
||||||
std::string getTransferEncoding() const;
|
std::string getTransferEncoding() const;
|
||||||
|
|
||||||
SharedHandle<TransferEncoding> getTransferDecoder() const;
|
SharedHandle<Decoder> getTransferEncodingDecoder() const;
|
||||||
|
|
||||||
bool isContentEncodingSpecified() const;
|
bool isContentEncodingSpecified() const;
|
||||||
|
|
||||||
|
|
|
@ -180,20 +180,20 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SharedHandle<TransferEncoding> getTransferEncoding
|
static SharedHandle<Decoder> getTransferEncodingDecoder
|
||||||
(const SharedHandle<HttpResponse>& httpResponse)
|
(const SharedHandle<HttpResponse>& httpResponse)
|
||||||
{
|
{
|
||||||
TransferEncodingHandle enc;
|
SharedHandle<Decoder> decoder;
|
||||||
if(httpResponse->isTransferEncodingSpecified()) {
|
if(httpResponse->isTransferEncodingSpecified()) {
|
||||||
enc = httpResponse->getTransferDecoder();
|
decoder = httpResponse->getTransferEncodingDecoder();
|
||||||
if(enc.isNull()) {
|
if(decoder.isNull()) {
|
||||||
throw DlAbortEx
|
throw DlAbortEx
|
||||||
(StringFormat(EX_TRANSFER_ENCODING_NOT_SUPPORTED,
|
(StringFormat(EX_TRANSFER_ENCODING_NOT_SUPPORTED,
|
||||||
httpResponse->getTransferEncoding().c_str()).str());
|
httpResponse->getTransferEncoding().c_str()).str());
|
||||||
}
|
}
|
||||||
enc->init();
|
decoder->init();
|
||||||
}
|
}
|
||||||
return enc;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SharedHandle<Decoder> getContentEncodingDecoder
|
static SharedHandle<Decoder> getContentEncodingDecoder
|
||||||
|
@ -218,13 +218,13 @@ static SharedHandle<Decoder> getContentEncodingDecoder
|
||||||
bool HttpResponseCommand::skipResponseBody
|
bool HttpResponseCommand::skipResponseBody
|
||||||
(const SharedHandle<HttpResponse>& httpResponse)
|
(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
|
// We don't use Content-Encoding here because this response body is just
|
||||||
// thrown away.
|
// thrown away.
|
||||||
|
|
||||||
HttpSkipResponseCommand* command = new HttpSkipResponseCommand
|
HttpSkipResponseCommand* command = new HttpSkipResponseCommand
|
||||||
(cuid, req, _requestGroup, httpConnection, httpResponse, e, socket);
|
(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
|
// If the response body is zero-length, set command's status to real time
|
||||||
// so that avoid read check blocking
|
// so that avoid read check blocking
|
||||||
|
@ -238,18 +238,23 @@ bool HttpResponseCommand::skipResponseBody
|
||||||
return true;
|
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 =
|
SharedHandle<Decoder> contentEncodingDecoder =
|
||||||
getContentEncodingDecoder(httpResponse);
|
getContentEncodingDecoder(httpResponse);
|
||||||
|
|
||||||
HttpDownloadCommand* command =
|
HttpDownloadCommand* command =
|
||||||
new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e, socket);
|
new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e,
|
||||||
command->setMaxDownloadSpeedLimit(e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
|
socket);
|
||||||
|
command->setMaxDownloadSpeedLimit
|
||||||
|
(e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
|
||||||
command->setStartupIdleTime(e->option->getAsInt(PREF_STARTUP_IDLE_TIME));
|
command->setStartupIdleTime(e->option->getAsInt(PREF_STARTUP_IDLE_TIME));
|
||||||
command->setLowestDownloadSpeedLimit(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT));
|
command->setLowestDownloadSpeedLimit
|
||||||
command->setTransferDecoder(enc);
|
(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT));
|
||||||
|
command->setTransferEncodingDecoder(transferEncodingDecoder);
|
||||||
|
|
||||||
if(!contentEncodingDecoder.isNull()) {
|
if(!contentEncodingDecoder.isNull()) {
|
||||||
command->setContentEncodingDecoder(contentEncodingDecoder);
|
command->setContentEncodingDecoder(contentEncodingDecoder);
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
#include "HttpResponse.h"
|
#include "HttpResponse.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "SocketCore.h"
|
#include "SocketCore.h"
|
||||||
#include "TransferEncoding.h"
|
#include "Decoder.h"
|
||||||
#include "DlRetryEx.h"
|
#include "DlRetryEx.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "DownloadEngine.h"
|
#include "DownloadEngine.h"
|
||||||
|
@ -70,15 +70,15 @@ HttpSkipResponseCommand::HttpSkipResponseCommand
|
||||||
|
|
||||||
HttpSkipResponseCommand::~HttpSkipResponseCommand() {}
|
HttpSkipResponseCommand::~HttpSkipResponseCommand() {}
|
||||||
|
|
||||||
void HttpSkipResponseCommand::setTransferDecoder
|
void HttpSkipResponseCommand::setTransferEncodingDecoder
|
||||||
(const SharedHandle<TransferEncoding>& transferDecoder)
|
(const SharedHandle<Decoder>& decoder)
|
||||||
{
|
{
|
||||||
_transferDecoder = transferDecoder;
|
_transferEncodingDecoder = decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpSkipResponseCommand::executeInternal()
|
bool HttpSkipResponseCommand::executeInternal()
|
||||||
{
|
{
|
||||||
if(_totalLength == 0 && _transferDecoder.isNull()) {
|
if(_totalLength == 0 && _transferEncodingDecoder.isNull()) {
|
||||||
return processResponse();
|
return processResponse();
|
||||||
}
|
}
|
||||||
const size_t BUFSIZE = 16*1024;
|
const size_t BUFSIZE = 16*1024;
|
||||||
|
@ -88,13 +88,12 @@ bool HttpSkipResponseCommand::executeInternal()
|
||||||
try {
|
try {
|
||||||
socket->readData(buf, bufSize);
|
socket->readData(buf, bufSize);
|
||||||
|
|
||||||
if(_transferDecoder.isNull()) {
|
if(_transferEncodingDecoder.isNull()) {
|
||||||
_receivedBytes += bufSize;
|
_receivedBytes += bufSize;
|
||||||
} else {
|
} else {
|
||||||
// _receivedBytes is not updated if transferEncoding is set.
|
// _receivedBytes is not updated if transferEncoding is set.
|
||||||
size_t infbufSize = 16*1024;
|
// The return value is safely ignored here.
|
||||||
unsigned char infbuf[infbufSize];
|
_transferEncodingDecoder->decode(buf, bufSize);
|
||||||
_transferDecoder->inflate(infbuf, infbufSize, buf, bufSize);
|
|
||||||
}
|
}
|
||||||
if(_totalLength != 0 && bufSize == 0) {
|
if(_totalLength != 0 && bufSize == 0) {
|
||||||
throw DlRetryEx(EX_GOT_EOF);
|
throw DlRetryEx(EX_GOT_EOF);
|
||||||
|
@ -109,10 +108,10 @@ bool HttpSkipResponseCommand::executeInternal()
|
||||||
// readable, bufSize == 0 means server shutdown the connection.
|
// readable, bufSize == 0 means server shutdown the connection.
|
||||||
// So socket cannot be reused in this case.
|
// So socket cannot be reused in this case.
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
} else if((!_transferDecoder.isNull() && _transferDecoder->finished())
|
} else if((!_transferEncodingDecoder.isNull() &&
|
||||||
|| (_transferDecoder.isNull() && _totalLength == _receivedBytes)) {
|
_transferEncodingDecoder->finished())
|
||||||
if(!_transferDecoder.isNull()) _transferDecoder->end();
|
|| (_transferEncodingDecoder.isNull() &&
|
||||||
|
_totalLength == _receivedBytes)) {
|
||||||
if(!e->option->getAsBool(PREF_HTTP_PROXY_ENABLED) &&
|
if(!e->option->getAsBool(PREF_HTTP_PROXY_ENABLED) &&
|
||||||
req->supportsPersistentConnection()) {
|
req->supportsPersistentConnection()) {
|
||||||
std::pair<std::string, uint16_t> peerInfo;
|
std::pair<std::string, uint16_t> peerInfo;
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace aria2 {
|
||||||
|
|
||||||
class HttpConnection;
|
class HttpConnection;
|
||||||
class HttpResponse;
|
class HttpResponse;
|
||||||
class TransferEncoding;
|
class Decoder;
|
||||||
|
|
||||||
class HttpSkipResponseCommand : public AbstractCommand {
|
class HttpSkipResponseCommand : public AbstractCommand {
|
||||||
private:
|
private:
|
||||||
|
@ -49,7 +49,7 @@ private:
|
||||||
|
|
||||||
SharedHandle<HttpResponse> _httpResponse;
|
SharedHandle<HttpResponse> _httpResponse;
|
||||||
|
|
||||||
SharedHandle<TransferEncoding> _transferDecoder;
|
SharedHandle<Decoder> _transferEncodingDecoder;
|
||||||
|
|
||||||
uint64_t _totalLength;
|
uint64_t _totalLength;
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
|
|
||||||
virtual ~HttpSkipResponseCommand();
|
virtual ~HttpSkipResponseCommand();
|
||||||
|
|
||||||
void setTransferDecoder(const SharedHandle<TransferEncoding>& transferDecoder);
|
void setTransferEncodingDecoder(const SharedHandle<Decoder>& decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -41,8 +41,6 @@ SRCS = Socket.h\
|
||||||
DownloadFailureException.h\
|
DownloadFailureException.h\
|
||||||
Logger.h\
|
Logger.h\
|
||||||
SimpleLogger.cc SimpleLogger.h\
|
SimpleLogger.cc SimpleLogger.h\
|
||||||
TransferEncoding.h\
|
|
||||||
ChunkedEncoding.cc ChunkedEncoding.h\
|
|
||||||
DiskWriter.h\
|
DiskWriter.h\
|
||||||
DiskWriterFactory.h\
|
DiskWriterFactory.h\
|
||||||
AbstractDiskWriter.cc AbstractDiskWriter.h\
|
AbstractDiskWriter.cc AbstractDiskWriter.h\
|
||||||
|
@ -189,7 +187,8 @@ SRCS = Socket.h\
|
||||||
FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h\
|
FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h\
|
||||||
A2STR.cc A2STR.h\
|
A2STR.cc A2STR.h\
|
||||||
RarestPieceSelector.cc RarestPieceSelector.h\
|
RarestPieceSelector.cc RarestPieceSelector.h\
|
||||||
Decoder.h
|
Decoder.h\
|
||||||
|
ChunkedDecoder.cc ChunkedDecoder.h
|
||||||
|
|
||||||
if HAVE_LIBZ
|
if HAVE_LIBZ
|
||||||
SRCS += GZipDecoder.cc GZipDecoder.h
|
SRCS += GZipDecoder.cc GZipDecoder.h
|
||||||
|
|
|
@ -317,8 +317,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
||||||
message.h Exception.cc Exception.h FatalException.h \
|
message.h Exception.cc Exception.h FatalException.h \
|
||||||
RecoverableException.h DlAbortEx.h DlRetryEx.h \
|
RecoverableException.h DlAbortEx.h DlRetryEx.h \
|
||||||
DownloadFailureException.h Logger.h SimpleLogger.cc \
|
DownloadFailureException.h Logger.h SimpleLogger.cc \
|
||||||
SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \
|
SimpleLogger.h DiskWriter.h DiskWriterFactory.h \
|
||||||
ChunkedEncoding.h DiskWriter.h DiskWriterFactory.h \
|
|
||||||
AbstractDiskWriter.cc AbstractDiskWriter.h \
|
AbstractDiskWriter.cc AbstractDiskWriter.h \
|
||||||
DefaultDiskWriter.cc DefaultDiskWriter.h \
|
DefaultDiskWriter.cc DefaultDiskWriter.h \
|
||||||
DefaultDiskWriterFactory.cc DefaultDiskWriterFactory.h File.cc \
|
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 \
|
InitiateConnectionCommand.cc InitiateConnectionCommand.h \
|
||||||
FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
|
FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
|
||||||
A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
|
A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
|
||||||
Decoder.h GZipDecoder.cc GZipDecoder.h AsyncNameResolver.cc \
|
Decoder.h ChunkedDecoder.cc ChunkedDecoder.h GZipDecoder.cc \
|
||||||
AsyncNameResolver.h IteratableChunkChecksumValidator.cc \
|
GZipDecoder.h AsyncNameResolver.cc AsyncNameResolver.h \
|
||||||
|
IteratableChunkChecksumValidator.cc \
|
||||||
IteratableChunkChecksumValidator.h \
|
IteratableChunkChecksumValidator.h \
|
||||||
IteratableChecksumValidator.cc IteratableChecksumValidator.h \
|
IteratableChecksumValidator.cc IteratableChecksumValidator.h \
|
||||||
CheckIntegrityCommand.cc CheckIntegrityCommand.h \
|
CheckIntegrityCommand.cc CheckIntegrityCommand.h \
|
||||||
|
@ -740,15 +740,14 @@ am__objects_17 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
|
||||||
DownloadEngine.$(OBJEXT) GrowSegment.$(OBJEXT) \
|
DownloadEngine.$(OBJEXT) GrowSegment.$(OBJEXT) \
|
||||||
PiecedSegment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \
|
PiecedSegment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \
|
||||||
Request.$(OBJEXT) Exception.$(OBJEXT) SimpleLogger.$(OBJEXT) \
|
Request.$(OBJEXT) Exception.$(OBJEXT) SimpleLogger.$(OBJEXT) \
|
||||||
ChunkedEncoding.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
|
AbstractDiskWriter.$(OBJEXT) DefaultDiskWriter.$(OBJEXT) \
|
||||||
DefaultDiskWriter.$(OBJEXT) DefaultDiskWriterFactory.$(OBJEXT) \
|
DefaultDiskWriterFactory.$(OBJEXT) File.$(OBJEXT) \
|
||||||
File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \
|
Option.$(OBJEXT) Base64.$(OBJEXT) CookieBox.$(OBJEXT) \
|
||||||
CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \
|
LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) FeatureConfig.$(OBJEXT) \
|
||||||
FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \
|
DownloadEngineFactory.$(OBJEXT) SpeedCalc.$(OBJEXT) \
|
||||||
SpeedCalc.$(OBJEXT) BitfieldMan.$(OBJEXT) \
|
BitfieldMan.$(OBJEXT) BitfieldManFactory.$(OBJEXT) \
|
||||||
BitfieldManFactory.$(OBJEXT) SimpleRandomizer.$(OBJEXT) \
|
SimpleRandomizer.$(OBJEXT) HttpResponse.$(OBJEXT) \
|
||||||
HttpResponse.$(OBJEXT) HttpRequest.$(OBJEXT) \
|
HttpRequest.$(OBJEXT) AbstractProxyRequestCommand.$(OBJEXT) \
|
||||||
AbstractProxyRequestCommand.$(OBJEXT) \
|
|
||||||
AbstractProxyResponseCommand.$(OBJEXT) Netrc.$(OBJEXT) \
|
AbstractProxyResponseCommand.$(OBJEXT) Netrc.$(OBJEXT) \
|
||||||
AuthConfig.$(OBJEXT) AbstractAuthResolver.$(OBJEXT) \
|
AuthConfig.$(OBJEXT) AbstractAuthResolver.$(OBJEXT) \
|
||||||
DefaultAuthResolver.$(OBJEXT) NetrcAuthResolver.$(OBJEXT) \
|
DefaultAuthResolver.$(OBJEXT) NetrcAuthResolver.$(OBJEXT) \
|
||||||
|
@ -794,12 +793,13 @@ am__objects_17 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
|
||||||
HttpSkipResponseCommand.$(OBJEXT) \
|
HttpSkipResponseCommand.$(OBJEXT) \
|
||||||
InitiateConnectionCommand.$(OBJEXT) \
|
InitiateConnectionCommand.$(OBJEXT) \
|
||||||
FtpFinishDownloadCommand.$(OBJEXT) A2STR.$(OBJEXT) \
|
FtpFinishDownloadCommand.$(OBJEXT) A2STR.$(OBJEXT) \
|
||||||
RarestPieceSelector.$(OBJEXT) $(am__objects_1) \
|
RarestPieceSelector.$(OBJEXT) ChunkedDecoder.$(OBJEXT) \
|
||||||
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||||
$(am__objects_5) $(am__objects_6) $(am__objects_7) \
|
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
|
||||||
$(am__objects_8) $(am__objects_9) $(am__objects_10) \
|
$(am__objects_7) $(am__objects_8) $(am__objects_9) \
|
||||||
$(am__objects_11) $(am__objects_12) $(am__objects_13) \
|
$(am__objects_10) $(am__objects_11) $(am__objects_12) \
|
||||||
$(am__objects_14) $(am__objects_15) $(am__objects_16)
|
$(am__objects_13) $(am__objects_14) $(am__objects_15) \
|
||||||
|
$(am__objects_16)
|
||||||
am_libaria2c_a_OBJECTS = $(am__objects_17)
|
am_libaria2c_a_OBJECTS = $(am__objects_17)
|
||||||
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
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 \
|
message.h Exception.cc Exception.h FatalException.h \
|
||||||
RecoverableException.h DlAbortEx.h DlRetryEx.h \
|
RecoverableException.h DlAbortEx.h DlRetryEx.h \
|
||||||
DownloadFailureException.h Logger.h SimpleLogger.cc \
|
DownloadFailureException.h Logger.h SimpleLogger.cc \
|
||||||
SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \
|
SimpleLogger.h DiskWriter.h DiskWriterFactory.h \
|
||||||
ChunkedEncoding.h DiskWriter.h DiskWriterFactory.h \
|
|
||||||
AbstractDiskWriter.cc AbstractDiskWriter.h \
|
AbstractDiskWriter.cc AbstractDiskWriter.h \
|
||||||
DefaultDiskWriter.cc DefaultDiskWriter.h \
|
DefaultDiskWriter.cc DefaultDiskWriter.h \
|
||||||
DefaultDiskWriterFactory.cc DefaultDiskWriterFactory.h File.cc \
|
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 \
|
InitiateConnectionCommand.cc InitiateConnectionCommand.h \
|
||||||
FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
|
FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
|
||||||
A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
|
A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
|
||||||
Decoder.h $(am__append_1) $(am__append_2) $(am__append_3) \
|
Decoder.h ChunkedDecoder.cc ChunkedDecoder.h $(am__append_1) \
|
||||||
$(am__append_4) $(am__append_5) $(am__append_6) \
|
$(am__append_2) $(am__append_3) $(am__append_4) \
|
||||||
$(am__append_7) $(am__append_8) $(am__append_9) \
|
$(am__append_5) $(am__append_6) $(am__append_7) \
|
||||||
$(am__append_10) $(am__append_11) $(am__append_12) \
|
$(am__append_8) $(am__append_9) $(am__append_10) \
|
||||||
$(am__append_13) $(am__append_14) $(am__append_15) \
|
$(am__append_11) $(am__append_12) $(am__append_13) \
|
||||||
$(am__append_16)
|
$(am__append_14) $(am__append_15) $(am__append_16)
|
||||||
noinst_LIBRARIES = libaria2c.a
|
noinst_LIBRARIES = libaria2c.a
|
||||||
libaria2c_a_SOURCES = $(SRCS)
|
libaria2c_a_SOURCES = $(SRCS)
|
||||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
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)/CheckIntegrityEntry.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityMan.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)/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)/Command.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompactPeerListProcessor.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@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleStatCalc.Po@am__quote@
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
#include "PiecedSegment.h"
|
#include "PiecedSegment.h"
|
||||||
#include "Piece.h"
|
#include "Piece.h"
|
||||||
#include "TransferEncoding.h"
|
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "HttpHeader.h"
|
#include "HttpHeader.h"
|
||||||
#include "HttpRequest.h"
|
#include "HttpRequest.h"
|
||||||
|
@ -30,7 +29,7 @@ class HttpResponseTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testIsRedirect);
|
CPPUNIT_TEST(testIsRedirect);
|
||||||
CPPUNIT_TEST(testIsTransferEncodingSpecified);
|
CPPUNIT_TEST(testIsTransferEncodingSpecified);
|
||||||
CPPUNIT_TEST(testGetTransferEncoding);
|
CPPUNIT_TEST(testGetTransferEncoding);
|
||||||
CPPUNIT_TEST(testGetTransferDecoder);
|
CPPUNIT_TEST(testGetTransferEncodingDecoder);
|
||||||
CPPUNIT_TEST(testIsContentEncodingSpecified);
|
CPPUNIT_TEST(testIsContentEncodingSpecified);
|
||||||
CPPUNIT_TEST(testGetContentEncoding);
|
CPPUNIT_TEST(testGetContentEncoding);
|
||||||
CPPUNIT_TEST(testGetContentEncodingDecoder);
|
CPPUNIT_TEST(testGetContentEncodingDecoder);
|
||||||
|
@ -58,7 +57,7 @@ public:
|
||||||
void testIsRedirect();
|
void testIsRedirect();
|
||||||
void testIsTransferEncodingSpecified();
|
void testIsTransferEncodingSpecified();
|
||||||
void testGetTransferEncoding();
|
void testGetTransferEncoding();
|
||||||
void testGetTransferDecoder();
|
void testGetTransferEncodingDecoder();
|
||||||
void testIsContentEncodingSpecified();
|
void testIsContentEncodingSpecified();
|
||||||
void testGetContentEncoding();
|
void testGetContentEncoding();
|
||||||
void testGetContentEncodingDecoder();
|
void testGetContentEncodingDecoder();
|
||||||
|
@ -134,7 +133,8 @@ void HttpResponseTest::testDeterminFilename_without_ContentDisposition()
|
||||||
httpResponse.determinFilename());
|
httpResponse.determinFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length()
|
void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length
|
||||||
|
()
|
||||||
{
|
{
|
||||||
HttpResponse httpResponse;
|
HttpResponse httpResponse;
|
||||||
SharedHandle<HttpHeader> httpHeader(new HttpHeader());
|
SharedHandle<HttpHeader> httpHeader(new HttpHeader());
|
||||||
|
@ -155,7 +155,8 @@ void HttpResponseTest::testDeterminFilename_with_ContentDisposition()
|
||||||
{
|
{
|
||||||
HttpResponse httpResponse;
|
HttpResponse httpResponse;
|
||||||
SharedHandle<HttpHeader> httpHeader(new HttpHeader());
|
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<HttpRequest> httpRequest(new HttpRequest());
|
||||||
SharedHandle<Request> request(new Request());
|
SharedHandle<Request> request(new Request());
|
||||||
request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
|
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");
|
httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
|
||||||
httpResponse.setHttpHeader(httpHeader);
|
httpResponse.setHttpHeader(httpHeader);
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/download/aria2-1.0.0.tar.bz2"),
|
CPPUNIT_ASSERT_EQUAL
|
||||||
httpResponse.getRedirectURI());
|
(std::string("http://localhost/download/aria2-1.0.0.tar.bz2"),
|
||||||
|
httpResponse.getRedirectURI());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpResponseTest::testIsRedirect()
|
void HttpResponseTest::testIsRedirect()
|
||||||
|
@ -231,21 +233,22 @@ void HttpResponseTest::testGetTransferEncoding()
|
||||||
|
|
||||||
httpHeader->put("Transfer-Encoding", "chunked");
|
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;
|
HttpResponse httpResponse;
|
||||||
SharedHandle<HttpHeader> httpHeader(new HttpHeader());
|
SharedHandle<HttpHeader> httpHeader(new HttpHeader());
|
||||||
|
|
||||||
httpResponse.setHttpHeader(httpHeader);
|
httpResponse.setHttpHeader(httpHeader);
|
||||||
|
|
||||||
CPPUNIT_ASSERT(httpResponse.getTransferDecoder().isNull());
|
CPPUNIT_ASSERT(httpResponse.getTransferEncodingDecoder().isNull());
|
||||||
|
|
||||||
httpHeader->put("Transfer-Encoding", "chunked");
|
httpHeader->put("Transfer-Encoding", "chunked");
|
||||||
|
|
||||||
CPPUNIT_ASSERT(!httpResponse.getTransferDecoder().isNull());
|
CPPUNIT_ASSERT(!httpResponse.getTransferEncodingDecoder().isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpResponseTest::testIsContentEncodingSpecified()
|
void HttpResponseTest::testIsContentEncodingSpecified()
|
||||||
|
|
|
@ -40,7 +40,6 @@ aria2c_SOURCES = AllTest.cc\
|
||||||
HttpHeaderTest.cc\
|
HttpHeaderTest.cc\
|
||||||
HttpResponseTest.cc\
|
HttpResponseTest.cc\
|
||||||
SharedHandleTest.cc\
|
SharedHandleTest.cc\
|
||||||
ChunkedEncodingTest.cc\
|
|
||||||
FileTest.cc\
|
FileTest.cc\
|
||||||
OptionTest.cc\
|
OptionTest.cc\
|
||||||
DefaultDiskWriterTest.cc\
|
DefaultDiskWriterTest.cc\
|
||||||
|
@ -52,7 +51,8 @@ aria2c_SOURCES = AllTest.cc\
|
||||||
ProtocolDetectorTest.cc\
|
ProtocolDetectorTest.cc\
|
||||||
StringFormatTest.cc\
|
StringFormatTest.cc\
|
||||||
ExceptionTest.cc\
|
ExceptionTest.cc\
|
||||||
DownloadHandlerFactoryTest.cc
|
DownloadHandlerFactoryTest.cc\
|
||||||
|
ChunkedDecoderTest.cc
|
||||||
|
|
||||||
if HAVE_LIBZ
|
if HAVE_LIBZ
|
||||||
aria2c_SOURCES += GZipDecoderTest.cc
|
aria2c_SOURCES += GZipDecoderTest.cc
|
||||||
|
|
|
@ -182,13 +182,13 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \
|
||||||
NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
|
NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
|
||||||
OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
|
OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
|
||||||
NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \
|
NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \
|
||||||
HttpResponseTest.cc SharedHandleTest.cc ChunkedEncodingTest.cc \
|
HttpResponseTest.cc SharedHandleTest.cc FileTest.cc \
|
||||||
FileTest.cc OptionTest.cc DefaultDiskWriterTest.cc \
|
OptionTest.cc DefaultDiskWriterTest.cc FeatureConfigTest.cc \
|
||||||
FeatureConfigTest.cc SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
|
SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
|
||||||
MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \
|
MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \
|
||||||
ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \
|
ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \
|
||||||
DownloadHandlerFactoryTest.cc GZipDecoderTest.cc \
|
DownloadHandlerFactoryTest.cc ChunkedDecoderTest.cc \
|
||||||
MessageDigestHelperTest.cc \
|
GZipDecoderTest.cc MessageDigestHelperTest.cc \
|
||||||
IteratableChunkChecksumValidatorTest.cc \
|
IteratableChunkChecksumValidatorTest.cc \
|
||||||
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
|
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
|
||||||
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
|
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
|
||||||
|
@ -345,15 +345,15 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) SocketCoreTest.$(OBJEXT) \
|
||||||
SegmentManTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \
|
SegmentManTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \
|
||||||
NetrcTest.$(OBJEXT) SingletonHolderTest.$(OBJEXT) \
|
NetrcTest.$(OBJEXT) SingletonHolderTest.$(OBJEXT) \
|
||||||
HttpHeaderTest.$(OBJEXT) HttpResponseTest.$(OBJEXT) \
|
HttpHeaderTest.$(OBJEXT) HttpResponseTest.$(OBJEXT) \
|
||||||
SharedHandleTest.$(OBJEXT) ChunkedEncodingTest.$(OBJEXT) \
|
SharedHandleTest.$(OBJEXT) FileTest.$(OBJEXT) \
|
||||||
FileTest.$(OBJEXT) OptionTest.$(OBJEXT) \
|
OptionTest.$(OBJEXT) DefaultDiskWriterTest.$(OBJEXT) \
|
||||||
DefaultDiskWriterTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \
|
FeatureConfigTest.$(OBJEXT) SpeedCalcTest.$(OBJEXT) \
|
||||||
SpeedCalcTest.$(OBJEXT) MultiDiskAdaptorTest.$(OBJEXT) \
|
MultiDiskAdaptorTest.$(OBJEXT) \
|
||||||
MultiFileAllocationIteratorTest.$(OBJEXT) \
|
MultiFileAllocationIteratorTest.$(OBJEXT) \
|
||||||
ProtocolDetectorTest.$(OBJEXT) StringFormatTest.$(OBJEXT) \
|
ProtocolDetectorTest.$(OBJEXT) StringFormatTest.$(OBJEXT) \
|
||||||
ExceptionTest.$(OBJEXT) DownloadHandlerFactoryTest.$(OBJEXT) \
|
ExceptionTest.$(OBJEXT) DownloadHandlerFactoryTest.$(OBJEXT) \
|
||||||
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
ChunkedDecoderTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
||||||
$(am__objects_4)
|
$(am__objects_3) $(am__objects_4)
|
||||||
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
||||||
am__DEPENDENCIES_1 =
|
am__DEPENDENCIES_1 =
|
||||||
aria2c_DEPENDENCIES = ../src/libaria2c.a $(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 \
|
NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \
|
||||||
OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
|
OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \
|
||||||
NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \
|
NetrcTest.cc SingletonHolderTest.cc HttpHeaderTest.cc \
|
||||||
HttpResponseTest.cc SharedHandleTest.cc ChunkedEncodingTest.cc \
|
HttpResponseTest.cc SharedHandleTest.cc FileTest.cc \
|
||||||
FileTest.cc OptionTest.cc DefaultDiskWriterTest.cc \
|
OptionTest.cc DefaultDiskWriterTest.cc FeatureConfigTest.cc \
|
||||||
FeatureConfigTest.cc SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
|
SpeedCalcTest.cc MultiDiskAdaptorTest.cc \
|
||||||
MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \
|
MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \
|
||||||
ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \
|
ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \
|
||||||
DownloadHandlerFactoryTest.cc $(am__append_1) $(am__append_2) \
|
DownloadHandlerFactoryTest.cc ChunkedDecoderTest.cc \
|
||||||
$(am__append_3) $(am__append_4)
|
$(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_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
||||||
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
#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)/BtSuggestPieceMessageTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessageTest.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)/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)/CookieBoxFactoryTest.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxTest.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@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieParserTest.Po@am__quote@
|
||||||
|
|
Loading…
Reference in New Issue