diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2008-12-14 05:46:45 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2008-12-14 05:46:45 +0000 |
| commit | 9202fe23c8113cd02c77a2b1132372b1d0601190 (patch) | |
| tree | 322fd603b573504fb4a2d472705887a33074b4da /src/DHTMessageFactoryImpl.cc | |
| parent | 057132cd5f03294433648c5f794b43c57fd62375 (diff) | |
2008-12-14 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Use BDE instead of Dictionary/List/Data.
* src/DHTAbstractMessage.cc
* src/DHTAbstractMessage.h
* src/DHTAnnouncePeerMessage.cc
* src/DHTAnnouncePeerMessage.h
* src/DHTAnnouncePeerReplyMessage.cc
* src/DHTAnnouncePeerReplyMessage.h
* src/DHTFindNodeMessage.cc
* src/DHTFindNodeMessage.h
* src/DHTFindNodeReplyMessage.cc
* src/DHTFindNodeReplyMessage.h
* src/DHTGetPeersMessage.cc
* src/DHTGetPeersMessage.h
* src/DHTGetPeersReplyMessage.cc
* src/DHTGetPeersReplyMessage.h
* src/DHTMessageFactory.h
* src/DHTMessageFactoryImpl.cc
* src/DHTMessageFactoryImpl.h
* src/DHTMessageReceiver.cc
* src/DHTMessageTracker.cc
* src/DHTMessageTracker.h
* src/DHTPingMessage.cc
* src/DHTPingMessage.h
* src/DHTPingReplyMessage.cc
* src/DHTPingReplyMessage.h
* src/DHTQueryMessage.cc
* src/DHTQueryMessage.h
* src/DHTResponseMessage.cc
* src/DHTResponseMessage.h
* test/DHTAnnouncePeerMessageTest.cc
* test/DHTAnnouncePeerReplyMessageTest.cc
* test/DHTFindNodeMessageTest.cc
* test/DHTFindNodeReplyMessageTest.cc
* test/DHTGetPeersMessageTest.cc
* test/DHTGetPeersReplyMessageTest.cc
* test/DHTMessageFactoryImplTest.cc
* test/DHTMessageTrackerTest.cc
* test/DHTPingMessageTest.cc
* test/DHTPingReplyMessageTest.cc
* test/MockDHTMessageFactory.h
Diffstat (limited to 'src/DHTMessageFactoryImpl.cc')
| -rw-r--r-- | src/DHTMessageFactoryImpl.cc | 248 |
1 files changed, 142 insertions, 106 deletions
diff --git a/src/DHTMessageFactoryImpl.cc b/src/DHTMessageFactoryImpl.cc index f1985335..80845a43 100644 --- a/src/DHTMessageFactoryImpl.cc +++ b/src/DHTMessageFactoryImpl.cc @@ -39,9 +39,6 @@ #include "LogFactory.h" #include "DlAbortEx.h" -#include "Data.h" -#include "Dictionary.h" -#include "List.h" #include "DHTNode.h" #include "DHTRoutingTable.h" #include "DHTPingMessage.h" @@ -64,6 +61,7 @@ #include "Peer.h" #include "Logger.h" #include "StringFormat.h" +#include "bencode.h" namespace aria2 { @@ -84,10 +82,23 @@ DHTMessageFactoryImpl::getRemoteNode(const unsigned char* id, const std::string& return node; } -static const Dictionary* getDictionary(const Dictionary* d, const std::string& key) +static const bencode::BDE& getDictionary(const bencode::BDE& dict, + const std::string& key) { - const Dictionary* c = dynamic_cast<const Dictionary*>(d->get(key)); - if(c) { + const bencode::BDE& d = dict[key]; + if(d.isDict()) { + return d; + } else { + throw DlAbortEx + (StringFormat("Malformed DHT message. Missing %s", key.c_str()).str()); + } +} + +static const bencode::BDE& getString(const bencode::BDE& dict, + const std::string& key) +{ + const bencode::BDE& c = dict[key]; + if(c.isString()) { return c; } else { throw DlAbortEx @@ -95,10 +106,11 @@ static const Dictionary* getDictionary(const Dictionary* d, const std::string& k } } -static const Data* getData(const Dictionary* d, const std::string& key) +static const bencode::BDE& getInteger(const bencode::BDE& dict, + const std::string& key) { - const Data* c = dynamic_cast<const Data*>(d->get(key)); - if(c) { + const bencode::BDE& c = dict[key]; + if(c.isInteger()) { return c; } else { throw DlAbortEx @@ -106,22 +118,35 @@ static const Data* getData(const Dictionary* d, const std::string& key) } } -static const Data* getData(const List* l, size_t index) +static const bencode::BDE& getString(const bencode::BDE& list, size_t index) { - const Data* c = dynamic_cast<const Data*>(l->getList()[index]); - if(c) { + const bencode::BDE& c = list[index]; + if(c.isString()) { return c; } else { throw DlAbortEx - (StringFormat("Malformed DHT message. element[%u] is not Data.", + (StringFormat("Malformed DHT message. element[%u] is not String.", index).str()); } } -static const List* getList(const Dictionary* d, const std::string& key) +static const bencode::BDE& getInteger(const bencode::BDE& list, size_t index) { - const List* l = dynamic_cast<const List*>(d->get(key)); - if(l) { + const bencode::BDE& c = list[index]; + if(c.isInteger()) { + return c; + } else { + throw DlAbortEx + (StringFormat("Malformed DHT message. element[%u] is not Integer.", + index).str()); + } +} + +static const bencode::BDE& getList(const bencode::BDE& dict, + const std::string& key) +{ + const bencode::BDE& l = dict[key]; + if(l.isList()) { return l; } else { throw DlAbortEx @@ -129,121 +154,121 @@ static const List* getList(const Dictionary* d, const std::string& key) } } -void DHTMessageFactoryImpl::validateID(const Data* id) const +void DHTMessageFactoryImpl::validateID(const bencode::BDE& id) const { - if(id->getLen() != DHT_ID_LENGTH) { + if(id.s().size() != DHT_ID_LENGTH) { throw DlAbortEx - (StringFormat("Malformed DHT message. Invalid ID length. Expected:%d, Actual:%d", DHT_ID_LENGTH, id->getLen()).str()); + (StringFormat("Malformed DHT message. Invalid ID length." + " Expected:%d, Actual:%d", + DHT_ID_LENGTH, id.s().size()).str()); } } -void DHTMessageFactoryImpl::validatePort(const Data* i) const +void DHTMessageFactoryImpl::validatePort(const bencode::BDE& i) const { - if(!i->isNumber()) { + bencode::BDE::Integer port = i.i(); + if(!(0 < port && port < UINT16_MAX)) { throw DlAbortEx (StringFormat("Malformed DHT message. Invalid port=%s", - Util::toHex(i->toString()).c_str()).str()); - } - uint32_t port = i->toInt(); - if(UINT16_MAX < port) { - throw DlAbortEx - (StringFormat("Malformed DHT message. Invalid port=%u", port).str()); + Util::itos(port).c_str()).str()); } } -SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage(const Dictionary* d, - const std::string& ipaddr, - uint16_t port) +SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage +(const bencode::BDE& dict, + const std::string& ipaddr, + uint16_t port) { - const Data* q = getData(d, DHTQueryMessage::Q); - const Data* t = getData(d, DHTMessage::T); - const Data* y = getData(d, DHTMessage::Y); - const Dictionary* a = getDictionary(d, DHTQueryMessage::A); - if(y->toString() != DHTQueryMessage::Q) { + const bencode::BDE& messageType = getString(dict, DHTQueryMessage::Q); + const bencode::BDE& transactionID = getString(dict, DHTMessage::T); + const bencode::BDE& y = getString(dict, DHTMessage::Y); + const bencode::BDE& aDict = getDictionary(dict, DHTQueryMessage::A); + if(y.s() != DHTQueryMessage::Q) { throw DlAbortEx("Malformed DHT message. y != q"); } - const Data* id = getData(getDictionary(d, DHTQueryMessage::A), DHTMessage::ID); + const bencode::BDE& id = getString(aDict, DHTMessage::ID); validateID(id); - SharedHandle<DHTNode> remoteNode = getRemoteNode(id->getData(), ipaddr, port); - std::string messageType = q->toString(); - std::string transactionID = t->toString(); - if(messageType == DHTPingMessage::PING) { - return createPingMessage(remoteNode, transactionID); - } else if(messageType == DHTFindNodeMessage::FIND_NODE) { - const Data* targetNodeID = getData(a, DHTFindNodeMessage::TARGET_NODE); + SharedHandle<DHTNode> remoteNode = getRemoteNode(id.uc(), ipaddr, port); + if(messageType.s() == DHTPingMessage::PING) { + return createPingMessage(remoteNode, transactionID.s()); + } else if(messageType.s() == DHTFindNodeMessage::FIND_NODE) { + const bencode::BDE& targetNodeID = + getString(aDict, DHTFindNodeMessage::TARGET_NODE); validateID(targetNodeID); - return createFindNodeMessage(remoteNode, targetNodeID->getData(), - transactionID); - } else if(messageType == DHTGetPeersMessage::GET_PEERS) { - const Data* infoHash = getData(a, DHTGetPeersMessage::INFO_HASH); + return createFindNodeMessage(remoteNode, targetNodeID.uc(), + transactionID.s()); + } else if(messageType.s() == DHTGetPeersMessage::GET_PEERS) { + const bencode::BDE& infoHash = + getString(aDict, DHTGetPeersMessage::INFO_HASH); validateID(infoHash); return createGetPeersMessage(remoteNode, - infoHash->getData(), transactionID); - } else if(messageType == DHTAnnouncePeerMessage::ANNOUNCE_PEER) { - const Data* infoHash = getData(a, DHTAnnouncePeerMessage::INFO_HASH); + infoHash.uc(), transactionID.s()); + } else if(messageType.s() == DHTAnnouncePeerMessage::ANNOUNCE_PEER) { + const bencode::BDE& infoHash = + getString(aDict, DHTAnnouncePeerMessage::INFO_HASH); validateID(infoHash); - const Data* port = getData(a, DHTAnnouncePeerMessage::PORT); + const bencode::BDE& port = getInteger(aDict, DHTAnnouncePeerMessage::PORT); validatePort(port); - const Data* token = getData(a, DHTAnnouncePeerMessage::TOKEN); - return createAnnouncePeerMessage(remoteNode, infoHash->getData(), - static_cast<uint16_t>(port->toInt()), - token->toString(), transactionID); + const bencode::BDE& token = getString(aDict, DHTAnnouncePeerMessage::TOKEN); + return createAnnouncePeerMessage(remoteNode, infoHash.uc(), + static_cast<uint16_t>(port.i()), + token.s(), transactionID.s()); } else { throw DlAbortEx - (StringFormat("Unsupported message type: %s", messageType.c_str()).str()); + (StringFormat("Unsupported message type: %s", + messageType.s().c_str()).str()); } } SharedHandle<DHTMessage> DHTMessageFactoryImpl::createResponseMessage(const std::string& messageType, - const Dictionary* d, + const bencode::BDE& dict, const std::string& ipaddr, uint16_t port) { - const Data* t = getData(d, DHTMessage::T); - const Data* y = getData(d, DHTMessage::Y); - if(y->toString() == DHTUnknownMessage::E) { + const bencode::BDE& transactionID = getString(dict, DHTMessage::T); + const bencode::BDE& y = getString(dict, DHTMessage::Y); + if(y.s() == DHTUnknownMessage::E) { // for now, just report error message arrived and throw exception. - const List* e = getList(d, DHTUnknownMessage::E); - if(e->getList().size() == 2) { + const bencode::BDE& e = getList(dict, DHTUnknownMessage::E); + if(e.size() == 2) { _logger->info("Received Error DHT message. code=%s, msg=%s", - Util::urlencode(getData(e, 0)->toString()).c_str(), - Util::urlencode(getData(e, 1)->toString()).c_str()); + Util::itos(getInteger(e, 0).i()).c_str(), + Util::urlencode(getString(e, 1).s()).c_str()); } else { _logger->debug("e doesn't have 2 elements."); } throw DlAbortEx("Received Error DHT message."); - } else if(y->toString() != DHTResponseMessage::R) { + } else if(y.s() != DHTResponseMessage::R) { throw DlAbortEx (StringFormat("Malformed DHT message. y != r: y=%s", - Util::urlencode(y->toString()).c_str()).str()); + Util::urlencode(y.s()).c_str()).str()); } - const Dictionary* r = getDictionary(d, DHTResponseMessage::R); - const Data* id = getData(r, DHTMessage::ID); + const bencode::BDE& rDict = getDictionary(dict, DHTResponseMessage::R); + const bencode::BDE& id = getString(rDict, DHTMessage::ID); validateID(id); - SharedHandle<DHTNode> remoteNode = getRemoteNode(id->getData(), ipaddr, port); + SharedHandle<DHTNode> remoteNode = getRemoteNode(id.uc(), ipaddr, port); - std::string transactionID = t->toString(); if(messageType == DHTPingReplyMessage::PING) { - return createPingReplyMessage(remoteNode, - id->getData(), transactionID); + return createPingReplyMessage(remoteNode, id.uc(), transactionID.s()); } else if(messageType == DHTFindNodeReplyMessage::FIND_NODE) { - return createFindNodeReplyMessage(remoteNode, d, transactionID); + return createFindNodeReplyMessage(remoteNode, dict, transactionID.s()); } else if(messageType == DHTGetPeersReplyMessage::GET_PEERS) { - const List* values = - dynamic_cast<const List*>(r->get(DHTGetPeersReplyMessage::VALUES)); - if(values) { - return createGetPeersReplyMessageWithValues(remoteNode, d, transactionID); + const bencode::BDE& valuesList = rDict[DHTGetPeersReplyMessage::VALUES]; + if(valuesList.isList()) { + return createGetPeersReplyMessageWithValues(remoteNode, dict, + transactionID.s()); } else { - const Data* nodes = dynamic_cast<const Data*>(r->get(DHTGetPeersReplyMessage::NODES)); - if(nodes) { - return createGetPeersReplyMessageWithNodes(remoteNode, d, transactionID); + const bencode::BDE& nodes = rDict[DHTGetPeersReplyMessage::NODES]; + if(nodes.isString()) { + return createGetPeersReplyMessageWithNodes(remoteNode, dict, + transactionID.s()); } else { throw DlAbortEx("Malformed DHT message: missing nodes/values"); } } } else if(messageType == DHTAnnouncePeerReplyMessage::ANNOUNCE_PEER) { - return createAnnouncePeerReplyMessage(remoteNode, transactionID); + return createAnnouncePeerReplyMessage(remoteNode, transactionID.s()); } else { throw DlAbortEx (StringFormat("Unsupported message type: %s", messageType.c_str()).str()); @@ -319,12 +344,16 @@ DHTMessageFactoryImpl::extractNodes(const unsigned char* src, size_t length) } SharedHandle<DHTMessage> -DHTMessageFactoryImpl::createFindNodeReplyMessage(const SharedHandle<DHTNode>& remoteNode, - const Dictionary* d, - const std::string& transactionID) +DHTMessageFactoryImpl::createFindNodeReplyMessage +(const SharedHandle<DHTNode>& remoteNode, + const bencode::BDE& dict, + const std::string& transactionID) { - const Data* nodesData = getData(getDictionary(d, DHTResponseMessage::R), DHTFindNodeReplyMessage::NODES); - std::deque<SharedHandle<DHTNode> > nodes = extractNodes(nodesData->getData(), nodesData->getLen()); + const bencode::BDE& nodesData = + getString(getDictionary(dict, DHTResponseMessage::R), + DHTFindNodeReplyMessage::NODES); + std::deque<SharedHandle<DHTNode> > nodes = extractNodes(nodesData.uc(), + nodesData.s().size()); return createFindNodeReplyMessage(remoteNode, nodes, transactionID); } @@ -344,15 +373,18 @@ DHTMessageFactoryImpl::createGetPeersMessage(const SharedHandle<DHTNode>& remote } SharedHandle<DHTMessage> -DHTMessageFactoryImpl::createGetPeersReplyMessageWithNodes(const SharedHandle<DHTNode>& remoteNode, - const Dictionary* d, - const std::string& transactionID) -{ - const Dictionary* r = getDictionary(d, DHTResponseMessage::R); - const Data* nodesData = getData(r, DHTGetPeersReplyMessage::NODES); - std::deque<SharedHandle<DHTNode> > nodes = extractNodes(nodesData->getData(), nodesData->getLen()); - const Data* token = getData(r, DHTGetPeersReplyMessage::TOKEN); - return createGetPeersReplyMessage(remoteNode, nodes, token->toString(), +DHTMessageFactoryImpl::createGetPeersReplyMessageWithNodes +(const SharedHandle<DHTNode>& remoteNode, + const bencode::BDE& dict, + const std::string& transactionID) +{ + const bencode::BDE& rDict = getDictionary(dict, DHTResponseMessage::R); + const bencode::BDE& nodesData = getString(rDict, + DHTGetPeersReplyMessage::NODES); + std::deque<SharedHandle<DHTNode> > nodes = extractNodes(nodesData.uc(), + nodesData.s().size()); + const bencode::BDE& token = getString(rDict, DHTGetPeersReplyMessage::TOKEN); + return createGetPeersReplyMessage(remoteNode, nodes, token.s(), transactionID); } @@ -370,23 +402,27 @@ DHTMessageFactoryImpl::createGetPeersReplyMessage(const SharedHandle<DHTNode>& r } SharedHandle<DHTMessage> -DHTMessageFactoryImpl::createGetPeersReplyMessageWithValues(const SharedHandle<DHTNode>& remoteNode, - const Dictionary* d, - const std::string& transactionID) +DHTMessageFactoryImpl::createGetPeersReplyMessageWithValues +(const SharedHandle<DHTNode>& remoteNode, + const bencode::BDE& dict, + const std::string& transactionID) { - const Dictionary* r = getDictionary(d, DHTResponseMessage::R); - const List* valuesList = getList(r, DHTGetPeersReplyMessage::VALUES); + const bencode::BDE& rDict = getDictionary(dict, DHTResponseMessage::R); + const bencode::BDE& valuesList = getList(rDict, + DHTGetPeersReplyMessage::VALUES); std::deque<SharedHandle<Peer> > peers; - for(std::deque<MetaEntry*>::const_iterator i = valuesList->getList().begin(); i != valuesList->getList().end(); ++i) { - const Data* data = dynamic_cast<const Data*>(*i); - if(data && data->getLen() == 6) { - std::pair<std::string, uint16_t> addr = PeerMessageUtil::unpackcompact(data->getData()); + for(bencode::BDE::List::const_iterator i = valuesList.listBegin(); + i != valuesList.listEnd(); ++i) { + const bencode::BDE& data = *i; + if(data.isString() && data.s().size() == 6) { + std::pair<std::string, uint16_t> addr = + PeerMessageUtil::unpackcompact(data.uc()); PeerHandle peer(new Peer(addr.first, addr.second)); peers.push_back(peer); } } - const Data* token = getData(r, DHTGetPeersReplyMessage::TOKEN); - return createGetPeersReplyMessage(remoteNode, peers, token->toString(), + const bencode::BDE& token = getString(rDict, DHTGetPeersReplyMessage::TOKEN); + return createGetPeersReplyMessage(remoteNode, peers, token.s(), transactionID); } |
