/* */ #include "DHTMessageReceiver.h" #include "DHTMessageTracker.h" #include "DHTConnection.h" #include "DHTMessage.h" #include "DHTMessageFactory.h" #include "DHTRoutingTable.h" #include "DHTNode.h" #include "DHTMessageCallback.h" #include "Dictionary.h" #include "Data.h" #include "MetaFileUtil.h" #include "DlAbortEx.h" #include "LogFactory.h" #include "Logger.h" #include "Util.h" #include namespace aria2 { DHTMessageReceiver::DHTMessageReceiver(const SharedHandle& tracker): _tracker(tracker), _connection(0), _factory(0), _routingTable(0), _logger(LogFactory::getInstance()) {} DHTMessageReceiver::~DHTMessageReceiver() {} SharedHandle DHTMessageReceiver::receiveMessage() { std::string remoteAddr; uint16_t remotePort; unsigned char data[64*1024]; ssize_t length = _connection->receiveMessage(data, sizeof(data), remoteAddr, remotePort); if(length <= 0) { return 0; } try { bool isReply = false; MetaEntryHandle msgroot = MetaFileUtil::bdecoding(data, length); const Dictionary* d = dynamic_cast(msgroot.get()); if(d) { const Data* y = dynamic_cast(d->get("y")); if(y) { if(y->toString() == "r" || y->toString() == "e") { isReply = true; } } else { _logger->info("Malformed DHT message. Missing 'y' key. From:%s:%u", remoteAddr.c_str(), remotePort); return handleUnknownMessage(data, sizeof(data), remoteAddr, remotePort); } } else { _logger->info("Malformed DHT message. This is not a bencoded directory. From:%s:%u", remoteAddr.c_str(), remotePort); return handleUnknownMessage(data, sizeof(data), remoteAddr, remotePort); } SharedHandle message = 0; SharedHandle callback = 0; if(isReply) { std::pair, SharedHandle > p = _tracker->messageArrived(d, remoteAddr, remotePort); message = p.first; callback = p.second; if(message.isNull()) { // timeout or malicious? message return handleUnknownMessage(data, sizeof(data), remoteAddr, remotePort); } } else { message = _factory->createQueryMessage(d, remoteAddr, remotePort); } _logger->info("Message received: %s", message->toString().c_str()); message->validate(); message->doReceivedAction(); message->getRemoteNode()->markGood(); message->getRemoteNode()->updateLastContact(); _routingTable->addGoodNode(message->getRemoteNode()); if(!callback.isNull()) { callback->onReceived(message); } return message; } catch(RecoverableException* e) { _logger->info("Exception thrown while receiving DHT message.", e); delete e; return handleUnknownMessage(data, sizeof(data), remoteAddr, remotePort); } } void DHTMessageReceiver::handleTimeout() { _tracker->handleTimeout(); } SharedHandle DHTMessageReceiver::handleUnknownMessage(const unsigned char* data, size_t length, const std::string& remoteAddr, uint16_t remotePort) { SharedHandle m = _factory->createUnknownMessage(data, length, remoteAddr, remotePort); _logger->info("Message received: %s", m->toString().c_str()); return m; } SharedHandle DHTMessageReceiver::getConnection() const { return _connection; } SharedHandle DHTMessageReceiver::getMessageTracker() const { return _tracker; } void DHTMessageReceiver::setConnection(const SharedHandle& connection) { _connection = connection; } void DHTMessageReceiver::setMessageFactory(const SharedHandle& factory) { _factory = factory; } void DHTMessageReceiver::setRoutingTable(const SharedHandle& routingTable) { _routingTable = routingTable; } } // namespace aria2