/* */ #include "DHTPeerAnnounceStorage.h" #include "DHTPeerAnnounceEntry.h" #include "Peer.h" #include "BtContext.h" #include "DHTConstants.h" #include "DHTTaskQueue.h" #include "DHTTaskFactory.h" #include "DHTTask.h" #include "LogFactory.h" #include "Logger.h" #include "Util.h" #include #include namespace aria2 { DHTPeerAnnounceStorage::DHTPeerAnnounceStorage(): _logger(LogFactory::getInstance()) {} DHTPeerAnnounceStorage::~DHTPeerAnnounceStorage() {} class FindPeerAnnounceEntry { private: unsigned char _infoHash[DHT_ID_LENGTH]; public: FindPeerAnnounceEntry(const unsigned char* infoHash) { memcpy(_infoHash, infoHash, DHT_ID_LENGTH); } bool operator()(const SharedHandle& entry) const { return memcmp(_infoHash, entry->getInfoHash(), DHT_ID_LENGTH) == 0; } }; SharedHandle DHTPeerAnnounceStorage::getPeerAnnounceEntry(const unsigned char* infoHash) { std::deque >::iterator i = std::find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(infoHash)); SharedHandle entry; if(i == _entries.end()) { entry.reset(new DHTPeerAnnounceEntry(infoHash)); _entries.push_back(entry); } else { entry = *i; } return entry; } void DHTPeerAnnounceStorage::addPeerAnnounce(const unsigned char* infoHash, const std::string& ipaddr, uint16_t port) { _logger->debug("Adding %s:%u to peer announce list: infoHash=%s", ipaddr.c_str(), port, Util::toHex(infoHash, DHT_ID_LENGTH).c_str()); getPeerAnnounceEntry(infoHash)->addPeerAddrEntry(PeerAddrEntry(ipaddr, port)); } // add peer announce as localhost downloading the content void DHTPeerAnnounceStorage::addPeerAnnounce(const BtContextHandle& ctx) { _logger->debug("Adding localhost to peer announce list: infoHash=%s", ctx->getInfoHashAsString().c_str()); getPeerAnnounceEntry(ctx->getInfoHash())->setBtContext(ctx); } void DHTPeerAnnounceStorage::removePeerAnnounce(const BtContextHandle& ctx) { std::deque >::iterator i = std::find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(ctx->getInfoHash())); if(i != _entries.end()) { (*i)->setBtContext(SharedHandle()); if((*i)->empty()) { _entries.erase(i); } } } bool DHTPeerAnnounceStorage::contains(const unsigned char* infoHash) const { return std::find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(infoHash)) != _entries.end(); } Peers DHTPeerAnnounceStorage::getPeers(const unsigned char* infoHash) { std::deque >::iterator i = std::find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(infoHash)); if(i == _entries.end() || (*i)->empty()) { return Peers(); } return (*i)->getPeers(); } void DHTPeerAnnounceStorage::handleTimeout() { _logger->debug("Now purge peer announces which are timed out."); size_t numPeerAddr = 0; for(std::deque >::iterator i = _entries.begin(); i != _entries.end();) { (*i)->removeStalePeerAddrEntry(DHT_PEER_ANNOUNCE_PURGE_INTERVAL); if((*i)->empty()) { _logger->debug("1 entry purged: infoHash=%s", Util::toHex((*i)->getInfoHash(), DHT_ID_LENGTH).c_str()); i = _entries.erase(i); } else { numPeerAddr += (*i)->countPeerAddrEntry(); ++i; } } _logger->debug("Currently %zu peer announce entries, %zu PeerAddr entries", _entries.size(), numPeerAddr); } void DHTPeerAnnounceStorage::announcePeer() { _logger->debug("Now announcing peer."); for(std::deque >::iterator i = _entries.begin(); i != _entries.end(); ++i) { if((*i)->getLastUpdated().elapsed(DHT_PEER_ANNOUNCE_INTERVAL)) { (*i)->notifyUpdate(); SharedHandle task = _taskFactory->createPeerAnnounceTask((*i)->getInfoHash()); _taskQueue->addPeriodicTask2(task); _logger->debug("Added 1 peer announce: infoHash=%s", Util::toHex((*i)->getInfoHash(), DHT_ID_LENGTH).c_str()); } } } void DHTPeerAnnounceStorage::setTaskQueue(const SharedHandle& taskQueue) { _taskQueue = taskQueue; } void DHTPeerAnnounceStorage::setTaskFactory(const SharedHandle& taskFactory) { _taskFactory = taskFactory; } } // namespace aria2