summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2007-01-29 16:46:48 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2007-01-29 16:46:48 +0000
commit77a05c00b1410687a3045ffe693aaa0496361fc8 (patch)
treed08984a2fba7457b2b1afd6f12eddb1d4d171484
parent2ab41c4f173182891ba0f4af1712028f8c26024f (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--ChangeLog34
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac2
-rw-r--r--po/Makefile.in2
-rw-r--r--src/FtpNegotiationCommand.cc17
-rw-r--r--src/FtpNegotiationCommand.h3
-rw-r--r--src/HttpResponseCommand.cc18
-rw-r--r--src/MetalinkRequestInfo.cc10
-rw-r--r--src/SegmentMan.cc5
-rw-r--r--src/UrlRequestInfo.cc69
-rw-r--r--src/UrlRequestInfo.h20
11 files changed, 121 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index f1891ed9..6265f359 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/configure b/configure
index 5914e217..097e0fc4 100755
--- a/configure
+++ b/configure
@@ -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;