/* */ #include "ActivePeerConnectionCommand.h" #include "PeerInitiateConnectionCommand.h" #include "message.h" #include "DownloadEngine.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "BtRuntime.h" #include "Peer.h" #include "Logger.h" #include "LogFactory.h" #include "prefs.h" #include "Option.h" #include "BtConstants.h" #include "SocketCore.h" #include "BtAnnounce.h" #include "RequestGroup.h" #include "DownloadContext.h" #include "bittorrent_helper.h" #include "wallclock.h" #include "util.h" #include "fmt.h" namespace aria2 { ActivePeerConnectionCommand::ActivePeerConnectionCommand (cuid_t cuid, RequestGroup* requestGroup, DownloadEngine* e, time_t interval) : Command(cuid), requestGroup_(requestGroup), interval_(interval), e_(e), numNewConnection_(5) { requestGroup_->increaseNumCommand(); } ActivePeerConnectionCommand::~ActivePeerConnectionCommand() { requestGroup_->decreaseNumCommand(); } bool ActivePeerConnectionCommand::execute() { if(btRuntime_->isHalt()) { return true; } if(checkPoint_.difference(global::wallclock()) >= interval_) { checkPoint_ = global::wallclock(); NetStat& stat = requestGroup_->getDownloadContext()->getNetStat(); const int maxDownloadLimit = requestGroup_->getMaxDownloadSpeedLimit(); const int maxUploadLimit = requestGroup_->getMaxUploadSpeedLimit(); int thresholdSpeed; if(!bittorrent::getTorrentAttrs (requestGroup_->getDownloadContext())->metadata.empty()) { thresholdSpeed = requestGroup_->getOption()->getAsInt(PREF_BT_REQUEST_PEER_SPEED_LIMIT); } else { thresholdSpeed = 0; } if(maxDownloadLimit > 0) { thresholdSpeed = std::min(maxDownloadLimit, thresholdSpeed); } if(// for seeder state (pieceStorage_->downloadFinished() && btRuntime_->lessThanMaxPeers() && (maxUploadLimit == 0 || stat.calculateUploadSpeed() < maxUploadLimit*0.8)) || // for leecher state (!pieceStorage_->downloadFinished() && (stat.calculateDownloadSpeed() < thresholdSpeed || btRuntime_->lessThanMinPeers()))) { int numConnection = 0; if(pieceStorage_->downloadFinished()) { if(btRuntime_->getMaxPeers() > btRuntime_->getConnections()) { numConnection = std::min(numNewConnection_, btRuntime_->getMaxPeers()-btRuntime_->getConnections()); } } else { numConnection = numNewConnection_; } makeNewConnections(numConnection); if(btRuntime_->getConnections() == 0 && !pieceStorage_->downloadFinished()) { btAnnounce_->overrideMinInterval(BtAnnounce::DEFAULT_ANNOUNCE_INTERVAL); } } } e_->addCommand(std::unique_ptr(this)); return false; } void ActivePeerConnectionCommand::makeNewConnections(int num) { for(; num && peerStorage_->isPeerAvailable(); --num) { cuid_t ncuid = e_->newCUID(); std::shared_ptr peer = peerStorage_->checkoutPeer(ncuid); // sanity check if(!peer) { break; } auto command = make_unique (ncuid, requestGroup_, peer, e_, btRuntime_); command->setPeerStorage(peerStorage_); command->setPieceStorage(pieceStorage_); e_->addCommand(std::move(command)); A2_LOG_INFO(fmt(MSG_CONNECTING_TO_PEER, getCuid(), peer->getIPAddress().c_str())); } } void ActivePeerConnectionCommand::setBtRuntime (const std::shared_ptr& btRuntime) { btRuntime_ = btRuntime; } void ActivePeerConnectionCommand::setPieceStorage (const std::shared_ptr& pieceStorage) { pieceStorage_ = pieceStorage; } void ActivePeerConnectionCommand::setPeerStorage (const std::shared_ptr& peerStorage) { peerStorage_ = peerStorage; } void ActivePeerConnectionCommand::setBtAnnounce (const std::shared_ptr& btAnnounce) { btAnnounce_ = btAnnounce; } } // namespace aria2