/* */ #include "DHTPeerLookupTask.h" #include "Peer.h" #include "DHTGetPeersReplyMessage.h" #include "Logger.h" #include "LogFactory.h" #include "DHTMessageFactory.h" #include "DHTNode.h" #include "DHTNodeLookupEntry.h" #include "DHTMessageDispatcher.h" #include "DHTMessageCallback.h" #include "PeerStorage.h" #include "util.h" #include "DHTBucket.h" #include "bittorrent_helper.h" #include "DHTPeerLookupTaskCallback.h" #include "DHTQueryMessage.h" #include "DHTGetPeersMessage.h" #include "DHTAnnouncePeerMessage.h" #include "fmt.h" namespace aria2 { DHTPeerLookupTask::DHTPeerLookupTask( const std::shared_ptr& downloadContext, uint16_t tcpPort) : DHTAbstractNodeLookupTask( bittorrent::getInfoHash(downloadContext)), tcpPort_(tcpPort) { } void DHTPeerLookupTask::getNodesFromMessage( std::vector>& nodes, const DHTGetPeersReplyMessage* message) { auto& knodes = message->getClosestKNodes(); nodes.insert(std::end(nodes), std::begin(knodes), std::end(knodes)); } void DHTPeerLookupTask::onReceivedInternal( const DHTGetPeersReplyMessage* message) { std::shared_ptr remoteNode = message->getRemoteNode(); tokenStorage_[util::toHex(remoteNode->getID(), DHT_ID_LENGTH)] = message->getToken(); peerStorage_->addPeer(message->getValues()); A2_LOG_INFO(fmt("Received %lu peers.", static_cast(message->getValues().size()))); } std::unique_ptr DHTPeerLookupTask::createMessage(const std::shared_ptr& remoteNode) { return getMessageFactory()->createGetPeersMessage(remoteNode, getTargetID()); } std::unique_ptr DHTPeerLookupTask::createCallback() { return make_unique(this); } void DHTPeerLookupTask::onFinish() { A2_LOG_DEBUG(fmt("Peer lookup for %s finished", util::toHex(getTargetID(), DHT_ID_LENGTH).c_str())); // send announce_peer message to K closest nodes size_t num = DHTBucket::K; for (auto i = std::begin(getEntries()), eoi = std::end(getEntries()); i != eoi && num > 0; ++i) { if (!(*i)->used) { continue; } auto& node = (*i)->node; std::string idHex = util::toHex(node->getID(), DHT_ID_LENGTH); std::string token = tokenStorage_[idHex]; if (token.empty()) { A2_LOG_DEBUG(fmt("Token is empty for ID:%s", idHex.c_str())); continue; } getMessageDispatcher()->addMessageToQueue( getMessageFactory()->createAnnouncePeerMessage( node, getTargetID(), // this is infoHash tcpPort_, token)); --num; } } void DHTPeerLookupTask::setPeerStorage(const std::shared_ptr& ps) { peerStorage_ = ps; } } // namespace aria2