File indexing completed on 2025-01-05 04:37:23

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "peermanager.h"
0007 
0008 #include <QDateTime>
0009 #include <QFile>
0010 #include <QList>
0011 #include <QSet>
0012 #include <QTextStream>
0013 #include <QtAlgorithms>
0014 #include <klocalizedstring.h>
0015 
0016 #include "authenticate.h"
0017 #include "authenticationmonitor.h"
0018 #include "chunkcounter.h"
0019 #include "connectionlimit.h"
0020 #include "peer.h"
0021 #include "peerconnector.h"
0022 #include <dht/dhtbase.h>
0023 #include <mse/encryptedauthenticate.h>
0024 #include <mse/encryptedpacketsocket.h>
0025 #include <net/address.h>
0026 #include <peer/accessmanager.h>
0027 #include <peer/peer.h>
0028 #include <peer/peerid.h>
0029 #include <torrent/globals.h>
0030 #include <torrent/server.h>
0031 #include <torrent/torrent.h>
0032 #include <util/bitset.h>
0033 #include <util/error.h>
0034 #include <util/file.h>
0035 #include <util/functions.h>
0036 #include <util/log.h>
0037 #include <util/ptrmap.h>
0038 
0039 using namespace KNetwork;
0040 
0041 namespace bt
0042 {
0043 typedef std::map<net::Address, bool>::iterator PPItr;
0044 typedef QMap<Uint32, Peer::Ptr> PeerMap;
0045 
0046 static ConnectionLimit climit;
0047 
0048 class PeerManager::Private
0049 {
0050 public:
0051     Private(PeerManager *p, Torrent &tor);
0052     ~Private();
0053 
0054     void updateAvailableChunks();
0055     bool killBadPeer();
0056     void createPeer(mse::EncryptedPacketSocket::Ptr sock, const PeerID &peer_id, Uint32 support, bool local, ConnectionLimit::Token::Ptr token);
0057     bool connectedTo(const net::Address &addr) const;
0058     void update();
0059     void have(Peer *peer, Uint32 index);
0060     void connectToPeers();
0061 
0062 public:
0063     PeerManager *p;
0064     QMap<Uint32, Peer::Ptr> peer_map;
0065     Torrent &tor;
0066     bool started;
0067     BitSet available_chunks, wanted_chunks;
0068     ChunkCounter cnt;
0069     bool pex_on;
0070     bool wanted_changed;
0071     PieceHandler *piece_handler;
0072     bool paused;
0073     QSet<PeerConnector::Ptr> connectors;
0074     QScopedPointer<SuperSeeder> superseeder;
0075     std::map<net::Address, bool> potential_peers;
0076     bool partial_seed;
0077     Uint32 num_cleared;
0078 };
0079 
0080 PeerManager::PeerManager(Torrent &tor)
0081     : d(new Private(this, tor))
0082 {
0083 }
0084 
0085 PeerManager::~PeerManager()
0086 {
0087     delete d;
0088 }
0089 
0090 ConnectionLimit &PeerManager::connectionLimits()
0091 {
0092     return climit;
0093 }
0094 
0095 void PeerManager::pause()
0096 {
0097     if (d->paused)
0098         return;
0099 
0100     for (Peer::Ptr p : std::as_const(d->peer_map)) {
0101         p->pause();
0102     }
0103     d->paused = true;
0104 }
0105 
0106 void PeerManager::unpause()
0107 {
0108     if (!d->paused)
0109         return;
0110 
0111     for (Peer::Ptr p : std::as_const(d->peer_map)) {
0112         p->unpause();
0113         if (p->hasWantedChunks(d->wanted_chunks)) // send interested when it has wanted chunks
0114             p->sendInterested();
0115     }
0116     d->paused = false;
0117 }
0118 
0119 void PeerManager::update()
0120 {
0121     d->update();
0122 }
0123 
0124 #if 0
0125 
0126 void PeerManager::setMaxTotalConnections(Uint32 max)
0127 {
0128 #ifndef Q_WS_WIN
0129     Uint32 sys_max = bt::MaxOpenFiles() - 50; // leave about 50 free for regular files
0130 #else
0131     Uint32 sys_max = 9999; // there isn't a real limit on windows
0132 #endif
0133     max_total_connections = max;
0134     if (max == 0 || max_total_connections > sys_max)
0135         max_total_connections = sys_max;
0136 }
0137 #endif
0138 
0139 void PeerManager::setWantedChunks(const BitSet &bs)
0140 {
0141     d->wanted_chunks = bs;
0142     d->wanted_changed = true;
0143 }
0144 
0145 void PeerManager::addPotentialPeer(const net::Address &addr, bool local)
0146 {
0147     if (d->potential_peers.size() < 500) {
0148         d->potential_peers[addr] = local;
0149     }
0150 }
0151 
0152 void PeerManager::killSeeders()
0153 {
0154     for (Peer::Ptr peer : std::as_const(d->peer_map)) {
0155         if (peer->isSeeder())
0156             peer->kill();
0157     }
0158 }
0159 
0160 void PeerManager::killUninterested()
0161 {
0162     QTime now = QTime::currentTime();
0163     for (Peer::Ptr peer : std::as_const(d->peer_map)) {
0164         if (!peer->isInterested() && (peer->getConnectTime().secsTo(now) > 30))
0165             peer->kill();
0166     }
0167 }
0168 
0169 void PeerManager::have(Peer *p, Uint32 index)
0170 {
0171     d->have(p, index);
0172 }
0173 
0174 void PeerManager::bitSetReceived(Peer *p, const BitSet &bs)
0175 {
0176     bool interested = false;
0177     for (Uint32 i = 0; i < bs.getNumBits(); i++) {
0178         if (bs.get(i)) {
0179             if (d->wanted_chunks.get(i))
0180                 interested = true;
0181             d->available_chunks.set(i, true);
0182             d->cnt.inc(i);
0183         }
0184     }
0185 
0186     if (interested && !d->paused)
0187         p->sendInterested();
0188 
0189     if (d->superseeder)
0190         d->superseeder->bitset(p, bs);
0191 }
0192 
0193 void PeerManager::newConnection(mse::EncryptedPacketSocket::Ptr sock, const PeerID &peer_id, Uint32 support)
0194 {
0195     if (!d->started)
0196         return;
0197 
0198     ConnectionLimit::Token::Ptr token = climit.acquire(d->tor.getInfoHash());
0199     if (!token) {
0200         d->killBadPeer();
0201         token = climit.acquire(d->tor.getInfoHash());
0202     }
0203 
0204     if (token)
0205         d->createPeer(sock, peer_id, support, false, token);
0206 }
0207 
0208 void PeerManager::peerAuthenticated(bt::Authenticate *auth, bt::PeerConnector::WPtr pcon, bool ok, bt::ConnectionLimit::Token::Ptr token)
0209 {
0210     if (d->started) {
0211         if (ok && !connectedTo(auth->getPeerID()))
0212             d->createPeer(auth->getSocket(), auth->getPeerID(), auth->supportedExtensions(), auth->isLocal(), token);
0213     }
0214 
0215     PeerConnector::Ptr ptr = pcon.toStrongRef();
0216     d->connectors.remove(ptr);
0217 }
0218 
0219 bool PeerManager::connectedTo(const PeerID &peer_id)
0220 {
0221     if (!d->started)
0222         return false;
0223 
0224     for (const Peer::Ptr &p : std::as_const(d->peer_map)) {
0225         if (p->getPeerID() == peer_id)
0226             return true;
0227     }
0228     return false;
0229 }
0230 
0231 void PeerManager::closeAllConnections()
0232 {
0233     d->peer_map.clear();
0234 }
0235 
0236 void PeerManager::savePeerList(const QString &file)
0237 {
0238     // Lets save the entries line based
0239     QFile fptr(file);
0240     if (!fptr.open(QIODevice::WriteOnly))
0241         return;
0242 
0243     try {
0244         Out(SYS_GEN | LOG_DEBUG) << "Saving list of peers to " << file << endl;
0245 
0246         QTextStream out(&fptr);
0247         // first the active peers
0248         for (const Peer::Ptr &p : std::as_const(d->peer_map)) {
0249             const net::Address &addr = p->getAddress();
0250             out << addr.toString() << " " << (unsigned short)addr.port() << Qt::endl;
0251         }
0252 
0253         // now the potential_peers
0254         std::map<net::Address, bool>::const_iterator i = d->potential_peers.cbegin();
0255         while (i != d->potential_peers.cend()) {
0256             out << i->first.toString() << " " << i->first.port() << Qt::endl;
0257             ++i;
0258         }
0259     } catch (bt::Error &err) {
0260         Out(SYS_GEN | LOG_DEBUG) << "Error happened during saving of peer list : " << err.toString() << endl;
0261     }
0262 }
0263 
0264 void PeerManager::loadPeerList(const QString &file)
0265 {
0266     QFile fptr(file);
0267     if (!fptr.open(QIODevice::ReadOnly))
0268         return;
0269 
0270     try {
0271         Out(SYS_GEN | LOG_DEBUG) << "Loading list of peers from " << file << endl;
0272 
0273         while (!fptr.atEnd()) {
0274             QStringList sl = QString(fptr.readLine()).split(" ");
0275             if (sl.count() != 2)
0276                 continue;
0277 
0278             bool ok = false;
0279             net::Address addr(sl[0], sl[1].toInt(&ok));
0280             if (ok)
0281                 addPotentialPeer(addr, false);
0282         }
0283     } catch (bt::Error &err) {
0284         Out(SYS_GEN | LOG_DEBUG) << "Error happened during saving of peer list : " << err.toString() << endl;
0285     }
0286 }
0287 
0288 void PeerManager::start(bool superseed)
0289 {
0290     d->started = true;
0291     if (superseed && !d->superseeder)
0292         d->superseeder.reset(new SuperSeeder(d->cnt.getNumChunks()));
0293 
0294     unpause();
0295     ServerInterface::addPeerManager(this);
0296 }
0297 
0298 void PeerManager::stop()
0299 {
0300     d->cnt.reset();
0301     d->available_chunks.clear();
0302     d->started = false;
0303     ServerInterface::removePeerManager(this);
0304     d->connectors.clear();
0305     d->superseeder.reset();
0306     closeAllConnections();
0307 }
0308 
0309 Peer::Ptr PeerManager::findPeer(Uint32 peer_id)
0310 {
0311     PeerMap::iterator i = d->peer_map.find(peer_id);
0312     if (i == d->peer_map.end())
0313         return Peer::Ptr();
0314     else
0315         return *i;
0316 }
0317 
0318 Peer::Ptr PeerManager::findPeer(PieceDownloader *pd)
0319 {
0320     for (Peer::Ptr p : std::as_const(d->peer_map)) {
0321         if ((PieceDownloader *)p->getPeerDownloader() == pd)
0322             return p;
0323     }
0324     return Peer::Ptr();
0325 }
0326 
0327 void PeerManager::rerunChoker()
0328 {
0329     d->num_cleared++;
0330 }
0331 
0332 bool PeerManager::chokerNeedsToRun() const
0333 {
0334     return d->num_cleared > 0;
0335 }
0336 
0337 void PeerManager::peerSourceReady(PeerSource *ps)
0338 {
0339     net::Address addr;
0340     bool local = false;
0341     while (ps->takePeer(addr, local))
0342         addPotentialPeer(addr, local);
0343 }
0344 
0345 void PeerManager::pex(const QByteArray &arr)
0346 {
0347     if (!d->pex_on)
0348         return;
0349 
0350     Out(SYS_CON | LOG_NOTICE) << "PEX: found " << (arr.size() / 6) << " peers" << endl;
0351     for (int i = 0; i + 6 <= arr.size(); i += 6) {
0352         const Uint8 *tmp = (const Uint8 *)arr.data() + i;
0353         addPotentialPeer(net::Address(ReadUint32(tmp, 0), ReadUint16(tmp, 4)), false);
0354     }
0355 }
0356 
0357 void PeerManager::setPexEnabled(bool on)
0358 {
0359     if (on && d->tor.isPrivate())
0360         return;
0361 
0362     if (d->pex_on == on)
0363         return;
0364 
0365     for (Peer::Ptr p : std::as_const(d->peer_map)) {
0366         if (!p->isKilled()) {
0367             p->setPexEnabled(on);
0368             bt::Uint16 port = ServerInterface::getPort();
0369             p->sendExtProtHandshake(port, d->tor.getMetaData().size(), d->partial_seed);
0370         }
0371     }
0372     d->pex_on = on;
0373 }
0374 
0375 void PeerManager::setGroupIDs(Uint32 up, Uint32 down)
0376 {
0377     for (Peer::Ptr p : std::as_const(d->peer_map))
0378         p->setGroupIDs(up, down);
0379 }
0380 
0381 void PeerManager::portPacketReceived(const QString &ip, Uint16 port)
0382 {
0383     if (Globals::instance().getDHT().isRunning() && !d->tor.isPrivate())
0384         Globals::instance().getDHT().portReceived(ip, port);
0385 }
0386 
0387 void PeerManager::pieceReceived(const Piece &p)
0388 {
0389     if (d->piece_handler)
0390         d->piece_handler->pieceReceived(p);
0391 }
0392 
0393 void PeerManager::setPieceHandler(PieceHandler *ph)
0394 {
0395     d->piece_handler = ph;
0396 }
0397 
0398 void PeerManager::killStalePeers()
0399 {
0400     for (Peer::Ptr p : std::as_const(d->peer_map)) {
0401         if (p->getDownloadRate() == 0 && p->getUploadRate() == 0)
0402             p->kill();
0403     }
0404 }
0405 
0406 void PeerManager::setSuperSeeding(bool on, const BitSet &chunks)
0407 {
0408     Q_UNUSED(chunks);
0409     if ((d->superseeder && on) || (!d->superseeder && !on))
0410         return;
0411 
0412     d->superseeder.reset(on ? new SuperSeeder(d->cnt.getNumChunks()) : nullptr);
0413 
0414     // When entering or exiting superseeding mode kill all peers
0415     // but first add the current list to the potential_peers list, so we can reconnect later.
0416     for (Peer::Ptr p : std::as_const(d->peer_map)) {
0417         const net::Address &addr = p->getAddress();
0418         addPotentialPeer(addr, false);
0419         p->kill();
0420     }
0421 }
0422 
0423 void PeerManager::sendHave(Uint32 index)
0424 {
0425     if (d->superseeder)
0426         return;
0427 
0428     for (Peer::Ptr peer : std::as_const(d->peer_map)) {
0429         peer->sendHave(index);
0430     }
0431 }
0432 
0433 Uint32 PeerManager::getNumConnectedPeers() const
0434 {
0435     return d->peer_map.count();
0436 }
0437 
0438 Uint32 PeerManager::getNumConnectedLeechers() const
0439 {
0440     Uint32 cnt = 0;
0441     for (const Peer::Ptr &peer : std::as_const(d->peer_map)) {
0442         if (!peer->isSeeder())
0443             cnt++;
0444     }
0445 
0446     return cnt;
0447 }
0448 
0449 Uint32 PeerManager::getNumConnectedSeeders() const
0450 {
0451     Uint32 cnt = 0;
0452     for (const Peer::Ptr &peer : std::as_const(d->peer_map)) {
0453         if (peer->isSeeder())
0454             cnt++;
0455     }
0456 
0457     return cnt;
0458 }
0459 
0460 Uint32 PeerManager::getNumPending() const
0461 {
0462     return d->connectors.size();
0463 }
0464 
0465 const bt::BitSet &PeerManager::getAvailableChunksBitSet() const
0466 {
0467     return d->available_chunks;
0468 }
0469 
0470 ChunkCounter &PeerManager::getChunkCounter()
0471 {
0472     return d->cnt;
0473 }
0474 
0475 bool PeerManager::isPexEnabled() const
0476 {
0477     return d->pex_on;
0478 }
0479 
0480 const bt::Torrent &PeerManager::getTorrent() const
0481 {
0482     return d->tor;
0483 }
0484 
0485 bool PeerManager::isStarted() const
0486 {
0487     return d->started;
0488 }
0489 
0490 void PeerManager::visit(PeerManager::PeerVisitor &visitor)
0491 {
0492     for (const Peer::Ptr &p : std::as_const(d->peer_map)) {
0493         visitor.visit(p);
0494     }
0495 }
0496 
0497 Uint32 PeerManager::uploadRate() const
0498 {
0499     Uint32 rate = 0;
0500     for (const Peer::Ptr &p : std::as_const(d->peer_map)) {
0501         rate += p->getUploadRate();
0502     }
0503     return rate;
0504 }
0505 
0506 QList<Peer::Ptr> PeerManager::getPeers() const
0507 {
0508     return d->peer_map.values();
0509 }
0510 
0511 void PeerManager::setPartialSeed(bool partial_seed)
0512 {
0513     if (d->partial_seed != partial_seed) {
0514         d->partial_seed = partial_seed;
0515 
0516         // If partial seeding status changes, update all peers
0517         bt::Uint16 port = ServerInterface::getPort();
0518         for (Peer::Ptr peer : std::as_const(d->peer_map)) {
0519             peer->sendExtProtHandshake(port, d->tor.getMetaData().size(), d->partial_seed);
0520         }
0521     }
0522 }
0523 
0524 bool PeerManager::isPartialSeed() const
0525 {
0526     return d->partial_seed;
0527 }
0528 
0529 //////////////////////////////////////////////////
0530 
0531 PeerManager::Private::Private(PeerManager *p, Torrent &tor)
0532     : p(p)
0533     , tor(tor)
0534     , available_chunks(tor.getNumChunks())
0535     , wanted_chunks(tor.getNumChunks())
0536     , cnt(tor.getNumChunks())
0537     , partial_seed(false)
0538     , num_cleared(0)
0539 {
0540     started = false;
0541     wanted_chunks.setAll(true);
0542     wanted_changed = false;
0543     pex_on = !tor.isPrivate();
0544     piece_handler = nullptr;
0545     paused = false;
0546 }
0547 
0548 PeerManager::Private::~Private()
0549 {
0550     ServerInterface::removePeerManager(p);
0551     started = false;
0552     connectors.clear();
0553 }
0554 
0555 void PeerManager::Private::update()
0556 {
0557     if (!started)
0558         return;
0559 
0560     num_cleared = 0;
0561 
0562     // update the speed of each peer,
0563     // and get rid of some killed peers
0564     for (PeerMap::iterator i = peer_map.begin(); i != peer_map.end();) {
0565         Peer::Ptr peer = i.value();
0566         if (!peer->isKilled() && peer->isStalled()) {
0567             p->addPotentialPeer(peer->getAddress(), peer->getStats().local);
0568             peer->kill();
0569         }
0570 
0571         if (peer->isKilled()) {
0572             cnt.decBitSet(peer->getBitSet());
0573             updateAvailableChunks();
0574             i = peer_map.erase(i);
0575             p->peerKilled(peer.data());
0576             if (superseeder)
0577                 superseeder->peerRemoved(peer.data());
0578             num_cleared++;
0579         } else {
0580             peer->update();
0581             if (wanted_changed) {
0582                 if (peer->hasWantedChunks(wanted_chunks))
0583                     peer->sendInterested();
0584                 else
0585                     peer->sendNotInterested();
0586             }
0587             ++i;
0588         }
0589     }
0590 
0591     wanted_changed = false;
0592     connectToPeers();
0593 }
0594 
0595 void PeerManager::Private::have(Peer *peer, Uint32 index)
0596 {
0597     if (wanted_chunks.get(index) && !paused)
0598         peer->sendInterested();
0599     available_chunks.set(index, true);
0600     cnt.inc(index);
0601     if (superseeder)
0602         superseeder->have(peer, index);
0603 }
0604 
0605 void PeerManager::Private::updateAvailableChunks()
0606 {
0607     for (Uint32 i = 0; i < available_chunks.getNumBits(); i++) {
0608         available_chunks.set(i, cnt.get(i) > 0);
0609     }
0610 }
0611 
0612 bool PeerManager::Private::killBadPeer()
0613 {
0614     for (Peer::Ptr peer : std::as_const(peer_map)) {
0615         if (peer->getStats().aca_score <= -5.0 && peer->getStats().aca_score > -50.0) {
0616             Out(SYS_GEN | LOG_DEBUG) << "Killing bad peer, to make room for other peers" << endl;
0617             peer->kill();
0618             return true;
0619         }
0620     }
0621     return false;
0622 }
0623 
0624 void PeerManager::Private::createPeer(mse::EncryptedPacketSocket::Ptr sock,
0625                                       const bt::PeerID &peer_id,
0626                                       Uint32 support,
0627                                       bool local,
0628                                       bt::ConnectionLimit::Token::Ptr token)
0629 {
0630     Peer::Ptr peer(new Peer(sock, peer_id, tor.getNumChunks(), tor.getChunkSize(), support, local, token, p));
0631     peer_map.insert(peer->getID(), peer);
0632     p->newPeer(peer.data());
0633     peer->setPexEnabled(pex_on);
0634     // send extension protocol handshake
0635     bt::Uint16 port = ServerInterface::getPort();
0636     peer->sendExtProtHandshake(port, tor.getMetaData().size(), partial_seed);
0637 
0638     if (superseeder)
0639         superseeder->peerAdded(peer.data());
0640 }
0641 
0642 bool PeerManager::Private::connectedTo(const net::Address &addr) const
0643 {
0644     PeerMap::const_iterator i = peer_map.begin();
0645     while (i != peer_map.end()) {
0646         if (i.value()->getAddress() == addr)
0647             return true;
0648         ++i;
0649     }
0650     return false;
0651 }
0652 
0653 void PeerManager::Private::connectToPeers()
0654 {
0655     if (paused || potential_peers.size() == 0 || (Uint32)connectors.size() > MAX_SIMULTANIOUS_AUTHS)
0656         return;
0657 
0658     while (!potential_peers.empty()) {
0659         if ((Uint32)connectors.size() > MAX_SIMULTANIOUS_AUTHS)
0660             return;
0661 
0662         PPItr itr = potential_peers.begin();
0663 
0664         AccessManager &aman = AccessManager::instance();
0665 
0666         if (aman.allowed(itr->first) && !connectedTo(itr->first)) {
0667             ConnectionLimit::Token::Ptr token = climit.acquire(tor.getInfoHash());
0668             if (!token)
0669                 break;
0670 
0671             PeerConnector::Ptr pcon(new PeerConnector(itr->first, itr->second, p, token));
0672             pcon->setWeakPointer(PeerConnector::WPtr(pcon));
0673             connectors.insert(pcon);
0674             pcon->start();
0675         }
0676 
0677         potential_peers.erase(itr);
0678     }
0679 }
0680 
0681 }
0682 
0683 #include "moc_peermanager.cpp"