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"