mirror of https://github.com/aria2/aria2
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.hpull/1/head
parent
b1eee48ee3
commit
b1edad42ff
17
ChangeLog
17
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -62,6 +62,8 @@ private:
|
|||
= SharedHandle<Decoder>());
|
||||
|
||||
void updateLastModifiedTime(const Time& lastModified);
|
||||
|
||||
void poolConnection();
|
||||
protected:
|
||||
bool executeInternal();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -64,6 +64,11 @@ public:
|
|||
return totalLength;
|
||||
}
|
||||
|
||||
virtual bool knowsTotalLength() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void setTotalLength(uint64_t length) {
|
||||
this->totalLength = length;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue