/* */ #include "UTPexExtensionMessage.h" #include "Peer.h" #include "BtContext.h" #include "Dictionary.h" #include "Data.h" #include "BencodeVisitor.h" #include "Util.h" #include "PeerMessageUtil.h" #include "BtRegistry.h" #include "PeerStorage.h" #include "CompactPeerListProcessor.h" #include "MetaFileUtil.h" #include "DlAbortEx.h" #include "message.h" namespace aria2 { const std::string UTPexExtensionMessage::EXTENSION_NAME = "ut_pex"; UTPexExtensionMessage::UTPexExtensionMessage(uint8_t extensionMessageID): _extensionMessageID(extensionMessageID), _btContext(0) {} UTPexExtensionMessage::~UTPexExtensionMessage() {} std::string UTPexExtensionMessage::getBencodedData() { SharedHandle d = new Dictionary(); std::pair freshPeerPair = createCompactPeerListAndFlag(_freshPeers); std::pair droppedPeerPair = createCompactPeerListAndFlag(_droppedPeers); d->put("added", new Data(freshPeerPair.first)); d->put("added.f", new Data(freshPeerPair.second)); d->put("dropped", new Data(droppedPeerPair.first)); BencodeVisitor v; d->accept(&v); return v.getBencodedData(); } 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() { PEER_STORAGE(_btContext)->addPeer(_freshPeers); } void UTPexExtensionMessage::addFreshPeer(const PeerHandle& peer) { _freshPeers.push_back(peer); } const Peers& UTPexExtensionMessage::getFreshPeers() const { return _freshPeers; } void UTPexExtensionMessage::addDroppedPeer(const PeerHandle& peer) { _droppedPeers.push_back(peer); } const Peers& UTPexExtensionMessage::getDroppedPeers() const { return _droppedPeers; } void UTPexExtensionMessage::setBtContext(const BtContextHandle& btContext) { _btContext = btContext; } UTPexExtensionMessageHandle UTPexExtensionMessage::create(const BtContextHandle& btContext, const unsigned char* data, size_t len) { if(len < 1) { throw new DlAbortEx(MSG_TOO_SMALL_PAYLOAD_SIZE, EXTENSION_NAME.c_str(), len); } UTPexExtensionMessageHandle msg = new UTPexExtensionMessage(*data); SharedHandle root = MetaFileUtil::bdecoding(data+1, len-1); if(root.isNull()) { return msg; } const Dictionary* d = dynamic_cast(root.get()); if(d) { CompactPeerListProcessor proc(btContext->getPieceLength(), btContext->getTotalLength()); const Data* added = dynamic_cast(d->get("added")); if(added) { msg->_freshPeers = proc.extractPeer(added); } const Data* dropped = dynamic_cast(d->get("dropped")); if(dropped) { msg->_droppedPeers = proc.extractPeer(dropped); } } return msg; } } // namespace aria2