diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2007-01-29 16:46:48 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2007-01-29 16:46:48 +0000 |
| commit | 77a05c00b1410687a3045ffe693aaa0496361fc8 (patch) | |
| tree | d08984a2fba7457b2b1afd6f12eddb1d4d171484 | |
| parent | 2ab41c4f173182891ba0f4af1712028f8c26024f (diff) | |
2007-01-30 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To fix segfault in Metalink download:
* src/UrlRequestInfo.h
(filename): Removed.
(totalLength): Removed.
(setTotalLength): Removed.
(setFilename): Removed.
* src/MetalinkRequestInfo.cc
(execute): Do not set filename and totalLength to reqInfo.
Set chunk checksum to reqInfo if it is not null.
* src/HttpResponseCommand.cc
(executeInternal): Fixed filename in log.
(handleDefaultEncoding): Removed the call to initBitfield() and
markAllPiecesDone().
(handleOtherEncoding): Added HEAD method handling.
* src/FtpNegotiateCommand.cc
(executeInternal): Added SEQ_HEAD_OK handling.
(recvSize): In HEAD handling, set sequence to SEQ_HEAD_OK and
return false.
* src/FtpNegotiateCommand.h
(SEQ_HEAD_OK): New definition.
* src/SegmentMan.cc
(initBitfield): Delete bitfield.
(isChunkChecksumValidationReady): Fixed the condition.
* src/UrlRequestInfo.cc: Fixed so that Metalink and Torrent
download
works fine.
| -rw-r--r-- | ChangeLog | 34 | ||||
| -rwxr-xr-x | configure | 20 | ||||
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | po/Makefile.in | 2 | ||||
| -rw-r--r-- | src/FtpNegotiationCommand.cc | 17 | ||||
| -rw-r--r-- | src/FtpNegotiationCommand.h | 3 | ||||
| -rw-r--r-- | src/HttpResponseCommand.cc | 18 | ||||
| -rw-r--r-- | src/MetalinkRequestInfo.cc | 10 | ||||
| -rw-r--r-- | src/SegmentMan.cc | 5 | ||||
| -rw-r--r-- | src/UrlRequestInfo.cc | 69 | ||||
| -rw-r--r-- | src/UrlRequestInfo.h | 20 |
11 files changed, 121 insertions, 79 deletions
@@ -1,3 +1,37 @@ +2007-01-30 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> + + To fix segfault in Metalink download: + + * src/UrlRequestInfo.h + (filename): Removed. + (totalLength): Removed. + (setTotalLength): Removed. + (setFilename): Removed. + * src/MetalinkRequestInfo.cc + (execute): Do not set filename and totalLength to reqInfo. + Set chunk checksum to reqInfo if it is not null. + + * src/HttpResponseCommand.cc + (executeInternal): Fixed filename in log. + (handleDefaultEncoding): Removed the call to initBitfield() and + markAllPiecesDone(). + (handleOtherEncoding): Added HEAD method handling. + + * src/FtpNegotiateCommand.cc + (executeInternal): Added SEQ_HEAD_OK handling. + (recvSize): In HEAD handling, set sequence to SEQ_HEAD_OK and + return false. + + * src/FtpNegotiateCommand.h + (SEQ_HEAD_OK): New definition. + + * src/SegmentMan.cc + (initBitfield): Delete bitfield. + (isChunkChecksumValidationReady): Fixed the condition. + + * src/UrlRequestInfo.cc: Fixed so that Metalink and Torrent download + works fine. + 2007-01-28 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> * src/Xml2MetalinkProcessor.h @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for aria2c 0.10.0. +# Generated by GNU Autoconf 2.61 for aria2c 0.10.0+1. # # Report bugs to <t-tujikawa@users.sourceforge.net>. # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='aria2c' PACKAGE_TARNAME='aria2c' -PACKAGE_VERSION='0.10.0' -PACKAGE_STRING='aria2c 0.10.0' +PACKAGE_VERSION='0.10.0+1' +PACKAGE_STRING='aria2c 0.10.0+1' PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net' ac_unique_file="src/Socket.h" @@ -1275,7 +1275,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures aria2c 0.10.0 to adapt to many kinds of systems. +\`configure' configures aria2c 0.10.0+1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1345,7 +1345,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of aria2c 0.10.0:";; + short | recursive ) echo "Configuration of aria2c 0.10.0+1:";; esac cat <<\_ACEOF @@ -1466,7 +1466,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -aria2c configure 0.10.0 +aria2c configure 0.10.0+1 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1480,7 +1480,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by aria2c $as_me 0.10.0, which was +It was created by aria2c $as_me 0.10.0+1, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -2150,7 +2150,7 @@ fi # Define the identity of the package. PACKAGE='aria2c' - VERSION='0.10.0' + VERSION='0.10.0+1' cat >>confdefs.h <<_ACEOF @@ -12941,7 +12941,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by aria2c $as_me 0.10.0, which was +This file was extended by aria2c $as_me 0.10.0+1, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12994,7 +12994,7 @@ Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -aria2c config.status 0.10.0 +aria2c config.status 0.10.0+1 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.ac b/configure.ac index 42419209..601be61d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. # AC_PREREQ(2.59) -AC_INIT(aria2c, 0.10.0, t-tujikawa@users.sourceforge.net) +AC_INIT(aria2c, 0.10.0+1, t-tujikawa@users.sourceforge.net) AM_INIT_AUTOMAKE() AM_PATH_CPPUNIT(1.10.2) AC_CONFIG_SRCDIR([src/Socket.h]) diff --git a/po/Makefile.in b/po/Makefile.in index 9a736b13..434ed7be 100644 --- a/po/Makefile.in +++ b/po/Makefile.in @@ -9,7 +9,7 @@ # General Public License and is *not* in the public domain. PACKAGE = aria2c -VERSION = 0.10.0 +VERSION = 0.10.0+1 SHELL = /bin/sh diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index ad014069..15214ce3 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -67,6 +67,8 @@ bool FtpNegotiationCommand::executeInternal(Segment& segment) { command->setLowestDownloadSpeedLimit(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT)); e->commands.push_back(command); return true; + } else if(sequence == SEQ_HEAD_OK) { + return true; } else { e->commands.push_back(this); return false; @@ -186,21 +188,16 @@ bool FtpNegotiationCommand::recvSize() { throw new DlAbortEx(EX_TOO_LARGE_FILE, size); } if(!e->segmentMan->downloadStarted) { - if(req->getMethod() == Request::METHOD_HEAD) { - e->segmentMan->downloadStarted = true; - e->segmentMan->totalSize = size; - e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), - e->segmentMan->totalSize); - e->segmentMan->markAllPiecesDone(); - e->segmentMan->isSplittable = false; // TODO because we don't want segment file to be saved. - return true; - } e->segmentMan->downloadStarted = true; e->segmentMan->totalSize = size; e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), e->segmentMan->totalSize); - e->segmentMan->filename = Util::urldecode(req->getFile()); + if(req->getMethod() == Request::METHOD_HEAD) { + e->segmentMan->isSplittable = false; // TODO because we don't want segment file to be saved. + sequence = SEQ_HEAD_OK; + return false; + } bool segFileExists = e->segmentMan->segmentFileExists(); if(segFileExists) { e->segmentMan->load(); diff --git a/src/FtpNegotiationCommand.h b/src/FtpNegotiationCommand.h index 87b66a27..138cfac8 100644 --- a/src/FtpNegotiationCommand.h +++ b/src/FtpNegotiationCommand.h @@ -62,7 +62,8 @@ private: SEQ_SEND_RETR, SEQ_RECV_RETR, SEQ_NEGOTIATION_COMPLETED, - SEQ_RETRY + SEQ_RETRY, + SEQ_HEAD_OK }; bool recvGreeting(); bool sendUser(); diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index e478e9a1..c2cc4070 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -91,8 +91,11 @@ bool HttpResponseCommand::executeInternal(Segment& segment) { return handleDefaultEncoding(headers); } } else { - if(determinFilename(headers) != e->segmentMan->filename) { - throw new DlAbortEx(EX_FILENAME_MISMATCH, req->getFile().c_str(), e->segmentMan->filename.c_str()); + string filenameInHeader = determinFilename(headers); + if(filenameInHeader != e->segmentMan->filename) { + throw new DlAbortEx(EX_FILENAME_MISMATCH, + filenameInHeader.c_str(), + e->segmentMan->filename.c_str()); } createHttpDownloadCommand(); return true; @@ -158,9 +161,6 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { if(req->getMethod() == Request::METHOD_HEAD) { e->segmentMan->downloadStarted = true; e->segmentMan->totalSize = size; - e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), - e->segmentMan->totalSize); - e->segmentMan->markAllPiecesDone(); e->segmentMan->isSplittable = false; // TODO because we don't want segment file to be saved. return true; } @@ -182,6 +182,14 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { } bool HttpResponseCommand::handleOtherEncoding(const string& transferEncoding, const HttpHeader& headers) { + // quick hack for method 'head' + if(req->getMethod() == Request::METHOD_HEAD) { + e->segmentMan->downloadStarted = true; + e->segmentMan->isSplittable = false; + e->segmentMan->filename = determinFilename(headers); + e->segmentMan->totalSize = 0; + return true; + } if(e->segmentMan->shouldCancelDownloadForSafety()) { throw new FatalException(EX_FILE_ALREADY_EXISTS, e->segmentMan->getFilePath().c_str(), diff --git a/src/MetalinkRequestInfo.cc b/src/MetalinkRequestInfo.cc index 4cff522a..8e151a4a 100644 --- a/src/MetalinkRequestInfo.cc +++ b/src/MetalinkRequestInfo.cc @@ -122,13 +122,13 @@ RequestInfos MetalinkRequestInfo::execute() { urls.push_back((*itr)->url); } UrlRequestInfoHandle reqInfo = new UrlRequestInfo(urls, maxConnection, op); - reqInfo->setFilename(entry->filename); - reqInfo->setTotalLength(entry->size); #ifdef ENABLE_MESSAGE_DIGEST reqInfo->setChecksum(checksum); - reqInfo->setDigestAlgo(entry->chunkChecksum->digestAlgo); - reqInfo->setChunkChecksumLength(entry->chunkChecksum->pieceLength); - reqInfo->setChunkChecksums(entry->chunkChecksum->pieceHashes); + if(!entry->chunkChecksum.isNull()) { + reqInfo->setDigestAlgo(entry->chunkChecksum->digestAlgo); + reqInfo->setChunkChecksumLength(entry->chunkChecksum->pieceLength); + reqInfo->setChunkChecksums(entry->chunkChecksum->pieceHashes); + } #endif // ENABLE_MESSAGE_DIGEST nextReqInfos.push_front(reqInfo); } diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index 1e93593c..2c433641 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -237,6 +237,7 @@ void SegmentMan::init() { } void SegmentMan::initBitfield(int segmentLength, long long int totalLength) { + delete bitfield; this->bitfield = BitfieldManFactory::getNewFactory()->createBitfieldMan(segmentLength, totalLength); } @@ -479,8 +480,8 @@ void SegmentMan::checkIntegrity() #ifdef ENABLE_MESSAGE_DIGEST bool SegmentMan::isChunkChecksumValidationReady() const { - return bitfield && - ((int64_t)pieceHashes.size())*chunkHashLength == ((int64_t)bitfield->getBlockLength())*(bitfield->getMaxIndex()+1); + return bitfield && totalSize > 0 && + ((int64_t)pieceHashes.size())*chunkHashLength >= totalSize; } #endif // ENABLE_MESSAGE_DIGEST diff --git a/src/UrlRequestInfo.cc b/src/UrlRequestInfo.cc index 0cd9643d..5bc69b45 100644 --- a/src/UrlRequestInfo.cc +++ b/src/UrlRequestInfo.cc @@ -127,6 +127,10 @@ HeadResult UrlRequestInfo::getHeadResult() { op->get(PREF_REFERER), 1, Request::METHOD_HEAD)); + if(requests.size() == 0) { + fail = true; + return HeadResult(); + } Requests reserved(requests.begin()+1, requests.end()); requests.erase(requests.begin()+1, requests.end()); @@ -135,8 +139,12 @@ HeadResult UrlRequestInfo::getHeadResult() { HeadResult hr; try { e->run(); - hr.filename = e->segmentMan->filename; - hr.totalLength = e->segmentMan->totalSize; + if(e->segmentMan->errors > 0) { + fail = true; + } else { + hr.filename = e->segmentMan->filename; + hr.totalLength = e->segmentMan->totalSize; + } } catch(RecoverableException *ex) { logger->error("Exception caught", ex); delete ex; @@ -150,34 +158,33 @@ RequestInfos UrlRequestInfo::execute() { Requests requests; Requests reserved; printUrls(urls); + HeadResult hr = getHeadResult(); + if(fail) { + return RequestInfos(); + } + for_each(urls.begin(), urls.end(), CreateRequest(&requests, op->get(PREF_REFERER), op->getAsInt(PREF_SPLIT))); + + logger->info("Head result: filename=%s, total length=%s", + hr.filename.c_str(), Util::ullitos(hr.totalLength, true).c_str()); - HeadResult hr; - if(filename.size() && totalLength > 0) { - hr.filename = filename; - hr.totalLength = totalLength; - } else { - hr = getHeadResult(); - if(fail) { - return RequestInfos(); - } - - logger->info("Head result: filename=%s, total length=%s", - hr.filename.c_str(), Util::ullitos(hr.totalLength, true).c_str()); - } adjustRequestSize(requests, reserved, maxConnections); SharedHandle<ConsoleDownloadEngine> e(DownloadEngineFactory::newConsoleEngine(op, requests, reserved)); - e->segmentMan->filename = hr.filename; - e->segmentMan->totalSize = hr.totalLength; - e->segmentMan->downloadStarted = true; + if(hr.totalLength > 0) { + e->segmentMan->filename = hr.filename; + e->segmentMan->totalSize = hr.totalLength; + e->segmentMan->downloadStarted = true; + } #ifdef ENABLE_MESSAGE_DIGEST - e->segmentMan->digestAlgo = digestAlgo; - e->segmentMan->chunkHashLength = chunkChecksumLength; - e->segmentMan->pieceHashes = chunkChecksums; + if(chunkChecksumLength > 0) { + e->segmentMan->digestAlgo = digestAlgo; + e->segmentMan->chunkHashLength = chunkChecksumLength; + e->segmentMan->pieceHashes = chunkChecksums; + } #endif // ENABLE_MESSAGE_DIGEST if(e->segmentMan->segmentFileExists()) { @@ -194,17 +201,19 @@ RequestInfos UrlRequestInfo::execute() { e->segmentMan->getFilePath().c_str(), e->segmentMan->getSegmentFilePath().c_str()); } - e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), - e->segmentMan->totalSize); - if(e->segmentMan->fileExists() && e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE) { - e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath()); + if(e->segmentMan->totalSize > 0) { + e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), + e->segmentMan->totalSize); + if(e->segmentMan->fileExists() && e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE) { + e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath()); #ifdef ENABLE_MESSAGE_DIGEST - e->segmentMan->markAllPiecesDone(); - e->segmentMan->checkIntegrity(); + e->segmentMan->markAllPiecesDone(); + e->segmentMan->checkIntegrity(); #endif // ENABLE_MESSAGE_DIGEST - } else { - e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath(), - e->segmentMan->totalSize); + } else { + e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath(), + e->segmentMan->totalSize); + } } } Util::setGlobalSignalHandler(SIGINT, handler, 0); diff --git a/src/UrlRequestInfo.h b/src/UrlRequestInfo.h index bf7f0f26..14eacf7f 100644 --- a/src/UrlRequestInfo.h +++ b/src/UrlRequestInfo.h @@ -39,9 +39,10 @@ class HeadResult { public: - HeadResult():totalLength(0) {} string filename; int64_t totalLength; +public: + HeadResult():totalLength(0) {} }; std::ostream& operator<<(std::ostream& o, const HeadResult& hr); @@ -55,8 +56,6 @@ private: int32_t chunkChecksumLength; Strings chunkChecksums; #endif // ENABLE_MESSAGE_DIGEST - string filename; - int64_t totalLength; RequestInfo* createNextRequestInfo() const; void adjustRequestSize(Requests& requests, @@ -68,12 +67,13 @@ public: UrlRequestInfo(const Strings& urls, int maxConnections, Option* op): RequestInfo(op), urls(urls), - maxConnections(maxConnections), + maxConnections(maxConnections) #ifdef ENABLE_MESSAGE_DIGEST + , digestAlgo(DIGEST_ALGO_SHA1), - chunkChecksumLength(0), + chunkChecksumLength(0) #endif // ENABLE_MESSAGE_DIGEST - totalLength(0) {} + {} virtual ~UrlRequestInfo() {} @@ -96,14 +96,6 @@ public: this->chunkChecksums = chunkChecksums; } #endif // ENABLE_MESSAGE_DIGEST - - void setTotalLength(int64_t totalLength) { - this->totalLength = totalLength; - } - - void setFilename(const string& filename) { - this->filename = filename; - } }; typedef SharedHandle<UrlRequestInfo> UrlRequestInfoHandle; |
