2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Use BDE instead of Dictionary/List/Data classes.
	* src/CompactPeerListProcessor.cc
	* src/CompactPeerListProcessor.h
	* src/DefaultBtAnnounce.cc
	* src/DefaultBtContext.cc
	* src/DefaultBtContext.h
	* src/DefaultPeerListProcessor.cc
	* src/DefaultPeerListProcessor.h
	* src/DelegatingPeerListProcessor.cc
	* src/DelegatingPeerListProcessor.h
	* src/PeerListProcessor.h
	* src/UTPexExtensionMessage.cc
	* src/Util.h
	* src/message.h
	* test/DefaultBtContextTest.cc
	* test/DefaultPeerListProcessorTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2008-12-09 15:03:29 +00:00
parent 1b54e64d34
commit 8129042a3a
16 changed files with 303 additions and 334 deletions

View File

@ -1,3 +1,22 @@
2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Use BDE instead of Dictionary/List/Data classes.
* src/CompactPeerListProcessor.cc
* src/CompactPeerListProcessor.h
* src/DefaultBtAnnounce.cc
* src/DefaultBtContext.cc
* src/DefaultBtContext.h
* src/DefaultPeerListProcessor.cc
* src/DefaultPeerListProcessor.h
* src/DelegatingPeerListProcessor.cc
* src/DelegatingPeerListProcessor.h
* src/PeerListProcessor.h
* src/UTPexExtensionMessage.cc
* src/Util.h
* src/message.h
* test/DefaultBtContextTest.cc
* test/DefaultPeerListProcessorTest.cc
2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2008-12-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added bencode helper functions and BDE class. Added bencode helper functions and BDE class.

View File

@ -32,9 +32,9 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "CompactPeerListProcessor.h" #include "CompactPeerListProcessor.h"
#include "Peer.h"
#include "Data.h"
#include "a2netcompat.h" #include "a2netcompat.h"
#include "bencode.h"
#include "Peer.h"
namespace aria2 { namespace aria2 {
@ -42,23 +42,24 @@ CompactPeerListProcessor::CompactPeerListProcessor() {}
CompactPeerListProcessor::~CompactPeerListProcessor() {} CompactPeerListProcessor::~CompactPeerListProcessor() {}
bool CompactPeerListProcessor::canHandle(const MetaEntry* peersEntry) const { bool CompactPeerListProcessor::canHandle(const bencode::BDE& peerData) const
return dynamic_cast<const Data*>(peersEntry) != 0; {
return peerData.isString();
} }
void CompactPeerListProcessor::extractPeer void CompactPeerListProcessor::extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry) (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData)
{ {
const Data* peersData = dynamic_cast<const Data*>(peersEntry); if(!canHandle(peerData)) {
if(!peersData) {
return; return;
} }
if(peersData->getLen()%6 == 0) { size_t length = peerData.s().size();
for(size_t i = 0; i < peersData->getLen(); i += 6) { if(length%6 == 0) {
for(size_t i = 0; i < length; i += 6) {
struct in_addr in; struct in_addr in;
in.s_addr = *(uint32_t*)(peersData->getData()+i); in.s_addr = *(uint32_t*)(peerData.s().c_str()+i);
std::string ipaddr = inet_ntoa(in); std::string ipaddr = inet_ntoa(in);
uint16_t port = ntohs(*(uint16_t*)(peersData->getData()+i+4)); uint16_t port = ntohs(*(uint16_t*)(peerData.s().c_str()+i+4));
PeerHandle peer(new Peer(ipaddr, port)); PeerHandle peer(new Peer(ipaddr, port));
peers.push_back(peer); peers.push_back(peer);
} }

View File

@ -45,9 +45,9 @@ public:
virtual ~CompactPeerListProcessor(); virtual ~CompactPeerListProcessor();
virtual void extractPeer virtual void extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry); (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData);
virtual bool canHandle(const MetaEntry* peersEntry) const; virtual bool canHandle(const bencode::BDE& peerData) const;
}; };
} // namespace aria2 } // namespace aria2

View File

@ -35,10 +35,6 @@
#include "DefaultBtAnnounce.h" #include "DefaultBtAnnounce.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "Logger.h" #include "Logger.h"
#include "MetaFileUtil.h"
#include "Dictionary.h"
#include "List.h"
#include "Data.h"
#include "DelegatingPeerListProcessor.h" #include "DelegatingPeerListProcessor.h"
#include "Util.h" #include "Util.h"
#include "prefs.h" #include "prefs.h"
@ -54,6 +50,7 @@
#include "StringFormat.h" #include "StringFormat.h"
#include "A2STR.h" #include "A2STR.h"
#include "Request.h" #include "Request.h"
#include "bencode.h"
namespace aria2 { namespace aria2 {
@ -200,48 +197,35 @@ void
DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse, DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse,
size_t trackerResponseLength) size_t trackerResponseLength)
{ {
SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse, logger->debug("Now processing tracker response.");
trackerResponseLength)); const bencode::BDE dict =
const Dictionary* response = dynamic_cast<const Dictionary*>(entry.get()); bencode::decode(trackerResponse, trackerResponseLength);
if(!response) { if(!dict.isDict()) {
throw DlAbortEx(MSG_NULL_TRACKER_RESPONSE); throw DlAbortEx(MSG_NULL_TRACKER_RESPONSE);
} }
const Data* failureReasonData = const bencode::BDE& failure = dict[BtAnnounce::FAILURE_REASON];
dynamic_cast<const Data*>(response->get(BtAnnounce::FAILURE_REASON)); if(failure.isString()) {
if(failureReasonData) {
throw DlAbortEx throw DlAbortEx
(StringFormat(EX_TRACKER_FAILURE, (StringFormat(EX_TRACKER_FAILURE, failure.s().c_str()).str());
failureReasonData->toString().c_str()).str());
} }
const Data* warningMessageData = const bencode::BDE& warn = dict[BtAnnounce::WARNING_MESSAGE];
dynamic_cast<const Data*>(response->get(BtAnnounce::WARNING_MESSAGE)); if(warn.isString()) {
if(warningMessageData) { logger->warn(MSG_TRACKER_WARNING_MESSAGE, warn.s().c_str());
logger->warn(MSG_TRACKER_WARNING_MESSAGE,
warningMessageData->toString().c_str());
} }
const Data* trackerIdData = const bencode::BDE& tid = dict[BtAnnounce::TRACKER_ID];
dynamic_cast<const Data*>(response->get(BtAnnounce::TRACKER_ID)); if(tid.isString()) {
if(trackerIdData) { trackerId = tid.s();
trackerId = trackerIdData->toString();
logger->debug("Tracker ID:%s", trackerId.c_str()); logger->debug("Tracker ID:%s", trackerId.c_str());
} }
const Data* intervalData = const bencode::BDE& ival = dict[BtAnnounce::INTERVAL];
dynamic_cast<const Data*>(response->get(BtAnnounce::INTERVAL)); if(ival.isInteger() && ival.i() > 0) {
if(intervalData) { interval = ival.i();
time_t t = intervalData->toInt(); logger->debug("Interval:%d", interval);
if(t > 0) {
interval = intervalData->toInt();
logger->debug("Interval:%d", interval);
}
} }
const Data* minIntervalData = const bencode::BDE& mival = dict[BtAnnounce::MIN_INTERVAL];
dynamic_cast<const Data*>(response->get(BtAnnounce::MIN_INTERVAL)); if(mival.isInteger() && mival.i() > 0) {
if(minIntervalData) { minInterval = mival.i();
time_t t = minIntervalData->toInt(); logger->debug("Min interval:%d", minInterval);
if(t > 0) {
minInterval = minIntervalData->toInt();
logger->debug("Min interval:%d", minInterval);
}
if(minInterval > interval) { if(minInterval > interval) {
minInterval = interval; minInterval = interval;
} }
@ -249,28 +233,25 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse,
// Use interval as a minInterval if minInterval is not supplied. // Use interval as a minInterval if minInterval is not supplied.
minInterval = interval; minInterval = interval;
} }
const Data* completeData = const bencode::BDE& comp = dict[BtAnnounce::COMPLETE];
dynamic_cast<const Data*>(response->get(BtAnnounce::COMPLETE)); if(comp.isInteger()) {
if(completeData) { complete = comp.i();
complete = completeData->toInt();
logger->debug("Complete:%d", complete); logger->debug("Complete:%d", complete);
} }
const Data* incompleteData = const bencode::BDE& incomp = dict[BtAnnounce::INCOMPLETE];
dynamic_cast<const Data*>(response->get(BtAnnounce::INCOMPLETE)); if(incomp.isInteger()) {
if(incompleteData) { incomplete = incomp.i();
incomplete = incompleteData->toInt();
logger->debug("Incomplete:%d", incomplete); logger->debug("Incomplete:%d", incomplete);
} }
const MetaEntry* peersEntry = response->get(BtAnnounce::PEERS); const bencode::BDE& peerData = dict[BtAnnounce::PEERS];
if(peersEntry && if(!peerData.isNone()) {
!btRuntime->isHalt() && if(!btRuntime->isHalt() && btRuntime->lessThanMinPeers()) {
btRuntime->lessThanMinPeers()) { DelegatingPeerListProcessor proc;
DelegatingPeerListProcessor proc; std::deque<SharedHandle<Peer> > peers;
std::deque<SharedHandle<Peer> > peers; proc.extractPeer(peers, peerData);
proc.extractPeer(peers, peersEntry); peerStorage->addPeer(peers);
peerStorage->addPeer(peers); }
} } else {
if(!peersEntry) {
logger->info(MSG_NO_PEER_LIST_RECEIVED); logger->info(MSG_NO_PEER_LIST_RECEIVED);
} }
} }

View File

@ -33,12 +33,13 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DefaultBtContext.h" #include "DefaultBtContext.h"
#include "MetaFileUtil.h"
#include "Dictionary.h" #include <cstring>
#include "List.h" #include <ostream>
#include "Data.h" #include <functional>
#include <algorithm>
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "BencodeVisitor.h"
#include "Util.h" #include "Util.h"
#include "MessageDigestHelper.h" #include "MessageDigestHelper.h"
#include "a2netcompat.h" #include "a2netcompat.h"
@ -51,10 +52,7 @@
#include "PeerMessageUtil.h" #include "PeerMessageUtil.h"
#include "StringFormat.h" #include "StringFormat.h"
#include "A2STR.h" #include "A2STR.h"
#include <cstring> #include "bencode.h"
#include <ostream>
#include <functional>
#include <algorithm>
namespace aria2 { namespace aria2 {
@ -102,84 +100,67 @@ void DefaultBtContext::clear() {
_private = false; _private = false;
} }
void DefaultBtContext::extractPieceHash(const unsigned char* hashData, void DefaultBtContext::extractPieceHash(const std::string& hashData,
size_t hashDataLength, size_t hashLength)
size_t hashLength) { {
size_t numPieces = hashDataLength/hashLength; size_t numPieces = hashData.size()/hashLength;
for(size_t i = 0; i < numPieces; i++) { for(size_t i = 0; i < numPieces; i++) {
pieceHashes.push_back(Util::toHex(&hashData[i*hashLength], pieceHashes.push_back(Util::toHex(hashData.data()+i*hashLength,
hashLength)); hashLength));
} }
} }
void DefaultBtContext::extractFileEntries(const Dictionary* infoDic, void DefaultBtContext::extractFileEntries(const bencode::BDE& infoDict,
const std::string& defaultName, const std::string& defaultName,
const std::string& overrideName, const std::string& overrideName,
const std::deque<std::string>& urlList) { const std::deque<std::string>& urlList)
{
if(overrideName.empty()) { if(overrideName.empty()) {
const Data* nameData = const bencode::BDE& nameData = infoDict[BtContext::C_NAME];
dynamic_cast<const Data*>(infoDic->get(BtContext::C_NAME)); if(nameData.isString()) {
if(nameData) { name = nameData.s();
name = nameData->toString();
} else { } else {
name = File(defaultName).getBasename()+".file"; name = File(defaultName).getBasename()+".file";
} }
} else { } else {
name = overrideName; name = overrideName;
} }
const List* files = dynamic_cast<const List*>(infoDic->get(BtContext::C_FILES)); const bencode::BDE& filesList = infoDict[BtContext::C_FILES];
if(files) { if(filesList.isList()) {
uint64_t length = 0; uint64_t length = 0;
off_t offset = 0; off_t offset = 0;
// multi-file mode // multi-file mode
fileMode = BtContext::MULTI; fileMode = BtContext::MULTI;
const std::deque<MetaEntry*>& metaList = files->getList(); for(bencode::BDE::List::const_iterator itr = filesList.listBegin();
for(std::deque<MetaEntry*>::const_iterator itr = metaList.begin(); itr != filesList.listEnd(); ++itr) {
itr != metaList.end(); itr++) { const bencode::BDE& fileDict = *itr;
const Dictionary* fileDic = dynamic_cast<const Dictionary*>((*itr)); if(!fileDict.isDict()) {
if(!fileDic) {
continue; continue;
} }
const Data* lengthData =
dynamic_cast<const Data*>(fileDic->get(BtContext::C_LENGTH)); const bencode::BDE& fileLengthData = fileDict[BtContext::C_LENGTH];
if(lengthData) { if(!fileLengthData.isInteger()) {
length += lengthData->toLLInt(); throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
} else { BtContext::C_LENGTH.c_str()).str());
throw DlAbortEx
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file length").str());
} }
const List* pathList = length += fileLengthData.i();
dynamic_cast<const List*>(fileDic->get(BtContext::C_PATH));
if(!pathList) { const bencode::BDE& pathList = fileDict[BtContext::C_PATH];
throw DlAbortEx if(!pathList.isList() || pathList.empty()) {
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file path list").str()); throw DlAbortEx("Path is empty.");
} }
const std::deque<MetaEntry*>& paths = pathList->getList();
std::string path; std::string path;
for(size_t i = 0; i < paths.size()-1; i++) { for(size_t i = 0; i < pathList.size()-1; ++i) {
const Data* subpath = dynamic_cast<const Data*>(paths[i]); path += pathList[i].s()+"/";
if(subpath) {
path += subpath->toString()+"/";
} else {
throw DlAbortEx
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file path element").str());
}
}
const Data* lastPath = dynamic_cast<const Data*>(paths.back());
if(lastPath) {
path += lastPath->toString();
} else {
throw DlAbortEx
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file path element").str());
} }
path += pathList[pathList.size()-1].s();
std::deque<std::string> uris; std::deque<std::string> uris;
std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris), std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris),
std::bind2nd(std::plus<std::string>(), "/"+name+"/"+path)); std::bind2nd(std::plus<std::string>(), "/"+name+"/"+path));
FileEntryHandle fileEntry(new FileEntry(path, FileEntryHandle fileEntry(new FileEntry(path, fileLengthData.i(),
lengthData->toLLInt(), offset, uris));
offset,
uris));
fileEntries.push_back(fileEntry); fileEntries.push_back(fileEntry);
offset += fileEntry->getLength(); offset += fileEntry->getLength();
} }
@ -187,91 +168,100 @@ void DefaultBtContext::extractFileEntries(const Dictionary* infoDic,
} else { } else {
// single-file mode; // single-file mode;
fileMode = BtContext::SINGLE; fileMode = BtContext::SINGLE;
const Data* length = const bencode::BDE& lengthData = infoDict[BtContext::C_LENGTH];
dynamic_cast<const Data*>(infoDic->get(BtContext::C_LENGTH)); if(!lengthData.isInteger()) {
if(length) { throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
totalLength = length->toLLInt(); BtContext::C_LENGTH.c_str()).str());
} else {
throw DlAbortEx
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "file length").str());
} }
totalLength = lengthData.i();
FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0, urlList)); FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0, urlList));
fileEntries.push_back(fileEntry); fileEntries.push_back(fileEntry);
} }
} }
void DefaultBtContext::extractAnnounce(const Data* announceData) { void DefaultBtContext::extractAnnounceURI(const bencode::BDE& announceData)
{
// Assumed announceData is string
std::deque<std::string> urls; std::deque<std::string> urls;
urls.push_back(Util::trim(announceData->toString())); urls.push_back(Util::trim(announceData.s()));
announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls))); announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls)));
} }
void DefaultBtContext::extractAnnounceList(const List* announceListData) { void DefaultBtContext::extractAnnounceList(const bencode::BDE& announceList)
for(std::deque<MetaEntry*>::const_iterator itr = announceListData->getList().begin(); {
itr != announceListData->getList().end(); itr++) { // Assumed announceList is string
const List* elem = dynamic_cast<const List*>(*itr); for(bencode::BDE::List::const_iterator itr = announceList.listBegin();
if(!elem) { itr != announceList.listEnd(); ++itr) {
const bencode::BDE& elemList = *itr;
if(!elemList.isList()) {
continue; continue;
} }
std::deque<std::string> urls; std::deque<std::string> urls;
for(std::deque<MetaEntry*>::const_iterator elemItr = elem->getList().begin(); for(bencode::BDE::List::const_iterator elemItr = elemList.listBegin();
elemItr != elem->getList().end(); elemItr++) { elemItr != elemList.listEnd(); ++elemItr) {
const Data* data = dynamic_cast<const Data*>(*elemItr); const bencode::BDE& url = (*elemItr);
if(data) { if(url.isString()) {
urls.push_back(Util::trim(data->toString())); urls.push_back(Util::trim(url.s()));
} }
} }
if(urls.size()) { if(!urls.empty()) {
AnnounceTierHandle tier(new AnnounceTier(urls)); AnnounceTierHandle tier(new AnnounceTier(urls));
announceTiers.push_back(tier); announceTiers.push_back(tier);
} }
} }
} }
void DefaultBtContext::extractUrlList(std::deque<std::string>& uris, void DefaultBtContext::extractAnnounce(const bencode::BDE& rootDict)
const MetaEntry* obj)
{ {
if(dynamic_cast<const List*>(obj)) { const bencode::BDE& announceList = rootDict[BtContext::C_ANNOUNCE_LIST];
const List* urlList = reinterpret_cast<const List*>(obj); if(announceList.isList()) {
for(std::deque<MetaEntry*>::const_iterator itr = urlList->getList().begin(); extractAnnounceList(announceList);
itr != urlList->getList().end(); ++itr) { } else {
const Data* data = dynamic_cast<const Data*>(*itr); const bencode::BDE& announce = rootDict[BtContext::C_ANNOUNCE];
if(data) { if(announce.isString()) {
uris.push_back(data->toString()); extractAnnounceURI(announce);
}
} }
} else if(dynamic_cast<const Data*>(obj)) {
const Data* urlData = reinterpret_cast<const Data*>(obj);
uris.push_back(urlData->toString());
} }
} }
void DefaultBtContext::extractNodes(const List* nodes) void DefaultBtContext::extractUrlList(std::deque<std::string>& uris,
const bencode::BDE& bde)
{ {
if(bde.isList()) {
for(std::deque<MetaEntry*>::const_iterator i = nodes->getList().begin(); for(bencode::BDE::List::const_iterator itr = bde.listBegin();
i != nodes->getList().end(); ++i) { itr != bde.listEnd(); ++itr) {
const List* addrPair = dynamic_cast<const List*>(*i); if((*itr).isString()) {
if(!addrPair || addrPair->getList().size() != 2) { uris.push_back((*itr).s());
}
}
} else if(bde.isString()) {
uris.push_back(bde.s());
}
}
void DefaultBtContext::extractNodes(const bencode::BDE& nodesList)
{
if(!nodesList.isList()) {
return;
}
for(bencode::BDE::List::const_iterator i = nodesList.listBegin();
i != nodesList.listEnd(); ++i) {
const bencode::BDE& addrPairList = (*i);
if(!addrPairList.isList() || addrPairList.size() != 2) {
continue; continue;
} }
const Data* hostname = dynamic_cast<const Data*>(addrPair->getList()[0]); const bencode::BDE& hostname = addrPairList[0];
if(!hostname) { if(!hostname.isString()) {
continue; continue;
} }
std::string h = hostname->toString(); if(Util::trim(hostname.s()).empty()) {
if(Util::trim(h).empty()) {
continue; continue;
} }
const Data* port = dynamic_cast<const Data*>(addrPair->getList()[1]); const bencode::BDE& port = addrPairList[1];
if(!port) { if(!port.isInteger() || !(0 < port.i() && port.i() < 65536)) {
continue; continue;
} }
uint16_t p = port->toInt(); _nodes.push_back(std::pair<std::string, uint16_t>(hostname.s(), port.i()));
if(p == 0) {
continue;
}
_nodes.push_back(std::pair<std::string, uint16_t>(h, p));
} }
} }
@ -280,103 +270,78 @@ void DefaultBtContext::loadFromMemory(const unsigned char* content,
const std::string& defaultName, const std::string& defaultName,
const std::string& overrideName) const std::string& overrideName)
{ {
SharedHandle<MetaEntry> rootEntry(MetaFileUtil::bdecoding(content, length)); processRootDictionary(bencode::decode(content, length), defaultName,
const Dictionary* rootDic = dynamic_cast<const Dictionary*>(rootEntry.get()); overrideName);
if(!rootDic) {
throw DlAbortEx
(StringFormat("torrent file does not contain a root dictionary .").str());
}
processRootDictionary(rootDic, defaultName, overrideName);
} }
void DefaultBtContext::load(const std::string& torrentFile, void DefaultBtContext::load(const std::string& torrentFile,
const std::string& overrideName) { const std::string& overrideName) {
SharedHandle<MetaEntry> rootEntry(MetaFileUtil::parseMetaFile(torrentFile)); processRootDictionary(bencode::decodeFromFile(torrentFile), torrentFile,
const Dictionary* rootDic = dynamic_cast<const Dictionary*>(rootEntry.get()); overrideName);
if(!rootDic) {
throw DlAbortEx
(StringFormat("torrent file does not contain a root dictionary .").str());
}
processRootDictionary(rootDic, torrentFile, overrideName);
} }
void DefaultBtContext::processRootDictionary(const Dictionary* rootDic, void DefaultBtContext::processRootDictionary(const bencode::BDE& rootDict,
const std::string& defaultName, const std::string& defaultName,
const std::string& overrideName) const std::string& overrideName)
{ {
clear(); clear();
const Dictionary* infoDic = if(!rootDict.isDict()) {
dynamic_cast<const Dictionary*>(rootDic->get(BtContext::C_INFO)); throw DlAbortEx("torrent file does not contain a root dictionary.");
if(!infoDic) { }
throw DlAbortEx const bencode::BDE& infoDict = rootDict[BtContext::C_INFO];
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "info directory").str()); if(!infoDict.isDict()) {
throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
BtContext::C_INFO.c_str()).str());
} }
// retrieve infoHash // retrieve infoHash
BencodeVisitor v; std::string encodedInfoDict = bencode::encode(infoDict);
infoDic->accept(&v);
MessageDigestHelper::digest(infoHash, INFO_HASH_LENGTH, MessageDigestHelper::digest(infoHash, INFO_HASH_LENGTH,
MessageDigestContext::SHA1, MessageDigestContext::SHA1,
v.getBencodedData().c_str(), encodedInfoDict.data(),
v.getBencodedData().size()); encodedInfoDict.size());
infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH); infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH);
// calculate the number of pieces // calculate the number of pieces
const Data* pieceHashData = const bencode::BDE& piecesData = infoDict[BtContext::C_PIECES];
dynamic_cast<const Data*>(infoDic->get(BtContext::C_PIECES)); if(!piecesData.isString()) {
if(!pieceHashData) { throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
throw DlAbortEx BtContext::C_PIECES.c_str()).str());
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "pieces").str());
} }
if(pieceHashData->getLen() == 0) { if(piecesData.s().empty()) {
throw DlAbortEx("The length of piece hash is 0."); throw DlAbortEx("The length of piece hash is 0.");
} }
numPieces = pieceHashData->getLen()/PIECE_HASH_LENGTH; numPieces = piecesData.s().size()/PIECE_HASH_LENGTH;
if(numPieces == 0) { if(numPieces == 0) {
throw DlAbortEx("The number of pieces is 0."); throw DlAbortEx("The number of pieces is 0.");
} }
// retrieve piece length // retrieve piece length
const Data* pieceLengthData = const bencode::BDE& pieceLengthData = infoDict[BtContext::C_PIECE_LENGTH];
dynamic_cast<const Data*>(infoDic->get(BtContext::C_PIECE_LENGTH)); if(!pieceLengthData.isInteger()) {
if(!pieceLengthData) { throw DlAbortEx(StringFormat(MSG_MISSING_BT_INFO,
throw DlAbortEx BtContext::C_PIECE_LENGTH.c_str()).str());
(StringFormat(MSG_SOMETHING_MISSING_IN_TORRENT, "piece length").str());
} }
pieceLength = pieceLengthData->toInt(); pieceLength = pieceLengthData.i();
// retrieve piece hashes // retrieve piece hashes
extractPieceHash(pieceHashData->getData(), pieceHashData->getLen(), extractPieceHash(piecesData.s(), PIECE_HASH_LENGTH);
PIECE_HASH_LENGTH); // private flag
const Data* privateFlag = const bencode::BDE& privateData = infoDict[BtContext::C_PRIVATE];
dynamic_cast<const Data*>(infoDic->get(BtContext::C_PRIVATE)); if(privateData.isInteger()) {
if(privateFlag) { _private = (privateData.i() == 1);
if(privateFlag->toString() == BtContext::C_PRIVATE_ON) {
_private = true;
}
} }
// retrieve uri-list. // retrieve uri-list.
// This implemantation obeys HTTP-Seeding specification: // This implemantation obeys HTTP-Seeding specification:
// see http://www.getright.com/seedtorrent.html // see http://www.getright.com/seedtorrent.html
std::deque<std::string> urlList; std::deque<std::string> urlList;
extractUrlList(urlList, rootDic->get(BtContext::C_URL_LIST)); extractUrlList(urlList, rootDict[BtContext::C_URL_LIST]);
// retrieve file entries // retrieve file entries
extractFileEntries(infoDic, defaultName, overrideName, urlList); extractFileEntries(infoDict, defaultName, overrideName, urlList);
if((totalLength+pieceLength-1)/pieceLength != numPieces) { if((totalLength+pieceLength-1)/pieceLength != numPieces) {
throw DlAbortEx("Too few/many piece hash."); throw DlAbortEx("Too few/many piece hash.");
} }
// retrieve announce // retrieve announce
const Data* announceData = extractAnnounce(rootDict);
dynamic_cast<const Data*>(rootDic->get(BtContext::C_ANNOUNCE));
const List* announceListData =
dynamic_cast<const List*>(rootDic->get(BtContext::C_ANNOUNCE_LIST));
if(announceListData) {
extractAnnounceList(announceListData);
} else if(announceData) {
extractAnnounce(announceData);
}
// retrieve nodes // retrieve nodes
const List* nodes = extractNodes(rootDict[BtContext::C_NODES]);
dynamic_cast<const List*>(rootDic->get(BtContext::C_NODES));
if(nodes) {
extractNodes(nodes);
}
} }
const std::string& DefaultBtContext::getPieceHash(size_t index) const { const std::string& DefaultBtContext::getPieceHash(size_t index) const {

View File

@ -36,17 +36,17 @@
#define _D_DEFAULT_BT_CONTEXT_H_ #define _D_DEFAULT_BT_CONTEXT_H_
#include "BtContext.h" #include "BtContext.h"
#include "A2STR.h"
#include <iosfwd> #include <iosfwd>
namespace aria2 { namespace aria2 {
class Randomizer; class Randomizer;
class Logger; class Logger;
class MetaEntry;
class Dictionary; namespace bencode {
class List; class BDE;
class Data; }
#define INFO_HASH_LENGTH 20 #define INFO_HASH_LENGTH 20
#define PIECE_HASH_LENGTH 20 #define PIECE_HASH_LENGTH 20
@ -73,21 +73,20 @@ private:
Logger* _logger; Logger* _logger;
void clear(); void clear();
void extractPieceHash(const unsigned char* hashData, void extractPieceHash(const std::string& hashData, size_t hashLength);
size_t hashDataLength, void extractFileEntries(const bencode::BDE& infoDic,
size_t hashLength);
void extractFileEntries(const Dictionary* infoDic,
const std::string& defaultName, const std::string& defaultName,
const std::string& overrideName, const std::string& overrideName,
const std::deque<std::string>& urlList); const std::deque<std::string>& urlList);
void extractAnnounce(const Data* announceData); void extractAnnounceURI(const bencode::BDE& announceData);
void extractAnnounceList(const List* announceListData); void extractAnnounceList(const bencode::BDE& announceListData);
void extractAnnounce(const bencode::BDE& rootDict);
void extractUrlList(std::deque<std::string>& uris, const MetaEntry* obj); void extractUrlList(std::deque<std::string>& uris, const bencode::BDE& obj);
void extractNodes(const List* nodes); void extractNodes(const bencode::BDE& nodes);
void processRootDictionary(const Dictionary* rootDic, void processRootDictionary(const bencode::BDE& rootDic,
const std::string& defaultName, const std::string& defaultName,
const std::string& overrideName); const std::string& overrideName);

View File

@ -34,9 +34,7 @@
/* copyright --> */ /* copyright --> */
#include "DefaultPeerListProcessor.h" #include "DefaultPeerListProcessor.h"
#include "Peer.h" #include "Peer.h"
#include "List.h" #include "bencode.h"
#include "Dictionary.h"
#include "Data.h"
namespace aria2 { namespace aria2 {
@ -48,31 +46,30 @@ DefaultPeerListProcessor::DefaultPeerListProcessor() {}
DefaultPeerListProcessor::~DefaultPeerListProcessor() {} DefaultPeerListProcessor::~DefaultPeerListProcessor() {}
bool DefaultPeerListProcessor::canHandle(const MetaEntry* peersEntry) const { bool DefaultPeerListProcessor::canHandle(const bencode::BDE& peerData) const
const List* peersList = dynamic_cast<const List*>(peersEntry); {
return peersList != 0; return peerData.isList();
} }
void DefaultPeerListProcessor::extractPeer void DefaultPeerListProcessor::extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry) (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData)
{ {
const List* peersList = dynamic_cast<const List*>(peersEntry); if(!canHandle(peerData)) {
if(!peersList) {
return; return;
} }
const std::deque<MetaEntry*>& metaList = peersList->getList(); for(bencode::BDE::List::const_iterator itr = peerData.listBegin();
for(std::deque<MetaEntry*>::const_iterator itr = metaList.begin(); itr != peerData.listEnd(); ++itr) {
itr != metaList.end(); itr++) { const bencode::BDE& peerDict = *itr;
const Dictionary* peerDic = dynamic_cast<const Dictionary*>(*itr); if(!peerDict.isDict()) {
if(!peerDic) {
break;
}
const Data* ip = dynamic_cast<const Data*>(peerDic->get(IP));
const Data* port = dynamic_cast<const Data*>(peerDic->get(PORT));
if(!ip || !port || !port->isNumber()) {
continue; continue;
} }
PeerHandle peer(new Peer(ip->toString(), port->toInt())); const bencode::BDE& ip = peerDict[IP];
const bencode::BDE& port = peerDict[PORT];
if(!ip.isString() || !port.isInteger() ||
!(0 < port.i() && port.i() < 65536)) {
continue;
}
PeerHandle peer(new Peer(ip.s(), port.i()));
peers.push_back(peer); peers.push_back(peer);
} }
} }

View File

@ -50,9 +50,9 @@ public:
virtual ~DefaultPeerListProcessor(); virtual ~DefaultPeerListProcessor();
virtual void extractPeer virtual void extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry); (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData);
virtual bool canHandle(const MetaEntry* peersEntry) const; virtual bool canHandle(const bencode::BDE& peerData) const;
}; };
} // namespace aria2 } // namespace aria2

View File

@ -32,10 +32,13 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DelegatingPeerListProcessor.h" #include "DelegatingPeerListProcessor.h"
#include <algorithm>
#include "DefaultPeerListProcessor.h" #include "DefaultPeerListProcessor.h"
#include "CompactPeerListProcessor.h" #include "CompactPeerListProcessor.h"
#include "Peer.h" #include "Peer.h"
#include <algorithm> #include "bencode.h"
namespace aria2 { namespace aria2 {
@ -54,22 +57,23 @@ DelegatingPeerListProcessor::DelegatingPeerListProcessor()
DelegatingPeerListProcessor::~DelegatingPeerListProcessor() {} DelegatingPeerListProcessor::~DelegatingPeerListProcessor() {}
void DelegatingPeerListProcessor::extractPeer void DelegatingPeerListProcessor::extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry) (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData)
{ {
for(std::deque<SharedHandle<PeerListProcessor> >::iterator itr = processors.begin(); for(std::deque<SharedHandle<PeerListProcessor> >::iterator itr =
itr != processors.end(); itr++) { processors.begin(); itr != processors.end(); ++itr) {
PeerListProcessorHandle processor = *itr; PeerListProcessorHandle processor = *itr;
if(processor->canHandle(peersEntry)) { if(processor->canHandle(peerData)) {
processor->extractPeer(peers, peersEntry); processor->extractPeer(peers, peerData);
break; break;
} }
} }
} }
bool DelegatingPeerListProcessor::canHandle(const MetaEntry* peersEntry) const { bool DelegatingPeerListProcessor::canHandle(const bencode::BDE& peerData) const
for(std::deque<SharedHandle<PeerListProcessor> >::const_iterator itr = processors.begin(); {
itr != processors.end(); itr++) { for(std::deque<SharedHandle<PeerListProcessor> >::const_iterator itr =
if((*itr)->canHandle(peersEntry)) { processors.begin(); itr != processors.end(); ++itr) {
if((*itr)->canHandle(peerData)) {
return true; return true;
} }
} }

View File

@ -47,9 +47,9 @@ public:
virtual ~DelegatingPeerListProcessor(); virtual ~DelegatingPeerListProcessor();
virtual void extractPeer virtual void extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry); (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData);
virtual bool canHandle(const MetaEntry* peersEntry) const; virtual bool canHandle(const bencode::BDE& peerData) const;
}; };
} // namespace aria2 } // namespace aria2

View File

@ -36,22 +36,26 @@
#define _D_PEER_LIST_PROCESSOR_H_ #define _D_PEER_LIST_PROCESSOR_H_
#include "common.h" #include "common.h"
#include "SharedHandle.h"
#include <deque> #include <deque>
#include "SharedHandle.h"
namespace aria2 { namespace aria2 {
class MetaEntry;
class Peer; class Peer;
namespace bencode {
class BDE;
}
class PeerListProcessor { class PeerListProcessor {
public: public:
virtual ~PeerListProcessor() {} virtual ~PeerListProcessor() {}
virtual void extractPeer virtual void extractPeer
(std::deque<SharedHandle<Peer> >& peers, const MetaEntry* peersEntry) = 0; (std::deque<SharedHandle<Peer> >& peers, const bencode::BDE& peerData) = 0;
virtual bool canHandle(const MetaEntry* peersEntry) const = 0; virtual bool canHandle(const bencode::BDE& peerData) const = 0;
}; };
typedef SharedHandle<PeerListProcessor> PeerListProcessorHandle; typedef SharedHandle<PeerListProcessor> PeerListProcessorHandle;

View File

@ -34,17 +34,14 @@
/* copyright --> */ /* copyright --> */
#include "UTPexExtensionMessage.h" #include "UTPexExtensionMessage.h"
#include "Peer.h" #include "Peer.h"
#include "Dictionary.h"
#include "Data.h"
#include "BencodeVisitor.h"
#include "Util.h" #include "Util.h"
#include "PeerMessageUtil.h" #include "PeerMessageUtil.h"
#include "PeerStorage.h" #include "PeerStorage.h"
#include "CompactPeerListProcessor.h" #include "CompactPeerListProcessor.h"
#include "MetaFileUtil.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "message.h" #include "message.h"
#include "StringFormat.h" #include "StringFormat.h"
#include "bencode.h"
namespace aria2 { namespace aria2 {
@ -60,19 +57,20 @@ UTPexExtensionMessage::~UTPexExtensionMessage() {}
std::string UTPexExtensionMessage::getBencodedData() std::string UTPexExtensionMessage::getBencodedData()
{ {
SharedHandle<Dictionary> d(new Dictionary()); std::pair<std::string, std::string> freshPeerPair =
std::pair<std::string, std::string> freshPeerPair = createCompactPeerListAndFlag(_freshPeers); createCompactPeerListAndFlag(_freshPeers);
std::pair<std::string, std::string> droppedPeerPair = createCompactPeerListAndFlag(_droppedPeers); std::pair<std::string, std::string> droppedPeerPair =
d->put("added", new Data(freshPeerPair.first)); createCompactPeerListAndFlag(_droppedPeers);
d->put("added.f", new Data(freshPeerPair.second));
d->put("dropped", new Data(droppedPeerPair.first));
BencodeVisitor v; bencode::BDE dict = bencode::BDE::dict();
d->accept(&v); dict["added"] = freshPeerPair.first;
return v.getBencodedData(); dict["added.f"] = freshPeerPair.second;
dict["dropped"] = droppedPeerPair.first;
return bencode::encode(dict);
} }
std::pair<std::string, std::string> UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers) std::pair<std::string, std::string>
UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers)
{ {
std::string addrstring; std::string addrstring;
std::string flagstring; std::string flagstring;
@ -173,19 +171,16 @@ UTPexExtensionMessage::create(const unsigned char* data, size_t len)
EXTENSION_NAME.c_str(), len).str()); EXTENSION_NAME.c_str(), len).str());
} }
UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data)); UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data));
SharedHandle<MetaEntry> root(MetaFileUtil::bdecoding(data+1, len-1));
if(root.isNull()) { const bencode::BDE dict = bencode::decode(data+1, len-1);
return msg; if(dict.isDict()) {
}
const Dictionary* d = dynamic_cast<const Dictionary*>(root.get());
if(d) {
CompactPeerListProcessor proc; CompactPeerListProcessor proc;
const Data* added = dynamic_cast<const Data*>(d->get("added")); const bencode::BDE& added = dict["added"];
if(added) { if(added.isString()) {
proc.extractPeer(msg->_freshPeers, added); proc.extractPeer(msg->_freshPeers, added);
} }
const Data* dropped = dynamic_cast<const Data*>(d->get("dropped")); const bencode::BDE& dropped = dict["dropped"];
if(dropped) { if(dropped.isString()) {
proc.extractPeer(msg->_droppedPeers, dropped); proc.extractPeer(msg->_droppedPeers, dropped);
} }
} }

View File

@ -172,6 +172,11 @@ public:
static std::string toHex(const unsigned char* src, size_t len); static std::string toHex(const unsigned char* src, size_t len);
static std::string toHex(const char* src, size_t len)
{
return toHex(reinterpret_cast<const unsigned char*>(src), len);
}
static std::string toHex(const std::string& src) static std::string toHex(const std::string& src)
{ {
return toHex(reinterpret_cast<const unsigned char*>(src.c_str()), src.size()); return toHex(reinterpret_cast<const unsigned char*>(src.c_str()), src.size());

View File

@ -136,7 +136,7 @@
#define MSG_TOO_SMALL_PAYLOAD_SIZE _("Too small payload size for %s, size=%d.") #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_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_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_MISSING_BT_INFO _("Missing %s in torrent metainfo.")
#define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.") #define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.")
#define MSG_WINSOCK_INIT_FAILD _("Windows socket library initialization failed") #define MSG_WINSOCK_INIT_FAILD _("Windows socket library initialization failed")
#define MSG_TIME_HAS_PASSED _("%d second(s) has passed. Stopping application.") #define MSG_TIME_HAS_PASSED _("%d second(s) has passed. Stopping application.")

View File

@ -372,7 +372,7 @@ void DefaultBtContextTest::testGetNodes()
std::string memory = std::string memory =
"d5:nodesl" "d5:nodesl"
"l11:192.168.0.1i6881ee" "l11:192.168.0.1i6881ee"
"l11:192.168.0.24:6882e" "l11:192.168.0.2i6882ee"
"e4:infod4:name13:aria2.tar.bz26:lengthi262144e" "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
"12:piece lengthi262144e" "12:piece lengthi262144e"
"6:pieces20:AAAAAAAAAAAAAAAAAAAA" "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@ -393,7 +393,7 @@ void DefaultBtContextTest::testGetNodes()
std::string memory = std::string memory =
"d5:nodesl" "d5:nodesl"
"l1: i6881ee" "l1: i6881ee"
"l11:192.168.0.24:6882e" "l11:192.168.0.2i6882ee"
"e4:infod4:name13:aria2.tar.bz26:lengthi262144e" "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
"12:piece lengthi262144e" "12:piece lengthi262144e"
"6:pieces20:AAAAAAAAAAAAAAAAAAAA" "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@ -412,7 +412,7 @@ void DefaultBtContextTest::testGetNodes()
std::string memory = std::string memory =
"d5:nodesl" "d5:nodesl"
"l11:192.168.0.11:xe" "l11:192.168.0.11:xe"
"l11:192.168.0.24:6882e" "l11:192.168.0.2i6882ee"
"e4:infod4:name13:aria2.tar.bz26:lengthi262144e" "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
"12:piece lengthi262144e" "12:piece lengthi262144e"
"6:pieces20:AAAAAAAAAAAAAAAAAAAA" "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@ -431,7 +431,7 @@ void DefaultBtContextTest::testGetNodes()
std::string memory = std::string memory =
"d5:nodesl" "d5:nodesl"
"l11:192.168.0.1e" "l11:192.168.0.1e"
"l11:192.168.0.24:6882e" "l11:192.168.0.2i6882ee"
"e4:infod4:name13:aria2.tar.bz26:lengthi262144e" "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
"12:piece lengthi262144e" "12:piece lengthi262144e"
"6:pieces20:AAAAAAAAAAAAAAAAAAAA" "6:pieces20:AAAAAAAAAAAAAAAAAAAA"
@ -466,7 +466,7 @@ void DefaultBtContextTest::testGetNodes()
std::string memory = std::string memory =
"d5:nodesl" "d5:nodesl"
"ll11:192.168.0.1i6881eee" "ll11:192.168.0.1i6881eee"
"l11:192.168.0.24:6882e" "l11:192.168.0.2i6882ee"
"e4:infod4:name13:aria2.tar.bz26:lengthi262144e" "e4:infod4:name13:aria2.tar.bz26:lengthi262144e"
"12:piece lengthi262144e" "12:piece lengthi262144e"
"6:pieces20:AAAAAAAAAAAAAAAAAAAA" "6:pieces20:AAAAAAAAAAAAAAAAAAAA"

View File

@ -1,10 +1,11 @@
#include "DefaultPeerListProcessor.h" #include "DefaultPeerListProcessor.h"
#include "MetaFileUtil.h"
#include "Exception.h"
#include "Dictionary.h"
#include "Peer.h"
#include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/HelperMacros.h>
#include "Exception.h"
#include "Peer.h"
#include "bencode.h"
namespace aria2 { namespace aria2 {
class DefaultPeerListProcessorTest:public CppUnit::TestFixture { class DefaultPeerListProcessorTest:public CppUnit::TestFixture {
@ -30,13 +31,12 @@ void DefaultPeerListProcessorTest::testExtractPeer() {
DefaultPeerListProcessor proc; DefaultPeerListProcessor proc;
std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti2006eeee"; std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti2006eeee";
SharedHandle<Dictionary> dic const bencode::BDE dict = bencode::decode(peersString);
(dynamic_cast<Dictionary*>(MetaFileUtil::bdecoding(peersString)));
CPPUNIT_ASSERT(proc.canHandle(dic->get("peers"))); CPPUNIT_ASSERT(proc.canHandle(dict["peers"]));
std::deque<SharedHandle<Peer> > peers; std::deque<SharedHandle<Peer> > peers;
proc.extractPeer(peers, dic->get("peers")); proc.extractPeer(peers, dict["peers"]);
CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size()); CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size());
SharedHandle<Peer> peer = *peers.begin(); SharedHandle<Peer> peer = *peers.begin();
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->ipaddr); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->ipaddr);
@ -45,17 +45,16 @@ void DefaultPeerListProcessorTest::testExtractPeer() {
void DefaultPeerListProcessorTest::testExtract2Peers() { void DefaultPeerListProcessorTest::testExtract2Peers() {
DefaultPeerListProcessor proc; DefaultPeerListProcessor proc;
std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti2006eed2:ip11:192.168.0.27:peer id20:aria2-000000000000004:porti2007eeee"; std::string peersString = "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-000000000000004:porti65535eed2:ip11:192.168.0.27:peer id20:aria2-000000000000004:porti2007eeee";
SharedHandle<Dictionary> dic const bencode::BDE dict = bencode::decode(peersString);
(dynamic_cast<Dictionary*>(MetaFileUtil::bdecoding(peersString)));
std::deque<SharedHandle<Peer> > peers; std::deque<SharedHandle<Peer> > peers;
proc.extractPeer(peers, dic->get("peers")); proc.extractPeer(peers, dict["peers"]);
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size()); CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
SharedHandle<Peer> peer = *peers.begin(); SharedHandle<Peer> peer = *peers.begin();
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->ipaddr); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)2006, peer->port); CPPUNIT_ASSERT_EQUAL((uint16_t)65535, peer->port);
peer = *(peers.begin()+1); peer = *(peers.begin()+1);
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peer->ipaddr); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peer->ipaddr);