mirror of https://github.com/aria2/aria2
2008-01-04 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Fixed segmentation fault when bad torrent metainfo is parsed. Added dynamic_cast properly to detect the misconfiguration of metainfo and then throw exception or skip it. * src/DefaultBtContext.{h, cc} * test/DefaultBtContextTest.cc * src/AnnounceList.cc * src/CompactPeerListProcessor.cc * src/message.h * src/DefaultBtAnnounce.{h, cc} * test/DefaultBtAnnounceTest.cc * src/BencodeVisitor.ccpull/1/head
parent
853a8ef6aa
commit
da4d9092b2
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2008-01-04 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Fixed segmentation fault when bad torrent metainfo is parsed.
|
||||
Added dynamic_cast properly to detect the misconfiguration of metainfo
|
||||
and then throw exception or skip it.
|
||||
* src/DefaultBtContext.{h, cc}
|
||||
* test/DefaultBtContextTest.cc
|
||||
* src/AnnounceList.cc
|
||||
* src/CompactPeerListProcessor.cc
|
||||
* src/message.h
|
||||
* src/DefaultBtAnnounce.{h, cc}
|
||||
* test/DefaultBtAnnounceTest.cc
|
||||
* src/BencodeVisitor.cc
|
||||
|
||||
2007-12-29 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Added missing "B"(=Byte). So now the message looks like this:
|
||||
|
|
|
@ -51,12 +51,17 @@ void AnnounceList::reconfigure(const MetaEntry* announceListEntry) {
|
|||
if(l) {
|
||||
for(MetaList::const_iterator itr = l->getList().begin();
|
||||
itr != l->getList().end(); itr++) {
|
||||
const List* elem = (List*)*itr;
|
||||
const List* elem = dynamic_cast<const List*>(*itr);
|
||||
if(!elem) {
|
||||
continue;
|
||||
}
|
||||
Strings urls;
|
||||
for(MetaList::const_iterator elemItr = elem->getList().begin();
|
||||
elemItr != elem->getList().end(); elemItr++) {
|
||||
const Data* data = (Data*)*elemItr;
|
||||
urls.push_back(data->toString());
|
||||
const Data* data = dynamic_cast<const Data*>(*elemItr);
|
||||
if(data) {
|
||||
urls.push_back(data->toString());
|
||||
}
|
||||
}
|
||||
if(urls.size()) {
|
||||
AnnounceTierHandle tier(new AnnounceTier(urls));
|
||||
|
|
|
@ -75,10 +75,10 @@ void BencodeVisitor::visit(const Dictionary* d)
|
|||
void BencodeVisitor::visit(const MetaEntry* e)
|
||||
{
|
||||
if(dynamic_cast<const Data*>(e) != 0) {
|
||||
visit((const Data*)e);
|
||||
visit(reinterpret_cast<const Data*>(e));
|
||||
} else if(dynamic_cast<const List*>(e) != 0) {
|
||||
visit((const List*)e);
|
||||
visit(reinterpret_cast<const List*>(e));
|
||||
} else if(dynamic_cast<const Dictionary*>(e) != 0) {
|
||||
visit((const Dictionary*)e);
|
||||
visit(reinterpret_cast<const Dictionary*>(e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,10 @@ bool CompactPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
|
|||
|
||||
Peers CompactPeerListProcessor::extractPeer(const MetaEntry* peersEntry) {
|
||||
Peers peers;
|
||||
|
||||
const Data* peersData = (const Data*)peersEntry;
|
||||
const Data* peersData = dynamic_cast<const Data*>(peersEntry);
|
||||
if(!peersData) {
|
||||
return peers;
|
||||
}
|
||||
if(peersData->getLen()%6 == 0) {
|
||||
for(int32_t i = 0; i < peersData->getLen(); i += 6) {
|
||||
struct in_addr in;
|
||||
|
|
|
@ -184,41 +184,50 @@ DefaultBtAnnounce::processAnnounceResponse(const char* trackerResponse,
|
|||
{
|
||||
SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse,
|
||||
trackerResponseLength));
|
||||
Dictionary* response = (Dictionary*)entry.get();
|
||||
Data* failureReasonData = (Data*)response->get("failure reason");
|
||||
const Dictionary* response = dynamic_cast<const Dictionary*>(entry.get());
|
||||
if(!response) {
|
||||
throw new DlAbortEx(MSG_NULL_TRACKER_RESPONSE);
|
||||
}
|
||||
const Data* failureReasonData = dynamic_cast<const Data*>(response->get("failure reason"));
|
||||
if(failureReasonData) {
|
||||
throw new DlAbortEx(EX_TRACKER_FAILURE,
|
||||
failureReasonData->toString().c_str());
|
||||
}
|
||||
Data* warningMessageData = (Data*)response->get("warning message");
|
||||
const Data* warningMessageData = dynamic_cast<const Data*>(response->get("warning message"));
|
||||
if(warningMessageData) {
|
||||
logger->warn(MSG_TRACKER_WARNING_MESSAGE,
|
||||
warningMessageData->toString().c_str());
|
||||
}
|
||||
Data* trackerIdData = (Data*)response->get("tracker id");
|
||||
const Data* trackerIdData = dynamic_cast<const Data*>(response->get("tracker id"));
|
||||
if(trackerIdData) {
|
||||
trackerId = trackerIdData->toString();
|
||||
logger->debug("Tracker ID:%s", trackerId.c_str());
|
||||
}
|
||||
Data* intervalData = (Data*)response->get("interval");
|
||||
const Data* intervalData = dynamic_cast<const Data*>(response->get("interval"));
|
||||
if(intervalData) {
|
||||
interval = intervalData->toInt();
|
||||
logger->debug("Interval:%d", interval);
|
||||
int32_t t = intervalData->toInt();
|
||||
if(t > 0) {
|
||||
interval = intervalData->toInt();
|
||||
logger->debug("Interval:%d", interval);
|
||||
}
|
||||
}
|
||||
Data* minIntervalData = (Data*)response->get("min interval");
|
||||
const Data* minIntervalData = dynamic_cast<const Data*>(response->get("min interval"));
|
||||
if(minIntervalData) {
|
||||
minInterval = minIntervalData->toInt();
|
||||
logger->debug("Min interval:%d", minInterval);
|
||||
int32_t t = minIntervalData->toInt();
|
||||
if(t > 0) {
|
||||
minInterval = minIntervalData->toInt();
|
||||
logger->debug("Min interval:%d", minInterval);
|
||||
}
|
||||
}
|
||||
if(minInterval > interval) {
|
||||
minInterval = interval;
|
||||
}
|
||||
Data* completeData = (Data*)response->get("complete");
|
||||
const Data* completeData = dynamic_cast<const Data*>(response->get("complete"));
|
||||
if(completeData) {
|
||||
complete = completeData->toInt();
|
||||
logger->debug("Complete:%d", complete);
|
||||
}
|
||||
Data* incompleteData = (Data*)response->get("incomplete");
|
||||
const Data* incompleteData = dynamic_cast<const Data*>(response->get("incomplete"));
|
||||
if(incompleteData) {
|
||||
incomplete = incompleteData->toInt();
|
||||
logger->debug("Incomplete:%d", incomplete);
|
||||
|
|
|
@ -117,6 +117,31 @@ public:
|
|||
void generateKey();
|
||||
|
||||
void setRandomizer(const RandomizerHandle& randomizer);
|
||||
|
||||
int32_t getInterval() const
|
||||
{
|
||||
return interval;
|
||||
}
|
||||
|
||||
int32_t getMinInterval() const
|
||||
{
|
||||
return minInterval;
|
||||
}
|
||||
|
||||
int32_t getComplete() const
|
||||
{
|
||||
return complete;
|
||||
}
|
||||
|
||||
int32_t getIncomplete() const
|
||||
{
|
||||
return incomplete;
|
||||
}
|
||||
|
||||
const string& getTrackerID() const
|
||||
{
|
||||
return trackerId;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _D_DEFAULT_BT_ANNOUNCE_H_
|
||||
|
|
|
@ -44,11 +44,14 @@
|
|||
#include "a2netcompat.h"
|
||||
#include "AnnounceTier.h"
|
||||
#include "SimpleRandomizer.h"
|
||||
#include "LogFactory.h"
|
||||
#include "message.h"
|
||||
#include <libgen.h>
|
||||
|
||||
DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"),
|
||||
_randomizer(SimpleRandomizer::getInstance()),
|
||||
_ownerRequestGroup(0) {}
|
||||
_ownerRequestGroup(0),
|
||||
_logger(LogFactory::getInstance()) {}
|
||||
|
||||
DefaultBtContext::~DefaultBtContext() {}
|
||||
|
||||
|
@ -101,11 +104,10 @@ void DefaultBtContext::extractPieceHash(const unsigned char* hashData,
|
|||
}
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
|
||||
void DefaultBtContext::extractFileEntries(const Dictionary* infoDic,
|
||||
const string& defaultName,
|
||||
const Strings& urlList) {
|
||||
// TODO use dynamic_cast
|
||||
Data* nameData = (Data*)infoDic->get("name");
|
||||
const Data* nameData = dynamic_cast<const Data*>(infoDic->get("name"));
|
||||
if(nameData) {
|
||||
name = nameData->toString();
|
||||
} else {
|
||||
|
@ -113,8 +115,7 @@ void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
|
|||
name = string(basename(basec))+".file";
|
||||
free(basec);
|
||||
}
|
||||
// TODO use dynamic_cast
|
||||
List* files = (List*)infoDic->get("files");
|
||||
const List* files = dynamic_cast<const List*>(infoDic->get("files"));
|
||||
if(files) {
|
||||
int64_t length = 0;
|
||||
int64_t offset = 0;
|
||||
|
@ -123,21 +124,36 @@ void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
|
|||
const MetaList& metaList = files->getList();
|
||||
for(MetaList::const_iterator itr = metaList.begin();
|
||||
itr != metaList.end(); itr++) {
|
||||
Dictionary* fileDic = (Dictionary*)(*itr);
|
||||
// TODO use dynamic_cast
|
||||
Data* lengthData = (Data*)fileDic->get("length");
|
||||
length += lengthData->toLLInt();
|
||||
// TODO use dynamic_cast
|
||||
List* pathList = (List*)fileDic->get("path");
|
||||
const Dictionary* fileDic = dynamic_cast<const Dictionary*>((*itr));
|
||||
if(!fileDic) {
|
||||
continue;
|
||||
}
|
||||
const Data* lengthData = dynamic_cast<const Data*>(fileDic->get("length"));
|
||||
if(lengthData) {
|
||||
length += lengthData->toLLInt();
|
||||
} else {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "file length");
|
||||
}
|
||||
const List* pathList = dynamic_cast<const List*>(fileDic->get("path"));
|
||||
if(!pathList) {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "file path list");
|
||||
}
|
||||
const MetaList& paths = pathList->getList();
|
||||
string path;
|
||||
for(int32_t i = 0; i < (int32_t)paths.size()-1; i++) {
|
||||
Data* subpath = (Data*)paths[i];
|
||||
path += subpath->toString()+"/";
|
||||
const Data* subpath = dynamic_cast<const Data*>(paths[i]);
|
||||
if(subpath) {
|
||||
path += subpath->toString()+"/";
|
||||
} else {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "file path element");
|
||||
}
|
||||
}
|
||||
const Data* lastPath = dynamic_cast<const Data*>(paths.back());
|
||||
if(lastPath) {
|
||||
path += lastPath->toString();
|
||||
} else {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "file path element");
|
||||
}
|
||||
// TODO use dynamic_cast
|
||||
Data* lastPath = (Data*)paths.back();
|
||||
path += lastPath->toString();
|
||||
|
||||
Strings uris;
|
||||
transform(urlList.begin(), urlList.end(), back_inserter(uris),
|
||||
|
@ -153,28 +169,37 @@ void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
|
|||
} else {
|
||||
// single-file mode;
|
||||
fileMode = BtContext::SINGLE;
|
||||
Data* length = (Data*)infoDic->get("length");
|
||||
totalLength = length->toLLInt();
|
||||
const Data* length = dynamic_cast<const Data*>(infoDic->get("length"));
|
||||
if(length) {
|
||||
totalLength = length->toLLInt();
|
||||
} else {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "file length");
|
||||
}
|
||||
FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0, urlList));
|
||||
fileEntries.push_back(fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractAnnounce(Data* announceData) {
|
||||
void DefaultBtContext::extractAnnounce(const Data* announceData) {
|
||||
Strings urls;
|
||||
urls.push_back(Util::trim(announceData->toString()));
|
||||
announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls)));
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractAnnounceList(List* announceListData) {
|
||||
void DefaultBtContext::extractAnnounceList(const List* announceListData) {
|
||||
for(MetaList::const_iterator itr = announceListData->getList().begin();
|
||||
itr != announceListData->getList().end(); itr++) {
|
||||
const List* elem = (List*)*itr;
|
||||
const List* elem = dynamic_cast<const List*>(*itr);
|
||||
if(!elem) {
|
||||
continue;
|
||||
}
|
||||
Strings urls;
|
||||
for(MetaList::const_iterator elemItr = elem->getList().begin();
|
||||
elemItr != elem->getList().end(); elemItr++) {
|
||||
const Data* data = (Data*)*elemItr;
|
||||
urls.push_back(Util::trim(data->toString()));
|
||||
const Data* data = dynamic_cast<const Data*>(*elemItr);
|
||||
if(data) {
|
||||
urls.push_back(Util::trim(data->toString()));
|
||||
}
|
||||
}
|
||||
if(urls.size()) {
|
||||
AnnounceTierHandle tier(new AnnounceTier(urls));
|
||||
|
@ -187,16 +212,16 @@ Strings DefaultBtContext::extractUrlList(const MetaEntry* obj)
|
|||
{
|
||||
Strings uris;
|
||||
if(dynamic_cast<const List*>(obj)) {
|
||||
const List* urlList = (const List*)obj;
|
||||
const List* urlList = reinterpret_cast<const List*>(obj);
|
||||
for(MetaList::const_iterator itr = urlList->getList().begin();
|
||||
itr != urlList->getList().end(); ++itr) {
|
||||
Data* data = dynamic_cast<Data*>(*itr);
|
||||
const Data* data = dynamic_cast<const Data*>(*itr);
|
||||
if(data) {
|
||||
uris.push_back(data->toString());
|
||||
}
|
||||
}
|
||||
} else if(dynamic_cast<const Data*>(obj)) {
|
||||
const Data* urlData = (const Data*)obj;
|
||||
const Data* urlData = reinterpret_cast<const Data*>(obj);
|
||||
uris.push_back(urlData->toString());
|
||||
}
|
||||
return uris;
|
||||
|
@ -204,27 +229,30 @@ Strings DefaultBtContext::extractUrlList(const MetaEntry* obj)
|
|||
|
||||
void DefaultBtContext::loadFromMemory(const char* content, int32_t length, const string& defaultName)
|
||||
{
|
||||
MetaEntry* rootEntry = MetaFileUtil::bdecoding(content, length);
|
||||
if(!dynamic_cast<Dictionary*>(rootEntry)) {
|
||||
SharedHandle<MetaEntry> rootEntry = MetaFileUtil::bdecoding(content, length);
|
||||
const Dictionary* rootDic = dynamic_cast<const Dictionary*>(rootEntry.get());
|
||||
if(!rootDic) {
|
||||
throw new DlAbortEx("torrent file does not contain a root dictionary .");
|
||||
}
|
||||
processMetaInfo(rootEntry, defaultName);
|
||||
processRootDictionary(rootDic, defaultName);
|
||||
}
|
||||
|
||||
void DefaultBtContext::load(const string& torrentFile) {
|
||||
MetaEntry* rootEntry = MetaFileUtil::parseMetaFile(torrentFile);
|
||||
if(!dynamic_cast<Dictionary*>(rootEntry)) {
|
||||
SharedHandle<MetaEntry> rootEntry = MetaFileUtil::parseMetaFile(torrentFile);
|
||||
const Dictionary* rootDic = dynamic_cast<const Dictionary*>(rootEntry.get());
|
||||
if(!rootDic) {
|
||||
throw new DlAbortEx("torrent file does not contain a root dictionary .");
|
||||
}
|
||||
processMetaInfo(rootEntry, torrentFile);
|
||||
processRootDictionary(rootDic, torrentFile);
|
||||
}
|
||||
|
||||
void DefaultBtContext::processMetaInfo(const MetaEntry* rootEntry, const string& defaultName)
|
||||
void DefaultBtContext::processRootDictionary(const Dictionary* rootDic, const string& defaultName)
|
||||
{
|
||||
clear();
|
||||
SharedHandle<Dictionary> rootDic =
|
||||
SharedHandle<Dictionary>((Dictionary*)rootEntry);
|
||||
Dictionary* infoDic = (Dictionary*)rootDic->get("info");
|
||||
const Dictionary* infoDic = dynamic_cast<const Dictionary*>(rootDic->get("info"));
|
||||
if(!infoDic) {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "info directory");
|
||||
}
|
||||
// retrieve infoHash
|
||||
ShaVisitor v;
|
||||
infoDic->accept(&v);
|
||||
|
@ -232,10 +260,16 @@ void DefaultBtContext::processMetaInfo(const MetaEntry* rootEntry, const string&
|
|||
v.getHash(infoHash, len);
|
||||
infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH);
|
||||
// calculate the number of pieces
|
||||
Data* pieceHashData = (Data*)infoDic->get("pieces");
|
||||
const Data* pieceHashData = dynamic_cast<const Data*>(infoDic->get("pieces"));
|
||||
if(!pieceHashData) {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "pieces");
|
||||
}
|
||||
numPieces = pieceHashData->getLen()/PIECE_HASH_LENGTH;
|
||||
// retrieve piece length
|
||||
Data* pieceLengthData = (Data*)infoDic->get("piece length");
|
||||
const Data* pieceLengthData = dynamic_cast<const Data*>(infoDic->get("piece length"));
|
||||
if(!pieceLengthData) {
|
||||
throw new DlAbortEx(MSG_SOMETHING_MISSING_IN_TORRENT, "piece length");
|
||||
}
|
||||
pieceLength = pieceLengthData->toInt();
|
||||
// retrieve piece hashes
|
||||
extractPieceHash((unsigned char*)pieceHashData->getData(),
|
||||
|
@ -253,9 +287,12 @@ void DefaultBtContext::processMetaInfo(const MetaEntry* rootEntry, const string&
|
|||
Strings urlList = extractUrlList(rootDic->get("url-list"));
|
||||
// retrieve file entries
|
||||
extractFileEntries(infoDic, defaultName, urlList);
|
||||
if((totalLength+pieceLength-1)/pieceLength != numPieces) {
|
||||
throw new DlAbortEx("Too few/many piece hash.");
|
||||
}
|
||||
// retrieve announce
|
||||
Data* announceData = (Data*)rootDic->get("announce");
|
||||
List* announceListData = (List*)rootDic->get("announce-list");
|
||||
const Data* announceData = dynamic_cast<const Data*>(rootDic->get("announce"));
|
||||
const List* announceListData = dynamic_cast<const List*>(rootDic->get("announce-list"));
|
||||
if(announceListData) {
|
||||
extractAnnounceList(announceListData);
|
||||
} else if(announceData) {
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
class Randomizer;
|
||||
typedef SharedHandle<Randomizer> RandomizerHandle;
|
||||
class Logger;
|
||||
|
||||
#define INFO_HASH_LENGTH 20
|
||||
#define PIECE_HASH_LENGTH 20
|
||||
|
@ -66,19 +67,21 @@ private:
|
|||
|
||||
RequestGroup* _ownerRequestGroup;
|
||||
|
||||
const Logger* _logger;
|
||||
|
||||
void clear();
|
||||
void extractPieceHash(const unsigned char* hashData,
|
||||
int32_t hashDataLength,
|
||||
int32_t hashLength);
|
||||
void extractFileEntries(Dictionary* infoDic,
|
||||
void extractFileEntries(const Dictionary* infoDic,
|
||||
const string& defaultName,
|
||||
const Strings& urlList);
|
||||
void extractAnnounce(Data* announceData);
|
||||
void extractAnnounceList(List* announceListData);
|
||||
void extractAnnounce(const Data* announceData);
|
||||
void extractAnnounceList(const List* announceListData);
|
||||
|
||||
Strings extractUrlList(const MetaEntry* obj);
|
||||
|
||||
void processMetaInfo(const MetaEntry* rootEntry, const string& defaultName);
|
||||
void processRootDictionary(const Dictionary* rootDic, const string& defaultName);
|
||||
|
||||
public:
|
||||
DefaultBtContext();
|
||||
|
|
|
@ -135,6 +135,8 @@
|
|||
#define MSG_TOO_SMALL_PAYLOAD_SIZE _("Too small payload size for %s, size=%d.")
|
||||
#define MSG_REMOVED_DEFUNCT_CONTROL_FILE _("Removed the defunct control file %s because the download file %s doesn't exist.")
|
||||
#define MSG_SHARE_RATIO_REPORT _("Your share ratio was %.1f, uploaded/downloaded=%sB/%sB")
|
||||
#define MSG_SOMETHING_MISSING_IN_TORRENT _("Missing %s in torrent metainfo.")
|
||||
#define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.")
|
||||
|
||||
#define EX_TIME_OUT _("Timeout.")
|
||||
#define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.")
|
||||
|
|
|
@ -21,6 +21,9 @@ class DefaultBtAnnounceTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testIsAllAnnounceFailed);
|
||||
CPPUNIT_TEST(testURLOrderInStoppedEvent);
|
||||
CPPUNIT_TEST(testURLOrderInCompletedEvent);
|
||||
CPPUNIT_TEST(testProcessAnnounceResponse_malformed);
|
||||
CPPUNIT_TEST(testProcessAnnounceResponse_failureReason);
|
||||
CPPUNIT_TEST(testProcessAnnounceResponse);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
MockBtContextHandle _btContext;
|
||||
|
@ -78,6 +81,9 @@ public:
|
|||
void testIsAllAnnounceFailed();
|
||||
void testURLOrderInStoppedEvent();
|
||||
void testURLOrderInCompletedEvent();
|
||||
void testProcessAnnounceResponse_malformed();
|
||||
void testProcessAnnounceResponse_failureReason();
|
||||
void testProcessAnnounceResponse();
|
||||
};
|
||||
|
||||
|
||||
|
@ -275,3 +281,47 @@ void DefaultBtAnnounceTest::testURLOrderInCompletedEvent()
|
|||
|
||||
btAnnounce.announceSuccess();
|
||||
}
|
||||
|
||||
void DefaultBtAnnounceTest::testProcessAnnounceResponse_malformed()
|
||||
{
|
||||
try {
|
||||
string res = "i123e";
|
||||
DefaultBtAnnounce(new MockBtContext(), _option).processAnnounceResponse(res.c_str(), res.size());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(Exception* e) {
|
||||
cerr << *e << endl;
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtAnnounceTest::testProcessAnnounceResponse_failureReason()
|
||||
{
|
||||
try {
|
||||
string res = "d14:failure reason11:hello worlde";
|
||||
DefaultBtAnnounce(new MockBtContext(), _option).processAnnounceResponse(res.c_str(), res.size());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(Exception* e) {
|
||||
cerr << *e << endl;
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtAnnounceTest::testProcessAnnounceResponse()
|
||||
{
|
||||
string res = "d"
|
||||
"15:warning message11:hello world"
|
||||
"10:tracker id3:foo"
|
||||
"8:intervali3000e"
|
||||
"12:min intervali1800e"
|
||||
"8:completei100e"
|
||||
"10:incompletei200e"
|
||||
"e";
|
||||
|
||||
DefaultBtAnnounce an(new MockBtContext(), _option);
|
||||
an.processAnnounceResponse(res.c_str(), res.size());
|
||||
CPPUNIT_ASSERT_EQUAL(string("foo"), an.getTrackerID());
|
||||
CPPUNIT_ASSERT_EQUAL(3000, an.getInterval());
|
||||
CPPUNIT_ASSERT_EQUAL(1800, an.getMinInterval());
|
||||
CPPUNIT_ASSERT_EQUAL(100, an.getComplete());
|
||||
CPPUNIT_ASSERT_EQUAL(200, an.getIncomplete());
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class DefaultBtContextTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testGetFileEntries_multiFileUrlList);
|
||||
CPPUNIT_TEST(testGetFileEntries_singleFileUrlList);
|
||||
CPPUNIT_TEST(testLoadFromMemory);
|
||||
CPPUNIT_TEST(testLoadFromMemory_somethingMissing);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
public:
|
||||
void setUp() {
|
||||
|
@ -53,6 +54,7 @@ public:
|
|||
void testGetFileEntries_multiFileUrlList();
|
||||
void testGetFileEntries_singleFileUrlList();
|
||||
void testLoadFromMemory();
|
||||
void testLoadFromMemory_somethingMissing();
|
||||
};
|
||||
|
||||
|
||||
|
@ -325,3 +327,17 @@ void DefaultBtContextTest::testLoadFromMemory()
|
|||
CPPUNIT_ASSERT_EQUAL(correctHash, Util::toHex(btContext.getInfoHash(),
|
||||
btContext.getInfoHashLength()));
|
||||
}
|
||||
|
||||
void DefaultBtContextTest::testLoadFromMemory_somethingMissing()
|
||||
{
|
||||
// pieces missing
|
||||
try {
|
||||
string memory = "d8:announce36:http://aria.rednoah.com/announce.php4:infod4:name13:aria2.tar.bz26:lengthi262144eee";
|
||||
DefaultBtContext btContext;
|
||||
btContext.loadFromMemory(memory.c_str(), memory.size(), "default");
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(Exception* e) {
|
||||
cerr << *e << endl;
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
d8:url-list35:http://localhost/dist/aria2.tar.bz28:announce36:http://aria.rednoah.com/announce.php13:announce-listll15:http://tracker1el15:http://tracker2el15:http://tracker3ee7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod6:lengthi7680e4:name13:aria2.tar.bz212:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee
|
||||
d8:url-list35:http://localhost/dist/aria2.tar.bz28:announce36:http://aria.rednoah.com/announce.php13:announce-listll15:http://tracker1el15:http://tracker2el15:http://tracker3ee7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod6:lengthi380e4:name13:aria2.tar.bz212:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee
|
Loading…
Reference in New Issue