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>
Added bencode helper functions and BDE class.

View File

@ -32,9 +32,9 @@
*/
/* copyright --> */
#include "CompactPeerListProcessor.h"
#include "Peer.h"
#include "Data.h"
#include "a2netcompat.h"
#include "bencode.h"
#include "Peer.h"
namespace aria2 {
@ -42,23 +42,24 @@ CompactPeerListProcessor::CompactPeerListProcessor() {}
CompactPeerListProcessor::~CompactPeerListProcessor() {}
bool CompactPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
return dynamic_cast<const Data*>(peersEntry) != 0;
bool CompactPeerListProcessor::canHandle(const bencode::BDE& peerData) const
{
return peerData.isString();
}
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(!peersData) {
if(!canHandle(peerData)) {
return;
}
if(peersData->getLen()%6 == 0) {
for(size_t i = 0; i < peersData->getLen(); i += 6) {
size_t length = peerData.s().size();
if(length%6 == 0) {
for(size_t i = 0; i < length; i += 6) {
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);
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));
peers.push_back(peer);
}

View File

@ -45,9 +45,9 @@ public:
virtual ~CompactPeerListProcessor();
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

View File

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

View File

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

View File

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

View File

@ -34,9 +34,7 @@
/* copyright --> */
#include "DefaultPeerListProcessor.h"
#include "Peer.h"
#include "List.h"
#include "Dictionary.h"
#include "Data.h"
#include "bencode.h"
namespace aria2 {
@ -48,31 +46,30 @@ DefaultPeerListProcessor::DefaultPeerListProcessor() {}
DefaultPeerListProcessor::~DefaultPeerListProcessor() {}
bool DefaultPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
const List* peersList = dynamic_cast<const List*>(peersEntry);
return peersList != 0;
bool DefaultPeerListProcessor::canHandle(const bencode::BDE& peerData) const
{
return peerData.isList();
}
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(!peersList) {
if(!canHandle(peerData)) {
return;
}
const std::deque<MetaEntry*>& metaList = peersList->getList();
for(std::deque<MetaEntry*>::const_iterator itr = metaList.begin();
itr != metaList.end(); itr++) {
const Dictionary* peerDic = dynamic_cast<const Dictionary*>(*itr);
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()) {
for(bencode::BDE::List::const_iterator itr = peerData.listBegin();
itr != peerData.listEnd(); ++itr) {
const bencode::BDE& peerDict = *itr;
if(!peerDict.isDict()) {
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);
}
}

View File

@ -50,9 +50,9 @@ public:
virtual ~DefaultPeerListProcessor();
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

View File

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

View File

@ -47,9 +47,9 @@ public:
virtual ~DelegatingPeerListProcessor();
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

View File

@ -36,22 +36,26 @@
#define _D_PEER_LIST_PROCESSOR_H_
#include "common.h"
#include "SharedHandle.h"
#include <deque>
#include "SharedHandle.h"
namespace aria2 {
class MetaEntry;
class Peer;
namespace bencode {
class BDE;
}
class PeerListProcessor {
public:
virtual ~PeerListProcessor() {}
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;

View File

@ -34,17 +34,14 @@
/* copyright --> */
#include "UTPexExtensionMessage.h"
#include "Peer.h"
#include "Dictionary.h"
#include "Data.h"
#include "BencodeVisitor.h"
#include "Util.h"
#include "PeerMessageUtil.h"
#include "PeerStorage.h"
#include "CompactPeerListProcessor.h"
#include "MetaFileUtil.h"
#include "DlAbortEx.h"
#include "message.h"
#include "StringFormat.h"
#include "bencode.h"
namespace aria2 {
@ -60,19 +57,20 @@ UTPexExtensionMessage::~UTPexExtensionMessage() {}
std::string UTPexExtensionMessage::getBencodedData()
{
SharedHandle<Dictionary> d(new Dictionary());
std::pair<std::string, std::string> freshPeerPair = createCompactPeerListAndFlag(_freshPeers);
std::pair<std::string, std::string> droppedPeerPair = createCompactPeerListAndFlag(_droppedPeers);
d->put("added", new Data(freshPeerPair.first));
d->put("added.f", new Data(freshPeerPair.second));
d->put("dropped", new Data(droppedPeerPair.first));
std::pair<std::string, std::string> freshPeerPair =
createCompactPeerListAndFlag(_freshPeers);
std::pair<std::string, std::string> droppedPeerPair =
createCompactPeerListAndFlag(_droppedPeers);
BencodeVisitor v;
d->accept(&v);
return v.getBencodedData();
bencode::BDE dict = bencode::BDE::dict();
dict["added"] = freshPeerPair.first;
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 flagstring;
@ -173,19 +171,16 @@ UTPexExtensionMessage::create(const unsigned char* data, size_t len)
EXTENSION_NAME.c_str(), len).str());
}
UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data));
SharedHandle<MetaEntry> root(MetaFileUtil::bdecoding(data+1, len-1));
if(root.isNull()) {
return msg;
}
const Dictionary* d = dynamic_cast<const Dictionary*>(root.get());
if(d) {
const bencode::BDE dict = bencode::decode(data+1, len-1);
if(dict.isDict()) {
CompactPeerListProcessor proc;
const Data* added = dynamic_cast<const Data*>(d->get("added"));
if(added) {
const bencode::BDE& added = dict["added"];
if(added.isString()) {
proc.extractPeer(msg->_freshPeers, added);
}
const Data* dropped = dynamic_cast<const Data*>(d->get("dropped"));
if(dropped) {
const bencode::BDE& dropped = dict["dropped"];
if(dropped.isString()) {
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 char* src, size_t len)
{
return toHex(reinterpret_cast<const unsigned char*>(src), len);
}
static std::string toHex(const std::string& src)
{
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_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_MISSING_BT_INFO _("Missing %s in torrent metainfo.")
#define MSG_NULL_TRACKER_RESPONSE _("Tracker returned null data.")
#define MSG_WINSOCK_INIT_FAILD _("Windows socket library initialization failed")
#define MSG_TIME_HAS_PASSED _("%d second(s) has passed. Stopping application.")

View File

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

View File

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