From 8129042a3a395c8879c6b3ae36c3e9ec1e32e0b6 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 9 Dec 2008 15:03:29 +0000 Subject: [PATCH] 2008-12-09 Tatsuhiro Tsujikawa 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 --- ChangeLog | 19 ++ src/CompactPeerListProcessor.cc | 23 +- src/CompactPeerListProcessor.h | 4 +- src/DefaultBtAnnounce.cc | 93 ++++---- src/DefaultBtContext.cc | 305 ++++++++++++--------------- src/DefaultBtContext.h | 27 ++- src/DefaultPeerListProcessor.cc | 37 ++-- src/DefaultPeerListProcessor.h | 4 +- src/DelegatingPeerListProcessor.cc | 24 ++- src/DelegatingPeerListProcessor.h | 4 +- src/PeerListProcessor.h | 12 +- src/UTPexExtensionMessage.cc | 43 ++-- src/Util.h | 5 + src/message.h | 2 +- test/DefaultBtContextTest.cc | 10 +- test/DefaultPeerListProcessorTest.cc | 25 ++- 16 files changed, 303 insertions(+), 334 deletions(-) diff --git a/ChangeLog b/ChangeLog index 639835a1..2c66702a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2008-12-09 Tatsuhiro Tsujikawa + + 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 Added bencode helper functions and BDE class. diff --git a/src/CompactPeerListProcessor.cc b/src/CompactPeerListProcessor.cc index 726a99cd..1feb78a4 100644 --- a/src/CompactPeerListProcessor.cc +++ b/src/CompactPeerListProcessor.cc @@ -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(peersEntry) != 0; +bool CompactPeerListProcessor::canHandle(const bencode::BDE& peerData) const +{ + return peerData.isString(); } void CompactPeerListProcessor::extractPeer -(std::deque >& peers, const MetaEntry* peersEntry) +(std::deque >& peers, const bencode::BDE& peerData) { - const Data* peersData = dynamic_cast(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); } diff --git a/src/CompactPeerListProcessor.h b/src/CompactPeerListProcessor.h index fd8a8691..6a72444d 100644 --- a/src/CompactPeerListProcessor.h +++ b/src/CompactPeerListProcessor.h @@ -45,9 +45,9 @@ public: virtual ~CompactPeerListProcessor(); virtual void extractPeer - (std::deque >& peers, const MetaEntry* peersEntry); + (std::deque >& peers, const bencode::BDE& peerData); - virtual bool canHandle(const MetaEntry* peersEntry) const; + virtual bool canHandle(const bencode::BDE& peerData) const; }; } // namespace aria2 diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc index ec8b7c1f..d53b9360 100644 --- a/src/DefaultBtAnnounce.cc +++ b/src/DefaultBtAnnounce.cc @@ -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 entry(MetaFileUtil::bdecoding(trackerResponse, - trackerResponseLength)); - const Dictionary* response = dynamic_cast(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(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(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(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(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(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(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(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 > 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 > peers; + proc.extractPeer(peers, peerData); + peerStorage->addPeer(peers); + } + } else { logger->info(MSG_NO_PEER_LIST_RECEIVED); } } diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc index 0f48d899..eeee7f14 100644 --- a/src/DefaultBtContext.cc +++ b/src/DefaultBtContext.cc @@ -33,12 +33,13 @@ */ /* copyright --> */ #include "DefaultBtContext.h" -#include "MetaFileUtil.h" -#include "Dictionary.h" -#include "List.h" -#include "Data.h" + +#include +#include +#include +#include + #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 -#include -#include -#include +#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& urlList) { + const std::deque& urlList) +{ if(overrideName.empty()) { - const Data* nameData = - dynamic_cast(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(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& metaList = files->getList(); - for(std::deque::const_iterator itr = metaList.begin(); - itr != metaList.end(); itr++) { - const Dictionary* fileDic = dynamic_cast((*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(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(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& paths = pathList->getList(); std::string path; - for(size_t i = 0; i < paths.size()-1; i++) { - const Data* subpath = dynamic_cast(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(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 uris; std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris), std::bind2nd(std::plus(), "/"+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(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 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::const_iterator itr = announceListData->getList().begin(); - itr != announceListData->getList().end(); itr++) { - const List* elem = dynamic_cast(*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 urls; - for(std::deque::const_iterator elemItr = elem->getList().begin(); - elemItr != elem->getList().end(); elemItr++) { - const Data* data = dynamic_cast(*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& uris, - const MetaEntry* obj) +void DefaultBtContext::extractAnnounce(const bencode::BDE& rootDict) { - if(dynamic_cast(obj)) { - const List* urlList = reinterpret_cast(obj); - for(std::deque::const_iterator itr = urlList->getList().begin(); - itr != urlList->getList().end(); ++itr) { - const Data* data = dynamic_cast(*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(obj)) { - const Data* urlData = reinterpret_cast(obj); - uris.push_back(urlData->toString()); } } -void DefaultBtContext::extractNodes(const List* nodes) +void DefaultBtContext::extractUrlList(std::deque& uris, + const bencode::BDE& bde) { - - for(std::deque::const_iterator i = nodes->getList().begin(); - i != nodes->getList().end(); ++i) { - const List* addrPair = dynamic_cast(*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(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(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(h, p)); + _nodes.push_back(std::pair(hostname.s(), port.i())); } } @@ -280,103 +270,78 @@ void DefaultBtContext::loadFromMemory(const unsigned char* content, const std::string& defaultName, const std::string& overrideName) { - SharedHandle rootEntry(MetaFileUtil::bdecoding(content, length)); - const Dictionary* rootDic = dynamic_cast(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 rootEntry(MetaFileUtil::parseMetaFile(torrentFile)); - const Dictionary* rootDic = dynamic_cast(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(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(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(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(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 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(rootDic->get(BtContext::C_ANNOUNCE)); - const List* announceListData = - dynamic_cast(rootDic->get(BtContext::C_ANNOUNCE_LIST)); - if(announceListData) { - extractAnnounceList(announceListData); - } else if(announceData) { - extractAnnounce(announceData); - } + extractAnnounce(rootDict); // retrieve nodes - const List* nodes = - dynamic_cast(rootDic->get(BtContext::C_NODES)); - if(nodes) { - extractNodes(nodes); - } + extractNodes(rootDict[BtContext::C_NODES]); } const std::string& DefaultBtContext::getPieceHash(size_t index) const { diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h index abab597c..d6e72b92 100644 --- a/src/DefaultBtContext.h +++ b/src/DefaultBtContext.h @@ -36,17 +36,17 @@ #define _D_DEFAULT_BT_CONTEXT_H_ #include "BtContext.h" -#include "A2STR.h" + #include 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& 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& uris, const MetaEntry* obj); + void extractUrlList(std::deque& 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); diff --git a/src/DefaultPeerListProcessor.cc b/src/DefaultPeerListProcessor.cc index a72d19b0..3e52a15a 100644 --- a/src/DefaultPeerListProcessor.cc +++ b/src/DefaultPeerListProcessor.cc @@ -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(peersEntry); - return peersList != 0; +bool DefaultPeerListProcessor::canHandle(const bencode::BDE& peerData) const +{ + return peerData.isList(); } void DefaultPeerListProcessor::extractPeer -(std::deque >& peers, const MetaEntry* peersEntry) +(std::deque >& peers, const bencode::BDE& peerData) { - const List* peersList = dynamic_cast(peersEntry); - if(!peersList) { + if(!canHandle(peerData)) { return; } - const std::deque& metaList = peersList->getList(); - for(std::deque::const_iterator itr = metaList.begin(); - itr != metaList.end(); itr++) { - const Dictionary* peerDic = dynamic_cast(*itr); - if(!peerDic) { - break; - } - const Data* ip = dynamic_cast(peerDic->get(IP)); - const Data* port = dynamic_cast(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); } } diff --git a/src/DefaultPeerListProcessor.h b/src/DefaultPeerListProcessor.h index 371fe57d..f82bdeec 100644 --- a/src/DefaultPeerListProcessor.h +++ b/src/DefaultPeerListProcessor.h @@ -50,9 +50,9 @@ public: virtual ~DefaultPeerListProcessor(); virtual void extractPeer - (std::deque >& peers, const MetaEntry* peersEntry); + (std::deque >& peers, const bencode::BDE& peerData); - virtual bool canHandle(const MetaEntry* peersEntry) const; + virtual bool canHandle(const bencode::BDE& peerData) const; }; } // namespace aria2 diff --git a/src/DelegatingPeerListProcessor.cc b/src/DelegatingPeerListProcessor.cc index e0ddfcb9..30068de7 100644 --- a/src/DelegatingPeerListProcessor.cc +++ b/src/DelegatingPeerListProcessor.cc @@ -32,10 +32,13 @@ */ /* copyright --> */ #include "DelegatingPeerListProcessor.h" + +#include + #include "DefaultPeerListProcessor.h" #include "CompactPeerListProcessor.h" #include "Peer.h" -#include +#include "bencode.h" namespace aria2 { @@ -54,22 +57,23 @@ DelegatingPeerListProcessor::DelegatingPeerListProcessor() DelegatingPeerListProcessor::~DelegatingPeerListProcessor() {} void DelegatingPeerListProcessor::extractPeer -(std::deque >& peers, const MetaEntry* peersEntry) +(std::deque >& peers, const bencode::BDE& peerData) { - for(std::deque >::iterator itr = processors.begin(); - itr != processors.end(); itr++) { + for(std::deque >::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 >::const_iterator itr = processors.begin(); - itr != processors.end(); itr++) { - if((*itr)->canHandle(peersEntry)) { +bool DelegatingPeerListProcessor::canHandle(const bencode::BDE& peerData) const +{ + for(std::deque >::const_iterator itr = + processors.begin(); itr != processors.end(); ++itr) { + if((*itr)->canHandle(peerData)) { return true; } } diff --git a/src/DelegatingPeerListProcessor.h b/src/DelegatingPeerListProcessor.h index 16e83f8b..967f3b2d 100644 --- a/src/DelegatingPeerListProcessor.h +++ b/src/DelegatingPeerListProcessor.h @@ -47,9 +47,9 @@ public: virtual ~DelegatingPeerListProcessor(); virtual void extractPeer - (std::deque >& peers, const MetaEntry* peersEntry); + (std::deque >& peers, const bencode::BDE& peerData); - virtual bool canHandle(const MetaEntry* peersEntry) const; + virtual bool canHandle(const bencode::BDE& peerData) const; }; } // namespace aria2 diff --git a/src/PeerListProcessor.h b/src/PeerListProcessor.h index 683006bd..6872e381 100644 --- a/src/PeerListProcessor.h +++ b/src/PeerListProcessor.h @@ -36,22 +36,26 @@ #define _D_PEER_LIST_PROCESSOR_H_ #include "common.h" -#include "SharedHandle.h" + #include +#include "SharedHandle.h" + namespace aria2 { -class MetaEntry; class Peer; +namespace bencode { +class BDE; +} class PeerListProcessor { public: virtual ~PeerListProcessor() {} virtual void extractPeer - (std::deque >& peers, const MetaEntry* peersEntry) = 0; + (std::deque >& 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 PeerListProcessorHandle; diff --git a/src/UTPexExtensionMessage.cc b/src/UTPexExtensionMessage.cc index 892483b1..9b1890cd 100644 --- a/src/UTPexExtensionMessage.cc +++ b/src/UTPexExtensionMessage.cc @@ -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 d(new Dictionary()); - std::pair freshPeerPair = createCompactPeerListAndFlag(_freshPeers); - std::pair 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 freshPeerPair = + createCompactPeerListAndFlag(_freshPeers); + std::pair 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 UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers) +std::pair +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 root(MetaFileUtil::bdecoding(data+1, len-1)); - if(root.isNull()) { - return msg; - } - const Dictionary* d = dynamic_cast(root.get()); - if(d) { + + const bencode::BDE dict = bencode::decode(data+1, len-1); + if(dict.isDict()) { CompactPeerListProcessor proc; - const Data* added = dynamic_cast(d->get("added")); - if(added) { + const bencode::BDE& added = dict["added"]; + if(added.isString()) { proc.extractPeer(msg->_freshPeers, added); } - const Data* dropped = dynamic_cast(d->get("dropped")); - if(dropped) { + const bencode::BDE& dropped = dict["dropped"]; + if(dropped.isString()) { proc.extractPeer(msg->_droppedPeers, dropped); } } diff --git a/src/Util.h b/src/Util.h index 093e0e9a..002ddafd 100644 --- a/src/Util.h +++ b/src/Util.h @@ -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(src), len); + } + static std::string toHex(const std::string& src) { return toHex(reinterpret_cast(src.c_str()), src.size()); diff --git a/src/message.h b/src/message.h index b47a7815..e78d71ce 100644 --- a/src/message.h +++ b/src/message.h @@ -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.") diff --git a/test/DefaultBtContextTest.cc b/test/DefaultBtContextTest.cc index d0e2a8b2..14a1395f 100644 --- a/test/DefaultBtContextTest.cc +++ b/test/DefaultBtContextTest.cc @@ -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" diff --git a/test/DefaultPeerListProcessorTest.cc b/test/DefaultPeerListProcessorTest.cc index 4dc00e9e..24557d48 100644 --- a/test/DefaultPeerListProcessorTest.cc +++ b/test/DefaultPeerListProcessorTest.cc @@ -1,10 +1,11 @@ #include "DefaultPeerListProcessor.h" -#include "MetaFileUtil.h" -#include "Exception.h" -#include "Dictionary.h" -#include "Peer.h" + #include +#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 dic - (dynamic_cast(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 > peers; - proc.extractPeer(peers, dic->get("peers")); + proc.extractPeer(peers, dict["peers"]); CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size()); SharedHandle 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 dic - (dynamic_cast(MetaFileUtil::bdecoding(peersString))); + const bencode::BDE dict = bencode::decode(peersString); std::deque > peers; - proc.extractPeer(peers, dic->get("peers")); + proc.extractPeer(peers, dict["peers"]); CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size()); SharedHandle 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);