Kaynağa Gözat

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

	Added DHT functionality, compatible with mainline.
	DHT is disabled by default. To enable it, give --enable-dht to 
aria2c.
	You may need to specify entry point to DHT network using
	--dht-entry-point. DHT uses UDP port to listen incoming message.
	Use --dht-listen-port to specify port number. Make sure that 
your
	firewall configuration can pass through UDP traffic to the port.
	The routing table is saved in $HOME/.aria2/dht.dat.
	* src/DHT*
	* src/BNode.{h, cc}
	* src/PeerInteractionCommand.cc: enable DHT functionality for a
	particular torrent.
	* src/Data.cc: Rewritten ctor.
	* src/OptionHandlerFactory.cc: Added --enable-dht, 
--dht-listen-port,
	--dht-entry-point.
	* src/DefaultBtInteractive.cc: Send port message if dht is 
enabled.
	* src/RequestGroup.cc: Initialize DHT functionality. When 
download
	ends, remove BtContext from DHTPeerAnnounceStorage.
	* src/BtPortMessage.{h, cc}: Rewritten.
	* src/message.h
	* src/OptionHandlerImpl.cc
	* src/option_processing.cc: Added --enable-dht, 
--dht-listen-port,
	--dht-entry-point.
	* src/Dictionary.{h, cc} (remove): New function.
	* src/prefs.h
	* src/DefaultBtMessageFactory.h
	* src/BtHandshakeMessage.cc
	* src/ActivePeerConnectionCommand.cc
	* src/SocketCore.{h, cc}: Added datagram socket support.
	* src/DefaultBtMessageFactory.cc
	* src/BtSetup.cc: Add BtContext to DHTPeerAnnounceStorage here.
	Create DHT commands.
	* src/BtMessageFactory.h
	* src/PeerMessageUtil.{h, cc}
Tatsuhiro Tsujikawa 17 yıl önce
ebeveyn
işleme
0f13363229
100 değiştirilmiş dosya ile 7794 ekleme ve 26 silme
  1. 36 0
      ChangeLog
  2. 3 3
      src/ActivePeerConnectionCommand.cc
  3. 217 0
      src/BNode.cc
  4. 85 0
      src/BNode.h
  5. 44 0
      src/BNodeDecl.h
  6. 1 2
      src/BtContext.h
  7. 43 0
      src/BtContextDecl.h
  8. 6 0
      src/BtHandshakeMessage.cc
  9. 11 0
      src/BtHandshakeMessage.h
  10. 2 0
      src/BtMessageFactory.h
  11. 60 4
      src/BtPortMessage.cc
  12. 22 15
      src/BtPortMessage.h
  13. 15 2
      src/BtSetup.cc
  14. 90 0
      src/DHTAbstractMessage.cc
  15. 78 0
      src/DHTAbstractMessage.h
  16. 150 0
      src/DHTAbstractNodeLookupTask.cc
  17. 82 0
      src/DHTAbstractNodeLookupTask.h
  18. 81 0
      src/DHTAbstractTask.cc
  19. 82 0
      src/DHTAbstractTask.h
  20. 43 0
      src/DHTAbstractTaskDecl.h
  21. 113 0
      src/DHTAnnouncePeerMessage.cc
  22. 92 0
      src/DHTAnnouncePeerMessage.h
  23. 61 0
      src/DHTAnnouncePeerReplyMessage.cc
  24. 57 0
      src/DHTAnnouncePeerReplyMessage.h
  25. 109 0
      src/DHTAutoSaveCommand.cc
  26. 64 0
      src/DHTAutoSaveCommand.h
  27. 281 0
      src/DHTBucket.cc
  28. 132 0
      src/DHTBucket.h
  29. 45 0
      src/DHTBucketDecl.h
  30. 75 0
      src/DHTBucketRefreshCommand.cc
  31. 66 0
      src/DHTBucketRefreshCommand.h
  32. 69 0
      src/DHTBucketRefreshTask.cc
  33. 49 0
      src/DHTBucketRefreshTask.h
  34. 49 0
      src/DHTConnection.h
  35. 43 0
      src/DHTConnectionDecl.h
  36. 91 0
      src/DHTConnectionImpl.cc
  37. 65 0
      src/DHTConnectionImpl.h
  38. 60 0
      src/DHTConstants.h
  39. 161 0
      src/DHTEntryPointNameResolveCommand.cc
  40. 80 0
      src/DHTEntryPointNameResolveCommand.h
  41. 78 0
      src/DHTFindNodeMessage.cc
  42. 66 0
      src/DHTFindNodeMessage.h
  43. 95 0
      src/DHTFindNodeReplyMessage.cc
  44. 63 0
      src/DHTFindNodeReplyMessage.h
  45. 96 0
      src/DHTGetPeersCommand.cc
  46. 85 0
      src/DHTGetPeersCommand.h
  47. 103 0
      src/DHTGetPeersMessage.cc
  48. 77 0
      src/DHTGetPeersMessage.h
  49. 119 0
      src/DHTGetPeersReplyMessage.cc
  50. 79 0
      src/DHTGetPeersReplyMessage.h
  51. 57 0
      src/DHTIDCloser.h
  52. 111 0
      src/DHTInteractionCommand.cc
  53. 74 0
      src/DHTInteractionCommand.h
  54. 67 0
      src/DHTMessage.cc
  55. 80 0
      src/DHTMessage.h
  56. 52 0
      src/DHTMessageCallback.h
  57. 43 0
      src/DHTMessageCallbackDecl.h
  58. 55 0
      src/DHTMessageCallbackImpl.cc
  59. 55 0
      src/DHTMessageCallbackImpl.h
  60. 51 0
      src/DHTMessageCallbackListener.h
  61. 45 0
      src/DHTMessageDecl.h
  62. 86 0
      src/DHTMessageDispatcher.cc
  63. 73 0
      src/DHTMessageDispatcher.h
  64. 43 0
      src/DHTMessageDispatcherDecl.h
  65. 44 0
      src/DHTMessageEntry.cc
  66. 54 0
      src/DHTMessageEntry.h
  67. 45 0
      src/DHTMessageEntryDecl.h
  68. 107 0
      src/DHTMessageFactory.h
  69. 43 0
      src/DHTMessageFactoryDecl.h
  70. 418 0
      src/DHTMessageFactoryImpl.cc
  71. 168 0
      src/DHTMessageFactoryImpl.h
  72. 134 0
      src/DHTMessageReceiver.cc
  73. 80 0
      src/DHTMessageReceiver.h
  74. 43 0
      src/DHTMessageReceiverDecl.h
  75. 149 0
      src/DHTMessageTracker.cc
  76. 81 0
      src/DHTMessageTracker.h
  77. 43 0
      src/DHTMessageTrackerDecl.h
  78. 73 0
      src/DHTMessageTrackerEntry.cc
  79. 85 0
      src/DHTMessageTrackerEntry.h
  80. 45 0
      src/DHTMessageTrackerEntryDecl.h
  81. 115 0
      src/DHTNode.cc
  82. 123 0
      src/DHTNode.h
  83. 44 0
      src/DHTNodeDecl.h
  84. 47 0
      src/DHTNodeLookupEntry.cc
  85. 54 0
      src/DHTNodeLookupEntry.h
  86. 45 0
      src/DHTNodeLookupEntryDecl.h
  87. 56 0
      src/DHTNodeLookupTask.cc
  88. 49 0
      src/DHTNodeLookupTask.h
  89. 68 0
      src/DHTPeerAnnounceCommand.cc
  90. 56 0
      src/DHTPeerAnnounceCommand.h
  91. 121 0
      src/DHTPeerAnnounceEntry.cc
  92. 91 0
      src/DHTPeerAnnounceEntry.h
  93. 45 0
      src/DHTPeerAnnounceEntryDecl.h
  94. 165 0
      src/DHTPeerAnnounceStorage.cc
  95. 92 0
      src/DHTPeerAnnounceStorage.h
  96. 43 0
      src/DHTPeerAnnounceStorageDecl.h
  97. 102 0
      src/DHTPeerLookupTask.cc
  98. 73 0
      src/DHTPeerLookupTask.h
  99. 70 0
      src/DHTPingMessage.cc
  100. 57 0
      src/DHTPingMessage.h

+ 36 - 0
ChangeLog

@@ -1,3 +1,39 @@
+2008-02-01  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Added DHT functionality, compatible with mainline.
+	DHT is disabled by default. To enable it, give --enable-dht to aria2c.
+	You may need to specify entry point to DHT network using
+	--dht-entry-point. DHT uses UDP port to listen incoming message.
+	Use --dht-listen-port to specify port number. Make sure that your
+	firewall configuration can pass through UDP traffic to the port.
+	The routing table is saved in $HOME/.aria2/dht.dat.
+	* src/DHT*
+	* src/BNode.{h, cc}
+	* src/PeerInteractionCommand.cc: enable DHT functionality for a
+	particular torrent.
+	* src/Data.cc: Rewritten ctor.
+	* src/OptionHandlerFactory.cc: Added --enable-dht, --dht-listen-port,
+	--dht-entry-point.
+	* src/DefaultBtInteractive.cc: Send port message if dht is enabled.
+	* src/RequestGroup.cc: Initialize DHT functionality. When download
+	ends, remove BtContext from DHTPeerAnnounceStorage.
+	* src/BtPortMessage.{h, cc}: Rewritten.
+	* src/message.h
+	* src/OptionHandlerImpl.cc
+	* src/option_processing.cc: Added --enable-dht, --dht-listen-port,
+	--dht-entry-point.
+	* src/Dictionary.{h, cc} (remove): New function.
+	* src/prefs.h
+	* src/DefaultBtMessageFactory.h
+	* src/BtHandshakeMessage.cc
+	* src/ActivePeerConnectionCommand.cc
+	* src/SocketCore.{h, cc}: Added datagram socket support.
+	* src/DefaultBtMessageFactory.cc
+	* src/BtSetup.cc: Add BtContext to DHTPeerAnnounceStorage here.
+	Create DHT commands.
+	* src/BtMessageFactory.h
+	* src/PeerMessageUtil.{h, cc}
+
 2008-01-21  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Fixed the bug that log file is not written when configuration file doesn't exist.

+ 3 - 3
src/ActivePeerConnectionCommand.cc

@@ -59,10 +59,10 @@ bool ActivePeerConnectionCommand::execute() {
   }
   if(!pieceStorage->downloadFinished() && checkPoint.elapsed(interval)) {
     checkPoint.reset();
-
     TransferStat tstat = peerStorage->calculateStat();
-    if(tstat.getDownloadSpeed() < _lowestSpeedLimit) {
-      for(int i = 0; i < _numNewConnection && peerStorage->isPeerAvailable(); ++i) {
+    size_t numAdd = btRuntime->lessThanEqMinPeer() ? MIN_PEERS-btRuntime->getConnections():_numNewConnection;
+    if(tstat.getDownloadSpeed() < _lowestSpeedLimit || btRuntime->lessThanEqMinPeer()) {
+      for(; numAdd > 0 && peerStorage->isPeerAvailable(); --numAdd) {
 	PeerHandle peer = peerStorage->getUnusedPeer();
 	connectToPeer(peer);
       }

+ 217 - 0
src/BNode.cc

@@ -0,0 +1,217 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "BNode.h"
+#include "DHTBucket.h"
+#include "DHTNode.h"
+
+BNode::BNode(const DHTBucketHandle& bucket):_bucket(bucket),
+					    _up(0),
+					    _left(0), _right(0) {}
+
+BNode::~BNode()
+{
+  delete _left;
+  delete _right;
+}
+
+DHTBucketHandle BNode::getBucket() const
+{
+  return _bucket;
+}
+
+BNode* BNode::getLeft() const
+{
+  return _left;
+}
+
+BNode* BNode::getRight() const
+{
+  return _right;
+}
+
+BNode* BNode::getUp() const
+{
+  return _up;
+}
+
+void BNode::setLeft(BNode* left)
+{
+  _left = left;
+  _left->_up = this;
+}
+
+void BNode::setRight(BNode* right)
+{
+  _right = right;
+  _right->_up = this;
+}
+
+void BNode::setUp(BNode* up)
+{
+  _up = up;
+}
+
+void BNode::setBucket(const DHTBucketHandle& bucket)
+{
+  _bucket = bucket;
+}
+
+bool BNode::isInRange(const unsigned char* key) const
+{
+  if(_bucket.isNull()) {
+    return _left->isInRange(key) || _right->isInRange(key);
+  } else {
+    return _bucket->isInRange(key);
+  }
+}
+
+BNode* BNode::findBNodeFor(BNode* b, const unsigned char* key)
+{
+  if(!b->isInRange(key)) {
+    return 0;
+  }
+  while(1) {
+    if(!b->getBucket().isNull()) {
+      return b;
+    }
+    // we assume key fits in either left or right bucket range.
+    if(b->getLeft()->isInRange(key)) {
+      b = b->getLeft();
+    } else {
+      b = b->getRight();
+    }
+  }
+  // for properly configured BNode tree, here is unreachable.
+  return 0;
+}
+
+DHTBucketHandle BNode::findBucketFor(BNode* b, const unsigned char* key)
+{
+  BNode* bnode = findBNodeFor(b, key);
+  if(bnode) {
+    return bnode->getBucket();
+  } else {
+    return 0;
+  }
+}
+
+
+DHTNodes BNode::findClosestKNodes(BNode* b, const unsigned char* key)
+{
+  BNode* bnode = findBNodeFor(b, key);
+  DHTNodes nodes;
+  if(!bnode) {
+    return nodes;
+  }
+  {
+    DHTBucketHandle bucket = bnode->getBucket();
+    DHTNodes goodNodes = bucket->getGoodNodes();
+    nodes.insert(nodes.end(), goodNodes.begin(), goodNodes.end());
+  }
+  if(nodes.size() >= DHTBucket::K) {
+    return nodes;
+  }
+  BNodes visited;
+  visited.push_back(bnode);
+
+  BNode* up = bnode->getUp();
+  if(!up) {
+    return nodes;
+  }
+  bool leftFirst = false;
+  if(up->getLeft() == bnode) {
+    leftFirst = true;
+  }
+  bnode = up;
+
+  const_mem_fun_t<BNode*, BNode> firstfunc = leftFirst?mem_fun(&BNode::getLeft):mem_fun(&BNode::getRight);
+  const_mem_fun_t<BNode*, BNode> secondfunc = leftFirst?mem_fun(&BNode::getRight):mem_fun(&BNode::getLeft);
+  while(nodes.size() < DHTBucket::K) {
+    
+    if(!bnode->getLeft() && !bnode->getRight()) {
+      bnode = bnode->getUp();
+    } else {
+      if(find(visited.begin(), visited.end(), firstfunc(bnode)) == visited.end()) {
+	bnode = firstfunc(bnode);
+      } else if(find(visited.begin(), visited.end(), secondfunc(bnode)) == visited.end()) {
+	bnode = secondfunc(bnode);
+      } else {
+	bnode = bnode->getUp();
+      }
+    }
+    visited.push_back(bnode);
+    if(!bnode) {
+      break;
+    }
+    {
+      DHTBucketHandle bucket = bnode->getBucket();
+      if(!bucket.isNull()) {
+	DHTNodes goodNodes = bucket->getGoodNodes();
+	size_t r = DHTBucket::K-nodes.size();
+	if(goodNodes.size() <= r) {
+	  nodes.insert(nodes.end(), goodNodes.begin(), goodNodes.end());
+	} else {
+	  nodes.insert(nodes.end(), goodNodes.begin(), goodNodes.begin()+r);
+	}
+      }
+    }
+  }
+  return nodes;
+}
+
+DHTBuckets BNode::enumerateBucket(const BNode* b)
+{
+  DHTBuckets buckets;
+  deque<const BNode*> visited;
+  visited.push_back(b);
+  while(1) {
+    if(!b) {
+      break;
+    }
+    if(!b->getBucket().isNull()) {
+      buckets.push_back(b->getBucket());
+      b = b->getUp();
+    } else if(find(visited.begin(), visited.end(), b->getLeft()) == visited.end()) {
+      b = b->getLeft();
+      visited.push_back(b);
+    } else if(find(visited.begin(), visited.end(), b->getRight()) == visited.end()) {
+      b = b->getRight();
+      visited.push_back(b);
+    } else {
+      b = b->getUp();
+    }
+  }
+  return buckets;
+}

+ 85 - 0
src/BNode.h

@@ -0,0 +1,85 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BNODE_H_
+#define _D_BNODE_H_
+
+#include "common.h"
+#include "DHTBucketDecl.h"
+#include "BNodeDecl.h"
+#include "DHTNodeDecl.h"
+
+class BNode {
+private:
+  DHTBucketHandle _bucket;
+
+  BNode* _up;
+
+  BNode* _left;
+  
+  BNode* _right;
+
+public:
+  BNode(const DHTBucketHandle& bucket = 0);
+
+  ~BNode();
+
+  DHTBucketHandle getBucket() const;
+
+  void setBucket(const DHTBucketHandle& bucket);
+
+  BNode* getLeft() const;
+
+  void setLeft(BNode* left);
+
+  BNode* getRight() const;
+
+  void setRight(BNode* right);
+
+  BNode* getUp() const;
+
+  void setUp(BNode* up);
+  
+  bool isInRange(const unsigned char* key) const;
+
+  static BNode* findBNodeFor(BNode* b, const unsigned char* key);
+
+  static DHTBucketHandle findBucketFor(BNode* b, const unsigned char* key);
+
+  static DHTNodes findClosestKNodes(BNode* b, const unsigned char* key);
+
+  static DHTBuckets enumerateBucket(const BNode* b);
+};
+
+#endif // _D_BNODE_H_

+ 44 - 0
src/BNodeDecl.h

@@ -0,0 +1,44 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BNODE_DECL_H_
+#define _D_BNODE_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class BNode;
+
+typedef std::deque<BNode*> BNodes;
+#endif // _D_BNODE_DECL_H_

+ 1 - 2
src/BtContext.h

@@ -36,6 +36,7 @@
 #define _D_BT_CONTEXT_H_
 
 #include "DownloadContext.h"
+#include "BtContextDecl.h"
 
 #define INFO_HASH_LENGTH 20
 #define MAX_PEER_ERROR 5
@@ -81,6 +82,4 @@ public:
 
 };
 
-typedef SharedHandle<BtContext> BtContextHandle;
-
 #endif // _D_BT_CONTEXT_H_

+ 43 - 0
src/BtContextDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_BT_CONTEXT_DECL_H_
+#define _D_BT_CONTEXT_DECL_H_
+
+#include "SharedHandle.h"
+
+class BtContext;
+typedef SharedHandle<BtContext> BtContextHandle;
+
+#endif // _D_BT_CONTEXT_DECL_H_

+ 6 - 0
src/BtHandshakeMessage.cc

@@ -105,3 +105,9 @@ bool BtHandshakeMessage::isExtendedMessagingEnabled() const
 {
   return reserved[5]&0x10;
 }
+
+bool BtHandshakeMessage::isDHTEnabled() const
+{
+  return reserved[7]&0x01;
+}
+

+ 11 - 0
src/BtHandshakeMessage.h

@@ -89,6 +89,17 @@ public:
 
   bool isExtendedMessagingEnabled() const;
 
+  bool isDHTEnabled() const;
+
+  void setDHTEnabled(bool enabled)
+  {
+    if(enabled) {
+      this->reserved[7] |= 0x01;
+    } else {
+      this->reserved[7] &= ~0x01;
+    }
+  }
+
   int8_t getPstrlen() const {
     return pstrlen;
   }

+ 2 - 0
src/BtMessageFactory.h

@@ -88,6 +88,8 @@ public:
 
   virtual BtMessageHandle createAllowedFastMessage(int32_t index) = 0;
 
+  virtual BtMessageHandle createPortMessage(uint16_t port) = 0;
+
   virtual BtMessageHandle createBtExtendedMessage(const ExensionMessageHandle& msg) = 0;
 };
 

+ 60 - 4
src/BtPortMessage.cc

@@ -37,8 +37,20 @@
 #include "DlAbortEx.h"
 #include "Util.h"
 #include "message.h"
+#include "DHTNode.h"
+#include "DHTTaskQueue.h"
+#include "DHTTaskFactory.h"
+#include "DHTTask.h"
 
-BtPortMessageHandle BtPortMessage::create(const unsigned char* data, int32_t dataLength) {
+BtPortMessage::BtPortMessage(uint16_t port): _port(port), _msg(0) {}
+
+BtPortMessage::~BtPortMessage()
+{
+  delete [] _msg;
+}
+
+SharedHandle<BtPortMessage> BtPortMessage::create(const unsigned char* data, int32_t dataLength)
+{
   if(dataLength != 3) {
     throw new DlAbortEx(EX_INVALID_PAYLOAD_SIZE, "port", dataLength, 3);
   }
@@ -46,11 +58,55 @@ BtPortMessageHandle BtPortMessage::create(const unsigned char* data, int32_t dat
   if(id != ID) {
     throw new DlAbortEx(EX_INVALID_BT_MESSAGE_ID, id, "piece", ID);
   }
-  BtPortMessageHandle message = new BtPortMessage();
-  message->setPort(PeerMessageUtil::getShortIntParam(data, 1));
+  uint16_t port = PeerMessageUtil::getShortIntParam(data, 1);
+  SharedHandle<BtPortMessage> message = new BtPortMessage(port);
   return message;
 }
 
+void BtPortMessage::doReceivedAction()
+{
+  if(!_taskFactory.isNull() && !_taskQueue.isNull()) {
+    // node id is random at this point. When ping reply received, new DHTNode
+    // instance created with proper node ID and is added to a routing table.
+    DHTNodeHandle node = new DHTNode();
+    node->setIPAddress(peer->ipaddr);
+    node->setPort(_port);
+    DHTTaskHandle task = _taskFactory->createPingTask(node);
+    _taskQueue->addImmediateTask(task);
+  } else {
+    logger->info("DHT port message received while localhost didn't declare support it.");
+  }
+}
+
+const unsigned char* BtPortMessage::getMessage() {
+  if(!_msg) {
+    /**
+     * len --- 5, 4bytes
+     * id --- 4, 1byte
+     * port --- port number, 2bytes
+     * total: 7bytes
+     */
+    _msg = new unsigned char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(_msg, MESSAGE_LENGTH, 3, ID);
+    PeerMessageUtil::setShortIntParam(&_msg[5], _port);
+  }
+  return _msg;
+}
+
+int32_t BtPortMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
 string BtPortMessage::toString() const {
-  return "port port="+Util::itos(port);
+  return "port port="+Util::uitos(_port);
+}
+
+void BtPortMessage::setTaskQueue(const WeakHandle<DHTTaskQueue>& taskQueue)
+{
+  _taskQueue = taskQueue;
+}
+
+void BtPortMessage::setTaskFactory(const WeakHandle<DHTTaskFactory>& taskFactory)
+{
+  _taskFactory = taskFactory;
 }

+ 22 - 15
src/BtPortMessage.h

@@ -35,36 +35,43 @@
 #ifndef _D_BT_PORT_MESSAGE_H_
 #define _D_BT_PORT_MESSAGE_H_
 
-#include "AbstractBtMessage.h"
+#include "SimpleBtMessage.h"
+#include "DHTTaskQueueDecl.h"
+#include "DHTTaskFactoryDecl.h"
 
-class BtPortMessage;
+class BtPortMessage : public SimpleBtMessage {
+private:
+  uint16_t _port;
+  unsigned char* _msg;
+  static const size_t MESSAGE_LENGTH = 7;
 
-typedef SharedHandle<BtPortMessage> BtPortMessageHandle;
+  WeakHandle<DHTTaskQueue> _taskQueue;
 
-class BtPortMessage : public AbstractBtMessage {
-private:
-  int16_t port;
+  WeakHandle<DHTTaskFactory> _taskFactory;
 public:
-  BtPortMessage(int16_t port = 0):port(port) {}
+  BtPortMessage(uint16_t port);
 
-  virtual ~BtPortMessage() {}
+  virtual ~BtPortMessage();
 
   static const int8_t ID = 9;
 
-  int16_t getPort() const { return port; }
+  uint16_t getPort() const { return _port; }
 
-  void setPort(int16_t port) { this->port = port; }
+  static SharedHandle<BtPortMessage> create(const unsigned char* data, int32_t dataLength);
 
   virtual int8_t getId() { return ID; }
 
-  static BtPortMessageHandle create(const unsigned char* data, int32_t dataLength);
+  virtual void doReceivedAction();
+
+  virtual const unsigned char* getMessage();
 
-  virtual void doReceivedAction() {
-    logger->info("DHT is not supported yet.");
-  }
-  virtual void send() {}
+  virtual int32_t getMessageLength();
 
   virtual string toString() const;
+
+  void setTaskQueue(const WeakHandle<DHTTaskQueue>& taskQueue);
+
+  void setTaskFactory(const WeakHandle<DHTTaskFactory>& taskFactory);
 };
 
 #endif // _D_BT_PORT_MESSAGE_H_

+ 15 - 2
src/BtSetup.cc

@@ -54,6 +54,10 @@
 #include "Logger.h"
 #include "Util.h"
 #include "IntSequence.h"
+#include "DHTGetPeersCommand.h"
+#include "DHTPeerAnnounceStorage.h"
+#include "DHTSetup.h"
+#include "DHTRegistry.h"
 
 BtSetup::BtSetup():_logger(LogFactory::getInstance()) {}
 
@@ -80,8 +84,17 @@ Commands BtSetup::setup(RequestGroup* requestGroup,
 						     requestGroup,
 						     e,
 						     btContext,
-						     30));
-
+						     10));
+  if(!btContext->isPrivate() && DHTSetup::initialized()) {
+    DHTRegistry::_peerAnnounceStorage->addPeerAnnounce(btContext);
+    DHTGetPeersCommand* command = new DHTGetPeersCommand(CUIDCounterSingletonHolder::instance()->newID(),
+							 requestGroup,
+							 e,
+							 btContext);
+    command->setTaskQueue(DHTRegistry::_taskQueue);
+    command->setTaskFactory(DHTRegistry::_taskFactory);
+    commands.push_back(command);
+  }
   SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
   if(option->defined(PREF_SEED_TIME)) {
     unionCri->addSeedCriteria(new TimeSeedCriteria(option->getAsInt(PREF_SEED_TIME)*60));

+ 90 - 0
src/DHTAbstractMessage.cc

@@ -0,0 +1,90 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTAbstractMessage.h"
+#include "DHTNode.h"
+#include "BencodeVisitor.h"
+#include "DHTConnection.h"
+#include "Data.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageFactory.h"
+#include "DHTRoutingTable.h"
+
+DHTAbstractMessage::DHTAbstractMessage(const DHTNodeHandle& localNode,
+				       const DHTNodeHandle& remoteNode,
+				       const string& transactionID):
+  DHTMessage(localNode, remoteNode, transactionID) {}
+
+DHTAbstractMessage::~DHTAbstractMessage() {}
+
+string DHTAbstractMessage::getBencodedMessage()
+{
+  SharedHandle<Dictionary> msg = new Dictionary();
+  msg->put(string("t"), new Data(_transactionID));
+  msg->put(string("y"), new Data(getType()));
+  fillMessage(msg.get());
+  
+  BencodeVisitor v;
+  msg->accept(&v);
+  return v.getBencodedData();
+}
+
+void DHTAbstractMessage::send()
+{
+  string message = getBencodedMessage();
+  _connection->sendMessage(message.c_str(),
+			   message.size(),
+			   _remoteNode->getIPAddress(),
+			   _remoteNode->getPort());
+}
+
+void DHTAbstractMessage::setConnection(const WeakHandle<DHTConnection>& connection)
+{
+  _connection = connection;
+}
+
+void DHTAbstractMessage::setMessageDispatcher(const WeakHandle<DHTMessageDispatcher>& dispatcher)
+{
+  _dispatcher = dispatcher;
+}
+
+void DHTAbstractMessage::setMessageFactory(const WeakHandle<DHTMessageFactory>& factory)
+{
+  _factory = factory;
+}
+
+void DHTAbstractMessage::setRoutingTable(const WeakHandle<DHTRoutingTable>& routingTable)
+{
+  _routingTable = routingTable;
+}

+ 78 - 0
src/DHTAbstractMessage.h

@@ -0,0 +1,78 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ABSTRACT_MESSAGE_H_
+#define _D_DHT_ABSTRACT_MESSAGE_H_
+
+#include "DHTMessage.h"
+#include "Dictionary.h"
+#include "DHTConnectionDecl.h"
+#include "DHTMessageDispatcherDecl.h"
+#include "DHTMessageFactoryDecl.h"
+#include "DHTRoutingTableDecl.h"
+
+class DHTAbstractMessage:public DHTMessage {
+protected:
+  WeakHandle<DHTConnection> _connection;
+
+  WeakHandle<DHTMessageDispatcher> _dispatcher;
+
+  WeakHandle<DHTMessageFactory> _factory;
+
+  WeakHandle<DHTRoutingTable> _routingTable;
+public:
+  DHTAbstractMessage(const DHTNodeHandle& localNode,
+		     const DHTNodeHandle& remoteNode,
+		     const string& transactionID = "");
+
+  virtual ~DHTAbstractMessage();
+
+  virtual void send();
+
+  virtual string getType() const = 0;
+
+  virtual void fillMessage(Dictionary* message) = 0;
+
+  string getBencodedMessage();
+
+  void setConnection(const WeakHandle<DHTConnection>& connection);
+
+  void setMessageDispatcher(const WeakHandle<DHTMessageDispatcher>& dispatcher);
+  
+  void setMessageFactory(const WeakHandle<DHTMessageFactory>& factory);
+
+  void setRoutingTable(const WeakHandle<DHTRoutingTable>& routingTable);
+};
+
+#endif // _D_DHT_ABSTRACT_MESSAGE_H_

+ 150 - 0
src/DHTAbstractNodeLookupTask.cc

@@ -0,0 +1,150 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTAbstractNodeLookupTask.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessage.h"
+#include "DHTNode.h"
+#include "DHTNodeLookupEntry.h"
+#include "DHTMessageCallbackImpl.h"
+#include "DHTBucket.h"
+#include "LogFactory.h"
+#include "Util.h"
+#include "DHTIDCloser.h"
+
+DHTAbstractNodeLookupTask::DHTAbstractNodeLookupTask(const unsigned char* targetID):
+  _inFlightMessage(0)
+{
+  memcpy(_targetID, targetID, DHT_ID_LENGTH);
+}
+
+void DHTAbstractNodeLookupTask::onReceived(const DHTMessageHandle& message)
+{
+  --_inFlightMessage;
+  onReceivedInternal(message);
+  DHTNodeLookupEntries newEntries = toEntries(getNodesFromMessage(message));
+  size_t count = 0;
+  for(DHTNodeLookupEntries::const_iterator i = newEntries.begin();
+      i != newEntries.end(); ++i) {
+    if(memcmp(_localNode->getID(), (*i)->_node->getID(), DHT_ID_LENGTH) != 0) {
+      _entries.push_front(*i);
+      ++count;
+    }
+  }
+  _logger->debug("%u node lookup entries added.", count);
+  stable_sort(_entries.begin(), _entries.end(), DHTIDCloser(_targetID));
+  _entries.erase(unique(_entries.begin(), _entries.end()), _entries.end());
+  _logger->debug("%u node lookup entries are unique.", _entries.size());
+  if(_entries.size() > DHTBucket::K) {
+    _entries.erase(_entries.begin()+DHTBucket::K, _entries.end());
+  }
+  if(needsAdditionalOutgoingMessage()) {
+    sendMessage();
+  }
+  if(_inFlightMessage == 0) {
+    _logger->debug("Finished node_lookup for node ID %s",
+		   Util::toHex(_targetID, DHT_ID_LENGTH).c_str());
+    onFinish();
+    updateBucket();
+    _finished = true;
+  }
+}
+
+void DHTAbstractNodeLookupTask::onTimeout(const DHTNodeHandle& node)
+{
+  _logger->debug("node lookup message timeout for node ID=%s",
+		 Util::toHex(node->getID(), DHT_ID_LENGTH).c_str());
+  --_inFlightMessage;
+  for(DHTNodeLookupEntries::iterator i = _entries.begin(); i != _entries.end(); ++i) {
+    if((*i)->_node == node) {
+      _entries.erase(i);
+      break;
+    }
+  }
+  if(needsAdditionalOutgoingMessage()) {
+    sendMessage();
+  }
+  if(_inFlightMessage == 0) {
+    _logger->debug("Finished node_lookup for node ID %s",
+		   Util::toHex(_targetID, DHT_ID_LENGTH).c_str());
+    onFinish();
+    updateBucket();
+    _finished = true;
+  }  
+}
+
+void DHTAbstractNodeLookupTask::sendMessage()
+{
+  for(DHTNodeLookupEntries::iterator i = _entries.begin(); i != _entries.end() && _inFlightMessage < ALPHA; ++i) {
+    if((*i)->_used == false) {
+      ++_inFlightMessage;
+      (*i)->_used = true;
+      DHTMessageHandle m = createMessage((*i)->_node);
+      _dispatcher->addMessageToQueue(m, new DHTMessageCallbackImpl(this));
+    }
+  }
+}
+
+void DHTAbstractNodeLookupTask::updateBucket()
+{
+  // TODO we have to something here?
+}
+
+void DHTAbstractNodeLookupTask::startup()
+{
+  _entries = toEntries(_routingTable->getClosestKNodes(_targetID));
+  if(_entries.empty()) {
+    _finished = true;
+  } else {
+    // TODO use RTT here
+    _inFlightMessage = 0;
+    sendMessage();
+    if(_inFlightMessage == 0) {
+      _logger->debug("No message was sent in this lookup stage. Finished.");
+      _finished = true;
+    }
+  }
+}
+
+DHTNodeLookupEntries DHTAbstractNodeLookupTask::toEntries(const DHTNodes& nodes) const
+{
+  DHTNodeLookupEntries entries;
+  for(DHTNodes::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
+    DHTNodeLookupEntryHandle e = new DHTNodeLookupEntry(*i);
+    entries.push_back(e);
+  }
+  return entries;
+}

+ 82 - 0
src/DHTAbstractNodeLookupTask.h

@@ -0,0 +1,82 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ABSTRACT_NODE_LOOKUP_TASK_H_
+#define _D_DHT_ABSTRACT_NODE_LOOKUP_TASK_H_
+
+#include "DHTAbstractTask.h"
+#include "DHTNodeDecl.h"
+#include "DHTNodeLookupEntryDecl.h"
+#include "DHTConstants.h"
+#include "DHTTask.h"
+#include "DHTMessageDecl.h"
+#include "DHTMessageCallbackListener.h"
+
+class DHTAbstractNodeLookupTask:public DHTAbstractTask, public DHTMessageCallbackListener {
+protected:
+  unsigned char _targetID[DHT_ID_LENGTH];
+
+  DHTNodeLookupEntries _entries;
+  
+  size_t _inFlightMessage;
+
+  DHTNodeLookupEntries toEntries(const DHTNodes& nodes) const;
+
+  void sendMessage();
+
+  void updateBucket();
+
+public:
+  DHTAbstractNodeLookupTask(const unsigned char* targetID);
+
+  static const size_t ALPHA = 3;
+
+  virtual void startup();
+
+  virtual void onReceived(const DHTMessageHandle& message);
+
+  virtual void onTimeout(const DHTNodeHandle& node);
+
+  virtual DHTNodes getNodesFromMessage(const DHTMessageHandle& message) = 0;
+  
+  virtual void onReceivedInternal(const DHTMessageHandle& message) {}
+  
+  virtual bool needsAdditionalOutgoingMessage() { return true; }
+  
+  virtual void onFinish() {}
+
+  virtual DHTMessageHandle createMessage(const DHTNodeHandle& remoteNode) = 0;
+};
+
+#endif // _D_DHT_ABSTRACT_NODE_LOOKUP_TASK_H_

+ 81 - 0
src/DHTAbstractTask.cc

@@ -0,0 +1,81 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTAbstractTask.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessage.h"
+#include "DHTNode.h"
+#include "DHTMessageCallback.h"
+#include "DHTBucket.h"
+#include "DHTTaskQueue.h"
+#include "LogFactory.h"
+#include "Util.h"
+
+DHTAbstractTask::DHTAbstractTask():
+  _finished(false),
+  _logger(LogFactory::getInstance()),
+  _localNode(0)
+{}
+
+bool DHTAbstractTask::finished()
+{
+  return _finished;
+}
+
+void DHTAbstractTask::setRoutingTable(const WeakHandle<DHTRoutingTable> routingTable)
+{
+  _routingTable = routingTable;
+}
+
+void DHTAbstractTask::setMessageDispatcher(const WeakHandle<DHTMessageDispatcher> dispatcher)
+{
+  _dispatcher = dispatcher;
+}
+
+void DHTAbstractTask::setMessageFactory(const WeakHandle<DHTMessageFactory> factory)
+{
+  _factory = factory;
+}
+
+void DHTAbstractTask::setTaskQueue(const WeakHandle<DHTTaskQueue> taskQueue)
+{
+  _taskQueue = taskQueue;
+}
+
+void DHTAbstractTask::setLocalNode(const DHTNodeHandle& localNode)
+{
+  _localNode = localNode;
+}

+ 82 - 0
src/DHTAbstractTask.h

@@ -0,0 +1,82 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ABSTRACT_TASK_H_
+#define _D_DHT_ABSTRACT_TASK_H_
+
+#include "common.h"
+#include "DHTAbstractTaskDecl.h"
+#include "DHTNodeDecl.h"
+#include "DHTRoutingTableDecl.h"
+#include "DHTMessageDispatcherDecl.h"
+#include "DHTMessageFactoryDecl.h"
+#include "DHTConstants.h"
+#include "DHTTask.h"
+#include "DHTMessageDecl.h"
+#include "DHTTaskQueueDecl.h"
+
+class Logger;
+
+class DHTAbstractTask:public DHTTask {
+protected:
+  bool _finished;
+  
+  const Logger* _logger;
+  
+  DHTNodeHandle _localNode;
+
+  WeakHandle<DHTRoutingTable> _routingTable;
+
+  WeakHandle<DHTMessageDispatcher> _dispatcher;
+
+  WeakHandle<DHTMessageFactory> _factory;
+  
+  WeakHandle<DHTTaskQueue> _taskQueue;
+public:
+  DHTAbstractTask();
+
+  virtual bool finished();
+
+  void setRoutingTable(const WeakHandle<DHTRoutingTable> routingTable);
+
+  void setMessageDispatcher(const WeakHandle<DHTMessageDispatcher> dispatcher);
+
+  void setMessageFactory(const WeakHandle<DHTMessageFactory> factory);
+
+  void setTaskQueue(const WeakHandle<DHTTaskQueue> taskQueue);
+
+  void setLocalNode(const DHTNodeHandle& localNode);
+};
+
+#endif // _D_DHT_ABSTRACT_TASK_H_

+ 43 - 0
src/DHTAbstractTaskDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ABSTRACT_TASK_DECL_H_
+#define _D_DHT_ABSTRACT_TASK_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTAbstractTask;
+typedef SharedHandle<DHTAbstractTask> DHTAbstractTaskHandle;
+
+#endif // _D_DHT_ABSTRACT_TASK_DECL_H_

+ 113 - 0
src/DHTAnnouncePeerMessage.cc

@@ -0,0 +1,113 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTAnnouncePeerMessage.h"
+#include "DHTNode.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageCallback.h"
+#include "Util.h"
+#include "DHTPeerAnnounceStorage.h"
+#include "DHTTokenTracker.h"
+#include "DlAbortEx.h"
+
+DHTAnnouncePeerMessage::DHTAnnouncePeerMessage(const DHTNodeHandle& localNode,
+					       const DHTNodeHandle& remoteNode,
+					       const unsigned char* infoHash,
+					       uint16_t tcpPort,
+					       const string& token,
+					       const string& transactionID):
+  DHTQueryMessage(localNode, remoteNode, transactionID),
+  _token(token),
+  _tcpPort(tcpPort),
+  _peerAnnounceStorage(0),
+  _tokenTracker(0)
+{
+  memcpy(_infoHash, infoHash, DHT_ID_LENGTH);
+}
+
+DHTAnnouncePeerMessage::~DHTAnnouncePeerMessage() {}
+
+void DHTAnnouncePeerMessage::doReceivedAction()
+{
+  _peerAnnounceStorage->addPeerAnnounce(_infoHash, _remoteNode->getIPAddress(),
+					_tcpPort);
+
+  DHTMessageHandle reply =
+    _factory->createAnnouncePeerReplyMessage(_remoteNode, _transactionID);
+  _dispatcher->addMessageToQueue(reply);
+}
+
+Dictionary* DHTAnnouncePeerMessage::getArgument()
+{
+  Dictionary* a = new Dictionary();
+  a->put("id", new Data(reinterpret_cast<const char*>(_localNode->getID()),
+			DHT_ID_LENGTH));
+  a->put("info_hash", new Data(reinterpret_cast<const char*>(_infoHash),
+			       DHT_ID_LENGTH));
+  a->put("port", new Data(Util::uitos(_tcpPort), true));
+  a->put("token", new Data(_token));
+  
+  return a;
+}
+
+string DHTAnnouncePeerMessage::getMessageType() const
+{
+  return "announce_peer";
+}
+
+void DHTAnnouncePeerMessage::validate() const
+{
+  if(!_tokenTracker->validateToken(_token, _infoHash,
+				   _remoteNode->getIPAddress(),
+				   _remoteNode->getPort())) {
+    throw new DlAbortEx("Invalid token=%s from %s:%u",
+			Util::toHex(_token).c_str(),
+			_remoteNode->getIPAddress().c_str(),
+			_remoteNode->getPort());
+  }
+}
+
+void DHTAnnouncePeerMessage::setPeerAnnounceStorage(const WeakHandle<DHTPeerAnnounceStorage>& storage)
+{
+  _peerAnnounceStorage = storage;
+}
+
+void DHTAnnouncePeerMessage::setTokenTracker(const WeakHandle<DHTTokenTracker>& tokenTracker)
+{
+  _tokenTracker = tokenTracker;
+}

+ 92 - 0
src/DHTAnnouncePeerMessage.h

@@ -0,0 +1,92 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ANNOUNCE_PEER_MESSAGE_H_
+#define _D_DHT_ANNOUNCE_PEER_MESSAGE_H_
+
+#include "DHTQueryMessage.h"
+#include "DHTConstants.h"
+#include "DHTPeerAnnounceStorage.h"
+#include "DHTTokenTrackerDecl.h"
+
+class DHTAnnouncePeerMessage:public DHTQueryMessage {
+private:
+  string _token;
+
+  unsigned char _infoHash[DHT_ID_LENGTH];
+
+  uint16_t _tcpPort;
+
+  WeakHandle<DHTPeerAnnounceStorage> _peerAnnounceStorage;
+
+  WeakHandle<DHTTokenTracker> _tokenTracker;
+public:
+  DHTAnnouncePeerMessage(const DHTNodeHandle& localNode,
+			 const DHTNodeHandle& remoteNode,
+			 const unsigned char* infoHash,
+			 uint16_t tcpPort,
+			 const string& token,
+			 const string& transactionID = "");
+
+  virtual ~DHTAnnouncePeerMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getArgument();
+  
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+
+  const unsigned char* getInfoHash() const
+  {
+    return _infoHash;
+  }
+
+  const string& getToken() const
+  {
+    return _token;
+  }
+
+  uint16_t getTCPPort() const
+  {
+    return _tcpPort;
+  }
+
+  void setPeerAnnounceStorage(const WeakHandle<DHTPeerAnnounceStorage>& storage);
+
+  void setTokenTracker(const WeakHandle<DHTTokenTracker>& tokenTracker);
+};
+
+#endif // _D_DHT_ANNOUNCE_PEER_MESSAGE_H_

+ 61 - 0
src/DHTAnnouncePeerReplyMessage.cc

@@ -0,0 +1,61 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTAnnouncePeerReplyMessage.h"
+#include "DHTNode.h"
+#include "Dictionary.h"
+#include "Data.h"
+
+DHTAnnouncePeerReplyMessage::DHTAnnouncePeerReplyMessage(const DHTNodeHandle& localNode,
+							 const DHTNodeHandle& remoteNode,
+							 const string& transactionID):
+  DHTResponseMessage(localNode, remoteNode, transactionID) {}
+
+DHTAnnouncePeerReplyMessage::~DHTAnnouncePeerReplyMessage() {}
+
+void DHTAnnouncePeerReplyMessage::doReceivedAction() {}
+
+Dictionary* DHTAnnouncePeerReplyMessage::getResponse()
+{
+  Dictionary* r = new Dictionary();
+  r->put("id", new Data(_localNode->getID(), DHT_ID_LENGTH));
+  return r;
+}
+
+string DHTAnnouncePeerReplyMessage::getMessageType() const
+{
+  return "announce_peer";
+}
+
+void DHTAnnouncePeerReplyMessage::validate() const {}

+ 57 - 0
src/DHTAnnouncePeerReplyMessage.h

@@ -0,0 +1,57 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ANNOUNCE_PEER_REPLY_MESSAGE_H_
+#define _D_DHT_ANNOUNCE_PEER_REPLY_MESSAGE_H_
+
+#include "DHTResponseMessage.h"
+
+class DHTAnnouncePeerReplyMessage:public DHTResponseMessage {
+public:
+  DHTAnnouncePeerReplyMessage(const DHTNodeHandle& localNode,
+			      const DHTNodeHandle& remoteNode,
+			      const string& transactionID);
+
+  virtual ~DHTAnnouncePeerReplyMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getResponse();
+
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+};
+
+#endif // _D_DHT_ANNOUNCE_PEER_REPLY_MESSAGE_H_

+ 109 - 0
src/DHTAutoSaveCommand.cc

@@ -0,0 +1,109 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTAutoSaveCommand.h"
+#include "DHTRoutingTable.h"
+#include "DHTNode.h"
+#include "File.h"
+#include "DHTRoutingTableSerializer.h"
+#include "RecoverableException.h"
+#include "DownloadEngine.h"
+#include "Util.h"
+#include "DHTBucket.h"
+#include "RequestGroupMan.h"
+#include "prefs.h"
+#include "Option.h"
+#include <fstream>
+
+DHTAutoSaveCommand::DHTAutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval):
+  TimeBasedCommand(cuid, e, interval),
+  _localNode(0),
+  _routingTable(0) {}
+
+DHTAutoSaveCommand::~DHTAutoSaveCommand() {}
+
+void DHTAutoSaveCommand::preProcess()
+{
+  if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
+    save();
+    _exit = true;
+  }
+}
+
+void DHTAutoSaveCommand::process()
+{
+  save();
+}
+
+void DHTAutoSaveCommand::save()
+{
+  DHTNodes nodes;
+  DHTBuckets buckets = _routingTable->getBuckets();
+  for(DHTBuckets::const_iterator i = buckets.begin(); i != buckets.end(); ++i) {
+    const DHTBucketHandle& bucket = *i;
+    DHTNodes goodNodes = bucket->getGoodNodes();
+    nodes.insert(nodes.end(), goodNodes.begin(), goodNodes.end());
+  }
+
+  DHTRoutingTableSerializer serializer;
+  serializer.setLocalNode(_localNode);
+  serializer.setNodes(nodes);
+
+  string dhtFile = _e->option->get(PREF_DHT_FILE_PATH);
+  string tempFile = dhtFile+"__temp";
+  ofstream o(tempFile.c_str(), ios::out|ios::binary);
+  o.exceptions(ios::failbit);
+  try {
+    serializer.serialize(o);
+
+    if(!File(tempFile).renameTo(dhtFile)) {
+      logger->error("Cannot move file from %s to %s.",
+		    tempFile.c_str(), dhtFile.c_str());
+    }
+  } catch(RecoverableException* e) {
+    logger->error("Exception caught while saving DHT routing table to %s",
+		  e, tempFile.c_str());
+    delete e;
+  }
+}
+
+void DHTAutoSaveCommand::setLocalNode(const DHTNodeHandle& localNode)
+{
+  _localNode = localNode;
+}
+
+void DHTAutoSaveCommand::setRoutingTable(const DHTRoutingTableHandle& routingTable)
+{
+  _routingTable = routingTable;
+}

+ 64 - 0
src/DHTAutoSaveCommand.h

@@ -0,0 +1,64 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_AUTO_SAVE_COMMAND_H_
+#define _D_DHT_AUTO_SAVE_COMMAND_H_
+
+#include "TimeBasedCommand.h"
+#include "DHTRoutingTableDecl.h"
+#include "DHTNodeDecl.h"
+
+class DHTAutoSaveCommand : public TimeBasedCommand
+{
+private:
+  DHTNodeHandle _localNode;
+  
+  DHTRoutingTableHandle _routingTable;
+
+  void save();
+public:
+  DHTAutoSaveCommand(int32_t cuid, DownloadEngine* e, int32_t interval);
+
+  virtual ~DHTAutoSaveCommand();
+
+  virtual void preProcess();
+
+  virtual void process();
+
+  void setLocalNode(const DHTNodeHandle& localNode);
+
+  void setRoutingTable(const DHTRoutingTableHandle& routingTable);
+};
+
+#endif // _D_DHT_AUTO_SAVE_COMMAND_H_

+ 281 - 0
src/DHTBucket.cc

@@ -0,0 +1,281 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTBucket.h"
+#include "DHTUtil.h"
+#include "DHTNode.h"
+#include "LogFactory.h"
+#include "Util.h"
+#include "DHTConstants.h"
+#include "a2functional.h"
+
+DHTBucket::DHTBucket(uint32_t prefixLength,
+		     const unsigned char* max, const unsigned char* min,
+		     const DHTNodeHandle& localNode):
+  _prefixLength(prefixLength),
+  _localNode(localNode),
+  _logger(LogFactory::getInstance())
+{
+  memcpy(_max, max, DHT_ID_LENGTH);
+  memcpy(_min, min, DHT_ID_LENGTH);
+}
+
+DHTBucket::DHTBucket(const DHTNodeHandle& localNode):
+  _prefixLength(0),
+  _localNode(localNode),
+  _logger(LogFactory::getInstance())
+{
+  memset(_max, 0xff, DHT_ID_LENGTH);
+  memset(_min, 0, DHT_ID_LENGTH);
+}
+
+DHTBucket::~DHTBucket() {}
+
+void DHTBucket::getRandomNodeID(unsigned char* nodeID) const
+{
+  if(_prefixLength == 0) {
+    DHTUtil::generateRandomKey(nodeID);
+  } else {
+    size_t lastByteIndex = (_prefixLength-1)/8;
+    DHTUtil::generateRandomKey(nodeID);
+    memcpy(nodeID, _min, lastByteIndex+1);
+  }
+}
+
+bool DHTBucket::isInRange(const DHTNodeHandle& node) const
+{
+  return isInRange(node->getID());
+}
+
+bool DHTBucket::isInRange(const unsigned char* nodeID) const
+{
+  for(size_t i = 0; i < DHT_ID_LENGTH; ++i) {
+    if(nodeID[i] < _min[i]) {
+      return false;
+    } else if(_min[i] < nodeID[i]) {
+      break;
+    }
+  }
+  for(size_t i = 0; i < DHT_ID_LENGTH; ++i) {
+    if(_max[i] < nodeID[i]) {
+      return false;
+    } else if(nodeID[i] < _max[i]) {
+      break;
+    }
+  }
+  return true;
+}
+
+bool DHTBucket::addNode(const DHTNodeHandle& node)
+{
+  notifyUpdate();
+  DHTNodes::iterator itr = find(_nodes.begin(), _nodes.end(), node);
+  if(itr == _nodes.end()) {
+    if(_nodes.size() < K) {
+      _nodes.push_back(node);
+      return true;
+    } else {
+      if(_nodes.front()->isBad()) {
+	_nodes.erase(_nodes.begin());
+	_nodes.push_back(node);
+	return true;
+      } else {
+	return false;
+      }
+	/*
+      } else if(splitAllowed()) {
+	return false;
+      } else {
+	DHTNodes::iterator ci = find(_cachedNodes.begin(), _cachedNodes.end(), node);
+	if(ci == _cachedNodes.end()) {
+	  _cachedNodes.push_back(node);
+	  if(_cachedNodes.size() > CACHE_SIZE) {
+	    _cachedNodes.erase(_cachedNodes.begin(), _cachedNodes().begin()+CACHE_SIZE-_cachedNodes.size());
+	  }
+	} else {
+	  _cachedNodes.erase(ci);
+	  _cachedNodes.push_back(node);
+	}
+	return true;
+      }
+	*/
+    }
+  } else {
+    _nodes.erase(itr);
+    _nodes.push_back(node);
+    return true;
+  }
+}
+
+void DHTBucket::dropNode(const DHTNodeHandle& node)
+{
+  return;
+  /*
+  DHTNodes::iterator itr = find(_nodes.begin(), _nodes.end(), node);
+  if(itr != _nodes.end()) {
+    _nodes.erase(itr);
+    if(_cachedNodes.size()) {
+      _nodes.push_back(_cachedNodes.back());
+      _cachedNodes.erase(_cachedNodes.begin()+_cachedNodes.size()-1);
+    }
+  }
+  */
+}
+
+void DHTBucket::moveToHead(const DHTNodeHandle& node)
+{
+  DHTNodes::iterator itr = find(_nodes.begin(), _nodes.end(), node);
+  if(itr != _nodes.end()) {
+    _nodes.erase(itr);
+    _nodes.push_front(node);
+  }
+}
+
+void DHTBucket::moveToTail(const DHTNodeHandle& node)
+{
+  DHTNodes::iterator itr = find(_nodes.begin(), _nodes.end(), node);
+  if(itr != _nodes.end()) {
+    _nodes.erase(itr);
+    _nodes.push_back(node);
+  }
+}
+
+bool DHTBucket::splitAllowed() const
+{
+  return _prefixLength < DHT_ID_LENGTH*8-1 && isInRange(_localNode);
+}
+
+DHTBucketHandle DHTBucket::split()
+{
+  assert(splitAllowed());
+  size_t newPrefixLength = _prefixLength+1;
+
+  unsigned char rMax[DHT_ID_LENGTH];
+  memcpy(rMax, _max, DHT_ID_LENGTH);
+  DHTUtil::flipBit(rMax, DHT_ID_LENGTH, _prefixLength);
+
+  DHTBucketHandle rBucket = new DHTBucket(newPrefixLength,
+					  rMax, _min, _localNode);
+  DHTNodes tempNodes = _nodes;
+  for(DHTNodes::iterator i = tempNodes.begin(); i != tempNodes.end();) {
+    if(rBucket->isInRange(*i)) {
+      assert(rBucket->addNode(*i));
+      i = tempNodes.erase(i);
+    } else {
+      ++i;
+    }
+  }
+  DHTUtil::flipBit(_min, DHT_ID_LENGTH, _prefixLength);
+  _prefixLength = newPrefixLength;
+  _nodes = tempNodes;
+  // TODO create toString() and use it.
+  _logger->debug("New bucket. Range:%s-%s",
+ 		 Util::toHex(rBucket->getMinID(), DHT_ID_LENGTH).c_str(),
+ 		 Util::toHex(rBucket->getMaxID(), DHT_ID_LENGTH).c_str());
+  _logger->debug("Existing bucket. Range:%s-%s",
+		 Util::toHex(getMinID(), DHT_ID_LENGTH).c_str(),
+		 Util::toHex(getMaxID(), DHT_ID_LENGTH).c_str());
+
+  return rBucket;
+}
+
+size_t DHTBucket::countNode() const
+{
+  return _nodes.size();
+}
+
+const DHTNodes& DHTBucket::getNodes() const
+{
+  return _nodes;
+}
+
+DHTNodes DHTBucket::getGoodNodes() const
+{
+  DHTNodes goodNodes = _nodes;
+  goodNodes.erase(remove_if(goodNodes.begin(), goodNodes.end(),
+			    mem_fun_sh(&DHTNode::isBad)), goodNodes.end());
+  return goodNodes;
+}
+
+DHTNodeHandle DHTBucket::getNode(const unsigned char* nodeID, const string& ipaddr, uint16_t port) const
+{
+  DHTNodeHandle node = new DHTNode(nodeID);
+  node->setIPAddress(ipaddr);
+  node->setPort(port);
+  DHTNodes::const_iterator itr = find(_nodes.begin(), _nodes.end(), node);
+  if(itr == _nodes.end()) {
+    return 0;
+  } else {
+    return *itr;
+  }
+}
+
+bool DHTBucket::operator==(const DHTBucket& bucket) const
+{
+  return memcmp(_max, bucket._max, DHT_ID_LENGTH) == 0 &&
+    memcmp(_min, bucket._min, DHT_ID_LENGTH) == 0;
+}
+
+bool DHTBucket::needsRefresh() const
+{
+  return _nodes.size() < K || _lastUpdated.elapsed(DHT_BUCKET_REFRESH_INTERVAL);
+}
+
+void DHTBucket::notifyUpdate()
+{
+  _lastUpdated.reset();
+}
+
+class FindQuestionableNode {
+public:
+  bool operator()(const DHTNodeHandle& node) const
+  {
+    return node->isQuestionable();
+  }
+};
+
+bool DHTBucket::containsQuestionableNode() const
+{
+  return find_if(_nodes.begin(), _nodes.end(), FindQuestionableNode()) != _nodes.end();
+}
+
+DHTNodeHandle DHTBucket::getLRUQuestionableNode() const
+{
+  DHTNodes::const_iterator i = find_if(_nodes.begin(), _nodes.end(), FindQuestionableNode());
+  if(i == _nodes.end()) {
+    return 0;
+  } else {
+    return *i;
+  }
+}

+ 132 - 0
src/DHTBucket.h

@@ -0,0 +1,132 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_BUCKET_H_
+#define _D_DHT_BUCKET_H_
+
+#include "common.h"
+#include "DHTConstants.h"
+#include "DHTNodeDecl.h"
+#include "DHTBucketDecl.h"
+#include "TimeA2.h"
+
+class Logger;
+
+class DHTBucket {
+private:
+  size_t _prefixLength;
+
+  // this bucket contains nodes of distance between [_min, _max](inclusive).
+  unsigned char _min[DHT_ID_LENGTH];
+
+  unsigned char _max[DHT_ID_LENGTH];
+
+  DHTNodeHandle _localNode;
+
+  // sorted in ascending order
+  DHTNodes _nodes;
+
+  DHTNodes _cachedNodes;
+
+  Time _lastUpdated;
+
+  const Logger* _logger;
+public:
+  DHTBucket(const DHTNodeHandle& localNode);
+
+  DHTBucket(size_t prefixLength,
+	    const unsigned char* max, const unsigned char* min,
+	    const DHTNodeHandle& localNode);
+
+  ~DHTBucket();
+
+  static const size_t K = 8;
+
+  static const size_t CACHE_SIZE = 2;
+
+  void getRandomNodeID(unsigned char* nodeID) const;
+
+  DHTBucketHandle split();
+
+  bool isInRange(const DHTNodeHandle& node) const;
+
+  bool isInRange(const unsigned char* nodeID) const;
+
+  bool addNode(const DHTNodeHandle& node);
+
+  bool splitAllowed() const;
+  
+  size_t getPrefixLength() const
+  {
+    return _prefixLength;
+  }
+
+  const unsigned char* getMaxID() const
+  {
+    return _max;
+  }
+
+  const unsigned char* getMinID() const
+  {
+    return _min;
+  }
+
+  size_t countNode() const;
+
+  const DHTNodes& getNodes() const;
+
+  DHTNodes getGoodNodes() const;
+
+  void dropNode(const DHTNodeHandle& node);
+
+  void moveToHead(const DHTNodeHandle& node);
+
+  void moveToTail(const DHTNodeHandle& node);
+
+  bool contains(const DHTNodeHandle& node) const;
+
+  DHTNodeHandle getNode(const unsigned char* nodeID, const string& ipaddr, uint16_t port) const;
+
+  bool operator==(const DHTBucket& bucket) const;
+
+  bool needsRefresh() const;
+
+  void notifyUpdate();
+
+  bool containsQuestionableNode() const;
+
+  DHTNodeHandle getLRUQuestionableNode() const;
+};
+
+#endif // _D_DHT_BUCKET_H_

+ 45 - 0
src/DHTBucketDecl.h

@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_BUCKET_DECL_H_
+#define _D_DHT_BUCKET_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTBucket;
+typedef SharedHandle<DHTBucket> DHTBucketHandle;
+typedef std::deque<DHTBucketHandle> DHTBuckets;
+
+#endif // _D_DHT_BUCKET_DECL_H_

+ 75 - 0
src/DHTBucketRefreshCommand.cc

@@ -0,0 +1,75 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTBucketRefreshCommand.h"
+#include "DHTRoutingTable.h"
+#include "DHTTaskQueue.h"
+#include "DHTTaskFactory.h"
+#include "DHTTask.h"
+#include "DownloadEngine.h"
+#include "SingletonHolder.h"
+#include "RequestGroupMan.h"
+
+DHTBucketRefreshCommand::DHTBucketRefreshCommand(int32_t cuid, DownloadEngine* e, time_t interval):
+  TimeBasedCommand(cuid, e, interval),
+  _routingTable(0),
+  _taskQueue(0),
+  _taskFactory(0) {}
+
+DHTBucketRefreshCommand::~DHTBucketRefreshCommand() {}
+
+void DHTBucketRefreshCommand::preProcess()
+{
+  _exit = _e->_requestGroupMan->downloadFinished() || _e->isHaltRequested();
+}
+
+void DHTBucketRefreshCommand::process()
+{
+  _taskQueue->addPeriodicTask1(_taskFactory->createBucketRefreshTask());
+}
+
+void DHTBucketRefreshCommand::setRoutingTable(const DHTRoutingTableHandle& routingTable)
+{
+  _routingTable = routingTable;
+}
+
+void DHTBucketRefreshCommand::setTaskQueue(const DHTTaskQueueHandle& taskQueue)
+{
+  _taskQueue = taskQueue;
+}
+
+void DHTBucketRefreshCommand::setTaskFactory(const DHTTaskFactoryHandle& taskFactory)
+{
+  _taskFactory = taskFactory;
+}

+ 66 - 0
src/DHTBucketRefreshCommand.h

@@ -0,0 +1,66 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_BUCKET_REFRESH_COMMAND_H_
+#define _D_DHT_BUCKET_REFRESH_COMMAND_H_
+
+#include "TimeBasedCommand.h"
+#include "DHTRoutingTableDecl.h"
+#include "DHTTaskQueueDecl.h"
+#include "DHTTaskFactoryDecl.h"
+
+class DHTBucketRefreshCommand:public TimeBasedCommand {
+private:
+  DHTRoutingTableHandle _routingTable;
+
+  DHTTaskQueueHandle _taskQueue;
+
+  DHTTaskFactoryHandle _taskFactory;
+public:
+  DHTBucketRefreshCommand(int32_t cuid, DownloadEngine* e, time_t interval);
+
+  virtual ~DHTBucketRefreshCommand();
+
+  virtual void preProcess();
+
+  virtual void process();
+
+  void setRoutingTable(const DHTRoutingTableHandle& routingTable);
+
+  void setTaskQueue(const DHTTaskQueueHandle& taskQueue);
+
+  void setTaskFactory(const DHTTaskFactoryHandle& taskFactory);
+};
+
+#endif // _D_DHT_BUCKET_REFRESH_COMMAND_H_

+ 69 - 0
src/DHTBucketRefreshTask.cc

@@ -0,0 +1,69 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTBucketRefreshTask.h"
+#include "DHTBucket.h"
+#include "DHTRoutingTable.h"
+#include "DHTNodeLookupTask.h"
+#include "DHTTaskQueue.h"
+#include "DHTNode.h"
+#include "DHTNodeLookupEntry.h"
+#include "Util.h"
+#include "Logger.h"
+
+DHTBucketRefreshTask::DHTBucketRefreshTask() {}
+
+DHTBucketRefreshTask::~DHTBucketRefreshTask() {}
+
+void DHTBucketRefreshTask::startup()
+{
+  DHTBuckets buckets = _routingTable->getBuckets();
+  for(DHTBuckets::iterator i = buckets.begin(); i != buckets.end(); ++i) {
+    if((*i)->needsRefresh()) {
+      (*i)->notifyUpdate();
+      unsigned char targetID[DHT_ID_LENGTH];
+      (*i)->getRandomNodeID(targetID);
+      SharedHandle<DHTNodeLookupTask> task = new DHTNodeLookupTask(targetID);
+      task->setRoutingTable(_routingTable);
+      task->setMessageDispatcher(_dispatcher);
+      task->setMessageFactory(_factory);
+      task->setTaskQueue(_taskQueue);
+      task->setLocalNode(_localNode);
+
+      _logger->info("Dispating bucket refresh. targetID=%s", Util::toHex(targetID, DHT_ID_LENGTH).c_str());
+      _taskQueue->addPeriodicTask1(task);
+    }
+  }
+  _finished = true;
+}

+ 49 - 0
src/DHTBucketRefreshTask.h

@@ -0,0 +1,49 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_BUCKET_REFRESH_TASK_H_
+#define _D_DHT_BUCKET_REFRESH_TASK_H_
+
+#include "DHTAbstractTask.h"
+
+class DHTBucketRefreshTask:public DHTAbstractTask {
+public:
+  DHTBucketRefreshTask();
+
+  virtual ~DHTBucketRefreshTask();
+
+  virtual void startup();
+};
+
+#endif // _D_DHT_BUCKET_REFRESH_TASK_H_

+ 49 - 0
src/DHTConnection.h

@@ -0,0 +1,49 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_CONNECTION_H_
+#define _D_DHT_CONNECTION_H_
+
+#include "common.h"
+
+class DHTConnection {
+public:
+  virtual ~DHTConnection() {}
+
+  virtual ssize_t receiveMessage(char* data, size_t len, string& host, uint16_t& port) = 0;
+
+  virtual void sendMessage(const char* data, size_t len, const string& host, uint16_t port) = 0;
+};
+
+#endif // _D_DHT_CONNECTION_H_

+ 43 - 0
src/DHTConnectionDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_CONNECTION_DECL_H_
+#define _D_DHT_CONNECTION_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTConnection;
+typedef SharedHandle<DHTConnection> DHTConnectionHandle;
+
+#endif // _D_DHT_CONNECTION_DECL_H_

+ 91 - 0
src/DHTConnectionImpl.cc

@@ -0,0 +1,91 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTConnectionImpl.h"
+#include "LogFactory.h"
+#include "RecoverableException.h"
+#include "Util.h"
+DHTConnectionImpl::DHTConnectionImpl():_socket(new SocketCore(SOCK_DGRAM)),
+				       _logger(LogFactory::getInstance()) {}
+
+DHTConnectionImpl::~DHTConnectionImpl() {}
+
+uint16_t DHTConnectionImpl::bind(IntSequence& ports)
+{
+  while(ports.hasNext()) {
+    uint16_t port = bind(ports.next());
+    if(port > 0) {
+      return port;
+    }
+  }
+  return 0;
+}
+
+uint16_t DHTConnectionImpl::bind(uint16_t port)
+{
+  try {
+    _socket->bind(port);
+    pair<string, int32_t> svaddr;
+    _socket->getAddrInfo(svaddr);
+    _logger->info("Bind socket for DHT. port=%u", port);
+    return svaddr.second;
+  } catch(RecoverableException* e) {
+    _logger->error("Failed to bind for DHT. port=%u", e, port);
+    delete e;
+  }
+  return 0;
+}
+
+ssize_t DHTConnectionImpl::receiveMessage(char* data, size_t len, string& host, uint16_t& port)
+{
+  if(_socket->isReadable(0)) {
+    pair<string, uint16_t> remoteHost;
+    ssize_t length = _socket->readDataFrom(data, len, remoteHost);
+    host = remoteHost.first;
+    port = remoteHost.second;
+    return length;
+  } else {
+    return -1;
+  }
+}
+
+void DHTConnectionImpl::sendMessage(const char* data, size_t len, const string& host, uint16_t port)
+{
+  _socket->writeData(data, len, host, port);
+}
+
+SocketHandle DHTConnectionImpl::getSocket() const
+{
+  return _socket;
+}

+ 65 - 0
src/DHTConnectionImpl.h

@@ -0,0 +1,65 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_CONNECTION_IMPL_H_
+#define _D_DHT_CONNECTION_IMPL_H_
+
+#include "DHTConnection.h"
+#include "Socket.h"
+#include "IntSequence.h"
+
+class Logger;
+
+class DHTConnectionImpl:public DHTConnection {
+private:
+  SocketHandle _socket;
+
+  const Logger* _logger;
+public:
+  DHTConnectionImpl();
+
+  virtual ~DHTConnectionImpl();
+
+  uint16_t bind(IntSequence& ports);
+  
+  uint16_t bind(uint16_t port);
+
+  virtual ssize_t receiveMessage(char* data, size_t len, string& host, uint16_t& port);
+
+  virtual void sendMessage(const char* data, size_t len, const string& host, uint16_t port);
+
+  SocketHandle getSocket() const;
+};
+
+#endif // _D_DHT_CONNECTION_IMPL_H_

+ 60 - 0
src/DHTConstants.h

@@ -0,0 +1,60 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_CONSTANTS_H_
+#define _D_DHT_CONSTANTS_H_
+
+#define DHT_ID_LENGTH 20
+
+#define DHT_TRANSACTION_ID_LENGTH 2
+
+#define DHT_TOKEN_LENGTH 4
+
+#define DHT_MESSAGE_TIMEOUT 15
+
+#define DHT_NODE_CONTACT_INTERVAL (15*60)
+
+#define DHT_BUCKET_REFRESH_INTERVAL (15*60)
+
+#define DHT_BUCKET_REFRESH_CHECK_INTERVAL (5*60)
+
+#define DHT_PEER_ANNOUNCE_PURGE_INTERVAL (30*60)
+
+#define DHT_PEER_ANNOUNCE_INTERVAL (15*60)
+
+#define DHT_PEER_ANNOUNCE_CHECK_INTERVAL (5*60)
+
+#define DHT_TOKEN_UPDATE_INTERVAL (10*60)
+
+#endif // _D_DHT_CONSTANTS_H_

+ 161 - 0
src/DHTEntryPointNameResolveCommand.cc

@@ -0,0 +1,161 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTEntryPointNameResolveCommand.h"
+#include "DownloadEngine.h"
+#include "NameResolver.h"
+#include "DNSCache.h"
+#include "DlAbortEx.h"
+#include "prefs.h"
+#include "message.h"
+#include "Util.h"
+#include "Option.h"
+#include "DHTNode.h"
+#include "DHTTaskQueue.h"
+#include "DHTTaskFactory.h"
+#include "DHTTask.h"
+#include "RequestGroupMan.h"
+
+DHTEntryPointNameResolveCommand::DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e):
+  Command(cuid),
+  _e(e),
+  _resolver(new NameResolver()),
+  _taskQueue(0),
+  _taskFactory(0),
+  _localNode(0)
+{}
+
+DHTEntryPointNameResolveCommand::~DHTEntryPointNameResolveCommand()
+{
+#ifdef ENABLE_ASYNC_DNS
+  disableNameResolverCheck(_resolver);
+#endif // ENABLE_ASYNC_DNS
+}
+
+bool DHTEntryPointNameResolveCommand::execute()
+{
+  if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
+    return true;
+  }
+
+  try {
+    string hostname = _e->option->get(PREF_DHT_ENTRY_POINT_HOST);
+    if(!Util::isNumbersAndDotsNotation(hostname)) {
+      if(resolveHostname(hostname, _resolver)) {
+	hostname = _resolver->getAddrString();
+      } else {
+	_e->commands.push_back(this);
+	return false;
+      }
+    }
+    
+    DHTNodeHandle entryNode = new DHTNode();
+    entryNode->setIPAddress(hostname);
+    entryNode->setPort(_e->option->getAsInt(PREF_DHT_ENTRY_POINT_PORT));
+ 
+    _taskQueue->addPeriodicTask1(_taskFactory->createPingTask(entryNode, 10));
+    _taskQueue->addPeriodicTask1(_taskFactory->createNodeLookupTask(_localNode->getID()));
+    _taskQueue->addPeriodicTask1(_taskFactory->createBucketRefreshTask());
+  } catch(RecoverableException* e) {
+    logger->error(EX_EXCEPTION_CAUGHT, e);
+    delete e;
+  }
+  return true;
+}
+
+bool DHTEntryPointNameResolveCommand::resolveHostname(const string& hostname,
+						      const NameResolverHandle& resolver)
+{
+  string ipaddr = DNSCacheSingletonHolder::instance()->find(hostname);
+  if(ipaddr.empty()) {
+#ifdef ENABLE_ASYNC_DNS
+    switch(resolver->getStatus()) {
+    case NameResolver::STATUS_READY:
+      logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str());
+      resolver->resolve(hostname);
+      setNameResolverCheck(resolver);
+      return false;
+    case NameResolver::STATUS_SUCCESS:
+      logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid,
+		   hostname.c_str(), resolver->getAddrString().c_str());
+      DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString());
+      return true;
+      break;
+    case NameResolver::STATUS_ERROR:
+      throw new DlAbortEx(MSG_NAME_RESOLUTION_FAILED, cuid,
+			  hostname.c_str(),
+			  resolver->getError().c_str());
+    default:
+      return false;
+    }
+#else
+    logger->info(MSG_RESOLVING_HOSTNAME, cuid, hostname.c_str());
+    resolver->resolve(hostname);
+    logger->info(MSG_NAME_RESOLUTION_COMPLETE, cuid,
+		 hostname.c_str(), resolver->getAddrString().c_str());
+    DNSCacheSingletonHolder::instance()->put(hostname, resolver->getAddrString());
+    return true;
+#endif // ENABLE_ASYNC_DNS
+  } else {
+    logger->info(MSG_DNS_CACHE_HIT, cuid,
+		 hostname.c_str(), ipaddr.c_str());
+    resolver->setAddr(ipaddr);
+    return true;
+  }
+}
+
+#ifdef ENABLE_ASYNC_DNS
+void DHTEntryPointNameResolveCommand::setNameResolverCheck(const NameResolverHandle& resolver) {
+  _e->addNameResolverCheck(resolver, this);
+}
+
+void DHTEntryPointNameResolveCommand::disableNameResolverCheck(const NameResolverHandle& resolver) {
+  _e->deleteNameResolverCheck(resolver, this);
+}
+#endif // ENABLE_ASYNC_DNS
+
+void DHTEntryPointNameResolveCommand::setTaskQueue(const DHTTaskQueueHandle& taskQueue)
+{
+  _taskQueue = taskQueue;
+}
+
+void DHTEntryPointNameResolveCommand::setTaskFactory(const DHTTaskFactoryHandle& taskFactory)
+{
+  _taskFactory = taskFactory;
+}
+
+void DHTEntryPointNameResolveCommand::setLocalNode(const DHTNodeHandle& localNode)
+{
+  _localNode = localNode;
+}

+ 80 - 0
src/DHTEntryPointNameResolveCommand.h

@@ -0,0 +1,80 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ENTRY_POINT_NAME_RESOVE_COMMAND_H_
+#define _D_DHT_ENTRY_POINT_NAME_RESOVE_COMMAND_H_
+
+#include "Command.h"
+#include "DHTTaskQueueDecl.h"
+#include "DHTTaskFactoryDecl.h"
+#include "DHTNodeDecl.h"
+
+class DownloadEngine;
+class NameResolver;
+typedef SharedHandle<NameResolver> NameResolverHandle;
+
+class DHTEntryPointNameResolveCommand:public Command {
+protected:
+  DownloadEngine* _e;
+private:
+  NameResolverHandle _resolver;
+
+  DHTTaskQueueHandle _taskQueue;
+
+  DHTTaskFactoryHandle _taskFactory;
+
+  DHTNodeHandle _localNode;
+
+  bool resolveHostname(const string& hostname,
+		       const NameResolverHandle& resolver);
+
+  void setNameResolverCheck(const NameResolverHandle& resolver);
+
+  void disableNameResolverCheck(const NameResolverHandle& resolver);
+
+public:
+  DHTEntryPointNameResolveCommand(int32_t cuid, DownloadEngine* e);
+
+  virtual ~DHTEntryPointNameResolveCommand();
+
+  virtual bool execute();
+
+  void setTaskQueue(const DHTTaskQueueHandle& taskQueue);
+
+  void setTaskFactory(const DHTTaskFactoryHandle& taskFactory);
+
+  void setLocalNode(const DHTNodeHandle& localNode);
+};
+
+#endif // _D_DHT_ENTRY_POINT_NAME_RESOVE_COMMAND_H_

+ 78 - 0
src/DHTFindNodeMessage.cc

@@ -0,0 +1,78 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTFindNodeMessage.h"
+#include "DHTNode.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageCallback.h"
+
+DHTFindNodeMessage::DHTFindNodeMessage(const DHTNodeHandle& localNode,
+				       const DHTNodeHandle& remoteNode,
+				       const unsigned char* targetNodeID,
+				       const string& transactionID):
+  DHTQueryMessage(localNode, remoteNode, transactionID)
+{
+  memcpy(_targetNodeID, targetNodeID, DHT_ID_LENGTH);
+}
+
+DHTFindNodeMessage::~DHTFindNodeMessage() {}
+
+void DHTFindNodeMessage::doReceivedAction()
+{
+  DHTNodes nodes = _routingTable->getClosestKNodes(_targetNodeID);
+  DHTMessageHandle reply =
+    _factory->createFindNodeReplyMessage(_remoteNode, nodes, _transactionID);
+  _dispatcher->addMessageToQueue(reply);
+}
+
+Dictionary* DHTFindNodeMessage::getArgument()
+{
+  Dictionary* a = new Dictionary();
+  a->put("id", new Data(reinterpret_cast<const char*>(_localNode->getID()),
+			DHT_ID_LENGTH));
+  a->put("target", new Data(reinterpret_cast<const char*>(_targetNodeID),
+			    DHT_ID_LENGTH));
+  return a;
+}
+
+string DHTFindNodeMessage::getMessageType() const
+{
+  return "find_node";
+}
+
+void DHTFindNodeMessage::validate() const {}

+ 66 - 0
src/DHTFindNodeMessage.h

@@ -0,0 +1,66 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_FIND_NODE_MESSAGE_H_
+#define _D_DHT_FIND_NODE_MESSAGE_H_
+
+#include "DHTQueryMessage.h"
+#include "DHTConstants.h"
+
+class DHTFindNodeMessage:public DHTQueryMessage {
+private:
+  unsigned char _targetNodeID[DHT_ID_LENGTH];
+public:
+  DHTFindNodeMessage(const DHTNodeHandle& localNode,
+		     const DHTNodeHandle& remoteNode,
+		     const unsigned char* targetNodeID,
+		     const string& transactionID = "");
+
+  virtual ~DHTFindNodeMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getArgument();
+  
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+
+  const unsigned char* getTargetNodeID() const
+  {
+    return _targetNodeID;
+  }
+};
+
+#endif // _D_DHT_FIND_NODE_MESSAGE_H_

+ 95 - 0
src/DHTFindNodeReplyMessage.cc

@@ -0,0 +1,95 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTFindNodeReplyMessage.h"
+#include "DHTNode.h"
+#include "DHTBucket.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageCallback.h"
+#include "PeerMessageUtil.h"
+
+DHTFindNodeReplyMessage::DHTFindNodeReplyMessage(const DHTNodeHandle& localNode,
+						 const DHTNodeHandle& remoteNode,
+						 const string& transactionID):
+  DHTResponseMessage(localNode, remoteNode, transactionID) {}
+
+DHTFindNodeReplyMessage::~DHTFindNodeReplyMessage() {}
+
+void DHTFindNodeReplyMessage::doReceivedAction()
+{
+  for(DHTNodes::iterator i = _closestKNodes.begin(); i != _closestKNodes.end(); ++i) {
+    if(memcmp((*i)->getID(), _localNode->getID(), DHT_ID_LENGTH) != 0) {
+      _routingTable->addNode(*i);
+    }
+  }
+}
+
+Dictionary* DHTFindNodeReplyMessage::getResponse()
+{
+  Dictionary* a = new Dictionary();
+  a->put("id", new Data(reinterpret_cast<const char*>(_localNode->getID()),
+			DHT_ID_LENGTH));
+  size_t offset = 0;
+  char buffer[DHTBucket::K*26];
+  for(DHTNodes::const_iterator i = _closestKNodes.begin(); i != _closestKNodes.end(); ++i) {
+    DHTNodeHandle node = *i;
+    memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH);
+    if(PeerMessageUtil::createcompact(buffer+20+offset, node->getIPAddress(), node->getPort())) {
+      offset += 26;
+    }
+  }
+  a->put("nodes", new Data(buffer, offset));
+  return a;
+}
+
+string DHTFindNodeReplyMessage::getMessageType() const
+{
+  return "find_node";
+}
+
+void DHTFindNodeReplyMessage::validate() const {}
+
+const DHTNodes& DHTFindNodeReplyMessage::getClosestKNodes() const
+{
+  return _closestKNodes;
+}
+
+void DHTFindNodeReplyMessage::setClosestKNodes(const DHTNodes& closestKNodes)
+{
+  _closestKNodes = closestKNodes;
+}

+ 63 - 0
src/DHTFindNodeReplyMessage.h

@@ -0,0 +1,63 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_FIND_NODE_REPLY_MESSAGE_H_
+#define _D_DHT_FIND_NODE_REPLY_MESSAGE_H_
+
+#include "DHTResponseMessage.h"
+
+class DHTFindNodeReplyMessage:public DHTResponseMessage {
+private:
+  DHTNodes _closestKNodes;
+public:
+  DHTFindNodeReplyMessage(const DHTNodeHandle& localNode,
+			  const DHTNodeHandle& remoteNode,
+			  const string& transactionID);
+
+  virtual ~DHTFindNodeReplyMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getResponse();
+  
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+
+  const DHTNodes& getClosestKNodes() const;
+
+  void setClosestKNodes(const DHTNodes& closestKNodes);
+};
+
+#endif // _D_DHT_FIND_NODE_REPLY_MESSAGE_H_

+ 96 - 0
src/DHTGetPeersCommand.cc

@@ -0,0 +1,96 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTGetPeersCommand.h"
+#include "DHTTaskQueue.h"
+#include "DHTTaskFactory.h"
+#include "DHTTask.h"
+#include "DownloadEngine.h"
+#include "RequestGroup.h"
+#include "DHTPeerLookupTask.h"
+#include "DHTNode.h"
+#include "DHTNodeLookupEntry.h"
+
+DHTGetPeersCommand::DHTGetPeersCommand(int32_t cuid,
+				       RequestGroup* requestGroup,
+				       DownloadEngine* e,
+				       const BtContextHandle& ctx):
+  Command(cuid),
+  BtContextAwareCommand(ctx),
+  RequestGroupAware(requestGroup),
+  _e(e),
+  _taskQueue(0),
+  _taskFactory(0),
+  _task(0),
+  _numRetry(0),
+  _lastGetPeerTime(0)
+{}
+
+DHTGetPeersCommand::~DHTGetPeersCommand() {}
+
+bool DHTGetPeersCommand::execute()
+{
+  if(btRuntime->isHalt()) {
+    return true;
+  }
+  if(_task.isNull() &&
+     (_numRetry > 0 && _lastGetPeerTime.elapsed(RETRY_INTERVAL) ||
+      _lastGetPeerTime.elapsed(GET_PEER_INTERVAL))) {
+    logger->debug("Issuing PeerLookup for infoHash=%s",
+		  btContext->getInfoHashAsString().c_str());
+    _task = _taskFactory->createPeerLookupTask(btContext);
+    _taskQueue->addPeriodicTask2(_task);
+  } else if(!_task.isNull() && _task->finished()) {
+    _lastGetPeerTime.reset();
+    if(_numRetry < MAX_RETRIES && btRuntime->lessThanEqMinPeer()) {
+      ++_numRetry;
+    } else {
+      _numRetry = 0;
+    }
+    _task = 0;
+  }
+
+  _e->commands.push_back(this);
+  return false;
+}
+
+void DHTGetPeersCommand::setTaskQueue(const DHTTaskQueueHandle& taskQueue)
+{
+  _taskQueue = taskQueue;
+}
+
+void DHTGetPeersCommand::setTaskFactory(const DHTTaskFactoryHandle& taskFactory)
+{
+  _taskFactory = taskFactory;
+}

+ 85 - 0
src/DHTGetPeersCommand.h

@@ -0,0 +1,85 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_GET_PEERS_COMMAND_H_
+#define _D_DHT_GET_PEERS_COMMAND_H_
+
+#include "Command.h"
+#include "BtContextAwareCommand.h"
+#include "RequestGroupAware.h"
+#include "DHTTaskQueueDecl.h"
+#include "DHTTaskFactoryDecl.h"
+#include "TimeA2.h"
+
+class DHTPeerLookupTask;
+class DownloadEngine;
+class RequestGroup;
+typedef SharedHandle<RequestGroup> RequestGroupHandle;
+
+class DHTGetPeersCommand:public Command,
+			 public BtContextAwareCommand,
+			 public RequestGroupAware
+{
+private:
+  static const time_t GET_PEER_INTERVAL = (15*60);
+
+  static const time_t RETRY_INTERVAL = 60;
+
+  static const size_t MAX_RETRIES = 10;
+
+  DownloadEngine* _e;
+
+  DHTTaskQueueHandle _taskQueue;
+
+  DHTTaskFactoryHandle _taskFactory;
+
+  SharedHandle<DHTPeerLookupTask> _task;
+
+  size_t _numRetry;
+
+  Time _lastGetPeerTime;
+public:
+  DHTGetPeersCommand(int32_t cuid, RequestGroup* requestGroup,
+		     DownloadEngine* e, const BtContextHandle& ctx);
+
+  virtual ~DHTGetPeersCommand();
+
+  virtual bool execute();
+
+  void setTaskQueue(const DHTTaskQueueHandle& taskQueue);
+
+  void setTaskFactory(const DHTTaskFactoryHandle& taskFactory);
+};
+
+#endif // _D_DHT_GET_PEERS_COMMAND_H_

+ 103 - 0
src/DHTGetPeersMessage.cc

@@ -0,0 +1,103 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTGetPeersMessage.h"
+#include "DHTNode.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageCallback.h"
+#include "DHTPeerAnnounceStorage.h"
+#include "DHTUtil.h"
+#include "Peer.h"
+#include "DHTTokenTracker.h"
+
+DHTGetPeersMessage::DHTGetPeersMessage(const DHTNodeHandle& localNode,
+				       const DHTNodeHandle& remoteNode,
+				       const unsigned char* infoHash,
+				       const string& transactionID):
+  DHTQueryMessage(localNode, remoteNode, transactionID)
+{
+  memcpy(_infoHash, infoHash, DHT_ID_LENGTH);
+}
+
+DHTGetPeersMessage::~DHTGetPeersMessage() {}
+
+void DHTGetPeersMessage::doReceivedAction()
+{
+  string token = _tokenTracker->generateToken(_infoHash,
+					      _remoteNode->getIPAddress(),
+					      _remoteNode->getPort());
+  // Check to see localhost has the contents which has same infohash
+  Peers peers = _peerAnnounceStorage->getPeers(_infoHash);
+  DHTMessageHandle reply = 0;
+  if(peers.empty()) {
+    DHTNodes nodes = _routingTable->getClosestKNodes(_infoHash);
+    reply =
+      _factory->createGetPeersReplyMessage(_remoteNode, nodes, token,
+					   _transactionID);
+  } else {
+    reply =
+      _factory->createGetPeersReplyMessage(_remoteNode, peers, token,
+					   _transactionID);
+  }
+  _dispatcher->addMessageToQueue(reply);
+}
+
+Dictionary* DHTGetPeersMessage::getArgument()
+{
+  Dictionary* a = new Dictionary();
+  a->put("id", new Data(_localNode->getID(), DHT_ID_LENGTH));
+  a->put("info_hash", new Data(_infoHash, DHT_ID_LENGTH));
+  return a;
+}
+
+string DHTGetPeersMessage::getMessageType() const
+{
+  return "get_peers";
+}
+
+void DHTGetPeersMessage::validate() const {}
+
+void DHTGetPeersMessage::setPeerAnnounceStorage(const WeakHandle<DHTPeerAnnounceStorage>& storage)
+{
+  _peerAnnounceStorage = storage;
+}
+
+void DHTGetPeersMessage::setTokenTracker(const WeakHandle<DHTTokenTracker>& tokenTracker)
+{
+  _tokenTracker = tokenTracker;
+}

+ 77 - 0
src/DHTGetPeersMessage.h

@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_GET_PEERS_MESSAGE_H_
+#define _D_DHT_GET_PEERS_MESSAGE_H_
+
+#include "DHTQueryMessage.h"
+#include "DHTConstants.h"
+#include "DHTPeerAnnounceStorageDecl.h"
+#include "DHTTokenTrackerDecl.h"
+
+class DHTGetPeersMessage:public DHTQueryMessage {
+private:
+  unsigned char _infoHash[DHT_ID_LENGTH];
+
+  WeakHandle<DHTPeerAnnounceStorage> _peerAnnounceStorage;
+
+  WeakHandle<DHTTokenTracker> _tokenTracker;
+public:
+  DHTGetPeersMessage(const DHTNodeHandle& localNode,
+		     const DHTNodeHandle& remoteNode,
+		     const unsigned char* infoHash,
+		     const string& transactionID = "");
+
+  virtual ~DHTGetPeersMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getArgument();
+  
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+
+  const unsigned char* getInfoHash() const
+  {
+    return _infoHash;
+  }
+
+  void setPeerAnnounceStorage(const WeakHandle<DHTPeerAnnounceStorage>& storage);
+
+
+  void setTokenTracker(const WeakHandle<DHTTokenTracker>& tokenTracker);
+};
+
+#endif // _D_DHT_GET_PEERS_MESSAGE_H_

+ 119 - 0
src/DHTGetPeersReplyMessage.cc

@@ -0,0 +1,119 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTGetPeersReplyMessage.h"
+#include "DHTNode.h"
+#include "DHTBucket.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "List.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageCallback.h"
+#include "PeerMessageUtil.h"
+#include "Peer.h"
+#include "DHTUtil.h"
+
+DHTGetPeersReplyMessage::DHTGetPeersReplyMessage(const DHTNodeHandle& localNode,
+						 const DHTNodeHandle& remoteNode,
+						 const string& token,
+						 const string& transactionID):
+  DHTResponseMessage(localNode, remoteNode, transactionID),
+  _token(token) {}
+
+DHTGetPeersReplyMessage::~DHTGetPeersReplyMessage() {}
+
+void DHTGetPeersReplyMessage::doReceivedAction()
+{
+  // Returned peers and nodes are handled in DHTPeerLookupTask.
+}
+
+Dictionary* DHTGetPeersReplyMessage::getResponse()
+{
+  Dictionary* r = new Dictionary();
+  r->put("id", new Data(reinterpret_cast<const char*>(_localNode->getID()),
+			DHT_ID_LENGTH));
+  r->put("token", new Data(_token));
+  if(_values.size()) {
+    List* valuesList = new List();
+    r->put("values", valuesList);
+    for(Peers::const_iterator i = _values.begin(); i != _values.end(); ++i) {
+      PeerHandle peer = *i;
+      char buffer[6];
+      if(PeerMessageUtil::createcompact(buffer, peer->ipaddr, peer->port)) {
+	valuesList->add(new Data(buffer, sizeof(buffer)));
+      }
+    }
+  } else {
+    size_t offset = 0;
+    char buffer[DHTBucket::K*26];
+    for(DHTNodes::const_iterator i = _closestKNodes.begin(); i != _closestKNodes.end(); ++i) {
+      DHTNodeHandle node = *i;
+      memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH);
+      if(PeerMessageUtil::createcompact(buffer+20+offset, node->getIPAddress(), node->getPort())) {
+	offset += 26;
+      }
+    }
+    r->put("nodes", new Data(buffer, offset));
+  }
+  return r;
+}
+
+string DHTGetPeersReplyMessage::getMessageType() const
+{
+  return "get_peers";
+}
+
+void DHTGetPeersReplyMessage::validate() const {}
+
+const DHTNodes& DHTGetPeersReplyMessage::getClosestKNodes() const
+{
+  return _closestKNodes;
+}
+
+void DHTGetPeersReplyMessage::setClosestKNodes(const DHTNodes& closestKNodes)
+{
+  _closestKNodes = closestKNodes;
+}
+
+const Peers& DHTGetPeersReplyMessage::getValues() const
+{
+  return _values;
+}
+
+void DHTGetPeersReplyMessage::setValues(const Peers& peers)
+{
+  _values = peers;
+}

+ 79 - 0
src/DHTGetPeersReplyMessage.h

@@ -0,0 +1,79 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_GET_PEERS_REPLY_MESSAGE_H_
+#define _D_DHT_GET_PEERS_REPLY_MESSAGE_H_
+
+#include "DHTResponseMessage.h"
+#include "DHTConstants.h"
+#include "PeerDecl.h"
+
+class DHTGetPeersReplyMessage:public DHTResponseMessage {
+private:
+  string _token;
+
+  DHTNodes _closestKNodes;
+
+  Peers _values;
+public:
+  DHTGetPeersReplyMessage(const DHTNodeHandle& localNode,
+			  const DHTNodeHandle& remoteNode,
+			  const string& token,
+			  const string& transactionID);
+
+  virtual ~DHTGetPeersReplyMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getResponse();
+  
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+
+  const DHTNodes& getClosestKNodes() const;
+
+  const Peers& getValues() const;
+
+  void setClosestKNodes(const DHTNodes& closestKNodes);
+
+  void setValues(const Peers& peers);
+  
+  const string& getToken() const
+  {
+    return _token;
+  }
+};
+
+#endif // _D_DHT_GET_PEERS_REPLY_MESSAGE_H_

+ 57 - 0
src/DHTIDCloser.h

@@ -0,0 +1,57 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_ID_CLOSER_H_
+#define _D_DHT_ID_CLOSER_H_
+
+#include "DHTNodeLookupEntryDecl.h"
+#include "DHTConstants.h"
+#include "XORCloser.h"
+
+class DHTIDCloser {
+private:
+  const unsigned char* _targetID;
+
+  XORCloser _closer;
+public:
+  DHTIDCloser(const unsigned char* targetID):_closer(targetID, DHT_ID_LENGTH) {}
+
+  bool operator()(const DHTNodeLookupEntryHandle& m1,
+		  const DHTNodeLookupEntryHandle& m2) const
+  {
+    return _closer(m1->_node->getID(), m2->_node->getID());
+  }
+};
+
+#endif // _D_DHT_ID_CLOSER_H_

+ 111 - 0
src/DHTInteractionCommand.cc

@@ -0,0 +1,111 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTInteractionCommand.h"
+#include "DownloadEngine.h"
+#include "RecoverableException.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageReceiver.h"
+#include "DHTTaskQueue.h"
+#include "DHTMessage.h"
+#include "Socket.h"
+#include "message.h"
+#include "RequestGroupMan.h"
+
+DHTInteractionCommand::DHTInteractionCommand(int32_t cuid, DownloadEngine* e):
+  Command(cuid),
+  _e(e),
+  _dispatcher(0),
+  _receiver(0),
+  _taskQueue(0),
+  _readCheckSocket(0)
+{}
+
+DHTInteractionCommand::~DHTInteractionCommand()
+{
+  disableReadCheckSocket(_readCheckSocket);
+}
+
+void DHTInteractionCommand::setReadCheckSocket(const SocketHandle& socket)
+{
+  _readCheckSocket = socket;
+  _e->addSocketForReadCheck(socket, this);
+}
+
+void DHTInteractionCommand::disableReadCheckSocket(const SocketHandle& socket)
+{
+  _e->deleteSocketForReadCheck(socket, this);
+}
+
+bool DHTInteractionCommand::execute()
+{
+  if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
+    return true;
+  }
+
+  _taskQueue->executeTask();
+
+  for(size_t i = 0; i < 20 && _readCheckSocket->isReadable(0); ++i) {
+    try {
+      _receiver->receiveMessage();
+    } catch(RecoverableException* e) {
+      logger->error(EX_EXCEPTION_CAUGHT, e);
+      delete e;
+    }
+  }
+  try {
+    _receiver->handleTimeout();
+    _dispatcher->sendMessages();
+  } catch(RecoverableException* e) {
+    logger->error(EX_EXCEPTION_CAUGHT, e);
+    delete e;
+  }
+  _e->commands.push_back(this);
+  return false;
+}
+
+void DHTInteractionCommand::setMessageDispatcher(const DHTMessageDispatcherHandle& dispatcher)
+{
+  _dispatcher = dispatcher;
+}
+
+void DHTInteractionCommand::setMessageReceiver(const DHTMessageReceiverHandle& receiver)
+{
+  _receiver = receiver;
+}
+
+void DHTInteractionCommand::setTaskQueue(const DHTTaskQueueHandle& taskQueue)
+{
+  _taskQueue = taskQueue;
+}

+ 74 - 0
src/DHTInteractionCommand.h

@@ -0,0 +1,74 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_INTERACTION_COMMAND_H_
+#define _D_DHT_INTERACTION_COMMAND_H_
+
+#include "Command.h"
+#include "DHTMessageDispatcherDecl.h"
+#include "DHTMessageReceiverDecl.h"
+#include "DHTTaskQueueDecl.h"
+
+class DownloadEngine;
+class SocketCore;
+typedef SharedHandle<SocketCore> SocketHandle;
+
+class DHTInteractionCommand:public Command {
+protected:
+  DownloadEngine* _e;
+private:
+  DHTMessageDispatcherHandle _dispatcher;
+  DHTMessageReceiverHandle _receiver;
+  DHTTaskQueueHandle _taskQueue;
+  SocketHandle _readCheckSocket;
+
+public:
+  DHTInteractionCommand(int32_t cuid, DownloadEngine* e);
+
+  virtual ~DHTInteractionCommand();
+
+  virtual bool execute();
+
+  void setReadCheckSocket(const SocketHandle& socket);
+
+  void disableReadCheckSocket(const SocketHandle& socket);
+
+  void setMessageDispatcher(const DHTMessageDispatcherHandle& dispatcher);
+
+  void setMessageReceiver(const DHTMessageReceiverHandle& receiver);
+
+  void setTaskQueue(const DHTTaskQueueHandle& taskQueue);
+};
+
+#endif // _D_DHT_INTERACTION_COMMAND_H_

+ 67 - 0
src/DHTMessage.cc

@@ -0,0 +1,67 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessage.h"
+#include "DHTNode.h"
+#include "DHTUtil.h"
+
+DHTMessage::DHTMessage(const DHTNodeHandle& localNode,
+		       const DHTNodeHandle& remoteNode,
+		       const string& transactionID):
+  _localNode(localNode), _remoteNode(remoteNode), _transactionID(transactionID)
+{
+  if(transactionID.empty()) {
+    generateTransactionID();
+  }
+}
+
+DHTMessage::~DHTMessage() {}
+
+void DHTMessage::generateTransactionID()
+{
+  char tid[DHT_TRANSACTION_ID_LENGTH];
+  DHTUtil::generateRandomData(tid, DHT_TRANSACTION_ID_LENGTH);
+  _transactionID = string(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
+}
+
+DHTNodeHandle DHTMessage::getLocalNode() const
+{
+  return _localNode;
+}
+
+DHTNodeHandle DHTMessage::getRemoteNode() const
+{
+  return _remoteNode;
+}
+

+ 80 - 0
src/DHTMessage.h

@@ -0,0 +1,80 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_H_
+#define _D_DHT_MESSAGE_H_
+
+#include "common.h"
+#include "DHTMessageDecl.h"
+#include "DHTNodeDecl.h"
+
+class DHTMessage {
+protected:
+  DHTNodeHandle _localNode;
+
+  DHTNodeHandle _remoteNode;
+
+  string _transactionID;
+
+  void generateTransactionID();
+public:
+  DHTMessage(const DHTNodeHandle& localNode,
+	     const DHTNodeHandle& remoteNode,
+	     const string& transactionID = "");
+
+  virtual ~DHTMessage();
+
+  const string& getTransactionID() const
+  {
+    return _transactionID;
+  }
+
+  DHTNodeHandle getLocalNode() const;
+
+  DHTNodeHandle getRemoteNode() const;
+
+  virtual void doReceivedAction() = 0;
+
+  virtual void send() = 0;
+
+  virtual bool isReply() const = 0;
+
+  virtual void validate() const = 0;
+  
+  virtual string getMessageType() const = 0;
+
+  virtual string toString() const = 0;
+};
+
+#endif // _D_DHT_MESSAGE_H_

+ 52 - 0
src/DHTMessageCallback.h

@@ -0,0 +1,52 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_CALLBACK_H_
+#define _D_DHT_MESSAGE_CALLBACK_H_
+
+#include "common.h"
+#include "DHTMessageCallbackDecl.h"
+#include "DHTMessageDecl.h"
+#include "DHTNodeDecl.h"
+
+class DHTMessageCallback {
+public:
+  virtual ~DHTMessageCallback() {}
+
+  virtual void onReceived(const DHTMessageHandle& message) = 0;
+
+  virtual void onTimeout(const DHTNodeHandle& remoteNode) = 0;
+};
+
+#endif // _D_DHT_MESSAGE_CALLBACK_H_

+ 43 - 0
src/DHTMessageCallbackDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_CALLBACK_DECL_H_
+#define _D_DHT_MESSAGE_CALLBACK_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTMessageCallback;
+typedef SharedHandle<DHTMessageCallback> DHTMessageCallbackHandle;
+
+#endif // _D_DHT_MESSAGE_CALLBACK_DECL_H_

+ 55 - 0
src/DHTMessageCallbackImpl.cc

@@ -0,0 +1,55 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessageCallbackImpl.h"
+#include "DHTMessage.h"
+#include "DHTNode.h"
+ 
+DHTMessageCallbackImpl::DHTMessageCallbackImpl(const WeakHandle<DHTMessageCallbackListener>& listener):_listener(listener) {}
+
+DHTMessageCallbackImpl::~DHTMessageCallbackImpl() {}
+
+void DHTMessageCallbackImpl::onReceived(const DHTMessageHandle& message)
+{
+  if(!_listener.isNull()) {
+    _listener->onReceived(message);
+  }
+}
+
+void DHTMessageCallbackImpl::onTimeout(const DHTNodeHandle& remoteNode)
+{
+  if(!_listener.isNull()) {
+    _listener->onTimeout(remoteNode);
+  }
+}

+ 55 - 0
src/DHTMessageCallbackImpl.h

@@ -0,0 +1,55 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_CALLBACK_IMPL_H_
+#define _D_DHT_MESSAGE_CALLBACK_IMPL_H_
+
+#include "DHTMessageCallback.h"
+#include "DHTMessageCallbackListener.h"
+
+class DHTMessageCallbackImpl:public DHTMessageCallback {
+private:
+  WeakHandle<DHTMessageCallbackListener> _listener;
+
+public:
+  DHTMessageCallbackImpl(const WeakHandle<DHTMessageCallbackListener>& listener);
+
+  virtual ~DHTMessageCallbackImpl();
+
+  virtual void onReceived(const DHTMessageHandle& message);
+
+  virtual void onTimeout(const DHTNodeHandle& remoteNode);
+};
+
+#endif // _D_DHT_MESSAGE_CALLBACK_IMPL_H_

+ 51 - 0
src/DHTMessageCallbackListener.h

@@ -0,0 +1,51 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_CALLBACK_LISTENER_H_
+#define _D_DHT_MESSAGE_CALLBACK_LISTENER_H_
+
+#include "common.h"
+#include "DHTMessageDecl.h"
+#include "DHTNodeDecl.h"
+
+class DHTMessageCallbackListener {
+public:
+  virtual ~DHTMessageCallbackListener() {}
+
+  virtual void onReceived(const DHTMessageHandle& message) = 0;
+
+  virtual void onTimeout(const DHTNodeHandle& remoteNode) = 0;
+};
+
+#endif // _D_DHT_MESSAGE_CALLBACK_LISTENER_H_

+ 45 - 0
src/DHTMessageDecl.h

@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_DECL_H_
+#define _D_DHT_MESSAGE_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTMessage;
+typedef SharedHandle<DHTMessage> DHTMessageHandle;
+typedef std::deque<DHTMessageHandle> DHTMessages;
+
+#endif // _D_DHT_MESSAGE_DECL_H_

+ 86 - 0
src/DHTMessageDispatcher.cc

@@ -0,0 +1,86 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessageDispatcher.h"
+#include "DHTMessage.h"
+#include "DHTMessageCallback.h"
+#include "DHTMessageEntry.h"
+#include "DHTMessageTracker.h"
+#include "RecoverableException.h"
+#include "LogFactory.h"
+#include "DHTConstants.h"
+
+DHTMessageDispatcher::DHTMessageDispatcher(const DHTMessageTrackerHandle& tracker):_tracker(tracker), _logger(LogFactory::getInstance()) {}
+
+DHTMessageDispatcher::~DHTMessageDispatcher() {}
+
+void DHTMessageDispatcher::addMessageToQueue(const DHTMessageHandle& message,
+					     time_t timeout,
+					     const DHTMessageCallbackHandle& callback)
+{
+  _messageQueue.push_back(new DHTMessageEntry(message, timeout, callback));
+}
+
+void DHTMessageDispatcher::addMessageToQueue(const DHTMessageHandle& message,
+					     const DHTMessageCallbackHandle& callback)
+{
+  addMessageToQueue(message, DHT_MESSAGE_TIMEOUT, callback);
+}
+
+void DHTMessageDispatcher::sendMessage(const DHTMessageEntryHandle& entry)
+{
+  try {
+    entry->_message->send();
+    if(!entry->_message->isReply()) {
+      _tracker->addMessage(entry->_message, entry->_timeout, entry->_callback);
+    }
+    _logger->info("Message sent: %s", entry->_message->toString().c_str());
+  } catch(RecoverableException* e) {
+    _logger->error("Failed to send message: %s", e, entry->_message->toString().c_str());
+    delete e;
+  }
+}
+
+void DHTMessageDispatcher::sendMessages()
+{
+  for(DHTMessageEntries::iterator itr = _messageQueue.begin(); itr != _messageQueue.end(); ++itr) {
+    sendMessage(*itr);
+  }
+  _messageQueue.clear();
+}
+
+size_t DHTMessageDispatcher::countMessageInQueue() const
+{
+  return _messageQueue.size();
+}

+ 73 - 0
src/DHTMessageDispatcher.h

@@ -0,0 +1,73 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_DISPATCHER_H_
+#define _D_DHT_MESSAGE_DISPATCHER_H_
+
+#include "common.h"
+#include "DHTMessageDispatcherDecl.h"
+#include "DHTMessageTrackerDecl.h"
+#include "DHTMessageCallbackDecl.h"
+#include "DHTMessageEntryDecl.h"
+#include "DHTMessageDecl.h"
+
+class Logger;
+
+class DHTMessageDispatcher {
+private:
+  DHTMessageTrackerHandle _tracker;
+
+  DHTMessageEntries _messageQueue;
+
+  const Logger* _logger;
+
+  void sendMessage(const DHTMessageEntryHandle& msg);
+public:
+  DHTMessageDispatcher(const DHTMessageTrackerHandle& tracker);
+
+  ~DHTMessageDispatcher();
+
+  void addMessageToQueue(const DHTMessageHandle& message,
+			 time_t timeout,
+			 const DHTMessageCallbackHandle& callback = 0);
+
+  void addMessageToQueue(const DHTMessageHandle& message,
+			 const DHTMessageCallbackHandle& callback = 0);
+
+  void sendMessages();
+
+  size_t countMessageInQueue() const;
+};
+
+#endif // _D_DHT_MESSAGE_DISPATCHER_H_

+ 43 - 0
src/DHTMessageDispatcherDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_DISPATCHER_DECL_H_
+#define _D_DHT_MESSAGE_DISPATCHER_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTMessageDispatcher;
+typedef SharedHandle<DHTMessageDispatcher> DHTMessageDispatcherHandle;
+
+#endif // _D_DHT_MESSAGE_DISPATCHER_DECL_H_

+ 44 - 0
src/DHTMessageEntry.cc

@@ -0,0 +1,44 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessageEntry.h"
+#include "DHTMessage.h"
+#include "DHTMessageCallback.h"
+
+DHTMessageEntry::DHTMessageEntry(const DHTMessageHandle& message, time_t timeout, const DHTMessageCallbackHandle& callback):
+  _message(message),
+  _timeout(timeout),
+  _callback(callback) {}
+
+DHTMessageEntry::~DHTMessageEntry() {}

+ 54 - 0
src/DHTMessageEntry.h

@@ -0,0 +1,54 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_ENTRY_H_
+#define _D_DHT_MESSAGE_ENTRY_H_
+
+#include "common.h"
+#include "DHTMessageEntryDecl.h"
+#include "DHTMessageDecl.h"
+#include "DHTMessageCallbackDecl.h"
+
+class DHTMessageEntry {
+public:
+  DHTMessageHandle _message;
+  time_t _timeout;
+  DHTMessageCallbackHandle _callback;
+
+  DHTMessageEntry(const DHTMessageHandle& message, time_t timeout, const DHTMessageCallbackHandle& callback);
+
+  ~DHTMessageEntry();
+};
+
+#endif // _D_DHT_MESSAGE_ENTRY_H_

+ 45 - 0
src/DHTMessageEntryDecl.h

@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_ENTRY_DECL_H_
+#define _D_DHT_MESSAGE_ENTRY_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTMessageEntry;
+typedef SharedHandle<DHTMessageEntry> DHTMessageEntryHandle;
+typedef std::deque<DHTMessageEntryHandle> DHTMessageEntries;
+
+#endif // _D_DHT_MESSAGE_ENTRY_DECL_H_

+ 107 - 0
src/DHTMessageFactory.h

@@ -0,0 +1,107 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_FACTORY_H_
+#define _D_DHT_MESSAGE_FACTORY_H_
+
+#include "common.h"
+#include "DHTMessageDecl.h"
+#include "DHTNodeDecl.h"
+#include "PeerDecl.h"
+
+class Dictionary;
+
+class DHTMessageFactory {
+public:
+  virtual ~DHTMessageFactory() {}
+
+  virtual DHTMessageHandle
+  createQueryMessage(const Dictionary* d,
+		     const string& ipaddr, uint16_t port) = 0;
+
+  virtual DHTMessageHandle
+  createResponseMessage(const string& messageType,
+			const Dictionary* d,
+			const DHTNodeHandle& remoteNode) = 0;
+
+  virtual DHTMessageHandle
+  createPingMessage(const DHTNodeHandle& remoteNode,
+		    const string& transactionID = "") = 0;
+
+  virtual DHTMessageHandle
+  createPingReplyMessage(const DHTNodeHandle& remoteNode,
+			 const unsigned char* id,
+			 const string& transactionID) = 0;
+
+  virtual DHTMessageHandle
+  createFindNodeMessage(const DHTNodeHandle& remoteNode,
+			const unsigned char* targetNodeID,
+			const string& transactionID = "") = 0;
+
+  virtual DHTMessageHandle
+  createFindNodeReplyMessage(const DHTNodeHandle& remoteNode,
+			     const DHTNodes& closestKNodes,
+			     const string& transactionID) = 0;
+
+  virtual DHTMessageHandle
+  createGetPeersMessage(const DHTNodeHandle& remoteNode,
+			const unsigned char* infoHash,
+			const string& transactionID = "") = 0;
+
+  virtual DHTMessageHandle
+  createGetPeersReplyMessage(const DHTNodeHandle& remoteNode,
+			     const DHTNodes& closestKNodes,
+			     const string& token,
+			     const string& transactionID) = 0;
+
+  virtual DHTMessageHandle
+  createGetPeersReplyMessage(const DHTNodeHandle& remoteNode,
+			     const Peers& peers,
+			     const string& token,
+			     const string& transactionID) = 0;
+
+  virtual DHTMessageHandle
+  createAnnouncePeerMessage(const DHTNodeHandle& remoteNode,
+			    const unsigned char* infoHash,
+			    uint16_t tcpPort,
+			    const string& token,
+			    const string& transactionID = "") = 0;
+
+  virtual DHTMessageHandle
+  createAnnouncePeerReplyMessage(const DHTNodeHandle& remoteNode,
+				 const string& transactionID) = 0;
+
+};
+
+#endif // _D_DHT_MESSAGE_FACTORY_H_

+ 43 - 0
src/DHTMessageFactoryDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_FACTORY_DECL_H_
+#define _D_DHT_MESSAGE_FACTORY_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTMessageFactory;
+typedef SharedHandle<DHTMessageFactory> DHTMessageFactoryHandle;
+
+#endif // _D_DHT_MESSAGE_FACTORY_DECL_H_

+ 418 - 0
src/DHTMessageFactoryImpl.cc

@@ -0,0 +1,418 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessageFactoryImpl.h"
+#include "LogFactory.h"
+#include "DlAbortEx.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "List.h"
+#include "DHTNode.h"
+#include "DHTRoutingTable.h"
+#include "DHTPingMessage.h"
+#include "DHTPingReplyMessage.h"
+#include "DHTFindNodeMessage.h"
+#include "DHTFindNodeReplyMessage.h"
+#include "DHTGetPeersMessage.h"
+#include "DHTGetPeersReplyMessage.h"
+#include "DHTAnnouncePeerMessage.h"
+#include "DHTAnnouncePeerReplyMessage.h"
+#include "DHTConnection.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTPeerAnnounceStorage.h"
+#include "DHTTokenTracker.h"
+#include "PeerMessageUtil.h"
+#include "BtRuntime.h"
+#include "Util.h"
+#include "Peer.h"
+
+DHTMessageFactoryImpl::DHTMessageFactoryImpl():_localNode(0),
+					       _logger(LogFactory::getInstance()) {}
+
+DHTMessageFactoryImpl::~DHTMessageFactoryImpl() {}
+
+DHTNodeHandle
+DHTMessageFactoryImpl::getRemoteNode(const unsigned char* id, const string& ipaddr, uint16_t port) const
+{
+  DHTNodeHandle node = _routingTable->getNode(id, ipaddr, port);
+  if(node.isNull()) {
+    node = new DHTNode(id);
+    node->setIPAddress(ipaddr);
+    node->setPort(port);
+  }
+  return node;
+}
+
+static const Dictionary* getDictionary(const Dictionary* d, const string& key)
+{
+  const Dictionary* c = dynamic_cast<const Dictionary*>(d->get(key));
+  if(c) {
+    return c;
+  } else {
+    throw new DlAbortEx("Malformed DHT message. Missing %s", key.c_str());
+  }
+}
+
+static const Data* getData(const Dictionary* d, const string& key)
+{
+  const Data* c = dynamic_cast<const Data*>(d->get(key));
+  if(c) {
+    return c;
+  } else {
+    throw new DlAbortEx("Malformed DHT message. Missing %s", key.c_str());
+  }
+}
+
+static const List* getList(const Dictionary* d, const string& key)
+{
+  const List* l = dynamic_cast<const List*>(d->get(key));
+  if(l) {
+    return l;
+  } else {
+    throw new DlAbortEx("Malformed DHT message. Missing %s", key.c_str());
+  }
+}
+
+void DHTMessageFactoryImpl::validateID(const Data* id) const
+{
+  if(id->getLen() != DHT_ID_LENGTH) {
+    throw new DlAbortEx("Malformed DHT message. Invalid ID length. Expected:%d, Actual:%d", DHT_ID_LENGTH, id->getLen());
+  }
+}
+
+void DHTMessageFactoryImpl::validateIDMatch(const unsigned char* expected, const unsigned char* actual) const
+{
+  if(memcmp(expected, actual, DHT_ID_LENGTH) != 0) {
+    //throw new DlAbortEx("Different ID received.");
+  }
+}
+
+void DHTMessageFactoryImpl::validatePort(const Data* i) const
+{
+  if(!i->isNumber()) {
+    throw new DlAbortEx("Malformed DHT message. Invalid port=%s",
+			Util::toHex(i->toString()).c_str());
+  }
+  uint32_t port = i->toInt();
+  if(UINT16_MAX < port) {
+    throw new DlAbortEx("Malformed DHT message. Invalid port=%u", port);
+  }
+}
+
+DHTMessageHandle DHTMessageFactoryImpl::createQueryMessage(const Dictionary* d,
+							   const string& ipaddr,
+							   uint16_t port)
+{
+  const Data* q = getData(d, "q");
+  const Data* t = getData(d, "t");
+  const Data* y = getData(d, "y");
+  const Dictionary* a = getDictionary(d, "a");
+  if(y->toString() != "q") {
+    throw new DlAbortEx("Malformed DHT message. y != q");
+  }
+  const Data* id = getData(getDictionary(d, "a"), "id");
+  validateID(id);
+  DHTNodeHandle remoteNode = getRemoteNode((const unsigned char*)id->toString().c_str(), ipaddr, port);
+  string messageType = q->toString();
+  string transactionID = t->toString();
+  if(messageType == "ping") {
+    return createPingMessage(remoteNode, transactionID);
+  } else if(messageType == "find_node") {
+    const Data* targetNodeID = getData(a, "target");
+    validateID(targetNodeID);
+    return createFindNodeMessage(remoteNode,
+				 (const unsigned char*)targetNodeID->getData(),
+				 transactionID);
+  } else if(messageType == "get_peers") {
+    const Data* infoHash = getData(a, "info_hash");
+    validateID(infoHash);
+    return createGetPeersMessage(remoteNode,
+				 (const unsigned char*)infoHash->getData(),
+				 transactionID);
+  } else if(messageType == "announce_peer") {
+    const Data* infoHash = getData(a, "info_hash");
+    validateID(infoHash);
+    const Data* port = getData(a, "port");
+    validatePort(port);
+    const Data* token = getData(a, "token");
+    return createAnnouncePeerMessage(remoteNode,
+				     (const unsigned char*)infoHash->getData(),
+				     (uint16_t)port->toInt(),
+				     token->toString(),
+				     transactionID);
+  } else {
+    throw new DlAbortEx("Unsupported message type: %s", messageType.c_str());
+  }
+}
+
+DHTMessageHandle DHTMessageFactoryImpl::createResponseMessage(const string& messageType,
+							      const Dictionary* d,
+							      const DHTNodeHandle& remoteNode)
+{
+  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") {
+    throw new DlAbortEx("Malformed DHT message. y != r: y=%s",
+			Util::urlencode(y->toString()).c_str());
+  }
+  const Data* id = getData(r, "id");
+  validateID(id);
+  validateIDMatch(remoteNode->getID(),
+		      (const unsigned char*)id->toString().c_str());
+  string transactionID = t->toString();
+  if(messageType == "ping") {
+    return createPingReplyMessage(remoteNode, (const unsigned char*)id->getData(), transactionID);
+  } else if(messageType == "find_node") {
+    return createFindNodeReplyMessage(remoteNode, d, transactionID);
+  } else if(messageType == "get_peers") {
+    const List* values = dynamic_cast<const List*>(r->get("values"));
+    if(values) {
+      return createGetPeersReplyMessageWithValues(remoteNode, d, transactionID);
+    } else {
+      const Data* nodes = dynamic_cast<const Data*>(r->get("nodes"));
+      if(nodes) {
+	return createGetPeersReplyMessageWithNodes(remoteNode, d, transactionID);
+      } else {
+	throw new DlAbortEx("Malformed DHT message: missing nodes/values");
+      }
+    }
+  } else if(messageType == "announce_peer") {
+    return createAnnouncePeerReplyMessage(remoteNode, transactionID);
+  } else {
+    throw new DlAbortEx("Unsupported message type: %s", messageType.c_str());
+  }
+}
+
+void DHTMessageFactoryImpl::setCommonProperty(const SharedHandle<DHTAbstractMessage>& m)
+{
+  m->setConnection(_connection);
+  m->setMessageDispatcher(_dispatcher);
+  m->setRoutingTable(_routingTable);
+  m->setMessageFactory(this);
+}
+
+DHTMessageHandle DHTMessageFactoryImpl::createPingMessage(const DHTNodeHandle& remoteNode, const string& transactionID)
+{
+  SharedHandle<DHTPingMessage> m = new DHTPingMessage(_localNode, remoteNode, transactionID);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createPingReplyMessage(const DHTNodeHandle& remoteNode,
+					      const unsigned char* id,
+					      const string& transactionID)
+{
+  SharedHandle<DHTPingReplyMessage> m = new DHTPingReplyMessage(_localNode, remoteNode, id, transactionID);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createFindNodeMessage(const DHTNodeHandle& remoteNode,
+					     const unsigned char* targetNodeID,
+					     const string& transactionID)
+{
+  SharedHandle<DHTFindNodeMessage> m = new DHTFindNodeMessage(_localNode, remoteNode, targetNodeID, transactionID);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createFindNodeReplyMessage(const DHTNodeHandle& remoteNode,
+						  const DHTNodes& closestKNodes,
+						  const string& transactionID)
+{
+  SharedHandle<DHTFindNodeReplyMessage> m = new DHTFindNodeReplyMessage(_localNode, remoteNode, transactionID);
+  m->setClosestKNodes(closestKNodes);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTNodes DHTMessageFactoryImpl::extractNodes(const char* src, size_t length)
+{
+  if(length%26 != 0) {
+    throw new DlAbortEx("Nodes length is not multiple of 26");
+  }
+  DHTNodes nodes;
+  for(size_t offset = 0; offset < length; offset += 26) {
+    DHTNodeHandle node = new DHTNode(reinterpret_cast<const unsigned char*>(src+offset));
+    pair<string, uint16_t> addr =
+      PeerMessageUtil::unpackcompact(src+offset+DHT_ID_LENGTH);
+    node->setIPAddress(addr.first);
+    node->setPort(addr.second);
+    nodes.push_back(node);
+  }
+  return nodes;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createFindNodeReplyMessage(const DHTNodeHandle& remoteNode,
+						  const Dictionary* d,
+						  const string& transactionID)
+{
+  const Data* nodesData = getData(getDictionary(d, "r"), "nodes");
+  DHTNodes nodes = extractNodes(nodesData->getData(), nodesData->getLen());
+  return createFindNodeReplyMessage(remoteNode, nodes, transactionID);
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createGetPeersMessage(const DHTNodeHandle& remoteNode,
+					     const unsigned char* infoHash,
+					     const string& transactionID)
+{
+  SharedHandle<DHTGetPeersMessage> m = new DHTGetPeersMessage(_localNode,
+							      remoteNode,
+							      infoHash,
+							      transactionID);
+  m->setPeerAnnounceStorage(_peerAnnounceStorage);
+  m->setTokenTracker(_tokenTracker);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createGetPeersReplyMessageWithNodes(const DHTNodeHandle& remoteNode,
+							   const Dictionary* d,
+							   const string& transactionID)
+{
+  const Dictionary* r = getDictionary(d, "r");
+  const Data* nodesData = getData(r, "nodes");
+  DHTNodes nodes = extractNodes(nodesData->getData(), nodesData->getLen());
+  const Data* token = getData(r, "token");
+  return createGetPeersReplyMessage(remoteNode, nodes, token->toString(),
+				    transactionID);
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createGetPeersReplyMessage(const DHTNodeHandle& remoteNode,
+						  const DHTNodes& closestKNodes,
+						  const string& token,
+						  const string& transactionID)
+{
+  SharedHandle<DHTGetPeersReplyMessage> m = new DHTGetPeersReplyMessage(_localNode, remoteNode, token, transactionID);
+  m->setClosestKNodes(closestKNodes);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createGetPeersReplyMessageWithValues(const DHTNodeHandle& remoteNode,
+							    const Dictionary* d,
+							    const string& transactionID)
+{
+  const Dictionary* r = getDictionary(d, "r");
+  const List* valuesList = getList(r, "values");
+  Peers peers;
+  for(MetaList::const_iterator i = valuesList->getList().begin(); i != valuesList->getList().end(); ++i) {
+    const Data* data = dynamic_cast<const Data*>(*i);
+    if(data && data->getLen() == 6) {
+      pair<string, uint16_t> addr = PeerMessageUtil::unpackcompact(data->getData());
+      PeerHandle peer = new Peer(addr.first, addr.second);
+      peers.push_back(peer);
+    }
+  }
+  const Data* token = getData(r, "token");
+  return createGetPeersReplyMessage(remoteNode, peers, token->toString(),
+				    transactionID);
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createGetPeersReplyMessage(const DHTNodeHandle& remoteNode,
+						  const Peers& values,
+						  const string& token,
+						  const string& transactionID)
+{
+  SharedHandle<DHTGetPeersReplyMessage> m = new DHTGetPeersReplyMessage(_localNode, remoteNode, token, transactionID);
+  m->setValues(values);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createAnnouncePeerMessage(const DHTNodeHandle& remoteNode,
+						 const unsigned char* infoHash,
+						 uint16_t tcpPort,
+						 const string& token,
+						 const string& transactionID)
+{
+  SharedHandle<DHTAnnouncePeerMessage> m =
+    new DHTAnnouncePeerMessage(_localNode, remoteNode, infoHash, tcpPort, token, transactionID);
+  m->setPeerAnnounceStorage(_peerAnnounceStorage);
+  m->setTokenTracker(_tokenTracker);
+  setCommonProperty(m);
+  return m;
+}
+
+DHTMessageHandle
+DHTMessageFactoryImpl::createAnnouncePeerReplyMessage(const DHTNodeHandle& remoteNode,
+						      const string& transactionID)
+{
+  SharedHandle<DHTAnnouncePeerReplyMessage> m =
+    new DHTAnnouncePeerReplyMessage(_localNode, remoteNode, transactionID);
+  setCommonProperty(m);
+  return m;
+}
+
+void DHTMessageFactoryImpl::setRoutingTable(const DHTRoutingTableHandle& routingTable)
+{
+  _routingTable = routingTable;
+}
+
+void DHTMessageFactoryImpl::setConnection(const DHTConnectionHandle& connection)
+{
+  _connection = connection;
+}
+
+void DHTMessageFactoryImpl::setMessageDispatcher(const DHTMessageDispatcherHandle& dispatcher)
+{
+  _dispatcher = dispatcher;
+}
+  
+void DHTMessageFactoryImpl::setPeerAnnounceStorage(const DHTPeerAnnounceStorageHandle& storage)
+{
+  _peerAnnounceStorage = storage;
+}
+
+void DHTMessageFactoryImpl::setTokenTracker(const DHTTokenTrackerHandle& tokenTracker)
+{
+  _tokenTracker = tokenTracker;
+}
+
+void DHTMessageFactoryImpl::setLocalNode(const DHTNodeHandle& localNode)
+{
+  _localNode = localNode;
+}

+ 168 - 0
src/DHTMessageFactoryImpl.h

@@ -0,0 +1,168 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_FACTORY_IMPL_H_
+#define _D_DHT_MESSAGE_FACTORY_IMPL_H_
+
+#include "DHTMessageFactory.h"
+#include "DHTRoutingTableDecl.h"
+#include "DHTConnectionDecl.h"
+#include "DHTMessageDispatcherDecl.h"
+#include "DHTPeerAnnounceStorageDecl.h"
+#include "DHTTokenTrackerDecl.h"
+
+class Logger;
+class Data;
+class DHTAbstractMessage;
+
+class DHTMessageFactoryImpl:public DHTMessageFactory {
+private:
+  DHTNodeHandle _localNode;
+
+  WeakHandle<DHTConnection> _connection;
+
+  WeakHandle<DHTMessageDispatcher> _dispatcher;
+
+  WeakHandle<DHTRoutingTable> _routingTable;
+  
+  WeakHandle<DHTPeerAnnounceStorage> _peerAnnounceStorage;
+
+  WeakHandle<DHTTokenTracker> _tokenTracker;
+
+  const Logger* _logger;
+  
+  // search node in routingTable. If it is not found, create new one.
+  DHTNodeHandle getRemoteNode(const unsigned char* id, const string& ipaddr, uint16_t port) const;
+
+  void validateID(const Data* id) const;
+
+  void validateIDMatch(const unsigned char* expected, const unsigned char* actual) const;
+
+  void validatePort(const Data* i) const;
+
+  DHTNodes extractNodes(const char* src, size_t length);
+
+  void setCommonProperty(const SharedHandle<DHTAbstractMessage>& m);
+
+public:
+  DHTMessageFactoryImpl();
+
+  virtual ~DHTMessageFactoryImpl();
+
+  virtual DHTMessageHandle
+  createQueryMessage(const Dictionary* d,
+		     const string& ipaddr, uint16_t port);
+
+  virtual DHTMessageHandle
+  createResponseMessage(const string& messageType,
+			const Dictionary* d,
+			const DHTNodeHandle& remoteNode);
+
+  virtual DHTMessageHandle
+  createPingMessage(const DHTNodeHandle& remoteNode,
+		    const string& transactionID = "");
+
+  virtual DHTMessageHandle
+  createPingReplyMessage(const DHTNodeHandle& remoteNode,
+			 const unsigned char* id,
+			 const string& transactionID);
+
+  virtual DHTMessageHandle
+  createFindNodeMessage(const DHTNodeHandle& remoteNode,
+			const unsigned char* targetNodeID,
+			const string& transactionID = "");
+
+  DHTMessageHandle
+  createFindNodeReplyMessage(const DHTNodeHandle& remoteNode,
+			     const Dictionary* d,
+			     const string& transactionID);
+
+
+  virtual DHTMessageHandle
+  createFindNodeReplyMessage(const DHTNodeHandle& remoteNode,
+			     const DHTNodes& closestKNodes,
+			     const string& transactionID);
+
+  virtual DHTMessageHandle
+  createGetPeersMessage(const DHTNodeHandle& remoteNode,
+			const unsigned char* infoHash,
+			const string& transactionID = "");
+
+  virtual DHTMessageHandle
+  createGetPeersReplyMessage(const DHTNodeHandle& remoteNode,
+			     const DHTNodes& closestKNodes,
+			     const string& token,
+			     const string& transactionID);
+
+  DHTMessageHandle
+  createGetPeersReplyMessageWithNodes(const DHTNodeHandle& remoteNode,
+				      const Dictionary* d,
+				      const string& transactionID);
+
+  virtual DHTMessageHandle
+  createGetPeersReplyMessage(const DHTNodeHandle& remoteNode,
+			     const Peers& peers,
+			     const string& token,
+			     const string& transactionID);
+
+  DHTMessageHandle
+  createGetPeersReplyMessageWithValues(const DHTNodeHandle& remoteNode,
+				       const Dictionary* d,
+				       const string& transactionID);
+
+  virtual DHTMessageHandle
+  createAnnouncePeerMessage(const DHTNodeHandle& remoteNode,
+			    const unsigned char* infoHash,
+			    uint16_t tcpPort,
+			    const string& token,
+			    const string& transactionID = "");
+
+  virtual DHTMessageHandle
+  createAnnouncePeerReplyMessage(const DHTNodeHandle& remoteNode,
+				 const string& transactionID);
+
+  void setRoutingTable(const DHTRoutingTableHandle& routingTable);
+
+  void setConnection(const DHTConnectionHandle& connection);
+
+  void setMessageDispatcher(const DHTMessageDispatcherHandle& dispatcher);
+  
+  void setPeerAnnounceStorage(const DHTPeerAnnounceStorageHandle& storage);
+
+  void setTokenTracker(const DHTTokenTrackerHandle& tokenTracker);
+
+  void setLocalNode(const DHTNodeHandle& localNode);
+};
+
+#endif // _D_DHT_MESSAGE_FACTORY_IMPL_H_

+ 134 - 0
src/DHTMessageReceiver.cc

@@ -0,0 +1,134 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#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 "MetaEntry.h"
+#include "MetaFileUtil.h"
+#include "DlAbortEx.h"
+#include "LogFactory.h"
+#include "Util.h"
+
+DHTMessageReceiver::DHTMessageReceiver(const DHTMessageTrackerHandle& tracker):
+  _tracker(tracker),
+  _connection(0),
+  _factory(0),
+  _routingTable(0),
+  _logger(LogFactory::getInstance())
+{}
+
+DHTMessageReceiver::~DHTMessageReceiver() {}
+
+DHTMessageHandle DHTMessageReceiver::receiveMessage()
+{
+  string remoteAddr;
+  uint16_t remotePort;
+  char data[64*1024];
+  ssize_t length = _connection->receiveMessage(data, sizeof(data),
+					       remoteAddr,
+					       remotePort);
+  if(length <= 0) {
+    return 0;
+  }
+  bool isReply = false;
+  MetaEntryHandle msgroot = MetaFileUtil::bdecoding(data, length);
+  const Dictionary* d = dynamic_cast<const Dictionary*>(msgroot.get());
+  if(d) {
+    const Data* y = dynamic_cast<const Data*>(d->get("y"));
+    if(y->toString() == "r" || y->toString() == "e") {
+      isReply = true;
+    }
+  } else {
+    throw new DlAbortEx("Malformed DHT message. From:%s:%u", remoteAddr.c_str(), remotePort);
+  }
+  DHTMessageHandle message = 0;
+  DHTMessageCallbackHandle callback = 0;
+  if(isReply) {
+    std::pair<DHTMessageHandle, DHTMessageCallbackHandle> p = _tracker->messageArrived(d, remoteAddr, remotePort);
+    message = p.first;
+    callback = p.second;
+    if(message.isNull()) {
+      // timeout or malicious message
+      return 0;
+    }
+  } 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;
+}
+
+void DHTMessageReceiver::handleTimeout()
+{
+  _tracker->handleTimeout();
+}
+
+DHTConnectionHandle DHTMessageReceiver::getConnection() const
+{
+  return _connection;
+}
+
+DHTMessageTrackerHandle DHTMessageReceiver::getMessageTracker() const
+{
+  return _tracker;
+}
+
+void DHTMessageReceiver::setConnection(const DHTConnectionHandle& connection)
+{
+  _connection = connection;
+}
+
+void DHTMessageReceiver::setMessageFactory(const DHTMessageFactoryHandle& factory)
+{
+  _factory = factory;
+}
+
+void DHTMessageReceiver::setRoutingTable(const DHTRoutingTableHandle& routingTable)
+{
+  _routingTable = routingTable;
+}

+ 80 - 0
src/DHTMessageReceiver.h

@@ -0,0 +1,80 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_RECEIVER_H_
+#define _D_DHT_MESSAGE_RECEIVER_H_
+
+#include "common.h"
+#include "DHTMessageReceiverDecl.h"
+#include "DHTMessageTrackerDecl.h"
+#include "DHTMessageDecl.h"
+#include "DHTConnectionDecl.h"
+#include "DHTMessageFactoryDecl.h"
+#include "DHTRoutingTableDecl.h"
+
+class Logger;
+
+class DHTMessageReceiver {
+private:
+  DHTMessageTrackerHandle _tracker;
+
+  DHTConnectionHandle _connection;
+
+  DHTMessageFactoryHandle _factory;
+
+  DHTRoutingTableHandle _routingTable;
+
+  const Logger* _logger;
+public:
+  DHTMessageReceiver(const DHTMessageTrackerHandle& tracker);
+  
+  ~DHTMessageReceiver();
+
+  // caller must handle thrown exception.
+  DHTMessageHandle receiveMessage();
+
+  void handleTimeout();
+
+  DHTConnectionHandle getConnection() const;
+
+  DHTMessageTrackerHandle getMessageTracker() const;
+
+  void setConnection(const DHTConnectionHandle& connection);
+
+  void setMessageFactory(const DHTMessageFactoryHandle& factory);
+
+  void setRoutingTable(const DHTRoutingTableHandle& routingTable);
+};
+
+#endif // _D_DHT_MESSAGE_RECEIVER_H_

+ 43 - 0
src/DHTMessageReceiverDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_RECEIVER_DECL_H_
+#define _D_DHT_MESSAGE_RECEIVER_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTMessageReceiver;
+typedef SharedHandle<DHTMessageReceiver> DHTMessageReceiverHandle;
+
+#endif // _D_DHT_MESSAGE_RECEIVER_DECL_H_

+ 149 - 0
src/DHTMessageTracker.cc

@@ -0,0 +1,149 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessageTracker.h"
+#include "DHTMessage.h"
+#include "DHTMessageCallback.h"
+#include "DHTMessageTrackerEntry.h"
+#include "DHTNode.h"
+#include "DHTRoutingTable.h"
+#include "DHTMessageFactory.h"
+#include "Util.h"
+#include "LogFactory.h"
+#include "Dictionary.h"
+#include "Data.h"
+#include "DlAbortEx.h"
+#include "DHTConstants.h"
+
+DHTMessageTracker::DHTMessageTracker():
+  _routingTable(0),
+  _factory(0),
+  _logger(LogFactory::getInstance()) {}
+
+DHTMessageTracker::~DHTMessageTracker() {}
+
+void DHTMessageTracker::addMessage(const DHTMessageHandle& message, time_t timeout, const DHTMessageCallbackHandle& callback)
+{
+  _entries.push_back(new DHTMessageTrackerEntry(message, timeout, callback));
+}
+
+void DHTMessageTracker::addMessage(const DHTMessageHandle& message, const DHTMessageCallbackHandle& callback)
+{
+  addMessage(message, DHT_MESSAGE_TIMEOUT, callback);
+}
+
+pair<DHTMessageHandle, DHTMessageCallbackHandle>
+DHTMessageTracker::messageArrived(const Dictionary* d,
+				  const string& ipaddr, uint16_t port)
+{
+  const Data* tid = dynamic_cast<const Data*>(d->get("t"));
+  if(!tid) {
+    throw new DlAbortEx("Malformed DHT message. From:%s:%u", ipaddr.c_str(), port);
+  }
+  _logger->debug("Searching tracker entry for TransactionID=%s, Remote=%s:%u",
+		 Util::toHex(tid->toString()).c_str(), ipaddr.c_str(), port);
+  for(DHTMessageTrackerEntries::iterator i = _entries.begin();
+      i != _entries.end(); ++i) {
+    if((*i)->match(tid->toString(), ipaddr, port)) {
+      DHTMessageTrackerEntryHandle entry = *i;
+      _entries.erase(i);
+      _logger->debug("Tracker entry found.");
+      DHTNodeHandle targetNode = entry->getTargetNode();
+
+      DHTMessageHandle message = _factory->createResponseMessage(entry->getMessageType(),
+								 d, targetNode);
+      int64_t rtt = entry->getElapsedMillis();
+      _logger->debug("RTT is %s", Util::llitos(rtt).c_str());
+      targetNode->updateRTT(rtt);
+      DHTMessageCallbackHandle callback = entry->getCallback();
+      return pair<DHTMessageHandle, DHTMessageCallbackHandle>(message, callback);
+    }
+  }
+  _logger->debug("Tracker entry not found.");
+  return pair<DHTMessageHandle, DHTMessageCallbackHandle>(0, 0);
+}
+
+void DHTMessageTracker::handleTimeout()
+{
+  for(DHTMessageTrackerEntries::iterator i = _entries.begin();
+      i != _entries.end();) {
+    if((*i)->isTimeout()) {
+      DHTMessageTrackerEntryHandle entry = *i;
+      i = _entries.erase(i);
+      DHTNodeHandle node = entry->getTargetNode();
+      _logger->debug("Message timeout: To:%s:%u",
+		     node->getIPAddress().c_str(), node->getPort());
+      node->updateRTT(entry->getElapsedMillis());
+      node->timeout();
+      if(node->isBad()) {
+	_logger->debug("Marked bad: %s:%u",
+		       node->getIPAddress().c_str(), node->getPort());
+	_routingTable->dropNode(node);
+      }
+      DHTMessageCallbackHandle callback = entry->getCallback();
+      if(!callback.isNull()) {
+	callback->onTimeout(node);
+      }
+    } else {
+      ++i;
+    }
+  }
+}
+
+DHTMessageTrackerEntryHandle
+DHTMessageTracker::getEntryFor(const DHTMessageHandle& message) const
+{
+  for(DHTMessageTrackerEntries::const_iterator i = _entries.begin();
+      i != _entries.end(); ++i) {
+    if((*i)->match(message->getTransactionID(), message->getRemoteNode()->getIPAddress(), message->getRemoteNode()->getPort())) {
+      return *i;
+    }
+  }
+  return 0;
+}
+
+size_t DHTMessageTracker::countEntry() const
+{
+  return _entries.size();
+}
+
+void DHTMessageTracker::setRoutingTable(const DHTRoutingTableHandle& routingTable)
+{
+  _routingTable = routingTable;
+}
+
+void DHTMessageTracker::setMessageFactory(const DHTMessageFactoryHandle& factory)
+{
+  _factory = factory;
+}

+ 81 - 0
src/DHTMessageTracker.h

@@ -0,0 +1,81 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_TRACKER_H_
+#define _D_DHT_MESSAGE_TRACKER_H_
+
+#include "common.h"
+#include "DHTMessageTrackerDecl.h"
+#include "DHTMessageDecl.h"
+#include "DHTMessageCallbackDecl.h"
+#include "DHTMessageTrackerEntryDecl.h"
+#include "DHTRoutingTableDecl.h"
+#include "DHTMessageFactoryDecl.h"
+
+class Logger;
+class Dictionary;
+
+class DHTMessageTracker {
+private:
+  DHTMessageTrackerEntries _entries;
+  
+  DHTRoutingTableHandle _routingTable;
+
+  DHTMessageFactoryHandle _factory;
+
+  const Logger* _logger;
+public:
+  DHTMessageTracker();
+
+  ~DHTMessageTracker();
+
+  void addMessage(const DHTMessageHandle& message, time_t timeout, const DHTMessageCallbackHandle& callback = 0);
+
+  void addMessage(const DHTMessageHandle& message, const DHTMessageCallbackHandle& callback = 0);
+
+  pair<DHTMessageHandle, DHTMessageCallbackHandle>
+  messageArrived(const Dictionary* d, const string& ipaddr, uint16_t port);
+
+  void handleTimeout();
+
+  DHTMessageTrackerEntryHandle getEntryFor(const DHTMessageHandle& message) const;
+
+  size_t countEntry() const;
+
+  void setRoutingTable(const DHTRoutingTableHandle& routingTable);
+
+  void setMessageFactory(const DHTMessageFactoryHandle& factory);
+};
+
+#endif // _D_DHT_MESSAGE_TRACKER_H_

+ 43 - 0
src/DHTMessageTrackerDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_TRACKER_DECL_H_
+#define _D_DHT_MESSAGE_TRACKER_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTMessageTracker;
+typedef SharedHandle<DHTMessageTracker> DHTMessageTrackerHandle;
+
+#endif // _D_DHT_MESSAGE_TRACKER_DECL_H_

+ 73 - 0
src/DHTMessageTrackerEntry.cc

@@ -0,0 +1,73 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTMessageTrackerEntry.h"
+#include "DHTNode.h"
+#include "DHTMessage.h"
+#include "DHTMessageCallback.h"
+#include "DHTConstants.h"
+
+DHTMessageTrackerEntry::DHTMessageTrackerEntry(const DHTMessageHandle& sentMessage,
+					       time_t timeout,
+					       const DHTMessageCallbackHandle& callback):
+  _targetNode(sentMessage->getRemoteNode()),
+  _transactionID(sentMessage->getTransactionID()),
+  _messageType(sentMessage->getMessageType()),
+  _callback(callback),
+  _timeout(timeout)
+{}
+
+bool DHTMessageTrackerEntry::isTimeout() const
+{
+  return _dispatchedTime.elapsed(_timeout);
+}
+
+void DHTMessageTrackerEntry::extendTimeout()
+{}
+
+bool DHTMessageTrackerEntry::match(const string& transactionID, const string& ipaddr, uint16_t port) const
+{
+  return _transactionID == transactionID &&
+    _targetNode->getIPAddress() == ipaddr && _targetNode->getPort() == port;
+}
+
+DHTMessageCallbackHandle DHTMessageTrackerEntry::getCallback() const
+{
+  return _callback;
+}
+
+DHTNodeHandle DHTMessageTrackerEntry::getTargetNode() const
+{
+  return _targetNode;
+}

+ 85 - 0
src/DHTMessageTrackerEntry.h

@@ -0,0 +1,85 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_TRACKER_ENTRY_H_
+#define _D_DHT_MESSAGE_TRACKER_ENTRY_H_
+
+#include "common.h"
+#include "DHTMessageTrackerEntryDecl.h"
+#include "DHTConstants.h"
+#include "DHTNodeDecl.h"
+#include "DHTMessageDecl.h"
+#include "DHTMessageCallbackDecl.h"
+#include "TimeA2.h"
+
+class DHTMessageTrackerEntry {
+private:
+  DHTNodeHandle _targetNode;
+
+  string _transactionID;
+
+  string _messageType;
+  
+  DHTMessageCallbackHandle _callback;
+
+  Time _dispatchedTime;
+
+  time_t _timeout;
+public:
+  DHTMessageTrackerEntry(const DHTMessageHandle& sentMessage,
+			 time_t timeout,
+			 const DHTMessageCallbackHandle& callback = 0);
+
+  bool isTimeout() const;
+
+  void extendTimeout();
+
+  bool match(const string& transactionID, const string& ipaddr, uint16_t port) const;
+
+  DHTNodeHandle getTargetNode() const;
+
+  const string& getMessageType() const
+  {
+    return _messageType;
+  }
+
+  DHTMessageCallbackHandle getCallback() const;
+
+  int64_t getElapsedMillis() const
+  {
+    return _dispatchedTime.differenceInMillis();
+  }
+};
+
+#endif // _D_DHT_MESSAGE_TRACKER_ENTRY_H_

+ 45 - 0
src/DHTMessageTrackerEntryDecl.h

@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_MESSAGE_TRACKER_ENTRY_DECL_H_
+#define _D_DHT_MESSAGE_TRACKER_ENTRY_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTMessageTrackerEntry;
+typedef SharedHandle<DHTMessageTrackerEntry> DHTMessageTrackerEntryHandle;
+typedef std::deque<DHTMessageTrackerEntryHandle> DHTMessageTrackerEntries;
+
+#endif // _D_DHT_MESSAGE_TRACKER_ENTRY_DECL_H_

+ 115 - 0
src/DHTNode.cc

@@ -0,0 +1,115 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTNode.h"
+#include "DHTUtil.h"
+#include "Util.h"
+
+DHTNode::DHTNode():_port(0), _rtt(0), _condition(0), _lastContact(0)
+{
+  generateID();
+}
+
+DHTNode::DHTNode(const unsigned char* id):_port(0), _rtt(0), _condition(1), _lastContact(0)
+{
+  memcpy(_id, id, DHT_ID_LENGTH);
+}
+
+void DHTNode::generateID()
+{
+  DHTUtil::generateRandomKey(_id);
+}
+
+bool DHTNode::operator==(const DHTNode& node) const
+{
+  return memcmp(_id, node._id, DHT_ID_LENGTH) == 0 &&
+    _ipaddr == node._ipaddr && _port == node._port;
+}
+
+bool DHTNode::operator<(const DHTNode& node) const
+{
+  for(size_t i = 0; i < DHT_ID_LENGTH; ++i) {
+    if(_id[i] > node._id[i]) {
+      return false;
+    } else if(_id[i] < node._id[i]) {
+      return true;
+    }
+  }
+  return true;
+}
+
+bool DHTNode::isGood() const
+{
+  return !isBad() && !isQuestionable();
+}
+
+#define BAD_CONDITION 5
+
+bool DHTNode::isBad() const
+{
+  return _condition >= BAD_CONDITION;
+}
+
+bool DHTNode::isQuestionable() const
+{
+  return !isBad() && _lastContact.elapsed(DHT_NODE_CONTACT_INTERVAL);
+}
+
+void DHTNode::markGood()
+{
+  _condition = 0;
+}
+
+void DHTNode::markBad()
+{
+  _condition = BAD_CONDITION;
+}
+
+void DHTNode::updateLastContact()
+{
+  _lastContact.reset();
+}
+
+void DHTNode::timeout()
+{
+  ++_condition;
+}
+
+string DHTNode::toString() const
+{
+  return "DHTNode ID="+Util::toHex(_id, DHT_ID_LENGTH)+
+    ", Host="+_ipaddr+":"+Util::uitos(_port)+
+    ", Condition="+Util::uitos(_condition)+
+    ", RTT="+Util::itos(_rtt);
+}

+ 123 - 0
src/DHTNode.h

@@ -0,0 +1,123 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_NODE_H_
+#define _D_DHT_NODE_H_
+
+#include "common.h"
+#include "DHTConstants.h"
+#include "DHTNodeDecl.h"
+#include "TimeA2.h"
+
+class DHTNode {
+private:
+  unsigned char _id[DHT_ID_LENGTH];
+
+  string _ipaddr;
+
+  uint16_t _port;
+
+  // in milli sec
+  int32_t _rtt;
+
+  uint32_t _condition;
+
+  Time _lastContact;
+public:
+  DHTNode();
+  
+  /**
+   * id must be 20 bytes length
+   */
+  DHTNode(const unsigned char* id);
+
+  void generateID();
+
+  const unsigned char* getID() const
+  {
+    return _id;
+  }
+
+  void updateRTT(int32_t millisec)
+  {
+    _rtt = millisec;
+  }
+
+  string getIPAddress() const
+  {
+    return _ipaddr;
+  }
+
+  void setIPAddress(const string& ipaddr)
+  {
+    _ipaddr = ipaddr;
+  }
+
+  void setID(const unsigned char* id)
+  {
+    memcpy(_id, id, DHT_ID_LENGTH);
+  }
+
+  uint16_t getPort() const
+  {
+    return _port;
+  }
+
+  void setPort(uint16_t port)
+  {
+    _port = port;
+  }
+
+  bool isGood() const;
+
+  bool isBad() const;
+
+  bool isQuestionable() const;
+
+  void updateLastContact();
+
+  void markGood();
+
+  void markBad();
+
+  void timeout();
+
+  bool operator==(const DHTNode& node) const;
+
+  bool operator<(const DHTNode& node) const;
+
+  string toString() const;
+};
+
+#endif // _D_DHT_NODE_H_

+ 44 - 0
src/DHTNodeDecl.h

@@ -0,0 +1,44 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_NODE_DECL_H_
+#define _D_DHT_NODE_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTNode;
+typedef SharedHandle<DHTNode> DHTNodeHandle;
+typedef std::deque<DHTNodeHandle> DHTNodes;
+#endif // _D_DHT_NODE_DECL_H_

+ 47 - 0
src/DHTNodeLookupEntry.cc

@@ -0,0 +1,47 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTNodeLookupEntry.h"
+#include "DHTNode.h"
+
+DHTNodeLookupEntry::DHTNodeLookupEntry(const DHTNodeHandle& node):
+  _node(node), _used(false) {}
+
+DHTNodeLookupEntry::DHTNodeLookupEntry():
+  _node(0), _used(false) {}
+
+bool DHTNodeLookupEntry::operator==(const DHTNodeLookupEntry& entry) const
+{
+  return _node == entry._node;
+}

+ 54 - 0
src/DHTNodeLookupEntry.h

@@ -0,0 +1,54 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_NODE_LOOKUP_ENTRY_H_
+#define _D_DHT_NODE_LOOKUP_ENTRY_H_
+
+#include "common.h"
+#include "DHTNodeDecl.h"
+
+class DHTNodeLookupEntry {
+public:
+  DHTNodeHandle _node;
+
+  bool _used;
+
+  DHTNodeLookupEntry(const DHTNodeHandle& node);
+
+  DHTNodeLookupEntry();
+
+  bool operator==(const DHTNodeLookupEntry& entry) const;
+};
+
+#endif // _D_DHT_NODE_LOOKUP_ENTRY_H_

+ 45 - 0
src/DHTNodeLookupEntryDecl.h

@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_NODE_LOOKUP_ENTRY_DECL_H_
+#define _D_DHT_NODE_LOOKUP_ENTRY_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTNodeLookupEntry;
+typedef SharedHandle<DHTNodeLookupEntry> DHTNodeLookupEntryHandle;
+typedef std::deque<DHTNodeLookupEntryHandle> DHTNodeLookupEntries;
+
+#endif // _D_DHT_NODE_LOOKUP_ENTRY_DECL_H_

+ 56 - 0
src/DHTNodeLookupTask.cc

@@ -0,0 +1,56 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTNodeLookupTask.h"
+#include "DHTMessageFactory.h"
+#include "DHTFindNodeReplyMessage.h"
+#include "DHTNode.h"
+#include "DHTNodeLookupEntry.h"
+#include "LogFactory.h"
+#include "Util.h"
+
+DHTNodeLookupTask::DHTNodeLookupTask(const unsigned char* targetNodeID):
+  DHTAbstractNodeLookupTask(targetNodeID)
+{}
+
+DHTNodes DHTNodeLookupTask::getNodesFromMessage(const DHTMessageHandle& message)
+{
+  SharedHandle<DHTFindNodeReplyMessage> m = message;
+  return m->getClosestKNodes();
+}
+
+DHTMessageHandle DHTNodeLookupTask::createMessage(const DHTNodeHandle& remoteNode)
+{
+  return _factory->createFindNodeMessage(remoteNode, _targetID);
+}

+ 49 - 0
src/DHTNodeLookupTask.h

@@ -0,0 +1,49 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_NODE_LOOKUP_TASK_H_
+#define _D_DHT_NODE_LOOKUP_TASK_H_
+
+#include "DHTAbstractNodeLookupTask.h"
+
+class DHTNodeLookupTask:public DHTAbstractNodeLookupTask {
+public:
+  DHTNodeLookupTask(const unsigned char* targetNodeID);
+
+  virtual DHTNodes getNodesFromMessage(const DHTMessageHandle& message);
+
+  virtual DHTMessageHandle createMessage(const DHTNodeHandle& remoteNode);
+};
+
+#endif // _D_DHT_NODE_LOOKUP_TASK_H_

+ 68 - 0
src/DHTPeerAnnounceCommand.cc

@@ -0,0 +1,68 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTPeerAnnounceCommand.h"
+#include "DHTPeerAnnounceStorage.h"
+#include "DownloadEngine.h"
+#include "SingletonHolder.h"
+#include "RequestGroupMan.h"
+#include "RecoverableException.h"
+#include "message.h"
+
+DHTPeerAnnounceCommand::DHTPeerAnnounceCommand(int32_t cuid, DownloadEngine* e, time_t interval):
+  TimeBasedCommand(cuid, e, interval),
+  _peerAnnounceStorage(0)
+{}
+
+DHTPeerAnnounceCommand::~DHTPeerAnnounceCommand() {}
+
+void DHTPeerAnnounceCommand::preProcess()
+{
+  _exit = _e->_requestGroupMan->downloadFinished() || _e->isHaltRequested();
+}
+
+void DHTPeerAnnounceCommand::process()
+{
+  try {
+    _peerAnnounceStorage->handleTimeout();
+  } catch(RecoverableException* e) {
+    logger->error(EX_EXCEPTION_CAUGHT, e);
+    delete e;
+  }
+}
+
+void DHTPeerAnnounceCommand::setPeerAnnounceStorage(const DHTPeerAnnounceStorageHandle& storage)
+{
+  _peerAnnounceStorage = storage;
+}

+ 56 - 0
src/DHTPeerAnnounceCommand.h

@@ -0,0 +1,56 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PEER_ANNOUNCE_COMMAND_H_
+#define _D_DHT_PEER_ANNOUNCE_COMMAND_H_
+
+#include "TimeBasedCommand.h"
+#include "DHTPeerAnnounceStorageDecl.h"
+
+class DHTPeerAnnounceCommand:public TimeBasedCommand {
+private:
+  DHTPeerAnnounceStorageHandle _peerAnnounceStorage;
+public:
+  DHTPeerAnnounceCommand(int32_t cuid, DownloadEngine* e, time_t interval);
+
+  virtual ~DHTPeerAnnounceCommand();
+
+  virtual void preProcess();
+
+  virtual void process();
+
+  void setPeerAnnounceStorage(const DHTPeerAnnounceStorageHandle& storage);
+};
+
+#endif // _D_DHT_PEER_ANNOUNCE_COMMAND_H_

+ 121 - 0
src/DHTPeerAnnounceEntry.cc

@@ -0,0 +1,121 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTPeerAnnounceEntry.h"
+#include "BtContext.h"
+#include "Peer.h"
+#include "BtRegistry.h"
+
+DHTPeerAnnounceEntry::DHTPeerAnnounceEntry(const unsigned char* infoHash):
+  _btCtx(0)
+{
+  memcpy(_infoHash, infoHash, DHT_ID_LENGTH);
+}
+
+DHTPeerAnnounceEntry::~DHTPeerAnnounceEntry() {}
+
+void DHTPeerAnnounceEntry::addPeerAddrEntry(const PeerAddrEntry& entry)
+{
+  PeerAddrEntries::iterator i = find(_peerAddrEntries.begin(), _peerAddrEntries.end(), entry);
+  if(i == _peerAddrEntries.end()) {
+    _peerAddrEntries.push_back(entry);
+  } else {
+    (*i).notifyUpdate();
+  }
+  notifyUpdate();
+}
+
+void DHTPeerAnnounceEntry::setBtContext(const BtContextHandle& btCtx)
+{
+  _btCtx = btCtx;
+}
+
+size_t DHTPeerAnnounceEntry::countPeerAddrEntry() const
+{
+  return _peerAddrEntries.size();
+}
+
+const PeerAddrEntries& DHTPeerAnnounceEntry::getPeerAddrEntries() const
+{
+  return _peerAddrEntries;
+}
+
+class FindStaleEntry {
+private:
+  time_t _timeout;
+public:
+  FindStaleEntry(time_t timeout):_timeout(timeout) {}
+
+  bool operator()(const PeerAddrEntry& entry) const
+  {
+    if(entry.getLastUpdated().elapsed(_timeout)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+};
+
+void DHTPeerAnnounceEntry::removeStalePeerAddrEntry(time_t timeout)
+{
+  _peerAddrEntries.erase(remove_if(_peerAddrEntries.begin(), _peerAddrEntries.end(),
+				   FindStaleEntry(timeout)), _peerAddrEntries.end());
+}
+
+bool DHTPeerAnnounceEntry::empty() const
+{
+  return _peerAddrEntries.empty() && _btCtx.isNull();
+}
+
+Peers DHTPeerAnnounceEntry::getPeers() const
+{
+  Peers peers;
+  for(PeerAddrEntries::const_iterator i = _peerAddrEntries.begin();
+      i != _peerAddrEntries.end(); ++i) {
+    peers.push_back(new Peer((*i).getIPAddress(), (*i).getPort()));
+  }
+  if(!_btCtx.isNull()) {
+    PeerStorageHandle peerStorage = PEER_STORAGE(_btCtx);
+    if(!peerStorage.isNull()) {
+      const Peers& activePeers = peerStorage->getActivePeers();
+      peers.insert(peers.end(), activePeers.begin(), activePeers.end());
+    }
+  }
+  return peers;
+}
+
+void DHTPeerAnnounceEntry::notifyUpdate()
+{
+  _lastUpdated.reset();
+}

+ 91 - 0
src/DHTPeerAnnounceEntry.h

@@ -0,0 +1,91 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PEER_ANNOUNCE_ENTRY_H_
+#define _D_DHT_PEER_ANNOUNCE_ENTRY_H_
+
+#include "common.h"
+#include "DHTConstants.h"
+#include "PeerAddrEntry.h"
+#include "PeerDecl.h"
+#include "TimeA2.h"
+
+class BtContext;
+typedef SharedHandle<BtContext> BtContextHandle;
+
+class DHTPeerAnnounceEntry {
+private:
+  unsigned char _infoHash[DHT_ID_LENGTH];
+
+  PeerAddrEntries _peerAddrEntries;
+
+  BtContextHandle _btCtx;
+
+  Time _lastUpdated;
+public:
+  DHTPeerAnnounceEntry(const unsigned char* infoHash);
+
+  ~DHTPeerAnnounceEntry();
+
+  // add peer addr entry.
+  // if it already exists, update "Last Updated" property.
+  void addPeerAddrEntry(const PeerAddrEntry& entry);
+
+  void setBtContext(const BtContextHandle& btCtx);
+
+  size_t countPeerAddrEntry() const;
+
+  const PeerAddrEntries& getPeerAddrEntries() const;
+
+  void removeStalePeerAddrEntry(time_t timeout);
+  
+  bool empty() const;
+
+  const Time& getLastUpdated() const
+  {
+    return _lastUpdated;
+  }
+
+  void notifyUpdate();
+
+  const unsigned char* getInfoHash() const
+  {
+    return _infoHash;
+  }
+
+  Peers getPeers() const;
+
+};
+
+#endif // _D_DHT_PEER_ANNOUNCE_ENTRY_H_

+ 45 - 0
src/DHTPeerAnnounceEntryDecl.h

@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PEER_ANNOUNCE_ENTRY_DECL_H_
+#define _D_DHT_PEER_ANNOUNCE_ENTRY_DECL_H_
+
+#include "SharedHandle.h"
+#include <deque>
+
+class DHTPeerAnnounceEntry;
+typedef SharedHandle<DHTPeerAnnounceEntry> DHTPeerAnnounceEntryHandle;
+typedef std::deque<DHTPeerAnnounceEntryHandle> DHTPeerAnnounceEntries;
+
+#endif // _D_DHT_PEER_ANNOUNCE_ENTRY_DECL_H_

+ 165 - 0
src/DHTPeerAnnounceStorage.cc

@@ -0,0 +1,165 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTPeerAnnounceStorage.h"
+#include "DHTPeerAnnounceEntry.h"
+#include "Peer.h"
+#include "BtContext.h"
+#include "DHTConstants.h"
+#include "DHTTaskQueue.h"
+#include "DHTTaskFactory.h"
+#include "DHTTask.h"
+#include "LogFactory.h"
+#include "Util.h"
+
+DHTPeerAnnounceStorage::DHTPeerAnnounceStorage():_taskQueue(0),
+						 _taskFactory(0),
+						 _logger(LogFactory::getInstance()) {}
+
+DHTPeerAnnounceStorage::~DHTPeerAnnounceStorage() {}
+
+class FindPeerAnnounceEntry {
+private:
+  unsigned char _infoHash[DHT_ID_LENGTH];
+public:
+  FindPeerAnnounceEntry(const unsigned char* infoHash)
+  {
+    memcpy(_infoHash, infoHash, DHT_ID_LENGTH);
+  }
+
+  bool operator()(const DHTPeerAnnounceEntryHandle& entry) const
+  {
+    return memcmp(_infoHash, entry->getInfoHash(), DHT_ID_LENGTH) == 0;
+  }
+};
+
+DHTPeerAnnounceEntryHandle
+DHTPeerAnnounceStorage::getPeerAnnounceEntry(const unsigned char* infoHash)
+{
+  DHTPeerAnnounceEntries::iterator i = 
+    find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(infoHash));
+  DHTPeerAnnounceEntryHandle entry = 0;
+  if(i == _entries.end()) {
+    entry = new DHTPeerAnnounceEntry(infoHash);
+    _entries.push_back(entry);
+  } else {
+    entry = *i;
+  }
+  return entry;
+}
+
+void
+DHTPeerAnnounceStorage::addPeerAnnounce(const unsigned char* infoHash,
+					const string& ipaddr, uint16_t port)
+{
+  _logger->debug("Adding %s:%u to peer announce list: infoHash=%s",
+		 ipaddr.c_str(), port, Util::toHex(infoHash, DHT_ID_LENGTH).c_str());
+  getPeerAnnounceEntry(infoHash)->addPeerAddrEntry(PeerAddrEntry(ipaddr, port));
+}
+
+// add peer announce as localhost downloading the content
+void DHTPeerAnnounceStorage::addPeerAnnounce(const BtContextHandle& ctx)
+{
+  _logger->debug("Adding localhost to peer announce list: infoHash=%s",
+		 ctx->getInfoHashAsString().c_str());
+  getPeerAnnounceEntry(ctx->getInfoHash())->setBtContext(ctx);
+}
+
+void DHTPeerAnnounceStorage::removePeerAnnounce(const BtContextHandle& ctx)
+{
+  DHTPeerAnnounceEntries::iterator i = 
+    find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(ctx->getInfoHash()));
+  if(i != _entries.end()) {
+    (*i)->setBtContext(0);
+    if((*i)->empty()) {
+      _entries.erase(i);
+    }
+  }
+}
+
+bool DHTPeerAnnounceStorage::contains(const unsigned char* infoHash) const
+{
+  return 
+    find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(infoHash))
+    != _entries.end();
+}
+
+Peers DHTPeerAnnounceStorage::getPeers(const unsigned char* infoHash)
+{
+  DHTPeerAnnounceEntries::iterator i = 
+    find_if(_entries.begin(), _entries.end(), FindPeerAnnounceEntry(infoHash));
+  if(i == _entries.end() || (*i)->empty()) {
+    return Peers();
+  }
+  return (*i)->getPeers();
+}
+
+void DHTPeerAnnounceStorage::handleTimeout()
+{
+  _logger->debug("Now purge peer announces which are timed out.");
+  for(DHTPeerAnnounceEntries::iterator i = _entries.begin(); i != _entries.end();) {
+    (*i)->removeStalePeerAddrEntry(DHT_PEER_ANNOUNCE_PURGE_INTERVAL);
+    if((*i)->empty()) {
+      _logger->debug("1 entry purged: infoHash=%s",
+		     Util::toHex((*i)->getInfoHash(), DHT_ID_LENGTH).c_str());
+      i = _entries.erase(i);
+    } else {
+      ++i;
+    }
+  }
+}
+
+void DHTPeerAnnounceStorage::announcePeer()
+{
+  _logger->debug("Now announcing peer.");
+  for(DHTPeerAnnounceEntries::iterator i = _entries.begin(); i != _entries.end(); ++i) {
+    if((*i)->getLastUpdated().elapsed(DHT_PEER_ANNOUNCE_INTERVAL)) {
+      (*i)->notifyUpdate();
+      DHTTaskHandle task = _taskFactory->createPeerAnnounceTask((*i)->getInfoHash());
+      _taskQueue->addPeriodicTask2(task);
+      _logger->debug("Added 1 peer announce: infoHash=%s",
+		     Util::toHex((*i)->getInfoHash(), DHT_ID_LENGTH).c_str());
+    }
+  }
+}
+
+void DHTPeerAnnounceStorage::setTaskQueue(const DHTTaskQueueHandle& taskQueue)
+{
+  _taskQueue = taskQueue;
+}
+
+void DHTPeerAnnounceStorage::setTaskFactory(const DHTTaskFactoryHandle& taskFactory)
+{
+  _taskFactory = taskFactory;
+}

+ 92 - 0
src/DHTPeerAnnounceStorage.h

@@ -0,0 +1,92 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PEER_ANNOUNCE_STORAGE_H_
+#define _D_DHT_PEER_ANNOUNCE_STORAGE_H_
+
+#include "common.h"
+#include "DHTPeerAnnounceStorageDecl.h"
+#include "DHTPeerAnnounceEntryDecl.h"
+#include "PeerDecl.h"
+#include "BtContextDecl.h"
+#include "DHTTaskQueueDecl.h"
+#include "DHTTaskFactoryDecl.h"
+
+class Logger;
+
+class DHTPeerAnnounceStorage {
+private:
+  DHTPeerAnnounceEntries _entries;
+
+  DHTPeerAnnounceEntryHandle getPeerAnnounceEntry(const unsigned char* infoHash);
+
+  DHTTaskQueueHandle _taskQueue;
+
+  DHTTaskFactoryHandle _taskFactory;
+
+  const Logger* _logger;
+public:
+  DHTPeerAnnounceStorage();
+
+  ~DHTPeerAnnounceStorage();
+
+  void addPeerAnnounce(const unsigned char* infoHash,
+		       const string& ipaddr, uint16_t port);
+
+  // add peer announce as localhost downloading the content
+  void addPeerAnnounce(const BtContextHandle& ctx);
+  
+  // give 0 to DHTPeerAnnounceEntry::setBtContext().
+  // If DHTPeerAnnounceEntry is empty, it is erased.
+  void removePeerAnnounce(const BtContextHandle& ctx);
+
+  bool contains(const unsigned char* infoHash) const;
+
+  Peers getPeers(const unsigned char* infoHash);
+
+  // drop peer announce entry which is not updated in the past
+  // DHT_PEER_ANNOUNCE_PURGE_INTERVAL seconds.
+  void handleTimeout();
+
+  // announce peer in every DHT_PEER_ANNOUNCE_PURGE_INTERVAL.
+  // The torrents which are announced in the past DHT_PEER_ANNOUNCE_PURGE_INTERVAL
+  // are excluded from announce.
+  void announcePeer();
+
+  void setTaskQueue(const DHTTaskQueueHandle& taskQueue);
+
+  void setTaskFactory(const DHTTaskFactoryHandle& taskFactory);
+};
+
+#endif // _D_DHT_PEER_ANNOUNCE_STORAGE_H_

+ 43 - 0
src/DHTPeerAnnounceStorageDecl.h

@@ -0,0 +1,43 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PEER_ANNOUNCE_STORAGE_DECL_H_
+#define _D_DHT_PEER_ANNOUNCE_STORAGE_DECL_H_
+
+#include "SharedHandle.h"
+
+class DHTPeerAnnounceStorage;
+typedef SharedHandle<DHTPeerAnnounceStorage> DHTPeerAnnounceStorageHandle;
+
+#endif // _D_DHT_PEER_ANNOUNCE_STORAGE_DECL_H_

+ 102 - 0
src/DHTPeerLookupTask.cc

@@ -0,0 +1,102 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTPeerLookupTask.h"
+#include "Peer.h"
+#include "DHTGetPeersReplyMessage.h"
+#include "Logger.h"
+#include "DHTMessageFactory.h"
+#include "DHTNode.h"
+#include "DHTNodeLookupEntry.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageCallback.h"
+#include "BtRegistry.h"
+#include "PeerStorage.h"
+#include "BtRuntime.h"
+#include "BtContext.h"
+#include "Util.h"
+#include "DHTBucket.h"
+
+DHTPeerLookupTask::DHTPeerLookupTask(const BtContextHandle& btContext):
+  DHTAbstractNodeLookupTask(btContext->getInfoHash()),
+  _ctx(btContext),
+  _peerStorage(PEER_STORAGE(btContext)),
+  _btRuntime(BT_RUNTIME(btContext)) {}
+
+DHTNodes DHTPeerLookupTask::getNodesFromMessage(const DHTMessageHandle& message)
+{
+  SharedHandle<DHTGetPeersReplyMessage> m = message;
+  return m->getClosestKNodes();
+}
+  
+void DHTPeerLookupTask::onReceivedInternal(const DHTMessageHandle& message)
+{
+  SharedHandle<DHTGetPeersReplyMessage> m = message;
+
+  DHTNodeHandle remoteNode = m->getRemoteNode();
+  _tokenStorage[Util::toHex(remoteNode->getID(), DHT_ID_LENGTH)] = m->getToken();
+
+  _peerStorage->addPeer(m->getValues());
+  _peers.insert(_peers.end(), m->getValues().begin(), m->getValues().end());
+  _logger->info("Received %u peers.", m->getValues().size());
+}
+  
+DHTMessageHandle DHTPeerLookupTask::createMessage(const DHTNodeHandle& remoteNode)
+{
+  return _factory->createGetPeersMessage(remoteNode, _targetID);
+}
+
+void DHTPeerLookupTask::onFinish()
+{
+  // send announce_peer message to K closest nodes
+  size_t num = DHTBucket::K;
+  for(DHTNodeLookupEntries::const_iterator i = _entries.begin();
+      i != _entries.end() && num > 0; ++i, --num) {
+    if((*i)->_used) {
+      const DHTNodeHandle& node = (*i)->_node;
+      DHTMessageHandle m = 
+	_factory->createAnnouncePeerMessage(node,
+					    _ctx->getInfoHash(),
+					    _btRuntime->getListenPort(),
+					    _tokenStorage[Util::toHex(node->getID(),
+								      DHT_ID_LENGTH)]);
+      _dispatcher->addMessageToQueue(m);
+    }
+  }
+}
+
+const Peers& DHTPeerLookupTask::getPeers() const
+{
+  return _peers;
+}

+ 73 - 0
src/DHTPeerLookupTask.h

@@ -0,0 +1,73 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PEER_LOOKUP_TASK_H_
+#define _D_DHT_PEER_LOOKUP_TASK_H_
+
+#include "DHTAbstractNodeLookupTask.h"
+#include "BtContextDecl.h"
+#include "PeerDecl.h"
+#include <map>
+
+class PeerStorage;
+typedef SharedHandle<PeerStorage> PeerStorageHandle;
+class BtRuntime;
+typedef SharedHandle<BtRuntime> BtRuntimeHandle;
+
+class DHTPeerLookupTask:public DHTAbstractNodeLookupTask {
+private:
+  std::map<string, string> _tokenStorage;
+
+  Peers _peers;
+
+  BtContextHandle _ctx;
+
+  PeerStorageHandle _peerStorage;
+
+  BtRuntimeHandle _btRuntime;
+public:
+  DHTPeerLookupTask(const BtContextHandle& btContext);
+
+  virtual DHTNodes getNodesFromMessage(const DHTMessageHandle& message);
+  
+  virtual void onReceivedInternal(const DHTMessageHandle& message);
+  
+  virtual DHTMessageHandle createMessage(const DHTNodeHandle& remoteNode);
+
+  virtual void onFinish();
+  
+  const Peers& getPeers() const;
+};
+
+#endif // _D_DHT_PEER_LOOKUP_TASK_H_

+ 70 - 0
src/DHTPingMessage.cc

@@ -0,0 +1,70 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "DHTPingMessage.h"
+#include "DHTNode.h"
+#include "Data.h"
+#include "DHTConstants.h"
+#include "DHTMessageDispatcher.h"
+#include "DHTMessageFactory.h"
+#include "DHTMessageCallback.h"
+
+DHTPingMessage::DHTPingMessage(const DHTNodeHandle& localNode,
+			       const DHTNodeHandle& remoteNode,
+			       const string& transactionID):
+  DHTQueryMessage(localNode, remoteNode, transactionID) {}
+
+DHTPingMessage::~DHTPingMessage() {}
+
+void DHTPingMessage::doReceivedAction()
+{
+  // send back ping reply
+  DHTMessageHandle reply = _factory->createPingReplyMessage(_remoteNode, _localNode->getID(), _transactionID);
+  _dispatcher->addMessageToQueue(reply);
+}
+
+Dictionary* DHTPingMessage::getArgument()
+{
+  Dictionary* a = new Dictionary();
+  a->put("id", new Data(reinterpret_cast<const char*>(_localNode->getID()),
+			DHT_ID_LENGTH));
+  return a;
+}
+
+string DHTPingMessage::getMessageType() const
+{
+  return "ping";
+}
+
+void DHTPingMessage::validate() const {}

+ 57 - 0
src/DHTPingMessage.h

@@ -0,0 +1,57 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DHT_PING_MESSAGE_H_
+#define _D_DHT_PING_MESSAGE_H_
+
+#include "DHTQueryMessage.h"
+
+class DHTPingMessage:public DHTQueryMessage {
+public:
+  DHTPingMessage(const DHTNodeHandle& localNode,
+		 const DHTNodeHandle& remoteNode,
+		 const string& transactionID = "");
+
+  virtual ~DHTPingMessage();
+
+  virtual void doReceivedAction();
+
+  virtual Dictionary* getArgument();
+
+  virtual string getMessageType() const;
+
+  virtual void validate() const;
+};
+
+#endif // _D_DHT_PING_MESSAGE_H_

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor