浏览代码

2010-03-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added v key in DHT message. aria2's DHT version is independent of
	the package version and we defined it as 1 at the moment. It is
	defined as DHT_VERSION in src/DHTConstants.h. aria2's DHT version
	scheme is "A2"+2bytes DHT version number in network byte order.
	* src/DHTAbstractMessage.cc
	* src/DHTConstants.h
	* src/DHTMessage.cc
	* src/DHTMessage.h
	* src/DHTMessageFactoryImpl.cc
	* src/DHTQueryMessage.cc
	* src/DHTResponseMessage.cc
	* src/util.h
	* test/DHTAnnouncePeerMessageTest.cc
	* test/DHTAnnouncePeerReplyMessageTest.cc
	* test/DHTFindNodeMessageTest.cc
	* test/DHTFindNodeReplyMessageTest.cc
	* test/DHTGetPeersMessageTest.cc
	* test/DHTGetPeersReplyMessageTest.cc
	* test/DHTPingMessageTest.cc
	* test/DHTPingReplyMessageTest.cc
Tatsuhiro Tsujikawa 15 年之前
父节点
当前提交
10edc156ea

+ 23 - 0
ChangeLog

@@ -1,3 +1,26 @@
+2010-03-20  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added v key in DHT message. aria2's DHT version is independent of
+	the package version and we defined it as 1 at the moment. It is
+	defined as DHT_VERSION in src/DHTConstants.h. aria2's DHT version
+	scheme is "A2"+2bytes DHT version number in network byte order.
+	* src/DHTAbstractMessage.cc
+	* src/DHTConstants.h
+	* src/DHTMessage.cc
+	* src/DHTMessage.h
+	* src/DHTMessageFactoryImpl.cc
+	* src/DHTQueryMessage.cc
+	* src/DHTResponseMessage.cc
+	* src/util.h
+	* test/DHTAnnouncePeerMessageTest.cc
+	* test/DHTAnnouncePeerReplyMessageTest.cc
+	* test/DHTFindNodeMessageTest.cc
+	* test/DHTFindNodeReplyMessageTest.cc
+	* test/DHTGetPeersMessageTest.cc
+	* test/DHTGetPeersReplyMessageTest.cc
+	* test/DHTPingMessageTest.cc
+	* test/DHTPingReplyMessageTest.cc
+
 2010-03-19  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Fixed the bug that value of numSeeders in aria2.tellStatus XML-RPC

+ 1 - 0
src/DHTAbstractMessage.cc

@@ -58,6 +58,7 @@ std::string DHTAbstractMessage::getBencodedMessage()
   BDE msgDict = BDE::dict();
   msgDict[T] = _transactionID;
   msgDict[Y] = getType();
+  msgDict[V] = _version;
   fillMessage(msgDict);
   return bencode::encode(msgDict);
 }

+ 4 - 0
src/DHTConstants.h

@@ -35,6 +35,10 @@
 #ifndef _D_DHT_CONSTANTS_H_
 #define _D_DHT_CONSTANTS_H_
 
+// Increment this if major improvements or bug fixes are made in DHT
+// code.
+#define DHT_VERSION 1
+
 #define DHT_ID_LENGTH 20
 
 #define DHT_TRANSACTION_ID_LENGTH 2

+ 2 - 0
src/DHTMessage.cc

@@ -42,6 +42,8 @@ const std::string DHTMessage::Y("y");
 
 const std::string DHTMessage::T("t");
 
+const std::string DHTMessage::V("v");
+
 const std::string DHTMessage::ID("id");
 
 DHTMessage::DHTMessage(const SharedHandle<DHTNode>& localNode,

+ 9 - 0
src/DHTMessage.h

@@ -54,6 +54,8 @@ protected:
 
   std::string _transactionID;
 
+  std::string _version;
+
   void generateTransactionID();
 public:
   DHTMessage(const SharedHandle<DHTNode>& localNode,
@@ -89,10 +91,17 @@ public:
 
   virtual std::string toString() const = 0;
 
+  void setVersion(const std::string& version)
+  {
+    _version = version;
+  }
+
   static const std::string Y;
 
   static const std::string T;
 
+  static const std::string V;
+
   static const std::string ID;
 };
 

+ 44 - 15
src/DHTMessageFactoryImpl.cc

@@ -174,6 +174,16 @@ void DHTMessageFactoryImpl::validatePort(const BDE& i) const
   }
 }
 
+static void setVersion(const SharedHandle<DHTMessage>& msg, const BDE& dict)
+{
+  const BDE& v = dict[DHTMessage::V];
+  if(v.isString()) {
+    msg->setVersion(v.s());
+  } else {
+    msg->setVersion(A2STR::NIL);
+  }
+}
+
 SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage
 (const BDE& dict,
  const std::string& ipaddr,
@@ -189,20 +199,21 @@ SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage
   const BDE& id = getString(aDict, DHTMessage::ID);
   validateID(id);
   SharedHandle<DHTNode> remoteNode = getRemoteNode(id.uc(), ipaddr, port);
+  SharedHandle<DHTMessage> msg;
   if(messageType.s() == DHTPingMessage::PING) {
-    return createPingMessage(remoteNode, transactionID.s());
+    msg = createPingMessage(remoteNode, transactionID.s());
   } else if(messageType.s() == DHTFindNodeMessage::FIND_NODE) {
     const BDE& targetNodeID =
       getString(aDict, DHTFindNodeMessage::TARGET_NODE);
     validateID(targetNodeID);
-    return createFindNodeMessage(remoteNode, targetNodeID.uc(),
-                                 transactionID.s());
+    msg = createFindNodeMessage(remoteNode, targetNodeID.uc(),
+                                transactionID.s());
   } else if(messageType.s() == DHTGetPeersMessage::GET_PEERS) {
     const BDE& infoHash = 
       getString(aDict, DHTGetPeersMessage::INFO_HASH);
     validateID(infoHash);
-    return createGetPeersMessage(remoteNode,
-                                 infoHash.uc(), transactionID.s());
+    msg = createGetPeersMessage(remoteNode,
+                                infoHash.uc(), transactionID.s());
   } else if(messageType.s() == DHTAnnouncePeerMessage::ANNOUNCE_PEER) {
     const BDE& infoHash =
       getString(aDict, DHTAnnouncePeerMessage::INFO_HASH);
@@ -210,14 +221,16 @@ SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage
     const BDE& port = getInteger(aDict, DHTAnnouncePeerMessage::PORT);
     validatePort(port);
     const BDE& token = getString(aDict, DHTAnnouncePeerMessage::TOKEN);
-    return createAnnouncePeerMessage(remoteNode, infoHash.uc(),
-                                     static_cast<uint16_t>(port.i()),
-                                     token.s(), transactionID.s());
+    msg = createAnnouncePeerMessage(remoteNode, infoHash.uc(),
+                                    static_cast<uint16_t>(port.i()),
+                                    token.s(), transactionID.s());
   } else {
     throw DL_ABORT_EX
       (StringFormat("Unsupported message type: %s",
                     messageType.s().c_str()).str());
   }
+  setVersion(msg, dict);
+  return msg;
 }
 
 SharedHandle<DHTMessage>
@@ -252,31 +265,46 @@ DHTMessageFactoryImpl::createResponseMessage(const std::string& messageType,
   const BDE& id = getString(rDict, DHTMessage::ID);
   validateID(id);
   SharedHandle<DHTNode> remoteNode = getRemoteNode(id.uc(), ipaddr, port);
-
+  SharedHandle<DHTMessage> msg;
   if(messageType == DHTPingReplyMessage::PING) {
-    return createPingReplyMessage(remoteNode, id.uc(), transactionID.s());
+    msg = createPingReplyMessage(remoteNode, id.uc(), transactionID.s());
   } else if(messageType == DHTFindNodeReplyMessage::FIND_NODE) {
-    return createFindNodeReplyMessage(remoteNode, dict, transactionID.s());
+    msg = createFindNodeReplyMessage(remoteNode, dict, transactionID.s());
   } else if(messageType == DHTGetPeersReplyMessage::GET_PEERS) {
     const BDE& valuesList = rDict[DHTGetPeersReplyMessage::VALUES];
     if(valuesList.isList()) {
-      return createGetPeersReplyMessageWithValues(remoteNode, dict,
-                                                  transactionID.s());
+      msg = createGetPeersReplyMessageWithValues(remoteNode, dict,
+                                                 transactionID.s());
     } else {
       const BDE& nodes = rDict[DHTGetPeersReplyMessage::NODES];
       if(nodes.isString()) {
-        return createGetPeersReplyMessageWithNodes(remoteNode, dict,
+        msg = createGetPeersReplyMessageWithNodes(remoteNode, dict,
                                                    transactionID.s());
       } else {
         throw DL_ABORT_EX("Malformed DHT message: missing nodes/values");
       }
     }
   } else if(messageType == DHTAnnouncePeerReplyMessage::ANNOUNCE_PEER) {
-    return createAnnouncePeerReplyMessage(remoteNode, transactionID.s());
+    msg = createAnnouncePeerReplyMessage(remoteNode, transactionID.s());
   } else {
     throw DL_ABORT_EX
       (StringFormat("Unsupported message type: %s", messageType.c_str()).str());
   }
+  setVersion(msg, dict);
+  return msg;
+}
+
+static const std::string& getDefaultVersion()
+{
+  static std::string version;
+  if(version.empty()) {
+    uint16_t vnum16 = htons(DHT_VERSION);
+    unsigned char buf[] = { 'A' , '2', 0, 0 };
+    char* vnump = reinterpret_cast<char*>(&vnum16);
+    memcpy(buf+2, vnump, 2);
+    version.assign(&buf[0], &buf[4]);
+  }
+  return version;
 }
 
 void DHTMessageFactoryImpl::setCommonProperty(const SharedHandle<DHTAbstractMessage>& m)
@@ -286,6 +314,7 @@ void DHTMessageFactoryImpl::setCommonProperty(const SharedHandle<DHTAbstractMess
   m->setRoutingTable(_routingTable);
   WeakHandle<DHTMessageFactory> factory(this);
   m->setMessageFactory(factory);
+  m->setVersion(getDefaultVersion());
 }
 
 SharedHandle<DHTMessage> DHTMessageFactoryImpl::createPingMessage(const SharedHandle<DHTNode>& remoteNode, const std::string& transactionID)

+ 14 - 6
src/DHTQueryMessage.cc

@@ -69,12 +69,20 @@ bool DHTQueryMessage::isReply() const
 
 std::string DHTQueryMessage::toString() const
 {
-  return strconcat("dht query ", getMessageType(),
-                   " TransactionID=", util::toHex(_transactionID),
-                   " Remote:", _remoteNode->getIPAddress(),
-                   ":", util::uitos(_remoteNode->getPort()),
-                   ", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
-                   ", ", toStringOptional());
+  std::string s = strconcat
+    ("dht query ", getMessageType(),
+     " TransactionID=", util::toHex(_transactionID),
+     " Remote:", _remoteNode->getIPAddress(),
+     ":", util::uitos(_remoteNode->getPort()),
+     ", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
+     ", ");
+  if(!_version.empty()) {
+    s += "v=";
+    s += util::torrentPercentEncode(_version);
+    s += ", ";
+  }
+  s += toStringOptional();
+  return s;
 }
 
 } // namespace aria2

+ 14 - 6
src/DHTResponseMessage.cc

@@ -66,12 +66,20 @@ bool DHTResponseMessage::isReply() const
 
 std::string DHTResponseMessage::toString() const
 {
-  return strconcat("dht response ", getMessageType(),
-                   " TransactionID=", util::toHex(_transactionID),
-                   " Remote:", _remoteNode->getIPAddress(),
-                   ":", util::uitos(_remoteNode->getPort()),
-                   ", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
-                   ", ", toStringOptional());
+  std::string s = strconcat
+    ("dht response ", getMessageType(),
+     " TransactionID=", util::toHex(_transactionID),
+     " Remote:", _remoteNode->getIPAddress(),
+     ":", util::uitos(_remoteNode->getPort()),
+     ", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
+     ", ");
+  if(!_version.empty()) {
+    s += "v=";
+    s += util::torrentPercentEncode(_version);
+    s += ", ";
+  }
+  s += toStringOptional();
+  return s;
 }
 
 } // namespace aria2

+ 2 - 0
src/util.h

@@ -242,6 +242,8 @@ void usleep(long microseconds);
   
 bool isNumber(const std::string& what);
 
+bool isDigit(const char c);
+
 bool isHexDigit(const char c);
 
 bool isHexDigit(const std::string& s);

+ 2 - 1
test/DHTAnnouncePeerMessageTest.cc

@@ -56,11 +56,12 @@ void DHTAnnouncePeerMessageTest::testGetBencodedMessage()
   uint16_t port = 6881;
 
   DHTAnnouncePeerMessage msg(localNode, remoteNode, infoHash, port, token, transactionID);
-
+  msg.setVersion("A200");
   std::string msgbody = msg.getBencodedMessage();
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("q");
   dict["q"] = BDE("announce_peer");
   BDE aDict = BDE::dict();

+ 2 - 1
test/DHTAnnouncePeerReplyMessageTest.cc

@@ -35,11 +35,12 @@ void DHTAnnouncePeerReplyMessageTest::testGetBencodedMessage()
   std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
 
   DHTAnnouncePeerReplyMessage msg(localNode, remoteNode, transactionID);
-
+  msg.setVersion("A200");
   std::string msgbody = msg.getBencodedMessage();
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("r");
   BDE rDict = BDE::dict();
   rDict["id"] = BDE(localNode->getID(), DHT_ID_LENGTH);

+ 2 - 1
test/DHTFindNodeMessageTest.cc

@@ -58,11 +58,12 @@ void DHTFindNodeMessageTest::testGetBencodedMessage()
   SharedHandle<DHTNode> targetNode(new DHTNode());
 
   DHTFindNodeMessage msg(localNode, remoteNode, targetNode->getID(), transactionID);
-
+  msg.setVersion("A200");
   std::string msgbody = msg.getBencodedMessage();
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("q");
   dict["q"] = BDE("find_node");
   BDE aDict = BDE::dict();

+ 2 - 1
test/DHTFindNodeReplyMessageTest.cc

@@ -37,7 +37,7 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
   std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
 
   DHTFindNodeReplyMessage msg(localNode, remoteNode, transactionID);
-
+  msg.setVersion("A200");
   std::string compactNodeInfo;
   SharedHandle<DHTNode> nodes[8];
   for(size_t i = 0; i < DHTBucket::K; ++i) {
@@ -59,6 +59,7 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("r");
   BDE rDict = BDE::dict();
   rDict["id"] = BDE(localNode->getID(), DHT_ID_LENGTH);

+ 2 - 0
test/DHTGetPeersMessageTest.cc

@@ -77,11 +77,13 @@ void DHTGetPeersMessageTest::testGetBencodedMessage()
   util::generateRandomData(infoHash, DHT_ID_LENGTH);
 
   DHTGetPeersMessage msg(localNode, remoteNode, infoHash, transactionID);
+  msg.setVersion("A200");
 
   std::string msgbody = msg.getBencodedMessage();
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("q");
   dict["q"] = BDE("get_peers");
   BDE aDict = BDE::dict();

+ 2 - 1
test/DHTGetPeersReplyMessageTest.cc

@@ -40,9 +40,10 @@ void DHTGetPeersReplyMessageTest::testGetBencodedMessage()
   std::string token = "token";
 
   DHTGetPeersReplyMessage msg(localNode, remoteNode, token, transactionID);
-
+  msg.setVersion("A200");
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("r");
   BDE rDict = BDE::dict();
   rDict["id"] = BDE(localNode->getID(), DHT_ID_LENGTH);

+ 2 - 0
test/DHTPingMessageTest.cc

@@ -53,11 +53,13 @@ void DHTPingMessageTest::testGetBencodedMessage()
   std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
 
   DHTPingMessage msg(localNode, remoteNode, transactionID);
+  msg.setVersion("A200");
 
   std::string msgbody = msg.getBencodedMessage();
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("q");
   dict["q"] = BDE("ping");
   BDE aDict = BDE::dict();

+ 2 - 1
test/DHTPingReplyMessageTest.cc

@@ -38,11 +38,12 @@ void DHTPingReplyMessageTest::testGetBencodedMessage()
   util::generateRandomData(id, DHT_ID_LENGTH);
 
   DHTPingReplyMessage msg(localNode, remoteNode, id, transactionID);
-
+  msg.setVersion("A200");
   std::string msgbody = msg.getBencodedMessage();
 
   BDE dict = BDE::dict();
   dict["t"] = transactionID;
+  dict["v"] = BDE("A200");
   dict["y"] = BDE("r");
   BDE rDict = BDE::dict();
   rDict["id"] = BDE(id, DHT_ID_LENGTH);