File indexing completed on 2025-01-05 04:37:11
0001 /* 0002 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "nodelookup.h" 0007 #include "findnodereq.h" 0008 #include "findnodersp.h" 0009 #include "kbucket.h" 0010 #include "node.h" 0011 #include "pack.h" 0012 #include "rpcmsg.h" 0013 #include <torrent/globals.h> 0014 #include <util/log.h> 0015 0016 using namespace bt; 0017 0018 namespace dht 0019 { 0020 NodeLookup::NodeLookup(const dht::Key &key, RPCServer *rpc, Node *node, QObject *parent) 0021 : Task(rpc, node, parent) 0022 , node_id(key) 0023 , num_nodes_rsp(0) 0024 { 0025 } 0026 0027 NodeLookup::~NodeLookup() 0028 { 0029 } 0030 0031 void NodeLookup::handleNodes(const QByteArray &nodes, int ip_version) 0032 { 0033 Uint32 address_size = ip_version == 4 ? 26 : 38; 0034 Uint32 nnodes = nodes.size() / address_size; 0035 for (Uint32 j = 0; j < nnodes; j++) { 0036 // unpack an entry and add it to the todo list 0037 try { 0038 KBucketEntry e = UnpackBucketEntry(nodes, j * address_size, ip_version); 0039 // lets not talk to ourself 0040 if (e.getID() != node->getOurID() && !todo.contains(e) && !visited.contains(e)) 0041 todo.insert(e); 0042 } catch (...) { 0043 // bad data, just ignore it 0044 } 0045 } 0046 } 0047 0048 void NodeLookup::callFinished(RPCCall *, RPCMsg::Ptr rsp) 0049 { 0050 // Out(SYS_DHT|LOG_DEBUG) << "NodeLookup::callFinished" << endl; 0051 if (isFinished()) 0052 return; 0053 0054 // check the response and see if it is a good one 0055 if (rsp->getMethod() == dht::FIND_NODE && rsp->getType() == dht::RSP_MSG) { 0056 FindNodeRsp::Ptr fnr = rsp.dynamicCast<FindNodeRsp>(); 0057 if (!fnr) 0058 return; 0059 0060 const QByteArray &nodes = fnr->getNodes(); 0061 if (nodes.size() > 0) 0062 handleNodes(nodes, 4); 0063 0064 const QByteArray &nodes6 = fnr->getNodes6(); 0065 if (nodes6.size() > 0) 0066 handleNodes(nodes6, 6); 0067 num_nodes_rsp++; 0068 } 0069 } 0070 0071 void NodeLookup::callTimeout(RPCCall *) 0072 { 0073 // Out(SYS_DHT|LOG_DEBUG) << "NodeLookup::callTimeout" << endl; 0074 } 0075 0076 void NodeLookup::update() 0077 { 0078 // Out(SYS_DHT|LOG_DEBUG) << "NodeLookup::update" << endl; 0079 // Out(SYS_DHT|LOG_DEBUG) << "todo = " << todo.count() << " ; visited = " << visited.count() << endl; 0080 // go over the todo list and send find node calls 0081 // until we have nothing left 0082 while (!todo.empty() && canDoRequest()) { 0083 KBucketEntrySet::iterator itr = todo.begin(); 0084 // only send a findNode if we haven't allrready visited the node 0085 if (!visited.contains(*itr)) { 0086 // send a findNode to the node 0087 RPCMsg::Ptr fnr(new FindNodeReq(node->getOurID(), node_id)); 0088 fnr->setOrigin(itr->getAddress()); 0089 rpcCall(fnr); 0090 visited.insert(*itr); 0091 } 0092 // remove the entry from the todo list 0093 todo.erase(itr); 0094 } 0095 0096 if (todo.empty() && getNumOutstandingRequests() == 0 && !isFinished()) { 0097 Out(SYS_DHT | LOG_NOTICE) << "DHT: NodeLookup done" << endl; 0098 done(); 0099 } else if (visited.size() > 200) { 0100 // don't let the task run forever 0101 Out(SYS_DHT | LOG_NOTICE) << "DHT: NodeLookup done" << endl; 0102 done(); 0103 } 0104 } 0105 }