summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AbstractDiskWriter.cc31
-rw-r--r--src/AbstractDiskWriter.h5
-rw-r--r--src/AbstractSingleDiskAdaptor.cc4
-rw-r--r--src/AbstractSingleDiskAdaptor.h8
-rw-r--r--src/BtContext.h3
-rw-r--r--src/BtPieceMessage.cc7
-rw-r--r--src/ByteArrayDiskWriter.h8
-rw-r--r--src/Checksum.h34
-rw-r--r--src/ChunkChecksum.h6
-rw-r--r--src/ChunkChecksumValidator.cc78
-rw-r--r--src/ChunkChecksumValidator.h44
-rw-r--r--src/DefaultBtContext.cc38
-rw-r--r--src/DefaultBtContext.h14
-rw-r--r--src/DefaultBtInteractive.cc6
-rw-r--r--src/DefaultPieceStorage.cc15
-rw-r--r--src/DiskAdaptor.h10
-rw-r--r--src/DiskAdaptorWriter.h8
-rw-r--r--src/DiskWriter.h7
-rw-r--r--src/DownloadCommand.cc2
-rw-r--r--src/IteratableChecksumValidator.cc3
-rw-r--r--src/IteratableChunkChecksumValidator.cc3
-rw-r--r--src/IteratableChunkChecksumValidator.h5
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.in25
-rw-r--r--src/MessageDigestHelper.cc101
-rw-r--r--src/MessageDigestHelper.h77
-rw-r--r--src/MetalinkEntry.cc4
-rw-r--r--src/MetalinkEntry.h5
-rw-r--r--src/MetalinkRequestInfo.cc4
-rw-r--r--src/MultiDiskAdaptor.cc65
-rw-r--r--src/MultiDiskAdaptor.h14
-rw-r--r--src/Peer.cc3
-rw-r--r--src/SegmentMan.cc58
-rw-r--r--src/SegmentMan.h15
-rw-r--r--src/ShaVisitor.cc5
-rw-r--r--src/SimpleRandomizer.h11
-rw-r--r--src/TorrentRequestInfo.cc6
-rw-r--r--src/Util.cc87
-rw-r--r--src/Util.h29
-rw-r--r--src/Xml2MetalinkProcessor.cc51
-rw-r--r--src/main.cc5
-rw-r--r--src/message.h2
-rw-r--r--src/messageDigest.cc63
-rw-r--r--src/messageDigest.h61
44 files changed, 540 insertions, 495 deletions
diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc
index d6fec83d..943e0e76 100644
--- a/src/AbstractDiskWriter.cc
+++ b/src/AbstractDiskWriter.cc
@@ -113,36 +113,6 @@ int32_t AbstractDiskWriter::readDataInternal(char* data, int32_t len) {
return read(fd, data, len);
}
-#ifdef ENABLE_MESSAGE_DIGEST
-string AbstractDiskWriter::messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo)
-{
- MessageDigestContext ctx(algo);
- ctx.digestInit();
-
- int32_t BUFSIZE = 16*1024;
- char buf[BUFSIZE];
- for(int64_t i = 0; i < length/BUFSIZE; i++) {
- if(BUFSIZE != readData(buf, BUFSIZE, offset)) {
- throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno));
- }
- ctx.digestUpdate(buf, BUFSIZE);
- offset += BUFSIZE;
- }
- int32_t r = length%BUFSIZE;
- if(r > 0) {
- if(r != readData(buf, r, offset)) {
- throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno));
- }
- ctx.digestUpdate(buf, r);
- }
- unsigned char hashValue[20];
- ctx.digestFinal(hashValue);
-
- return Util::toHex(hashValue, 20);
-}
-#endif // ENABLE_MESSAGE_DIGEST
-
void AbstractDiskWriter::seek(int64_t offset) {
if(offset != lseek(fd, offset, SEEK_SET)) {
throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno));
@@ -170,6 +140,7 @@ void AbstractDiskWriter::truncate(int64_t length)
ftruncate(fd, length);
}
+// TODO the file descriptor fd must be opened before calling this function.
int64_t AbstractDiskWriter::size() const
{
struct stat fileStat;
diff --git a/src/AbstractDiskWriter.h b/src/AbstractDiskWriter.h
index 316ab3fc..f6b2d426 100644
--- a/src/AbstractDiskWriter.h
+++ b/src/AbstractDiskWriter.h
@@ -65,11 +65,6 @@ public:
virtual void openExistingFile(const string& filename, int64_t totalLength = 0);
-#ifdef ENABLE_MESSAGE_DIGEST
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo);
-#endif // ENABLE_MESSAGE_DIGEST
-
virtual void writeData(const char* data, int32_t len, int64_t offset);
virtual int32_t readData(char* data, int32_t len, int64_t offset);
diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc
index d1e5c4f0..e0bec6ee 100644
--- a/src/AbstractSingleDiskAdaptor.cc
+++ b/src/AbstractSingleDiskAdaptor.cc
@@ -59,10 +59,6 @@ int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, in
return diskWriter->readData(data, len, offset);
}
-string AbstractSingleDiskAdaptor::messageDigest(int64_t offset, int64_t length, const MessageDigestContext::DigestAlgo& algo) {
- return diskWriter->messageDigest(offset, length, algo);
-}
-
bool AbstractSingleDiskAdaptor::fileExists()
{
return File(getFilePath()).exists();
diff --git a/src/AbstractSingleDiskAdaptor.h b/src/AbstractSingleDiskAdaptor.h
index 57298d02..c4dc7e80 100644
--- a/src/AbstractSingleDiskAdaptor.h
+++ b/src/AbstractSingleDiskAdaptor.h
@@ -60,11 +60,13 @@ public:
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset);
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo);
-
virtual bool fileExists();
+ virtual int64_t size() const
+ {
+ return getTotalLength();
+ }
+
void setDiskWriter(const DiskWriterHandle diskWriter) {
this->diskWriter = diskWriter;
}
diff --git a/src/BtContext.h b/src/BtContext.h
index 5b4e832e..69d52029 100644
--- a/src/BtContext.h
+++ b/src/BtContext.h
@@ -84,6 +84,9 @@ public:
* Returns the peer id of localhost, 20 byte length
*/
virtual const unsigned char* getPeerId() = 0;
+
+ virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
+
};
typedef SharedHandle<BtContext> BtContextHandle;
diff --git a/src/BtPieceMessage.cc b/src/BtPieceMessage.cc
index dc6c8b8d..d3587583 100644
--- a/src/BtPieceMessage.cc
+++ b/src/BtPieceMessage.cc
@@ -39,6 +39,8 @@
#include "DlAbortEx.h"
#include "BtChokingEvent.h"
#include "BtCancelSendingPieceEvent.h"
+#include "DiskAdaptorWriter.h"
+#include "MessageDigestHelper.h"
void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) {
delete [] this->block;
@@ -190,8 +192,9 @@ string BtPieceMessage::toString() const {
bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) {
int64_t offset =
((int64_t)piece->getIndex())*btContext->getPieceLength();
- return pieceStorage->getDiskAdaptor()->messageDigest(offset, piece->getLength(), DIGEST_ALGO_SHA1) ==
- btContext->getPieceHash(piece->getIndex());
+
+ return MessageDigestHelper::digest("sha1", new DiskAdaptorWriter(pieceStorage->getDiskAdaptor()), offset, piece->getLength())
+ == btContext->getPieceHash(piece->getIndex());
}
void BtPieceMessage::onNewPiece(const PieceHandle& piece) {
diff --git a/src/ByteArrayDiskWriter.h b/src/ByteArrayDiskWriter.h
index 227cac74..a3583552 100644
--- a/src/ByteArrayDiskWriter.h
+++ b/src/ByteArrayDiskWriter.h
@@ -66,14 +66,6 @@ public:
{
return buf.str().size();
}
-
- // not implemented yet
-#ifdef ENABLE_MESSAGE_DIGEST
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo) {
- return "";
- }
-#endif // ENABLE_MESSAGE_DIGEST
};
#endif // _D_BYTE_ARRAY_DISK_WRITER_H_
diff --git a/src/Checksum.h b/src/Checksum.h
index eb1d5c34..54eea063 100644
--- a/src/Checksum.h
+++ b/src/Checksum.h
@@ -36,43 +36,39 @@
#define _D_CHECKSUM_H_
#include "common.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
class Checksum {
private:
- string md;
- MessageDigestContext::DigestAlgo algo;
+ string _algo;
+ string _messageDigest;
public:
- Checksum(const string& md, MessageDigestContext::DigestAlgo algo):
- md(md),
- algo(algo) {}
+ // _messageDigest is ascii hexadecimal notation.
+ Checksum(const string& algo, const string& messageDigest):
+ _algo(algo), _messageDigest(messageDigest) {}
Checksum():
- algo(DIGEST_ALGO_SHA1) {}
+ _algo("sha1") {}
+
~Checksum() {}
bool isEmpty() const {
- return md.size() == 0;
+ return _messageDigest.size() == 0;
}
void setMessageDigest(const string& md) {
- this->md = md;
+ this->_messageDigest = md;
}
const string& getMessageDigest() const {
- return md;
+ return _messageDigest;
}
- void setDigestAlgo(MessageDigestContext::DigestAlgo algo) {
- this->algo = algo;
+ void setAlgo(const string& algo) {
+ this->_algo = algo;
}
- const MessageDigestContext::DigestAlgo& getDigestAlgo() const {
- return algo;
+
+ const string& getAlgo() const {
+ return _algo;
}
};
-#else
-class Checksum {
-};
-#endif // ENABLE_MESSAGE_DIGEST
typedef SharedHandle<Checksum> ChecksumHandle;
diff --git a/src/ChunkChecksum.h b/src/ChunkChecksum.h
index 0df27efa..9b91b351 100644
--- a/src/ChunkChecksum.h
+++ b/src/ChunkChecksum.h
@@ -40,11 +40,11 @@
class ChunkChecksum {
private:
- MessageDigestContext::DigestAlgo _algo;
+ string _algo;
Strings _checksums;
int32_t _checksumLength;
public:
- ChunkChecksum(const MessageDigestContext::DigestAlgo& algo,
+ ChunkChecksum(const string& algo,
const Strings& checksums,
int32_t checksumLength):
_algo(algo),
@@ -85,7 +85,7 @@ public:
return _checksumLength;
}
- MessageDigestContext::DigestAlgo getAlgo() const
+ const string& getAlgo() const
{
return _algo;
}
diff --git a/src/ChunkChecksumValidator.cc b/src/ChunkChecksumValidator.cc
index ce62c24d..9e9b65ff 100644
--- a/src/ChunkChecksumValidator.cc
+++ b/src/ChunkChecksumValidator.cc
@@ -33,90 +33,34 @@
*/
/* copyright --> */
#include "ChunkChecksumValidator.h"
-#include "Util.h"
-#include "Exception.h"
#include "TimeA2.h"
#include "message.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-void ChunkChecksumValidator::validateSameLengthChecksum(BitfieldMan* bitfieldMan,
- int32_t index,
- const string& expectedChecksum,
- int32_t dataLength,
- int32_t checksumLength)
+void ChunkChecksumValidator::validate()
{
- int64_t offset = ((int64_t)index)*checksumLength;
- string actualChecksum = diskWriter->messageDigest(offset, dataLength, algo);
- if(actualChecksum != expectedChecksum) {
- logger->info(EX_INVALID_CHUNK_CHECKSUM,
- index, Util::llitos(offset, true).c_str(),
- expectedChecksum.c_str(), actualChecksum.c_str());
- bitfieldMan->unsetBit(index);
- }
-}
-
-void ChunkChecksumValidator::validateDifferentLengthChecksum(BitfieldMan* bitfieldMan,
- int32_t index,
- const string& expectedChecksum,
- int32_t dataLength,
- int32_t checksumLength)
-{
- int64_t offset = ((int64_t)index)*checksumLength;
- int32_t startIndex;
- int32_t endIndex;
- Util::indexRange(startIndex, endIndex, offset,
- checksumLength, bitfieldMan->getBlockLength());
- if(bitfieldMan->isBitRangeSet(startIndex, endIndex)) {
- string actualChecksum = diskWriter->messageDigest(offset, dataLength, algo);
- if(expectedChecksum != actualChecksum) {
- // wrong checksum
- logger->info(EX_INVALID_CHUNK_CHECKSUM,
- index, Util::llitos(offset, true).c_str(),
- expectedChecksum.c_str(), actualChecksum.c_str());
- bitfieldMan->unsetBitRange(startIndex, endIndex);
- }
- }
-}
-
-void ChunkChecksumValidator::validate(BitfieldMan* bitfieldMan,
- const Strings& checksums,
- int32_t checksumLength)
-{
- // We assume file is already opened using DiskWriter::open or openExistingFile.
- if(((int64_t)checksumLength*checksums.size()) < bitfieldMan->getTotalLength()) {
+ if(!_validator->canValidate()) {
// insufficient checksums.
logger->error(MSG_INSUFFICIENT_CHECKSUM,
- checksumLength, checksums.size());
+ _validator->getChunkChecksum()->getChecksumLength(),
+ _validator->getChunkChecksum()->countChecksum());
return;
}
- assert(bitfieldMan->getTotalLength()/checksumLength <= INT32_MAX);
- int32_t x = bitfieldMan->getTotalLength()/checksumLength;
- int32_t r = bitfieldMan->getTotalLength()%checksumLength;
- void (ChunkChecksumValidator::*f)(BitfieldMan*, int32_t, const string&, int32_t, int32_t);
-
- if(checksumLength == bitfieldMan->getBlockLength()) {
- f = &ChunkChecksumValidator::validateSameLengthChecksum;
- } else {
- f = &ChunkChecksumValidator::validateDifferentLengthChecksum;
- }
+ _validator->init();
+ int32_t numChecksum = _validator->getChunkChecksum()->countChecksum();
fileAllocationMonitor->setMinValue(0);
- fileAllocationMonitor->setMaxValue(bitfieldMan->getTotalLength());
+ fileAllocationMonitor->setMaxValue(numChecksum);
fileAllocationMonitor->setCurrentValue(0);
fileAllocationMonitor->showProgress();
Time cp;
- for(int32_t i = 0; i < x; ++i) {
- (this->*f)(bitfieldMan, i, checksums[i], checksumLength, checksumLength);
+ for(int32_t i = 0; i < numChecksum; ++i) {
+ _validator->validateChunk();
if(cp.elapsedInMillis(500)) {
- fileAllocationMonitor->setCurrentValue(i*checksumLength);
+ fileAllocationMonitor->setCurrentValue(i+1);
fileAllocationMonitor->showProgress();
cp.reset();
}
}
- if(r) {
- (this->*f)(bitfieldMan, x, checksums[x], r, checksumLength);
- }
- fileAllocationMonitor->setCurrentValue(bitfieldMan->getTotalLength());
+ fileAllocationMonitor->setCurrentValue(numChecksum);
fileAllocationMonitor->showProgress();
}
-#endif // ENABLE_MESSAGE_DIGEST
diff --git a/src/ChunkChecksumValidator.h b/src/ChunkChecksumValidator.h
index 717151a8..097b439b 100644
--- a/src/ChunkChecksumValidator.h
+++ b/src/ChunkChecksumValidator.h
@@ -36,63 +36,33 @@
#define _D_CHUNK_CHECKSUM_VALIDATOR_H_
#include "common.h"
-#include "DiskWriter.h"
-#include "BitfieldMan.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
-#endif // ENABLE_MESSAGE_DIGEST
#include "LogFactory.h"
#include "FileAllocationMonitor.h"
#include "NullFileAllocationMonitor.h"
+#include "IteratableChunkChecksumValidator.h"
class ChunkChecksumValidator {
-#ifdef ENABLE_MESSAGE_DIGEST
-protected:
- DiskWriterHandle diskWriter;
-
- MessageDigestContext::DigestAlgo algo;
+private:
+ IteratableChunkChecksumValidatorHandle _validator;
FileAllocationMonitorHandle fileAllocationMonitor;
const Logger* logger;
-
- void validateSameLengthChecksum(BitfieldMan* bitfieldMan,
- int32_t index,
- const string& expectedChecksum,
- int32_t thisLength,
- int32_t checksumLength);
-
- void validateDifferentLengthChecksum(BitfieldMan* bitfieldMan,
- int32_t index,
- const string& expectedChecksum,
- int32_t thisLength,
- int32_t checksumLength);
public:
- ChunkChecksumValidator():
- diskWriter(0),
- algo(DIGEST_ALGO_SHA1),
+ ChunkChecksumValidator(const IteratableChunkChecksumValidatorHandle v):
+ _validator(v),
fileAllocationMonitor(new NullFileAllocationMonitor()),
logger(LogFactory::getInstance())
{}
~ChunkChecksumValidator() {}
- void validate(BitfieldMan* bitfieldMan,
- const Strings& checksums,
- int32_t checksumLength);
-
- void setDiskWriter(const DiskWriterHandle& diskWriter) {
- this->diskWriter = diskWriter;
- }
-
- void setDigestAlgo(const MessageDigestContext::DigestAlgo& algo) {
- this->algo = algo;
- }
+ void validate();
void setFileAllocationMonitor(const FileAllocationMonitorHandle& monitor) {
this->fileAllocationMonitor = monitor;
}
-#endif // ENABLE_MESSAGE_DIGEST
};
+typedef SharedHandle<ChunkChecksumValidator> ChunkChecksumValidatorHandle;
#endif // _D_CHUNK_CHECKSUM_VALIDATOR_H_
diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc
index b5f3ad28..29c748ce 100644
--- a/src/DefaultBtContext.cc
+++ b/src/DefaultBtContext.cc
@@ -40,6 +40,8 @@
#include "DlAbortEx.h"
#include "ShaVisitor.h"
#include "Util.h"
+#include "MessageDigestHelper.h"
+#include "a2netcompat.h"
#include <libgen.h>
DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {}
@@ -245,3 +247,39 @@ int32_t DefaultBtContext::getPieceLength() const {
int32_t DefaultBtContext::getNumPieces() const {
return numPieces;
}
+
+Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
+{
+ Integers fastSet;
+ struct in_addr saddr;
+ if(inet_aton(ipaddr.c_str(), &saddr) == 0) {
+ abort();
+ }
+ unsigned char tx[24];
+ memcpy(tx, (void*)&saddr.s_addr, 4);
+ if((tx[0] & 0x80) == 0 || (tx[0] & 0x40) == 0) {
+ tx[2] = 0x00;
+ tx[3] = 0x00;
+ } else {
+ tx[3] = 0x00;
+ }
+ memcpy(tx+4, infoHash, 20);
+ unsigned char x[20];
+ MessageDigestHelper::digest(x, sizeof(x), "sha1", tx, 24);
+ while((int32_t)fastSet.size() < fastSetSize) {
+ for(int32_t i = 0; i < 5 && (int32_t)fastSet.size() < fastSetSize; i++) {
+ int32_t j = i*4;
+ uint32_t ny;
+ memcpy(&ny, x+j, 4);
+ uint32_t y = ntohl(ny);
+ int32_t index = y%numPieces;
+ if(find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) {
+ fastSet.push_back(index);
+ }
+ }
+ unsigned char temp[20];
+ MessageDigestHelper::digest(temp, sizeof(temp), "sha1", x, sizeof(x));
+ memcpy(x, temp, sizeof(x));
+ }
+ return fastSet;
+}
diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h
index 7a2c6811..36c9a543 100644
--- a/src/DefaultBtContext.h
+++ b/src/DefaultBtContext.h
@@ -107,12 +107,26 @@ private:
return (const unsigned char*)peerId.c_str();
}
+ virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
+
string generatePeerId() const;
void setPeerIdPrefix(const string& peerIdPrefix)
{
_peerIdPrefix = peerIdPrefix;
}
+
+ // for unit test
+ void setInfoHash(const unsigned char* infoHash)
+ {
+ memcpy(this->infoHash, infoHash, sizeof(this->infoHash));
+ }
+
+ void setNumPieces(int32_t numPieces)
+ {
+ this->numPieces = numPieces;
+ }
+
};
typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;
diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc
index 4b0246ee..0263bc43 100644
--- a/src/DefaultBtInteractive.cc
+++ b/src/DefaultBtInteractive.cc
@@ -96,10 +96,8 @@ void DefaultBtInteractive::addBitfieldMessageToQueue() {
void DefaultBtInteractive::addAllowedFastMessageToQueue() {
if(peer->isFastExtensionEnabled()) {
- Integers fastSet = Util::computeFastSet(peer->ipaddr,
- btContext->getInfoHash(),
- btContext->getNumPieces(),
- allowedFastSetSize);
+ Integers fastSet = btContext->computeFastSet(peer->ipaddr,
+ allowedFastSetSize);
for(Integers::const_iterator itr = fastSet.begin();
itr != fastSet.end(); itr++) {
dispatcher->addMessageToQueue(messageFactory->createAllowedFastMessage(*itr));
diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc
index 00c8c65d..5afb64e7 100644
--- a/src/DefaultPieceStorage.cc
+++ b/src/DefaultPieceStorage.cc
@@ -448,10 +448,15 @@ void DefaultPieceStorage::checkIntegrity()
{
logger->notice(MSG_VALIDATING_FILE,
diskAdaptor->getFilePath().c_str());
- ChunkChecksumValidator v;
- v.setDigestAlgo(DIGEST_ALGO_SHA1);
- v.setDiskWriter(new DiskAdaptorWriter(diskAdaptor));
+ ChunkChecksumHandle chunkChecksum = new ChunkChecksum("sha1",
+ btContext->getPieceHashes(),
+ btContext->getPieceLength());
+ IteratableChunkChecksumValidatorHandle iv = new IteratableChunkChecksumValidator();
+ iv->setDiskWriter(new DiskAdaptorWriter(diskAdaptor));
+ iv->setBitfield(bitfieldMan);
+ iv->setChunkChecksum(chunkChecksum);
+
+ ChunkChecksumValidator v(iv);
v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
- v.validate(bitfieldMan, btContext->getPieceHashes(),
- btContext->getPieceLength());
+ v.validate();
}
diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h
index 32f93022..5a1c6df1 100644
--- a/src/DiskAdaptor.h
+++ b/src/DiskAdaptor.h
@@ -38,9 +38,6 @@
#include "common.h"
#include "FileEntry.h"
#include "Logger.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
-#endif // ENABLE_MESSAGE_DIGEST
class DiskAdaptor {
protected:
@@ -63,17 +60,14 @@ public:
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0;
-#ifdef ENABLE_MESSAGE_DIGEST
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo) = 0;
-#endif // ENABLE_MESSAGE_DIGEST
-
virtual void onDownloadComplete() = 0;
virtual bool fileExists() = 0;
virtual string getFilePath() = 0;
+ virtual int64_t size() const = 0;
+
void setFileEntries(const FileEntries& fileEntries) {
this->fileEntries = fileEntries;
}
diff --git a/src/DiskAdaptorWriter.h b/src/DiskAdaptorWriter.h
index 3c400ddc..5a5fc5e3 100644
--- a/src/DiskAdaptorWriter.h
+++ b/src/DiskAdaptorWriter.h
@@ -78,12 +78,6 @@ public:
return diskAdaptor->readData((unsigned char*)data, len, position);
}
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo)
- {
- return diskAdaptor->messageDigest(offset, length, algo);
- }
-
virtual void truncate(int64_t length)
{
throw new FatalException("DiskAdaptorWriter::truncate() is not implemented yet.");
@@ -91,7 +85,7 @@ public:
virtual int64_t size() const
{
- throw new FatalException("DiskAdaptorWriter::size() is not implemented yet.");
+ return diskAdaptor->size();
}
};
diff --git a/src/DiskWriter.h b/src/DiskWriter.h
index 9ff7602f..5f0a93b5 100644
--- a/src/DiskWriter.h
+++ b/src/DiskWriter.h
@@ -36,9 +36,6 @@
#define _D_DISK_WRITER_H_
#include "common.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
-#endif // ENABLE_MESSAGE_DIGEST
using namespace std;
@@ -90,10 +87,6 @@ public:
virtual int32_t readData(unsigned char* data, int32_t len, int64_t position) {
return readData((char*)data, len, position);
}
-#ifdef ENABLE_MESSAGE_DIGEST
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo) = 0;
-#endif // ENABLE_MESSAGE_DIGEST
virtual void truncate(int64_t length) = 0;
diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc
index 243c048c..9a19b0fa 100644
--- a/src/DownloadCommand.cc
+++ b/src/DownloadCommand.cc
@@ -118,7 +118,7 @@ bool DownloadCommand::executeInternal() {
_requestGroup->getSegmentMan()->completeSegment(cuid, segment);
#ifdef ENABLE_MESSAGE_DIGEST
if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) {
- _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment);
+ _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum());
}
#endif // ENABLE_MESSAGE_DIGEST
// this unit is going to download another segment.
diff --git a/src/IteratableChecksumValidator.cc b/src/IteratableChecksumValidator.cc
index e094a632..545d4328 100644
--- a/src/IteratableChecksumValidator.cc
+++ b/src/IteratableChecksumValidator.cc
@@ -76,6 +76,7 @@ void IteratableChecksumValidator::init()
_bitfield->setAllBit();
_currentOffset = 0;
- _ctx = new MessageDigestContext(_checksum->getDigestAlgo());
+ _ctx = new MessageDigestContext();
+ _ctx->trySetAlgo(_checksum->getAlgo());
_ctx->digestInit();
}
diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc
index 9ad30c46..0e43acc3 100644
--- a/src/IteratableChunkChecksumValidator.cc
+++ b/src/IteratableChunkChecksumValidator.cc
@@ -35,6 +35,7 @@
#include "IteratableChunkChecksumValidator.h"
#include "Util.h"
#include "message.h"
+#include "MessageDigestHelper.h"
void IteratableChunkChecksumValidator::validateChunk()
{
@@ -65,7 +66,7 @@ string IteratableChunkChecksumValidator::calculateActualChecksum()
{
int64_t offset = ((int64_t)_currentIndex)*_chunkChecksum->getChecksumLength();
int32_t length = _diskWriter->size() < offset+_chunkChecksum->getChecksumLength() ? _diskWriter->size()-offset : _chunkChecksum->getChecksumLength();
- return _diskWriter->messageDigest(offset, length, _chunkChecksum->getAlgo());
+ return MessageDigestHelper::digest(_chunkChecksum->getAlgo(), _diskWriter, offset, length);
}
bool IteratableChunkChecksumValidator::canValidate() const
diff --git a/src/IteratableChunkChecksumValidator.h b/src/IteratableChunkChecksumValidator.h
index 908a3540..6e4bb4bc 100644
--- a/src/IteratableChunkChecksumValidator.h
+++ b/src/IteratableChunkChecksumValidator.h
@@ -89,6 +89,11 @@ public:
{
return _bitfield->getTotalLength();
}
+
+ ChunkChecksumHandle getChunkChecksum()
+ {
+ return _chunkChecksum;
+ }
};
typedef SharedHandle<IteratableChunkChecksumValidator> IteratableChunkChecksumValidatorHandle;
diff --git a/src/Makefile.am b/src/Makefile.am
index 4a8b3ed6..66d369a3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,7 +45,6 @@ SRCS = Socket.h\
Option.cc Option.h\
Base64.cc Base64.h\
CookieBox.cc CookieBox.h\
- messageDigest.h\
LogFactory.cc LogFactory.h\
NullLogger.h\
TimeA2.cc TimeA2.h\
@@ -109,7 +108,9 @@ SRCS += ChunkChecksumValidator.cc ChunkChecksumValidator.h\
ChecksumCommand.cc ChecksumCommand.h\
CheckIntegrityCommand.cc CheckIntegrityCommand.h\
CheckIntegrityEntry.cc CheckIntegrityEntry.h\
- CheckIntegrityMan.h
+ CheckIntegrityMan.h\
+ messageDigest.cc messageDigest.h\
+ MessageDigestHelper.cc MessageDigestHelper.h
endif # ENABLE_MESSAGE_DIGEST
if ENABLE_BITTORRENT
diff --git a/src/Makefile.in b/src/Makefile.in
index deb01f1c..9c38b3a2 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -46,7 +46,9 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.cc ChecksumCommand.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.cc CheckIntegrityEntry.h\
-@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.h
+@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.h\
+@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.cc messageDigest.h\
+@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.cc MessageDigestHelper.h
@ENABLE_BITTORRENT_TRUE@am__append_2 = MetaEntry.h\
@ENABLE_BITTORRENT_TRUE@ Data.cc Data.h\
@@ -219,8 +221,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \
AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \
File.cc File.h Option.cc Option.h Base64.cc Base64.h \
- CookieBox.cc CookieBox.h messageDigest.h LogFactory.cc \
- LogFactory.h NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \
+ CookieBox.cc CookieBox.h LogFactory.cc LogFactory.h \
+ NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \
HandleRegistry.h FeatureConfig.cc FeatureConfig.h \
DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \
SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \
@@ -259,9 +261,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
IteratableChecksumValidator.cc IteratableChecksumValidator.h \
ChecksumCommand.cc ChecksumCommand.h CheckIntegrityCommand.cc \
CheckIntegrityCommand.h CheckIntegrityEntry.cc \
- CheckIntegrityEntry.h CheckIntegrityMan.h MetaEntry.h Data.cc \
- Data.h Dictionary.cc Dictionary.h List.cc List.h \
- MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
+ CheckIntegrityEntry.h CheckIntegrityMan.h messageDigest.cc \
+ messageDigest.h MessageDigestHelper.cc MessageDigestHelper.h \
+ MetaEntry.h Data.cc Data.h Dictionary.cc Dictionary.h List.cc \
+ List.h MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \
PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
@@ -338,7 +341,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.$(OBJEXT) \
@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \
-@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.$(OBJEXT)
+@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.$(OBJEXT) \
+@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \
+@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT)
@ENABLE_BITTORRENT_TRUE@am__objects_2 = Data.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \
@@ -676,8 +681,8 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \
AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \
File.cc File.h Option.cc Option.h Base64.cc Base64.h \
- CookieBox.cc CookieBox.h messageDigest.h LogFactory.cc \
- LogFactory.h NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \
+ CookieBox.cc CookieBox.h LogFactory.cc LogFactory.h \
+ NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \
HandleRegistry.h FeatureConfig.cc FeatureConfig.h \
DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \
SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \
@@ -902,6 +907,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/List.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkRequestInfo.Po@am__quote@
@@ -960,6 +966,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localtime_r.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messageDigest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strptime.Po@am__quote@
.c.o:
diff --git a/src/MessageDigestHelper.cc b/src/MessageDigestHelper.cc
new file mode 100644
index 00000000..8819dcdc
--- /dev/null
+++ b/src/MessageDigestHelper.cc
@@ -0,0 +1,101 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "MessageDigestHelper.h"
+#include "messageDigest.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include "DefaultDiskWriter.h"
+#include "Util.h"
+#include <errno.h>
+
+string MessageDigestHelper::digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length)
+{
+ MessageDigestContext ctx;
+ ctx.trySetAlgo(algo);
+ ctx.digestInit();
+
+ int32_t BUFSIZE = 4096;
+ char BUF[BUFSIZE];
+ int64_t iteration = length/BUFSIZE;
+ int32_t tail = length%BUFSIZE;
+ for(int64_t i = 0; i < iteration; ++i) {
+ int32_t readLength = diskWriter->readData(BUF, BUFSIZE, offset);
+ if(readLength != BUFSIZE) {
+ throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno));
+ }
+ ctx.digestUpdate(BUF, readLength);
+ offset += readLength;
+ }
+ if(tail) {
+ int32_t readLength = diskWriter->readData(BUF, tail, offset);
+ if(readLength != tail) {
+ throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno));
+ }
+ ctx.digestUpdate(BUF, readLength);
+ }
+ string rawMD = ctx.digestFinal();
+ return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size());
+}
+
+string MessageDigestHelper::digest(const string& algo, const string& filename)
+{
+ DiskWriterHandle writer = new DefaultDiskWriter();
+ writer->openExistingFile(filename);
+ return digest(algo, writer);
+}
+
+string MessageDigestHelper::digest(const string& algo, const void* data, int32_t length)
+{
+ MessageDigestContext ctx;
+ ctx.trySetAlgo(algo);
+ ctx.digestInit();
+ ctx.digestUpdate(data, length);
+ string rawMD = ctx.digestFinal();
+ return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size());
+}
+
+void MessageDigestHelper::digest(unsigned char* md, int32_t mdLength,
+ const string& algo, const void* data, int32_t length)
+{
+ if(mdLength < MessageDigestContext::digestLength(algo)) {
+ throw new DlAbortEx("Insufficient space for storing message digest: %d required, but only %d is allocated", MessageDigestContext::digestLength(algo), mdLength);
+ }
+ MessageDigestContext ctx;
+ ctx.trySetAlgo(algo);
+ ctx.digestInit();
+ ctx.digestUpdate(data, length);
+ ctx.digestFinal(md);
+}
+
diff --git a/src/MessageDigestHelper.h b/src/MessageDigestHelper.h
new file mode 100644
index 00000000..21e4a215
--- /dev/null
+++ b/src/MessageDigestHelper.h
@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_MESSAGE_DIGEST_HELPER_H_
+#define _D_MESSAGE_DIGEST_HELPER_H_
+
+#include "common.h"
+#include "DiskWriter.h"
+
+class MessageDigestHelper {
+public:
+ /**
+ * Returns message digest in hexadecimal notation.
+ * Digest algorithm is specified by algo.
+ */
+ static string digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length);
+
+ /**
+ * Calculates message digest of file opened by diskWriter.
+ */
+ static string digest(const string& algo, DiskWriterHandle diskWriter)
+ {
+ return digest(algo, diskWriter, 0, diskWriter->size());
+ }
+
+ /**
+ * Calculates message digest of file denoted by filename.
+ */
+ static string digest(const string& algo, const string& filename);
+
+ static string digest(const string& algo, const void* data, int32_t length);
+
+ static string digestString(const string& algo, const string& data)
+ {
+ return digest(algo, data.c_str(), data.size());
+ }
+
+ /**
+ * Stores *raw* message digest into md.
+ * Throws exception when mdLength is less than the size of message digest.
+ */
+ static void digest(unsigned char* md, int32_t mdLength,
+ const string& algo, const void* data, int32_t length);
+};
+
+#endif // _D_MESSAGE_DIGEST_HELPER_H_
diff --git a/src/MetalinkEntry.cc b/src/MetalinkEntry.cc
index b82129fa..80e2def8 100644
--- a/src/MetalinkEntry.cc
+++ b/src/MetalinkEntry.cc
@@ -39,7 +39,7 @@
MetalinkEntry::MetalinkEntry()
#ifdef ENABLE_MESSAGE_DIGEST
:checksum(0),
- chunkChecksum(0)
+ chunkChecksum(0)
#endif // ENABLE_MESSAGE_DIGEST
{}
@@ -84,7 +84,9 @@ public:
switch(res->type) {
case MetalinkResource::TYPE_FTP:
case MetalinkResource::TYPE_HTTP:
+#ifdef ENABLE_SSL
case MetalinkResource::TYPE_HTTPS:
+#endif // ENABLE_SSL
#ifdef ENABLE_BITTORRENT
case MetalinkResource::TYPE_BITTORRENT:
#endif // ENABLE_BITTORRENT
diff --git a/src/MetalinkEntry.h b/src/MetalinkEntry.h
index 783e9d1f..9774e6e0 100644
--- a/src/MetalinkEntry.h
+++ b/src/MetalinkEntry.h
@@ -55,10 +55,9 @@ public:
string version;
string language;
string os;
- ChecksumHandle checksum;
-public:
MetalinkResources resources;
#ifdef ENABLE_MESSAGE_DIGEST
+ ChecksumHandle checksum;
ChunkChecksumHandle chunkChecksum;
#endif // ENABLE_MESSAGE_DIGEST
public:
@@ -72,8 +71,8 @@ public:
this->version = metalinkEntry.version;
this->language = metalinkEntry.language;
this->os = metalinkEntry.os;
- this->checksum = metalinkEntry.checksum;
#ifdef ENABLE_MESSAGE_DIGEST
+ this->checksum = metalinkEntry.checksum;
this->chunkChecksum = metalinkEntry.chunkChecksum;
#endif // ENABLE_MESSAGE_DIGEST
}
diff --git a/src/MetalinkRequestInfo.cc b/src/MetalinkRequestInfo.cc
index ddae83d8..6da65841 100644
--- a/src/MetalinkRequestInfo.cc
+++ b/src/MetalinkRequestInfo.cc
@@ -131,15 +131,19 @@ RequestInfos MetalinkRequestInfo::execute() {
entry->resources.end(),
FindBitTorrentUrl());
Strings urls;
+#ifdef ENABLE_MESSAGE_DIGEST
ChecksumHandle checksum = 0;
+#endif // ENABLE_MESSAGE_DIGEST
if(itr == entry->resources.end()) {
entry->reorderResourcesByPreference();
for_each(entry->resources.begin(), entry->resources.end(),
AccumulateNonP2PUrl(&urls, op->getAsInt(PREF_SPLIT)));
+#ifdef ENABLE_MESSAGE_DIGEST
// TODO
// set checksum
checksum = entry->checksum;
+#endif // ENABLE_MESSAGE_DIGEST
} else {
// BitTorrent downloading
urls.push_back((*itr)->url);
diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc
index 32375528..b866d68e 100644
--- a/src/MultiDiskAdaptor.cc
+++ b/src/MultiDiskAdaptor.cc
@@ -37,7 +37,6 @@
#include "DlAbortEx.h"
#include "message.h"
#include "Util.h"
-#include <errno.h>
void MultiDiskAdaptor::resetDiskWriterEntries() {
diskWriterEntries.clear();
@@ -169,58 +168,11 @@ int32_t MultiDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t off
return totalReadLength;
}
-void MultiDiskAdaptor::hashUpdate(MessageDigestContext& ctx,
- const DiskWriterEntryHandle& entry,
- int64_t offset, int64_t length)
-{
- int32_t BUFSIZE = 16*1024;
- unsigned char buf[BUFSIZE];
- for(int64_t i = 0; i < length/BUFSIZE; i++) {
- if(BUFSIZE != entry->getDiskWriter()->readData(buf, BUFSIZE, offset)) {
- throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno));
- }
- ctx.digestUpdate(buf, BUFSIZE);
- offset += BUFSIZE;
- }
- int32_t r = length%BUFSIZE;
- if(r > 0) {
- if((int32_t)r != entry->getDiskWriter()->readData(buf, r, offset)) {
- throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno));
- }
- ctx.digestUpdate(buf, r);
- }
-}
-
-string MultiDiskAdaptor::messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo) {
- int64_t fileOffset = offset;
- bool reading = false;
- int32_t rem = length;
- MessageDigestContext ctx(algo);
- ctx.digestInit();
-
- for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
- itr != diskWriterEntries.end() && rem != 0; itr++) {
- if(isInRange(*itr, offset) || reading) {
- int32_t readLength = calculateLength((*itr), fileOffset, rem);
- hashUpdate(ctx, *itr, fileOffset, readLength);
- rem -= readLength;
- reading = true;
- fileOffset = 0;
- } else {
- fileOffset -= (*itr)->getFileEntry()->getLength();
- }
- }
- if(!reading) {
- throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, Util::llitos(offset, true).c_str());
- }
- unsigned char hashValue[20];
- ctx.digestFinal(hashValue);
- return Util::toHex(hashValue, 20);
-}
-
bool MultiDiskAdaptor::fileExists()
{
+ if(diskWriterEntries.empty()) {
+ resetDiskWriterEntries();
+ }
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
itr != diskWriterEntries.end(); itr++) {
if((*itr)->fileExists(getTopDirPath())) {
@@ -229,3 +181,14 @@ bool MultiDiskAdaptor::fileExists()
}
return false;
}
+
+// TODO call DiskWriter::openFile() before calling this function.
+int64_t MultiDiskAdaptor::size() const
+{
+ int64_t size = 0;
+ for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin();
+ itr != diskWriterEntries.end(); itr++) {
+ size += (*itr)->size();
+ }
+ return size;
+}
diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h
index 0610517e..1d01d937 100644
--- a/src/MultiDiskAdaptor.h
+++ b/src/MultiDiskAdaptor.h
@@ -81,6 +81,11 @@ public:
return File(getFilePath(topDir)).exists();
}
+ int64_t size() const
+ {
+ return diskWriter->size();
+ }
+
FileEntryHandle getFileEntry() const {
return fileEntry;
}
@@ -115,10 +120,6 @@ private:
int64_t fileOffset,
int32_t rem) const;
- void hashUpdate(MessageDigestContext& ctx,
- const DiskWriterEntryHandle& entry,
- int64_t offset, int64_t length);
-
string getTopDirPath() const;
public:
MultiDiskAdaptor():pieceLength(0),
@@ -142,15 +143,14 @@ public:
virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset);
- virtual string messageDigest(int64_t offset, int64_t length,
- const MessageDigestContext::DigestAlgo& algo);
-
virtual bool fileExists();
virtual string getFilePath() {
return getTopDirPath();
}
+ virtual int64_t size() const;
+
void setTopDir(const string& topDir) {
this->topDir = topDir;
}
diff --git a/src/Peer.cc b/src/Peer.cc
index 685b1b36..1017c250 100644
--- a/src/Peer.cc
+++ b/src/Peer.cc
@@ -35,6 +35,7 @@
#include "Peer.h"
#include "BitfieldManFactory.h"
#include "Util.h"
+#include "MessageDigestHelper.h"
Peer::Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength):
ipaddr(ipaddr),
@@ -50,7 +51,7 @@ Peer::Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength
this->bitfield = BitfieldManFactory::getFactoryInstance()->
createBitfieldMan(pieceLength, totalLength);
string idSeed = ipaddr+":"+Util::itos(port);
- id = Util::simpleMessageDigest(idSeed);
+ id = MessageDigestHelper::digestString("sha1", idSeed);
}
/*
diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc
index 8c0f23a5..bcd784dd 100644
--- a/src/SegmentMan.cc
+++ b/src/SegmentMan.cc
@@ -41,7 +41,7 @@
#include "LogFactory.h"
#include "BitfieldManFactory.h"
#ifdef ENABLE_MESSAGE_DIGEST
-#include "ChunkChecksumValidator.h"
+#include "MessageDigestHelper.h"
#endif // ENABLE_MESSAGE_DIGEST
#include "a2io.h"
#include <errno.h>
@@ -54,11 +54,6 @@ SegmentMan::SegmentMan():logger(LogFactory::getInstance()),
dir("."),
errors(0),
diskWriter(0)
-#ifdef ENABLE_MESSAGE_DIGEST
- ,
- chunkHashLength(0),
- digestAlgo(DIGEST_ALGO_SHA1)
-#endif // ENABLE_MESSAGE_DIGEST
{}
SegmentMan::~SegmentMan() {
@@ -474,29 +469,16 @@ void SegmentMan::markPieceDone(int64_t length)
}
#ifdef ENABLE_MESSAGE_DIGEST
-void SegmentMan::checkIntegrity()
-{
- logger->notice(MSG_VALIDATING_FILE,
- getFilePath().c_str());
- ChunkChecksumValidator v;
- v.setDigestAlgo(digestAlgo);
- v.setDiskWriter(diskWriter);
- v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
- v.validate(bitfield, pieceHashes, chunkHashLength);
-}
-#endif // ENABLE_MESSAGE_DIGEST
-
-#ifdef ENABLE_MESSAGE_DIGEST
-bool SegmentMan::isChunkChecksumValidationReady() const {
- return bitfield && totalSize > 0 &&
- ((int64_t)pieceHashes.size())*chunkHashLength >= totalSize;
+bool SegmentMan::isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const {
+ return !chunkChecksum.isNull() && bitfield && totalSize > 0 &&
+ chunkChecksum->getEstimatedDataLength() >= totalSize;
}
#endif // ENABLE_MESSAGE_DIGEST
#ifdef ENABLE_MESSAGE_DIGEST
-void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment)
+void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum)
{
- if(!isChunkChecksumValidationReady()) {
+ if(!isChunkChecksumValidationReady(chunkChecksum)) {
return;
}
int32_t hashStartIndex;
@@ -504,13 +486,13 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment)
Util::indexRange(hashStartIndex, hashEndIndex,
segment->getPosition(),
segment->writtenLength,
- chunkHashLength);
- if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkHashLength,
- chunkHashLength)) {
+ chunkChecksum->getChecksumLength());
+ if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkChecksum->getChecksumLength(),
+ chunkChecksum->getChecksumLength())) {
++hashStartIndex;
}
- if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkHashLength,
- chunkHashLength)) {
+ if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkChecksum->getChecksumLength(),
+ chunkChecksum->getChecksumLength())) {
--hashEndIndex;
}
logger->debug("hashStartIndex=%d, hashEndIndex=%d",
@@ -519,27 +501,27 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment)
logger->debug(MSG_NO_CHUNK_CHECKSUM);
return;
}
- int64_t hashOffset = ((int64_t)hashStartIndex)*chunkHashLength;
+ int64_t hashOffset = ((int64_t)hashStartIndex)*chunkChecksum->getChecksumLength();
int32_t startIndex;
int32_t endIndex;
Util::indexRange(startIndex, endIndex,
hashOffset,
- (hashEndIndex-hashStartIndex+1)*chunkHashLength,
+ (hashEndIndex-hashStartIndex+1)*chunkChecksum->getChecksumLength(),
bitfield->getBlockLength());
logger->debug("startIndex=%d, endIndex=%d", startIndex, endIndex);
if(bitfield->isBitRangeSet(startIndex, endIndex)) {
for(int32_t index = hashStartIndex; index <= hashEndIndex; ++index) {
- int64_t offset = ((int64_t)index)*chunkHashLength;
+ int64_t offset = ((int64_t)index)*chunkChecksum->getChecksumLength();
int32_t dataLength =
- offset+chunkHashLength <= totalSize ? chunkHashLength : totalSize-offset;
- string actualChecksum = diskWriter->messageDigest(offset, dataLength, digestAlgo);
- string expectedChecksum = pieceHashes[index];
- if(expectedChecksum == actualChecksum) {
- logger->info(MSG_GOOD_CHUNK_CHECKSUM);
+ offset+chunkChecksum->getChecksumLength() <= totalSize ?
+ chunkChecksum->getChecksumLength() : totalSize-offset;
+ string actualChecksum = MessageDigestHelper::digest(chunkChecksum->getAlgo(), diskWriter, offset, dataLength);
+ if(chunkChecksum->validateChunk(actualChecksum, index)) {
+ logger->info(MSG_GOOD_CHUNK_CHECKSUM, actualChecksum.c_str());
} else {
logger->info(EX_INVALID_CHUNK_CHECKSUM,
index, Util::llitos(offset, true).c_str(),
- expectedChecksum.c_str(), actualChecksum.c_str());
+ chunkChecksum->getChecksum(index).c_str(), actualChecksum.c_str());
logger->debug("Unset bit from %d to %d(inclusive)", startIndex, endIndex);
bitfield->unsetBitRange(startIndex, endIndex);
break;
diff --git a/src/SegmentMan.h b/src/SegmentMan.h
index 1dc869c2..7e877e6a 100644
--- a/src/SegmentMan.h
+++ b/src/SegmentMan.h
@@ -43,6 +43,9 @@
#include "Request.h"
#include "BitfieldMan.h"
#include "PeerStat.h"
+#ifdef ENABLE_MESSAGE_DIGEST
+# include "ChunkChecksum.h"
+#endif // ENABLE_MESSAGE_DIGEST
using namespace std;
@@ -157,12 +160,6 @@ public:
DiskWriterHandle diskWriter;
Requests reserved;
-#ifdef ENABLE_MESSAGE_DIGEST
- Strings pieceHashes;
- int32_t chunkHashLength;
- MessageDigestContext::DigestAlgo digestAlgo;
-#endif // ENABLE_MESSAGE_DIGEST
-
SegmentMan();
~SegmentMan();
@@ -300,11 +297,9 @@ public:
}
#ifdef ENABLE_MESSAGE_DIGEST
- void checkIntegrity();
-
- void tryChunkChecksumValidation(const SegmentHandle& segment);
+ void tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum);
- bool isChunkChecksumValidationReady() const;
+ bool isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const;
#endif // ENABLE_MESSAGE_DIGEST
};
diff --git a/src/ShaVisitor.cc b/src/ShaVisitor.cc
index b760d72c..3aae84bd 100644
--- a/src/ShaVisitor.cc
+++ b/src/ShaVisitor.cc
@@ -35,8 +35,9 @@
#include "ShaVisitor.h"
#include "Util.h"
-ShaVisitor::ShaVisitor():
- ctx(DIGEST_ALGO_SHA1) {
+ShaVisitor::ShaVisitor()
+{
+ ctx.trySetAlgo("sha1");
ctx.digestInit();
}
diff --git a/src/SimpleRandomizer.h b/src/SimpleRandomizer.h
index 2afd068d..9a593c87 100644
--- a/src/SimpleRandomizer.h
+++ b/src/SimpleRandomizer.h
@@ -54,27 +54,22 @@ public:
}
static void init() {
-#ifdef HAVE_SRANDOM
- srandom(time(0));
-#else
srand(time(0));
-#endif
}
virtual ~SimpleRandomizer() {}
virtual long int getRandomNumber() {
-#ifdef HAVE_RANDOM
- return random();
-#else
return rand();
-#endif
}
virtual long int getMaxRandomNumber() {
return RAND_MAX;
}
+ /**
+ * Returns random number in [0, to).
+ */
virtual long int getRandomNumber(long int to)
{
return(int32_t)(((double)to)*getRandomNumber()/(getMaxRandomNumber()+1.0));
diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc
index c95661d5..1eb6391b 100644
--- a/src/TorrentRequestInfo.cc
+++ b/src/TorrentRequestInfo.cc
@@ -80,7 +80,7 @@ RequestInfos TorrentRequestInfo::execute() {
if(BT_PROGRESS_INFO_FILE(btContext)->exists()) {
// load .aria2 file if it exists.
BT_PROGRESS_INFO_FILE(btContext)->load();
- PIECE_STORAGE(btContext)->getDiskAdaptor()->openExistingFile();
+ PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile();
#ifdef ENABLE_MESSAGE_DIGEST
if(op->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
PIECE_STORAGE(btContext)->checkIntegrity();
@@ -94,7 +94,7 @@ RequestInfos TorrentRequestInfo::execute() {
BT_PROGRESS_INFO_FILE(btContext)->getFilename().c_str());
throw new FatalException(EX_DOWNLOAD_ABORTED);
} else {
- PIECE_STORAGE(btContext)->getDiskAdaptor()->openExistingFile();
+ PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile();
#ifdef ENABLE_MESSAGE_DIGEST
if(op->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
PIECE_STORAGE(btContext)->markAllPiecesDone();
@@ -103,7 +103,7 @@ RequestInfos TorrentRequestInfo::execute() {
#endif // ENABLE_MESSAGE_DIGEST
}
} else {
- PIECE_STORAGE(btContext)->getDiskAdaptor()->initAndOpenFile();
+ PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile();
}
}
diff --git a/src/Util.cc b/src/Util.cc
index 3c90208b..7e231c9c 100644
--- a/src/Util.cc
+++ b/src/Util.cc
@@ -480,93 +480,6 @@ string Util::getContentDispositionFilename(const string& header) {
return trim(header.substr(filenamesp, filenameep-filenamesp), "\r\n '\"");
}
-#ifdef ENABLE_MESSAGE_DIGEST
-void Util::sha1Sum(unsigned char* digest, const void* data, int32_t dataLength) {
- MessageDigestContext ctx(DIGEST_ALGO_SHA1);
- ctx.digestInit();
- ctx.digestUpdate(data, dataLength);
- ctx.digestFinal(digest);
-}
-
-string Util::simpleMessageDigest(const string& data) {
- unsigned char checksum[20];
- sha1Sum(checksum, data.c_str(), data.size());
- return Util::toHex(checksum, sizeof(checksum));
-}
-
-#endif // ENABLE_MESSAGE_DIGEST
-
-#ifdef ENABLE_MESSAGE_DIGEST
-void Util::fileChecksum(const string& filename, unsigned char* digest,
- MessageDigestContext::DigestAlgo algo) {
- MessageDigestContext ctx(algo);
- ctx.digestInit();
-
- int32_t BUFLEN = 4096;
- char buf[BUFLEN];
-
- int32_t fd;
- if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) {
- throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno));
- }
- while(1) {
- int32_t size = read(fd, buf, BUFLEN);
- if(size == -1) {
- if(errno == EINTR) {
- continue;
- } else {
- close(fd);
- throw new DlAbortEx(EX_FILE_READ, filename.c_str(), strerror(errno));
- }
- } else if(size > 0) {
- ctx.digestUpdate(buf, size);
- }
- if(size < BUFLEN) {
- break;
- }
- }
- ctx.digestFinal(digest);
-}
-#endif // ENABLE_MESSAGE_DIGEST
-
-#ifdef ENABLE_BITTORRENT
-Integers Util::computeFastSet(string ipaddr, const unsigned char* infoHash,
- int32_t pieces, int32_t fastSetSize) {
- Integers fastSet;
- struct in_addr saddr;
- if(inet_aton(ipaddr.c_str(), &saddr) == 0) {
- abort();
- }
- unsigned char tx[24];
- memcpy(tx, (void*)&saddr.s_addr, 4);
- if((tx[0] & 0x80) == 0 || (tx[0] & 0x40) == 0) {
- tx[2] = 0x00;
- tx[3] = 0x00;
- } else {
- tx[3] = 0x00;
- }
- memcpy(tx+4, infoHash, 20);
- unsigned char x[20];
- sha1Sum(x, tx, 24);
- while((int32_t)fastSet.size() < fastSetSize) {
- for(int32_t i = 0; i < 5 && (int32_t)fastSet.size() < fastSetSize; i++) {
- int32_t j = i*4;
- uint32_t ny;
- memcpy(&ny, x+j, 4);
- uint32_t y = ntohl(ny);
- int32_t index = y%pieces;
- if(find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) {
- fastSet.push_back(index);
- }
- }
- unsigned char temp[20];
- sha1Sum(temp, x, 20);
- memcpy(x, temp, sizeof(x));
- }
- return fastSet;
-}
-#endif // ENABLE_BITTORRENT
-
static int32_t nbits[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
diff --git a/src/Util.h b/src/Util.h
index 799cf105..89be6fc7 100644
--- a/src/Util.h
+++ b/src/Util.h
@@ -36,15 +36,10 @@
#define _D_UTIL_H_
#include "common.h"
-#include "FileEntry.h"
#include "a2time.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
-#endif // ENABLE_MESSAGE_DIGEST
-#include <string>
+#include "FileEntry.h"
#include <utility>
#include <deque>
-#include <stdio.h>
#include <ostream>
#define STRTOLL(X) strtoll(X, (char**)NULL, 10);
@@ -111,28 +106,10 @@ public:
// this function temporarily put here
static string getContentDispositionFilename(const string& header);
- // digest must be at least 20 bytes long.
-#ifdef ENABLE_MESSAGE_DIGEST
- static void sha1Sum(unsigned char* digest, const void* data, int32_t dataLength);
- static string simpleMessageDigest(const string& data);
-#endif // ENABLE_MESSAGE_DIGEST
-
- // Before call this method, allocate enough memory to the parameter "digest".
- // For sha1, you need 20 bytes. For md5, 16 bytes.
-#ifdef ENABLE_MESSAGE_DIGEST
- static void fileChecksum(const string& filename, unsigned char* digest,
- MessageDigestContext::DigestAlgo algo);
-#endif // ENABLE_MESSAGE_DIGEST
-
-#ifdef ENABLE_BITTORRENT
- static Integers computeFastSet(string ipaddr, const unsigned char* infoHash,
- int32_t pieces, int32_t fastSetSize);
-#endif // ENABLE_BITTORRENT
-
static int32_t countBit(uint32_t n);
-
+
static string randomAlpha(int32_t length);
-
+
static string toUpper(const string& src);
static string toLower(const string& src);
diff --git a/src/Xml2MetalinkProcessor.cc b/src/Xml2MetalinkProcessor.cc
index 793d8656..f1743821 100644
--- a/src/Xml2MetalinkProcessor.cc
+++ b/src/Xml2MetalinkProcessor.cc
@@ -111,20 +111,36 @@ MetalinkEntryHandle Xml2MetalinkProcessor::getEntry(const string& xpath) {
entry->language = Util::trim(xpathContent(xpath+"/m:language"));
entry->os = Util::trim(xpathContent(xpath+"/m:os"));
#ifdef ENABLE_MESSAGE_DIGEST
- string md;
- md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"sha1\"]")));
- if(md.size() > 0) {
- entry->checksum = new Checksum();
- entry->checksum->setMessageDigest(md);
- entry->checksum->setDigestAlgo(DIGEST_ALGO_SHA1);
- } else {
- md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"md5\"]")));
- if(md.size() > 0) {
- entry->checksum = new Checksum();
- entry->checksum->setMessageDigest(md);
- entry->checksum->setDigestAlgo(DIGEST_ALGO_MD5);
+ xmlXPathObjectPtr hashPathObj = xpathEvaluation(xpath+"/m:verification/m:hash");
+ if(hashPathObj) {
+ xmlNodeSetPtr nodeSet = hashPathObj->nodesetval;
+ for(int32_t i = 0; i < nodeSet->nodeNr; ++i) {
+ xmlNodePtr node = nodeSet->nodeTab[i];
+ string algo = Util::trim(xmlAttribute(node, "type"));
+ if(MessageDigestContext::supports(algo)) {
+ entry->checksum = new Checksum(algo, Util::trim(xmlContent(node)));
+ break;
+ }
}
}
+ xmlXPathFreeObject(hashPathObj);
+
+ string piecesPath = xpath+"/m:verification/m:pieces";
+ xmlXPathObjectPtr pieceHashPathObj = xpathEvaluation(piecesPath);
+ if(pieceHashPathObj) {
+ xmlNodeSetPtr nodeSet = pieceHashPathObj->nodesetval;
+ for(int32_t i = 0; i < nodeSet->nodeNr; ++i) {
+ xmlNodePtr node = nodeSet->nodeTab[i];
+ string algo = Util::trim(xmlAttribute(node, "type"));
+ if(MessageDigestContext::supports(algo)) {
+ entry->chunkChecksum = getPieceHash(piecesPath+"[@type=\""+algo+"\"]",
+ entry->getLength());
+ break;
+ }
+ }
+ }
+ xmlXPathFreeObject(pieceHashPathObj);
+ /*
string piecesPath = xpath+"/m:verification/m:pieces";
string sha1PiecesPath = piecesPath+"[@type=\"sha1\"]";
string md5PiecesPath = piecesPath+"[@type=\"md5\"]";
@@ -133,6 +149,7 @@ MetalinkEntryHandle Xml2MetalinkProcessor::getEntry(const string& xpath) {
} else if(xpathExists(md5PiecesPath)) {
entry->chunkChecksum = getPieceHash(md5PiecesPath, entry->getLength());
}
+ */
#endif // ENABLE_MESSAGE_DIGEST
for(int index = 1; 1; index++) {
MetalinkResourceHandle resource(getResource(xpath+"/m:resources/m:url["+Util::itos(index)+"]"));
@@ -159,12 +176,8 @@ ChunkChecksumHandle Xml2MetalinkProcessor::getPieceHash(const string& xpath,
int64_t checksumLength = STRTOLL(Util::trim(xmlAttribute(node, "length")).c_str());
string algoString = Util::trim(xmlAttribute(node, "type"));
xmlXPathFreeObject(result);
- MessageDigestContext::DigestAlgo algo;
- if(algoString == "sha1") {
- algo = DIGEST_ALGO_SHA1;
- } else if(algoString == "md5") {
- algo = DIGEST_ALGO_MD5;
- } else {
+
+ if(!MessageDigestContext::supports(algoString)) {
// unknown checksum type
return 0;
}
@@ -178,7 +191,7 @@ ChunkChecksumHandle Xml2MetalinkProcessor::getPieceHash(const string& xpath,
}
checksums.push_back(pieceHash);
}
- return new ChunkChecksum(algo, checksums, checksumLength);
+ return new ChunkChecksum(algoString, checksums, checksumLength);
}
#endif // ENABLE_MESSAGE_DIGEST
diff --git a/src/main.cc b/src/main.cc
index 800106d2..2a3e8eab 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -71,7 +71,6 @@ extern int optind, opterr, optopt;
#ifdef ENABLE_METALINK
#include "MetalinkRequestInfo.h"
-#include "Xml2MetalinkProcessor.h"
#endif
#ifdef HAVE_LIBSSL
@@ -89,6 +88,9 @@ void showVersion() {
cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl;
cout << "**Configuration**" << endl;
cout << FeatureConfig::getInstance()->getConfigurationSummary();
+#ifdef ENABLE_MESSAGE_DIGEST
+ cout << "message digest algorithms: " << MessageDigestContext::getSupportedAlgoString() << endl;
+#endif // ENABLE_MESSAGE_DIGEST
cout << endl;
cout << "Copyright (C) 2006, 2007 Tatsuhiro Tsujikawa" << endl;
cout << endl;
@@ -109,7 +111,6 @@ void showVersion() {
cout << endl;
cout << _("Contact Info:") << endl;
cout << "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>" << endl;
- cout << "Ross Smith II <aria2spam at netebb dot com> (Windows port)" << endl;
cout << endl;
}
diff --git a/src/message.h b/src/message.h
index cf11733b..4db22946 100644
--- a/src/message.h
+++ b/src/message.h
@@ -118,7 +118,7 @@
#define MSG_SEEDING_END _("Seeding is over.")
#define MSG_SEGMENT_FORWARDING _("CUID#%d cancels segment index=%d. CUID#%d handles it instead.")
#define MSG_NO_CHUNK_CHECKSUM _("No chunk to verify.")
-#define MSG_GOOD_CHUNK_CHECKSUM _("Good chunk checksum.")
+#define MSG_GOOD_CHUNK_CHECKSUM _("Good chunk checksum. hash=%s")
#define MSG_LOADING_COOKIE_FAILED _("Failed to load cookies from %s")
#define MSG_INCORRECT_NETRC_PERMISSION _(".netrc file %s does not have correct permissions. It should be 600. netrc support disabled.")
#define MSG_LOGGING_STARTED _("Logging started.")
diff --git a/src/messageDigest.cc b/src/messageDigest.cc
new file mode 100644
index 00000000..faa669d2
--- /dev/null
+++ b/src/messageDigest.cc
@@ -0,0 +1,63 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "messageDigest.h"
+
+static MessageDigestContext::DigestAlgoMap::value_type digests[] = {
+#ifdef HAVE_LIBSSL
+ MessageDigestContext::DigestAlgoMap::value_type("md5", EVP_md5()),
+ MessageDigestContext::DigestAlgoMap::value_type("sha1", EVP_sha1()),
+# ifdef HAVE_EVP_SHA256
+ MessageDigestContext::DigestAlgoMap::value_type("sha256", EVP_sha256()),
+# endif // HAVE_EVP_SHA256
+#elif HAVE_LIBGCRYPT
+ MessageDigestContext::DigestAlgoMap::value_type("md5", GCRY_MD_MD5),
+ MessageDigestContext::DigestAlgoMap::value_type("sha1", GCRY_MD_SHA1),
+ MessageDigestContext::DigestAlgoMap::value_type("sha256", GCRY_MD_SHA256),
+#endif // HAVE_LIBGCRYPT
+};
+
+MessageDigestContext::DigestAlgoMap
+MessageDigestContext::digestAlgos(&digests[0],
+ &digests[sizeof(digests)/sizeof(DigestAlgoMap::value_type)]);
+
+string MessageDigestContext::digestFinal()
+{
+ int32_t length = digestLength(algo);
+ unsigned char* rawMD = new unsigned char[length];
+ digestFinal(rawMD);
+ string rawMDString(&rawMD[0], &rawMD[length]);
+ delete [] rawMD;
+ return rawMDString;
+}
diff --git a/src/messageDigest.h b/src/messageDigest.h
index 345a5483..0f309feb 100644
--- a/src/messageDigest.h
+++ b/src/messageDigest.h
@@ -36,10 +36,8 @@
#define _D_MESSAGE_DIGEST_H_
#include "common.h"
-
-#ifdef ENABLE_SSL
-
-#define MAX_MD_LENGTH (16+20)
+#include "FatalException.h"
+#include <map>
#ifdef HAVE_LIBSSL
#include <openssl/evp.h>
@@ -53,14 +51,11 @@ class MessageDigestContext {
public:
#ifdef HAVE_LIBSSL
typedef const EVP_MD* DigestAlgo;
-# define DIGEST_ALGO_MD5 EVP_md5()
-# define DIGEST_ALGO_SHA1 EVP_sha1()
#endif // HAVE_LIBSSL
#ifdef HAVE_LIBGCRYPT
typedef int32_t DigestAlgo;
-# define DIGEST_ALGO_MD5 GCRY_MD_MD5
-# define DIGEST_ALGO_SHA1 GCRY_MD_SHA1
#endif // HAVE_LIBGCRYPT
+ typedef map<string, MessageDigestContext::DigestAlgo> DigestAlgoMap;
private:
#ifdef HAVE_LIBSSL
EVP_MD_CTX ctx;
@@ -69,17 +64,58 @@ private:
gcry_md_hd_t ctx;
#endif // HAVE_LIBGCRYPT
DigestAlgo algo;
+
+ static DigestAlgoMap digestAlgos;
public:
- MessageDigestContext():
- algo(DIGEST_ALGO_SHA1) {}
- MessageDigestContext(DigestAlgo algo):
- algo(algo) {}
+ MessageDigestContext():algo(getDigestAlgo("sha1"))
+ {}
~MessageDigestContext()
{
digestFree();
}
+ void trySetAlgo(const string& algostring)
+ {
+ algo = getDigestAlgo(algostring);
+ }
+
+ static bool supports(const string& algostring)
+ {
+ DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
+ if(itr == digestAlgos.end()) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ static DigestAlgo getDigestAlgo(const string& algostring)
+ {
+ DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
+ if(itr == digestAlgos.end()) {
+ throw new FatalException("Digest algorithm %s is not supported.", algostring.c_str());
+ }
+ return (*itr).second;
+ }
+
+ static string getSupportedAlgoString()
+ {
+ string algos;
+ for(DigestAlgoMap::const_iterator itr = digestAlgos.begin();
+ itr != digestAlgos.end(); ++itr) {
+ algos += (*itr).first+" ";
+ }
+ return algos;
+ }
+
+ static int digestLength(const string& algostring)
+ {
+ return digestLength(getDigestAlgo(algostring));
+ }
+
+ string digestFinal();
+
#if defined(HAVE_OLD_LIBSSL)
void digestInit() {EVP_DigestInit(&ctx, algo);}
void digestReset() {EVP_DigestInit(&ctx, algo);}
@@ -147,5 +183,4 @@ public:
#endif // HAVE_LIBGCRYPT
};
typedef SharedHandle<MessageDigestContext> MessageDigestContextHandle;
-#endif // ENABLE_SSL
#endif // _D_MESSAGE_DIGEST_H_