From 413cbe192b842c23759c9b31088b34e88ce96ed2 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 11 Feb 2008 06:23:01 +0000 Subject: [PATCH] 2008-02-11 Tatsuhiro Tsujikawa Adding handling of DHT error message. Just log error message and throw exception. * src/DHTMessageFactoryImpl.cc * test/DHTMessageFactoryImplTest.cc --- ChangeLog | 7 +++++++ src/DHTMessageFactoryImpl.cc | 28 +++++++++++++++++++++++++--- test/DHTMessageFactoryImplTest.cc | 24 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf92f807..ec779398 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-02-11 Tatsuhiro Tsujikawa + + Adding handling of DHT error message. Just log error message and + throw exception. + * src/DHTMessageFactoryImpl.cc + * test/DHTMessageFactoryImplTest.cc + 2008-02-11 Tatsuhiro Tsujikawa Added handling of dynamic cast failure. diff --git a/src/DHTMessageFactoryImpl.cc b/src/DHTMessageFactoryImpl.cc index 6d5552d3..8eb55071 100644 --- a/src/DHTMessageFactoryImpl.cc +++ b/src/DHTMessageFactoryImpl.cc @@ -57,6 +57,7 @@ #include "BtRuntime.h" #include "Util.h" #include "Peer.h" +#include "Logger.h" #include #include @@ -99,6 +100,17 @@ static const Data* getData(const Dictionary* d, const std::string& key) } } +static const Data* getData(const List* l, size_t index) +{ + const Data* c = dynamic_cast(l->getList()[index]); + if(c) { + return c; + } else { + throw new DlAbortEx("Malformed DHT message. element[%u] is not Data.", + index); + } +} + static const List* getList(const Dictionary* d, const std::string& key) { const List* l = dynamic_cast(d->get(key)); @@ -187,12 +199,22 @@ SharedHandle DHTMessageFactoryImpl::createResponseMessage(const std: { const Data* t = getData(d, "t"); const Data* y = getData(d, "y"); - const Dictionary* r = getDictionary(d, "r"); - // TODO handle y == "e" case - if(y->toString() != "r") { + if(y->toString() == "e") { + // for now, just report error message arrived and throw exception. + const List* e = getList(d, "e"); + if(e->getList().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()); + } else { + _logger->debug("e doesn't have 2 elements."); + } + throw new DlAbortEx("Received Error DHT message."); + } else if(y->toString() != "r") { throw new DlAbortEx("Malformed DHT message. y != r: y=%s", Util::urlencode(y->toString()).c_str()); } + const Dictionary* r = getDictionary(d, "r"); const Data* id = getData(r, "id"); validateID(id); validateIDMatch(remoteNode->getID(), diff --git a/test/DHTMessageFactoryImplTest.cc b/test/DHTMessageFactoryImplTest.cc index e1f583c6..baefb194 100644 --- a/test/DHTMessageFactoryImplTest.cc +++ b/test/DHTMessageFactoryImplTest.cc @@ -33,6 +33,7 @@ class DHTMessageFactoryImplTest:public CppUnit::TestFixture { CPPUNIT_TEST(testCreateGetPeersReplyMessage_values); CPPUNIT_TEST(testCreateAnnouncePeerMessage); CPPUNIT_TEST(testCreateAnnouncePeerReplyMessage); + CPPUNIT_TEST(testReceivedErrorMessage); CPPUNIT_TEST_SUITE_END(); public: DHTMessageFactoryImplTest():factory(0), routingTable(0), localNode(0) {} @@ -72,6 +73,7 @@ public: void testCreateGetPeersReplyMessage_values(); void testCreateAnnouncePeerMessage(); void testCreateAnnouncePeerReplyMessage(); + void testReceivedErrorMessage(); }; @@ -362,4 +364,26 @@ void DHTMessageFactoryImplTest::testCreateAnnouncePeerReplyMessage() Util::toHex(m->getTransactionID())); } +void DHTMessageFactoryImplTest::testReceivedErrorMessage() +{ + SharedHandle d = new Dictionary(); + d->put("t", new Data(transactionID, DHT_TRANSACTION_ID_LENGTH)); + d->put("y", new Data("e")); + List* l = new List(); + l->add(new Data("404")); + l->add(new Data("Not found")); + d->put("e", l); + + SharedHandle remoteNode = new DHTNode(remoteNodeID); + remoteNode->setIPAddress("192.168.0.1"); + remoteNode->setPort(6881); + + try { + factory->createResponseMessage("announce_peer", d.get(), remoteNode); + CPPUNIT_FAIL("exception must be thrown."); + } catch(RecoverableException* e) { + std::cerr << *e << std::endl; + } +} + } // namespace aria2