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.
pull/1/head
Tatsuhiro Tsujikawa 2007-01-29 16:46:48 +00:00
parent 2ab41c4f17
commit 77a05c00b1
11 changed files with 121 additions and 79 deletions

View File

@ -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> 2007-01-28 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/Xml2MetalinkProcessor.h * src/Xml2MetalinkProcessor.h

20
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # 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>. # Report bugs to <t-tujikawa@users.sourceforge.net>.
# #
@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='aria2c' PACKAGE_NAME='aria2c'
PACKAGE_TARNAME='aria2c' PACKAGE_TARNAME='aria2c'
PACKAGE_VERSION='0.10.0' PACKAGE_VERSION='0.10.0+1'
PACKAGE_STRING='aria2c 0.10.0' PACKAGE_STRING='aria2c 0.10.0+1'
PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net' PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net'
ac_unique_file="src/Socket.h" 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. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF 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]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1345,7 +1345,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in 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 esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1466,7 +1466,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
aria2c configure 0.10.0 aria2c configure 0.10.0+1
generated by GNU Autoconf 2.61 generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 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 This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. 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 generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@ $ $0 $@
@ -2150,7 +2150,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='aria2c' PACKAGE='aria2c'
VERSION='0.10.0' VERSION='0.10.0+1'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -12941,7 +12941,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" 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 generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -12994,7 +12994,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ 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, configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
# #
AC_PREREQ(2.59) 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_INIT_AUTOMAKE()
AM_PATH_CPPUNIT(1.10.2) AM_PATH_CPPUNIT(1.10.2)
AC_CONFIG_SRCDIR([src/Socket.h]) AC_CONFIG_SRCDIR([src/Socket.h])

View File

@ -9,7 +9,7 @@
# General Public License and is *not* in the public domain. # General Public License and is *not* in the public domain.
PACKAGE = aria2c PACKAGE = aria2c
VERSION = 0.10.0 VERSION = 0.10.0+1
SHELL = /bin/sh SHELL = /bin/sh

View File

@ -67,6 +67,8 @@ bool FtpNegotiationCommand::executeInternal(Segment& segment) {
command->setLowestDownloadSpeedLimit(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT)); command->setLowestDownloadSpeedLimit(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT));
e->commands.push_back(command); e->commands.push_back(command);
return true; return true;
} else if(sequence == SEQ_HEAD_OK) {
return true;
} else { } else {
e->commands.push_back(this); e->commands.push_back(this);
return false; return false;
@ -186,21 +188,16 @@ bool FtpNegotiationCommand::recvSize() {
throw new DlAbortEx(EX_TOO_LARGE_FILE, size); throw new DlAbortEx(EX_TOO_LARGE_FILE, size);
} }
if(!e->segmentMan->downloadStarted) { 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->downloadStarted = true;
e->segmentMan->totalSize = size; e->segmentMan->totalSize = size;
e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE),
e->segmentMan->totalSize); e->segmentMan->totalSize);
e->segmentMan->filename = Util::urldecode(req->getFile()); 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(); bool segFileExists = e->segmentMan->segmentFileExists();
if(segFileExists) { if(segFileExists) {
e->segmentMan->load(); e->segmentMan->load();

View File

@ -62,7 +62,8 @@ private:
SEQ_SEND_RETR, SEQ_SEND_RETR,
SEQ_RECV_RETR, SEQ_RECV_RETR,
SEQ_NEGOTIATION_COMPLETED, SEQ_NEGOTIATION_COMPLETED,
SEQ_RETRY SEQ_RETRY,
SEQ_HEAD_OK
}; };
bool recvGreeting(); bool recvGreeting();
bool sendUser(); bool sendUser();

View File

@ -91,8 +91,11 @@ bool HttpResponseCommand::executeInternal(Segment& segment) {
return handleDefaultEncoding(headers); return handleDefaultEncoding(headers);
} }
} else { } else {
if(determinFilename(headers) != e->segmentMan->filename) { string filenameInHeader = determinFilename(headers);
throw new DlAbortEx(EX_FILENAME_MISMATCH, req->getFile().c_str(), e->segmentMan->filename.c_str()); if(filenameInHeader != e->segmentMan->filename) {
throw new DlAbortEx(EX_FILENAME_MISMATCH,
filenameInHeader.c_str(),
e->segmentMan->filename.c_str());
} }
createHttpDownloadCommand(); createHttpDownloadCommand();
return true; return true;
@ -158,9 +161,6 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
if(req->getMethod() == Request::METHOD_HEAD) { if(req->getMethod() == Request::METHOD_HEAD) {
e->segmentMan->downloadStarted = true; e->segmentMan->downloadStarted = true;
e->segmentMan->totalSize = size; 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. e->segmentMan->isSplittable = false; // TODO because we don't want segment file to be saved.
return true; return true;
} }
@ -182,6 +182,14 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
} }
bool HttpResponseCommand::handleOtherEncoding(const string& transferEncoding, 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()) { if(e->segmentMan->shouldCancelDownloadForSafety()) {
throw new FatalException(EX_FILE_ALREADY_EXISTS, throw new FatalException(EX_FILE_ALREADY_EXISTS,
e->segmentMan->getFilePath().c_str(), e->segmentMan->getFilePath().c_str(),

View File

@ -122,13 +122,13 @@ RequestInfos MetalinkRequestInfo::execute() {
urls.push_back((*itr)->url); urls.push_back((*itr)->url);
} }
UrlRequestInfoHandle reqInfo = new UrlRequestInfo(urls, maxConnection, op); UrlRequestInfoHandle reqInfo = new UrlRequestInfo(urls, maxConnection, op);
reqInfo->setFilename(entry->filename);
reqInfo->setTotalLength(entry->size);
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
reqInfo->setChecksum(checksum); reqInfo->setChecksum(checksum);
reqInfo->setDigestAlgo(entry->chunkChecksum->digestAlgo); if(!entry->chunkChecksum.isNull()) {
reqInfo->setChunkChecksumLength(entry->chunkChecksum->pieceLength); reqInfo->setDigestAlgo(entry->chunkChecksum->digestAlgo);
reqInfo->setChunkChecksums(entry->chunkChecksum->pieceHashes); reqInfo->setChunkChecksumLength(entry->chunkChecksum->pieceLength);
reqInfo->setChunkChecksums(entry->chunkChecksum->pieceHashes);
}
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
nextReqInfos.push_front(reqInfo); nextReqInfos.push_front(reqInfo);
} }

View File

@ -237,6 +237,7 @@ void SegmentMan::init() {
} }
void SegmentMan::initBitfield(int segmentLength, long long int totalLength) { void SegmentMan::initBitfield(int segmentLength, long long int totalLength) {
delete bitfield;
this->bitfield = BitfieldManFactory::getNewFactory()->createBitfieldMan(segmentLength, totalLength); this->bitfield = BitfieldManFactory::getNewFactory()->createBitfieldMan(segmentLength, totalLength);
} }
@ -479,8 +480,8 @@ void SegmentMan::checkIntegrity()
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
bool SegmentMan::isChunkChecksumValidationReady() const { bool SegmentMan::isChunkChecksumValidationReady() const {
return bitfield && return bitfield && totalSize > 0 &&
((int64_t)pieceHashes.size())*chunkHashLength == ((int64_t)bitfield->getBlockLength())*(bitfield->getMaxIndex()+1); ((int64_t)pieceHashes.size())*chunkHashLength >= totalSize;
} }
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST

View File

@ -127,6 +127,10 @@ HeadResult UrlRequestInfo::getHeadResult() {
op->get(PREF_REFERER), op->get(PREF_REFERER),
1, 1,
Request::METHOD_HEAD)); Request::METHOD_HEAD));
if(requests.size() == 0) {
fail = true;
return HeadResult();
}
Requests reserved(requests.begin()+1, requests.end()); Requests reserved(requests.begin()+1, requests.end());
requests.erase(requests.begin()+1, requests.end()); requests.erase(requests.begin()+1, requests.end());
@ -135,8 +139,12 @@ HeadResult UrlRequestInfo::getHeadResult() {
HeadResult hr; HeadResult hr;
try { try {
e->run(); e->run();
hr.filename = e->segmentMan->filename; if(e->segmentMan->errors > 0) {
hr.totalLength = e->segmentMan->totalSize; fail = true;
} else {
hr.filename = e->segmentMan->filename;
hr.totalLength = e->segmentMan->totalSize;
}
} catch(RecoverableException *ex) { } catch(RecoverableException *ex) {
logger->error("Exception caught", ex); logger->error("Exception caught", ex);
delete ex; delete ex;
@ -150,34 +158,33 @@ RequestInfos UrlRequestInfo::execute() {
Requests requests; Requests requests;
Requests reserved; Requests reserved;
printUrls(urls); printUrls(urls);
HeadResult hr = getHeadResult();
if(fail) {
return RequestInfos();
}
for_each(urls.begin(), urls.end(), for_each(urls.begin(), urls.end(),
CreateRequest(&requests, CreateRequest(&requests,
op->get(PREF_REFERER), op->get(PREF_REFERER),
op->getAsInt(PREF_SPLIT))); 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); adjustRequestSize(requests, reserved, maxConnections);
SharedHandle<ConsoleDownloadEngine> e(DownloadEngineFactory::newConsoleEngine(op, requests, reserved)); SharedHandle<ConsoleDownloadEngine> e(DownloadEngineFactory::newConsoleEngine(op, requests, reserved));
e->segmentMan->filename = hr.filename; if(hr.totalLength > 0) {
e->segmentMan->totalSize = hr.totalLength; e->segmentMan->filename = hr.filename;
e->segmentMan->downloadStarted = true; e->segmentMan->totalSize = hr.totalLength;
e->segmentMan->downloadStarted = true;
}
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
e->segmentMan->digestAlgo = digestAlgo; if(chunkChecksumLength > 0) {
e->segmentMan->chunkHashLength = chunkChecksumLength; e->segmentMan->digestAlgo = digestAlgo;
e->segmentMan->pieceHashes = chunkChecksums; e->segmentMan->chunkHashLength = chunkChecksumLength;
e->segmentMan->pieceHashes = chunkChecksums;
}
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
if(e->segmentMan->segmentFileExists()) { if(e->segmentMan->segmentFileExists()) {
@ -194,17 +201,19 @@ RequestInfos UrlRequestInfo::execute() {
e->segmentMan->getFilePath().c_str(), e->segmentMan->getFilePath().c_str(),
e->segmentMan->getSegmentFilePath().c_str()); e->segmentMan->getSegmentFilePath().c_str());
} }
e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), if(e->segmentMan->totalSize > 0) {
e->segmentMan->totalSize); e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE),
if(e->segmentMan->fileExists() && e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE) { e->segmentMan->totalSize);
e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath()); if(e->segmentMan->fileExists() && e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
e->segmentMan->diskWriter->openExistingFile(e->segmentMan->getFilePath());
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
e->segmentMan->markAllPiecesDone(); e->segmentMan->markAllPiecesDone();
e->segmentMan->checkIntegrity(); e->segmentMan->checkIntegrity();
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
} else { } else {
e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath(), e->segmentMan->diskWriter->initAndOpenFile(e->segmentMan->getFilePath(),
e->segmentMan->totalSize); e->segmentMan->totalSize);
}
} }
} }
Util::setGlobalSignalHandler(SIGINT, handler, 0); Util::setGlobalSignalHandler(SIGINT, handler, 0);

View File

@ -39,9 +39,10 @@
class HeadResult { class HeadResult {
public: public:
HeadResult():totalLength(0) {}
string filename; string filename;
int64_t totalLength; int64_t totalLength;
public:
HeadResult():totalLength(0) {}
}; };
std::ostream& operator<<(std::ostream& o, const HeadResult& hr); std::ostream& operator<<(std::ostream& o, const HeadResult& hr);
@ -55,8 +56,6 @@ private:
int32_t chunkChecksumLength; int32_t chunkChecksumLength;
Strings chunkChecksums; Strings chunkChecksums;
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
string filename;
int64_t totalLength;
RequestInfo* createNextRequestInfo() const; RequestInfo* createNextRequestInfo() const;
void adjustRequestSize(Requests& requests, void adjustRequestSize(Requests& requests,
@ -68,12 +67,13 @@ public:
UrlRequestInfo(const Strings& urls, int maxConnections, Option* op): UrlRequestInfo(const Strings& urls, int maxConnections, Option* op):
RequestInfo(op), RequestInfo(op),
urls(urls), urls(urls),
maxConnections(maxConnections), maxConnections(maxConnections)
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
,
digestAlgo(DIGEST_ALGO_SHA1), digestAlgo(DIGEST_ALGO_SHA1),
chunkChecksumLength(0), chunkChecksumLength(0)
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
totalLength(0) {} {}
virtual ~UrlRequestInfo() {} virtual ~UrlRequestInfo() {}
@ -96,14 +96,6 @@ public:
this->chunkChecksums = chunkChecksums; this->chunkChecksums = chunkChecksums;
} }
#endif // ENABLE_MESSAGE_DIGEST #endif // ENABLE_MESSAGE_DIGEST
void setTotalLength(int64_t totalLength) {
this->totalLength = totalLength;
}
void setFilename(const string& filename) {
this->filename = filename;
}
}; };
typedef SharedHandle<UrlRequestInfo> UrlRequestInfoHandle; typedef SharedHandle<UrlRequestInfo> UrlRequestInfoHandle;