/* */ #include "UTPexExtensionMessage.h" #include "Peer.h" #include "Util.h" #include "PeerMessageUtil.h" #include "PeerStorage.h" #include "PeerListProcessor.h" #include "DlAbortEx.h" #include "message.h" #include "StringFormat.h" #include "bencode.h" namespace aria2 { const std::string UTPexExtensionMessage::EXTENSION_NAME = "ut_pex"; UTPexExtensionMessage::UTPexExtensionMessage(uint8_t extensionMessageID): _extensionMessageID(extensionMessageID), _interval(DEFAULT_INTERVAL), _maxFreshPeer(DEFAULT_MAX_FRESH_PEER), _maxDroppedPeer(DEFAULT_MAX_DROPPED_PEER) {} UTPexExtensionMessage::~UTPexExtensionMessage() {} std::string UTPexExtensionMessage::getBencodedData() { std::pair freshPeerPair = createCompactPeerListAndFlag(_freshPeers); std::pair droppedPeerPair = createCompactPeerListAndFlag(_droppedPeers); BDE dict = BDE::dict(); dict["added"] = freshPeerPair.first; dict["added.f"] = freshPeerPair.second; dict["dropped"] = droppedPeerPair.first; return bencode::encode(dict); } std::pair UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers) { std::string addrstring; std::string flagstring; for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); ++itr) { unsigned char compact[6]; if(PeerMessageUtil::createcompact(compact, (*itr)->ipaddr, (*itr)->port)) { addrstring.append(&compact[0], &compact[6]); flagstring += (*itr)->isSeeder() ? "2" : "0"; } } return std::pair(addrstring, flagstring); } std::string UTPexExtensionMessage::toString() const { return "ut_pex added="+Util::uitos(_freshPeers.size())+", dropped="+ Util::uitos(_droppedPeers.size()); } void UTPexExtensionMessage::doReceivedAction() { _peerStorage->addPeer(_freshPeers); } bool UTPexExtensionMessage::addFreshPeer(const PeerHandle& peer) { if(!peer->isIncomingPeer() && !peer->getFirstContactTime().elapsed(_interval)) { _freshPeers.push_back(peer); return true; } else { return false; } } bool UTPexExtensionMessage::freshPeersAreFull() const { return _freshPeers.size() >= _maxFreshPeer; } bool UTPexExtensionMessage::addDroppedPeer(const PeerHandle& peer) { if(!peer->isIncomingPeer() && !peer->getBadConditionStartTime().elapsed(_interval)) { _droppedPeers.push_back(peer); return true; } else { return false; } } bool UTPexExtensionMessage::droppedPeersAreFull() const { return _droppedPeers.size() >= _maxDroppedPeer; } void UTPexExtensionMessage::setMaxFreshPeer(size_t maxFreshPeer) { _maxFreshPeer = maxFreshPeer; } void UTPexExtensionMessage::setMaxDroppedPeer(size_t maxDroppedPeer) { _maxDroppedPeer = maxDroppedPeer; } void UTPexExtensionMessage::setPeerStorage (const SharedHandle& peerStorage) { _peerStorage = peerStorage; } UTPexExtensionMessageHandle UTPexExtensionMessage::create(const unsigned char* data, size_t len) { if(len < 1) { throw DL_ABORT_EX(StringFormat(MSG_TOO_SMALL_PAYLOAD_SIZE, EXTENSION_NAME.c_str(), len).str()); } UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data)); const BDE dict = bencode::decode(data+1, len-1); if(dict.isDict()) { PeerListProcessor proc; const BDE& added = dict["added"]; if(added.isString()) { proc.extractPeerFromCompact(added, std::back_inserter(msg->_freshPeers)); } const BDE& dropped = dict["dropped"]; if(dropped.isString()) { proc.extractPeerFromCompact(dropped, std::back_inserter(msg->_droppedPeers)); } } return msg; } } // namespace aria2