File indexing completed on 2024-06-02 05:05:14

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "dhtpeersource.h"
0007 #include "announcetask.h"
0008 #include "dht.h"
0009 #include <QHostAddress>
0010 #include <interfaces/torrentinterface.h>
0011 #include <torrent/globals.h>
0012 #include <torrent/server.h>
0013 #include <util/functions.h>
0014 #include <util/log.h>
0015 
0016 using namespace bt;
0017 
0018 namespace dht
0019 {
0020 DHTPeerSource::DHTPeerSource(DHTBase &dh_table, const bt::SHA1Hash &info_hash, const QString &torrent_name)
0021     : dh_table(dh_table)
0022     , curr_task(nullptr)
0023     , info_hash(info_hash)
0024     , torrent_name(torrent_name)
0025 {
0026     connect(&timer, &QTimer::timeout, this, &DHTPeerSource::onTimeout);
0027     connect(&dh_table, &DHTBase::started, this, &DHTPeerSource::manualUpdate);
0028     connect(&dh_table, &DHTBase::stopped, this, &DHTPeerSource::dhtStopped);
0029     started = false;
0030     timer.setSingleShot(true);
0031     request_interval = 5 * 60 * 1000;
0032 }
0033 
0034 DHTPeerSource::~DHTPeerSource()
0035 {
0036     if (curr_task)
0037         curr_task->kill();
0038 }
0039 
0040 void DHTPeerSource::start()
0041 {
0042     started = true;
0043     if (dh_table.isRunning())
0044         doRequest();
0045 }
0046 
0047 void DHTPeerSource::dhtStopped()
0048 {
0049     stop(nullptr);
0050     curr_task = nullptr;
0051 }
0052 
0053 void DHTPeerSource::stop(bt::WaitJob *)
0054 {
0055     started = false;
0056     if (curr_task) {
0057         curr_task->kill();
0058         timer.stop();
0059     }
0060 }
0061 
0062 void DHTPeerSource::manualUpdate()
0063 {
0064     if (dh_table.isRunning() && started)
0065         doRequest();
0066 }
0067 
0068 bool DHTPeerSource::doRequest()
0069 {
0070     if (!dh_table.isRunning())
0071         return false;
0072 
0073     if (curr_task)
0074         return true;
0075 
0076     Uint16 port = ServerInterface::getPort();
0077     curr_task = dh_table.announce(info_hash, port);
0078     if (curr_task) {
0079         for (const bt::DHTNode &n : std::as_const(nodes))
0080             curr_task->addDHTNode(n.ip, n.port);
0081 
0082         connect(curr_task, &AnnounceTask::dataReady, this, &DHTPeerSource::onDataReady);
0083         connect(curr_task, &AnnounceTask::finished, this, &DHTPeerSource::onFinished);
0084         return true;
0085     }
0086 
0087     return false;
0088 }
0089 
0090 void DHTPeerSource::onFinished(Task *t)
0091 {
0092     if (curr_task == t) {
0093         onDataReady(curr_task);
0094         curr_task = nullptr;
0095         timer.start(request_interval);
0096     }
0097 }
0098 
0099 void DHTPeerSource::onDataReady(Task *t)
0100 {
0101     if (curr_task == t) {
0102         Uint32 cnt = 0;
0103         DBItem item;
0104         while (curr_task->takeItem(item)) {
0105             const net::Address &addr = item.getAddress();
0106             /*  Out(SYS_DHT|LOG_NOTICE) <<
0107                         QString("DHT: Got potential peer %1 for torrent %2")
0108                         .arg(addr.toString()).arg(tor->getStats().torrent_name) << endl;*/
0109             addPeer(addr, false);
0110             cnt++;
0111         }
0112 
0113         if (cnt) {
0114             Out(SYS_DHT | LOG_NOTICE) << QString("DHT: Got %1 potential peers for torrent %2").arg(cnt).arg(torrent_name) << endl;
0115             peersReady(this);
0116         }
0117     }
0118 }
0119 
0120 void DHTPeerSource::onTimeout()
0121 {
0122     if (dh_table.isRunning() && started)
0123         doRequest();
0124 }
0125 
0126 void DHTPeerSource::addDHTNode(const bt::DHTNode &node)
0127 {
0128     nodes.append(node);
0129 }
0130 
0131 void DHTPeerSource::setRequestInterval(Uint32 interval)
0132 {
0133     request_interval = interval;
0134 }
0135 
0136 }