/* */ #include "HandshakeExtensionMessage.h" #include "Peer.h" #include "BtContext.h" #include "Dictionary.h" #include "Data.h" #include "Util.h" #include "BencodeVisitor.h" #include "MetaFileUtil.h" #include "DlAbortEx.h" #include "LogFactory.h" #include "Logger.h" #include "message.h" #include "StringFormat.h" namespace aria2 { const std::string HandshakeExtensionMessage::EXTENSION_NAME = "handshake"; HandshakeExtensionMessage::HandshakeExtensionMessage(): _tcpPort(0), _logger(LogFactory::getInstance()) {} HandshakeExtensionMessage::~HandshakeExtensionMessage() {} std::string HandshakeExtensionMessage::getBencodedData() { SharedHandle dic(new Dictionary()); if(!_clientVersion.empty()) { Data* v = new Data(_clientVersion); dic->put("v", v); } if(_tcpPort > 0) { std::string portStr = Util::uitos(_tcpPort); Data* p = new Data(portStr, true); dic->put("p", p); } Dictionary* exts = new Dictionary(); dic->put("m", exts); for(std::map::const_iterator itr = _extensions.begin(); itr != _extensions.end(); ++itr) { const std::map::value_type& vt = *itr; std::string idStr = Util::uitos(vt.second); exts->put(vt.first, new Data(idStr, true)); } BencodeVisitor v; dic->accept(&v); return v.getBencodedData(); } std::string HandshakeExtensionMessage::toString() const { std::string s = getExtensionName(); if(!_clientVersion.empty()) { s += " client="+Util::urlencode(_clientVersion); } if(_tcpPort > 0) { s += ", tcpPort="+Util::uitos(_tcpPort); } for(std::map::const_iterator itr = _extensions.begin(); itr != _extensions.end(); ++itr) { const std::map::value_type& vt = *itr; s += ", "+vt.first+"="+Util::uitos(vt.second); } return s; } void HandshakeExtensionMessage::doReceivedAction() { if(_tcpPort > 0) { _peer->port = _tcpPort; _peer->setIncomingPeer(false); } for(std::map::const_iterator itr = _extensions.begin(); itr != _extensions.end(); ++itr) { const std::map::value_type& vt = *itr; _peer->setExtension(vt.first, vt.second); } } void HandshakeExtensionMessage::setPeer(const PeerHandle& peer) { _peer = peer; } void HandshakeExtensionMessage::setBtContext(const BtContextHandle& btContext) { _btContext = btContext; } uint8_t HandshakeExtensionMessage::getExtensionMessageID(const std::string& name) const { std::map::const_iterator i = _extensions.find(name); if(i == _extensions.end()) { return 0; } else { return (*i).second; } } HandshakeExtensionMessageHandle HandshakeExtensionMessage::create(const unsigned char* data, size_t length) { if(length < 1) { throw DlAbortEx (StringFormat(MSG_TOO_SMALL_PAYLOAD_SIZE, EXTENSION_NAME.c_str(), length).str()); } HandshakeExtensionMessageHandle msg(new HandshakeExtensionMessage()); msg->_logger->debug("Creating HandshakeExtensionMessage from %s", Util::urlencode(data, length).c_str()); SharedHandle root(MetaFileUtil::bdecoding(data+1, length-1)); Dictionary* d = dynamic_cast(root.get()); if(d == 0) { throw DlAbortEx("Unexpected payload format for extended message handshake"); } const Data* p = dynamic_cast(d->get("p")); if(p) { msg->_tcpPort = p->toInt(); } const Data* v = dynamic_cast(d->get("v")); if(v) { msg->_clientVersion = v->toString(); } const Dictionary* m = dynamic_cast(d->get("m")); if(m) { const std::deque& order = m->getOrder(); for(std::deque::const_iterator i = order.begin(); i != order.end(); ++i) { const Data* e = dynamic_cast(m->get(*i)); if(e) { msg->_extensions[*i] = e->toInt(); } } } return msg; } } // namespace aria2