mirror of https://github.com/aria2/aria2
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.ccpull/1/head
parent
1b54e64d34
commit
8129042a3a
19
ChangeLog
19
ChangeLog
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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.")
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue