2008-11-27 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Fixed the bug that prevents aria2 from downloading 0-length
	files via HTTP/FTP.
	* src/DefaultBtContext.cc
	* src/DefaultBtContext.h
	* src/DownloadContext.h
	* src/FtpNegotiationCommand.cc
	* src/HttpResponseCommand.cc
	* src/HttpResponseCommand.h
	* src/RequestGroup.cc
	* src/SingleFileDownloadContext.cc
	* src/SingleFileDownloadContext.h
	* test/BtPostDownloadHandlerTest.cc
	* test/MetalinkPostDownloadHandlerTest.cc
	* test/MockBtContext.h
pull/1/head
Tatsuhiro Tsujikawa 2008-11-26 15:22:54 +00:00
parent b1eee48ee3
commit b1edad42ff
13 changed files with 111 additions and 18 deletions

View File

@ -1,3 +1,20 @@
2008-11-27 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that prevents aria2 from downloading 0-length files
via HTTP/FTP.
* src/DefaultBtContext.cc
* src/DefaultBtContext.h
* src/DownloadContext.h
* src/FtpNegotiationCommand.cc
* src/HttpResponseCommand.cc
* src/HttpResponseCommand.h
* src/RequestGroup.cc
* src/SingleFileDownloadContext.cc
* src/SingleFileDownloadContext.h
* test/BtPostDownloadHandlerTest.cc
* test/MetalinkPostDownloadHandlerTest.cc
* test/MockBtContext.h
2008-11-26 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that -pfalse and -ptrue are not recognized properly.

View File

@ -391,6 +391,11 @@ uint64_t DefaultBtContext::getTotalLength() const {
return totalLength;
}
bool DefaultBtContext::knowsTotalLength() const
{
return true;
}
BtContext::FILE_MODE DefaultBtContext::getFileMode() const {
return fileMode;
}

View File

@ -110,6 +110,8 @@ private:
virtual uint64_t getTotalLength() const;
virtual bool knowsTotalLength() const;
virtual FILE_MODE getFileMode() const;
virtual std::deque<SharedHandle<FileEntry> > getFileEntries() const;

View File

@ -75,6 +75,8 @@ public:
virtual uint64_t getTotalLength() const = 0;
virtual bool knowsTotalLength() const = 0;
virtual FILE_MODE getFileMode() const = 0;
virtual std::deque<SharedHandle<FileEntry> > getFileEntries() const = 0;

View File

@ -333,10 +333,29 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength)
}
if(totalLength == 0) {
if(e->option->getAsBool(PREF_FTP_PASV)) {
sequence = SEQ_SEND_PASV;
} else {
sequence = SEQ_PREPARE_SERVER_SOCKET;
}
_requestGroup->initPieceStorage();
if(dctx->knowsTotalLength() &&
_requestGroup->downloadFinishedByFileLength()) {
sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
poolConnection();
return false;
}
_requestGroup->shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
if(dctx->knowsTotalLength()) {
sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
poolConnection();
return false;
}
return true;
} else {
_requestGroup->initPieceStorage();
@ -387,12 +406,10 @@ bool FtpNegotiationCommand::recvSize() {
// command, resuming and segmented downloading are disabled when the first
// contacted FTP server doesn't support it.
if(_requestGroup->getPieceStorage().isNull()) {
if(e->option->getAsBool(PREF_FTP_PASV)) {
sequence = SEQ_SEND_PASV;
} else {
sequence = SEQ_PREPARE_SERVER_SOCKET;
}
SingleFileDownloadContextHandle dctx =
dynamic_pointer_cast<SingleFileDownloadContext>
(_requestGroup->getDownloadContext());
dctx->markTotalLengthIsUnknown();
return onFileSizeDetermined(0);
}

View File

@ -140,6 +140,11 @@ bool HttpResponseCommand::executeInternal()
shouldInflateContentEncoding(httpResponse)) {
// we ignore content-length when transfer-encoding is set
dctx->setTotalLength(0);
if(req->getMethod() == Request::METHOD_GET &&
(totalLength != 0 ||
!httpResponse->getHttpHeader()->defined(HttpHeader::CONTENT_LENGTH))){
dctx->markTotalLengthIsUnknown();
}
return handleOtherEncoding(httpResponse);
} else {
return handleDefaultEncoding(httpResponse);
@ -213,9 +218,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
}
prepareForNextAction(command);
if(req->getMethod() == Request::METHOD_HEAD) {
if(req->supportsPersistentConnection()) {
e->poolSocket(req, isProxyDefined(), socket);
}
poolConnection();
req->setMethod(Request::METHOD_GET);
}
} catch(Exception& e) {
@ -261,17 +264,30 @@ static SharedHandle<Decoder> getContentEncodingDecoder
}
bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
// We assume that RequestGroup::getTotalLength() == 0 here
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
if(req->getMethod() == Request::METHOD_HEAD) {
if(req->supportsPersistentConnection()) {
e->poolSocket(req, isProxyDefined(), socket);
}
poolConnection();
req->setMethod(Request::METHOD_GET);
return prepareForRetry(0);
}
_requestGroup->initPieceStorage();
// For zero-length file, check existing file comparing its size
if(_requestGroup->getDownloadContext()->knowsTotalLength() &&
_requestGroup->downloadFinishedByFileLength()) {
poolConnection();
return true;
}
_requestGroup->shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
if(_requestGroup->getDownloadContext()->knowsTotalLength()) {
poolConnection();
return true;
}
e->commands.push_back
(createHttpDownloadCommand(httpResponse,
getTransferEncodingDecoder(httpResponse),
@ -332,4 +348,11 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand
return command;
}
void HttpResponseCommand::poolConnection()
{
if(req->supportsPersistentConnection()) {
e->poolSocket(req, isProxyDefined(), socket);
}
}
} // namespace aria2

View File

@ -62,6 +62,8 @@ private:
= SharedHandle<Decoder>());
void updateLastModifiedTime(const Time& lastModified);
void poolConnection();
protected:
bool executeInternal();

View File

@ -347,14 +347,16 @@ void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
void RequestGroup::initPieceStorage()
{
if(_downloadContext->getTotalLength() == 0) {
UnknownLengthPieceStorageHandle ps(new UnknownLengthPieceStorage(_downloadContext, _option));
if(_downloadContext->knowsTotalLength()) {
DefaultPieceStorageHandle ps
(new DefaultPieceStorage(_downloadContext, _option));
if(!_diskWriterFactory.isNull()) {
ps->setDiskWriterFactory(_diskWriterFactory);
}
_pieceStorage = ps;
} else {
DefaultPieceStorageHandle ps(new DefaultPieceStorage(_downloadContext, _option));
UnknownLengthPieceStorageHandle ps
(new UnknownLengthPieceStorage(_downloadContext, _option));
if(!_diskWriterFactory.isNull()) {
ps->setDiskWriterFactory(_diskWriterFactory);
}

View File

@ -46,7 +46,8 @@ SingleFileDownloadContext::SingleFileDownloadContext(size_t pieceLength,
_pieceLength(pieceLength),
_fileEntry(new FileEntry(filename, totalLength, 0)),
_filename(filename),
_ufilename(ufilename)
_ufilename(ufilename),
_knowsTotalLength(true)
{
updateFileEntry();
}
@ -73,6 +74,11 @@ uint64_t SingleFileDownloadContext::getTotalLength() const
return _fileEntry->getLength();
}
bool SingleFileDownloadContext::knowsTotalLength() const
{
return _knowsTotalLength;
}
FileEntries
SingleFileDownloadContext::getFileEntries() const
{
@ -96,6 +102,11 @@ void SingleFileDownloadContext::setTotalLength(uint64_t totalLength)
_fileEntry->setLength(totalLength);
}
void SingleFileDownloadContext::markTotalLengthIsUnknown()
{
_knowsTotalLength = false;
}
const std::string& SingleFileDownloadContext::getName() const
{
return _fileEntry->getPath();

View File

@ -66,6 +66,8 @@ private:
std::string _checksum;
std::string _checksumHashAlgo;
bool _knowsTotalLength;
void updateFileEntry();
public:
SingleFileDownloadContext(size_t pieceLength,
@ -88,6 +90,9 @@ public:
virtual uint64_t getTotalLength() const;
virtual bool knowsTotalLength() const;
virtual FILE_MODE getFileMode() const
{
return SINGLE;
@ -150,6 +155,8 @@ public:
void setTotalLength(uint64_t totalLength);
void markTotalLengthIsUnknown();
void setPieceHashAlgo(const std::string& algo)
{
_pieceHashAlgo = algo;

View File

@ -65,7 +65,7 @@ void BtPostDownloadHandlerTest::testGetNextRequestGroups()
{
Option op;
SharedHandle<SingleFileDownloadContext> dctx
(new SingleFileDownloadContext(0, 0, "test.torrent"));
(new SingleFileDownloadContext(1024, 0, "test.torrent"));
RequestGroup rg(&op, std::deque<std::string>());
rg.setDownloadContext(dctx);
rg.initPieceStorage();

View File

@ -64,7 +64,7 @@ void MetalinkPostDownloadHandlerTest::testGetNextRequestGroups()
{
Option op;
SharedHandle<SingleFileDownloadContext> dctx
(new SingleFileDownloadContext(0, 0, "test.xml"));
(new SingleFileDownloadContext(1024, 0, "test.xml"));
RequestGroup rg(&op, std::deque<std::string>());
rg.setDownloadContext(dctx);
rg.initPieceStorage();

View File

@ -64,6 +64,11 @@ public:
return totalLength;
}
virtual bool knowsTotalLength() const
{
return true;
}
void setTotalLength(uint64_t length) {
this->totalLength = length;
}