Browse Source

2008-02-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Adding handling of DHT error message. Just log error message and
	throw exception.
	* src/DHTMessageFactoryImpl.cc
	* test/DHTMessageFactoryImplTest.cc
Tatsuhiro Tsujikawa 17 years ago
parent
commit
413cbe192b
3 changed files with 56 additions and 3 deletions
  1. 7 0
      ChangeLog
  2. 25 3
      src/DHTMessageFactoryImpl.cc
  3. 24 0
      test/DHTMessageFactoryImplTest.cc

+ 7 - 0
ChangeLog

@@ -1,3 +1,10 @@
+2008-02-11  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Adding handling of DHT error message. Just log error message and
+	throw exception.
+	* src/DHTMessageFactoryImpl.cc
+	* test/DHTMessageFactoryImplTest.cc
+
 2008-02-11  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Added handling of dynamic cast failure.

+ 25 - 3
src/DHTMessageFactoryImpl.cc

@@ -57,6 +57,7 @@
 #include "BtRuntime.h"
 #include "Util.h"
 #include "Peer.h"
+#include "Logger.h"
 #include <cstring>
 #include <utility>
 
@@ -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<const Data*>(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<const List*>(d->get(key));
@@ -187,12 +199,22 @@ SharedHandle<DHTMessage> 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(),

+ 24 - 0
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<Dictionary> 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<DHTNode> 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