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>
* src/Xml2MetalinkProcessor.h

20
configure vendored
View File

@ -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'`\\"

View File

@ -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])

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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(),

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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;