Kaynağa Gözat

2006-12-24 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Rewritten a portion of bittorrent implementation:
	
	* src/BtMessageValidator.h: New class.
	* src/BtBitfieldMessageValidator.h: New class.
	* src/BtHandshakeMessageValidator.h: New class.
	* src/BtRequestMessageValidator.h: New class.
	* src/BtSuggestPieceMessageValidator.h: New class.
	* src/BtAllowedFastMessageValidator.h: New class.
	* src/BtRejectMessageValidator.h: New class.
	* src/BtCancelMessageValidator.h: New class.
	* src/BtPieceMessageValidator.h: New class.
	* src/BtHaveMessageValidator.h: New class.
	* src/BtEventListener.h: New class.
	* src/AbstractBtEventListener.h: New class.
	* src/BtEvent.h: New class.
	* src/BtChokingEvent.h: New class.
	* src/BtChokedEvent.h: New class.
	* src/BtCancelSendingPieceEvent.h: New class.
	* src/BtAbortOutstandingRequestEvent.h: New class.
	* src/Randomizer.h: New class.
	* src/SimpleRandomizer.h: New class.
	* src/BtMessage.h: New class.
	* src/AbstractBtMessage.h: New class.
	* src/SimpleBtMessage.h: New class.
	* src/BtHaveMessage.h: New class.
	* src/BtInterestedMessage.h: New class.
	* src/BtAllowedFastMessage.h: New class.
	* src/BtUnchokeMessage.h: New class.
	* src/BtCancelMessage.h: New class.
	* src/BtNotInterestedMessage.h: New class.
	* src/BtChokeMessage.h: New class.
	* src/BtHaveNoneMessage.h: New class.
	* src/BtHandshakeMessage.h: New class.
	* src/BtSuggestPieceMessage.h: New class.
	* src/BtHaveMessage.h: New class.
	* src/BtPieceMessage.h: New class.
	* src/BtHaveAllMessage.h: New class.
	* src/BtKeepAliveMessage.h: New class.
	* src/BtPortMessage.h: New class.
	* src/BtRejectMessage.h: New class.
	* src/BtBitfieldMessage.h: New class.
	* src/BtRequestMessage.h: New class.
	* src/DefaultBtRequestFactory.h: New class.
	* src/DefaultBtMessageReceiver.h: New class.
	* src/BtInteractive.h: New class.
	* src/BtMessageDispatcher.h: New class.
	* src/DefaultBtMessageDispatcher.h: New class.
	* src/DefaultBtInteractive.h: New class.
	* src/BitfieldManFactory.h: New class.
	* src/HandleRegistry.h: New class.
	* src/BtMessageFactory.h: New class.
	* src/BtMessageReceiver.h: New class.
	* src/DefaultBtMessageFactory.h: New class.
	* src/PeerObject.h: New class.
	* src/BtRequestFactory.h: New class.
Tatsuhiro Tsujikawa 19 yıl önce
ebeveyn
işleme
9c3e8fbd9c
100 değiştirilmiş dosya ile 7561 ekleme ve 421 silme
  1. 58 0
      ChangeLog
  2. 10 1
      TODO
  3. 55 0
      src/AbstractBtEventListener.h
  4. 167 0
      src/AbstractBtMessage.h
  5. 6 3
      src/BitfieldMan.cc
  6. 13 0
      src/BitfieldMan.h
  7. 40 0
      src/BitfieldManFactory.cc
  8. 85 0
      src/BitfieldManFactory.h
  9. 57 0
      src/BtAbortOutstandingRequestEvent.h
  10. 89 0
      src/BtAllowedFastMessage.cc
  11. 85 0
      src/BtAllowedFastMessage.h
  12. 60 0
      src/BtAllowedFastMessageValidator.h
  13. 0 5
      src/BtAnnounce.h
  14. 95 0
      src/BtBitfieldMessage.cc
  15. 98 0
      src/BtBitfieldMessage.h
  16. 61 0
      src/BtBitfieldMessageValidator.h
  17. 88 0
      src/BtCancelMessage.cc
  18. 93 0
      src/BtCancelMessage.h
  19. 67 0
      src/BtCancelMessageValidator.h
  20. 78 0
      src/BtCancelSendingPieceEvent.h
  21. 87 0
      src/BtChokeMessage.cc
  22. 77 0
      src/BtChokeMessage.h
  23. 45 0
      src/BtChokedEvent.h
  24. 45 0
      src/BtChokingEvent.h
  25. 5 0
      src/BtContext.h
  26. 47 0
      src/BtEvent.h
  27. 51 0
      src/BtEventListener.h
  28. 100 0
      src/BtHandshakeMessage.cc
  29. 117 0
      src/BtHandshakeMessage.h
  30. 75 0
      src/BtHandshakeMessageValidator.h
  31. 81 0
      src/BtHaveAllMessage.cc
  32. 73 0
      src/BtHaveAllMessage.h
  33. 85 0
      src/BtHaveMessage.cc
  34. 81 0
      src/BtHaveMessage.h
  35. 60 0
      src/BtHaveMessageValidator.h
  36. 80 0
      src/BtHaveNoneMessage.cc
  37. 73 0
      src/BtHaveNoneMessage.h
  38. 66 0
      src/BtInteractive.h
  39. 85 0
      src/BtInterestedMessage.cc
  40. 77 0
      src/BtInterestedMessage.h
  41. 53 0
      src/BtKeepAliveMessage.cc
  42. 73 0
      src/BtKeepAliveMessage.h
  43. 72 0
      src/BtMessage.h
  44. 82 0
      src/BtMessageDispatcher.h
  45. 53 0
      src/BtMessageFactory.cc
  46. 91 0
      src/BtMessageFactory.h
  47. 54 0
      src/BtMessageReceiver.h
  48. 52 0
      src/BtMessageValidator.h
  49. 85 0
      src/BtNotInterestedMessage.cc
  50. 77 0
      src/BtNotInterestedMessage.h
  51. 283 0
      src/BtPieceMessage.cc
  52. 154 0
      src/BtPieceMessage.h
  53. 64 0
      src/BtPieceMessageValidator.h
  54. 56 0
      src/BtPortMessage.cc
  55. 72 0
      src/BtPortMessage.h
  56. 30 0
      src/BtRegistry.cc
  57. 39 0
      src/BtRegistry.h
  58. 101 0
      src/BtRejectMessage.cc
  59. 88 0
      src/BtRejectMessage.h
  60. 68 0
      src/BtRejectMessageValidator.h
  61. 72 0
      src/BtRequestFactory.h
  62. 129 0
      src/BtRequestMessage.cc
  63. 117 0
      src/BtRequestMessage.h
  64. 68 0
      src/BtRequestMessageValidator.h
  65. 78 0
      src/BtSuggestPieceMessage.cc
  66. 81 0
      src/BtSuggestPieceMessage.h
  67. 60 0
      src/BtSuggestPieceMessageValidator.h
  68. 85 0
      src/BtUnchokeMessage.cc
  69. 76 0
      src/BtUnchokeMessage.h
  70. 1 8
      src/DefaultBtAnnounce.cc
  71. 1 6
      src/DefaultBtAnnounce.h
  72. 6 0
      src/DefaultBtContext.cc
  73. 10 0
      src/DefaultBtContext.h
  74. 307 0
      src/DefaultBtInteractive.cc
  75. 195 0
      src/DefaultBtInteractive.h
  76. 214 0
      src/DefaultBtMessageDispatcher.cc
  77. 163 0
      src/DefaultBtMessageDispatcher.h
  78. 347 0
      src/DefaultBtMessageFactory.cc
  79. 131 0
      src/DefaultBtMessageFactory.h
  80. 95 0
      src/DefaultBtMessageReceiver.cc
  81. 120 0
      src/DefaultBtMessageReceiver.h
  82. 99 0
      src/DefaultBtRequestFactory.cc
  83. 125 0
      src/DefaultBtRequestFactory.h
  84. 3 8
      src/DefaultPeerStorage.cc
  85. 0 1
      src/DefaultPeerStorage.h
  86. 52 62
      src/DefaultPieceStorage.cc
  87. 12 11
      src/DefaultPieceStorage.h
  88. 18 0
      src/DownloadEngineFactory.cc
  89. 73 0
      src/HandleRegistry.h
  90. 54 2
      src/Makefile.am
  91. 165 20
      src/Makefile.in
  92. 50 1
      src/Peer.cc
  93. 22 23
      src/Peer.h
  94. 25 22
      src/PeerConnection.cc
  95. 21 10
      src/PeerConnection.h
  96. 29 25
      src/PeerInteraction.cc
  97. 2 3
      src/PeerInteraction.h
  98. 86 183
      src/PeerInteractionCommand.cc
  99. 6 27
      src/PeerInteractionCommand.h
  100. 1 0
      src/PeerMessage.cc

+ 58 - 0
ChangeLog

@@ -1,3 +1,61 @@
+2006-12-24  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Rewritten a portion of bittorrent implementation:
+	
+	* src/BtMessageValidator.h: New class.
+	* src/BtBitfieldMessageValidator.h: New class.
+	* src/BtHandshakeMessageValidator.h: New class.
+	* src/BtRequestMessageValidator.h: New class.
+	* src/BtSuggestPieceMessageValidator.h: New class.
+	* src/BtAllowedFastMessageValidator.h: New class.
+	* src/BtRejectMessageValidator.h: New class.
+	* src/BtCancelMessageValidator.h: New class.
+	* src/BtPieceMessageValidator.h: New class.
+	* src/BtHaveMessageValidator.h: New class.
+	* src/BtEventListener.h: New class.
+	* src/AbstractBtEventListener.h: New class.
+	* src/BtEvent.h: New class.
+	* src/BtChokingEvent.h: New class.
+	* src/BtChokedEvent.h: New class.
+	* src/BtCancelSendingPieceEvent.h: New class.
+	* src/BtAbortOutstandingRequestEvent.h: New class.
+	* src/Randomizer.h: New class.
+	* src/SimpleRandomizer.h: New class.
+	* src/BtMessage.h: New class.
+	* src/AbstractBtMessage.h: New class.
+	* src/SimpleBtMessage.h: New class.
+	* src/BtHaveMessage.h: New class.
+	* src/BtInterestedMessage.h: New class.
+	* src/BtAllowedFastMessage.h: New class.
+	* src/BtUnchokeMessage.h: New class.
+	* src/BtCancelMessage.h: New class.
+	* src/BtNotInterestedMessage.h: New class.
+	* src/BtChokeMessage.h: New class.
+	* src/BtHaveNoneMessage.h: New class.
+	* src/BtHandshakeMessage.h: New class.
+	* src/BtSuggestPieceMessage.h: New class.
+	* src/BtHaveMessage.h: New class.
+	* src/BtPieceMessage.h: New class.
+	* src/BtHaveAllMessage.h: New class.
+	* src/BtKeepAliveMessage.h: New class.
+	* src/BtPortMessage.h: New class.
+	* src/BtRejectMessage.h: New class.
+	* src/BtBitfieldMessage.h: New class.
+	* src/BtRequestMessage.h: New class.
+	* src/DefaultBtRequestFactory.h: New class.
+	* src/DefaultBtMessageReceiver.h: New class.
+	* src/BtInteractive.h: New class.
+	* src/BtMessageDispatcher.h: New class.
+	* src/DefaultBtMessageDispatcher.h: New class.
+	* src/DefaultBtInteractive.h: New class.
+	* src/BitfieldManFactory.h: New class.
+	* src/HandleRegistry.h: New class.
+	* src/BtMessageFactory.h: New class.
+	* src/BtMessageReceiver.h: New class.
+	* src/DefaultBtMessageFactory.h: New class.
+	* src/PeerObject.h: New class.
+	* src/BtRequestFactory.h: New class.
+	
 2006-12-01  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	To know root cause of exception:

+ 10 - 1
TODO

@@ -20,4 +20,13 @@
 * Add Turkish translation.
 * Add the message like "you can resume the transfer by invoking aria2 again" when the download stops.
 * Add --bt-timeout command line option.
-* Fix DefaultBtProgressInfoFile.cc: save(), load()
+* Fix DefaultBtProgressInfoFile.cc: save(), load()
+* Add a feature that if any existing file is detected, then
+do not start downloading and print some useful message to the user.
+* Fix Segfaults in BitfieldMan.cc:71
+https://sourceforge.net/tracker/index.php?func=detail&aid=1606060&group_id=159897&atid=813673
+* Prevent the file to be fragmented. Use PreAllocationDiskWriter
+https://sourceforge.net/tracker/index.php?func=detail&aid=1611886&group_id=159897&atid=813673
+* Add #include <libgen.h> to DefaultBtContext.h
+* int32_t
+* remove blockIndex

+ 55 - 0
src/AbstractBtEventListener.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_ABSTRACT_BT_EVENT_LISTENER_H_
+#define _D_ABSTRACT_BT_EVENT_LISTENER_H_
+
+#include "BtEventListener.h"
+
+class AbstractBtEventListener : public BtEventListener {
+public:
+  virtual ~AbstractBtEventListener() {}
+
+  virtual bool canHandle(const BtEventHandle& event) = 0;
+
+  virtual void handleEventInternal(const BtEventHandle& event) = 0;
+
+  virtual void handleEvent(const BtEventHandle& event) {
+    if(canHandle(event)) {
+      handleEventInternal(event);
+    }
+  }
+};
+
+#endif // _D_ABSTRACT_BT_EVENT_LISTENER_H_

+ 167 - 0
src/AbstractBtMessage.h

@@ -0,0 +1,167 @@
+/* <!-- 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_ABSTRACT_BT_MESSAGE_H_
+#define _D_ABSTRACT_BT_MESSAGE_H_
+
+#include "BtMessage.h"
+#include "Peer.h"
+#include "Piece.h"
+#include "LogFactory.h"
+#include "Logger.h"
+#include "BtEvent.h"
+#include "BtEventListener.h"
+#include "BtContext.h"
+#include "BtRegistry.h"
+
+class AbstractBtMessage : public BtMessage {
+protected:
+  bool sendingInProgress;
+  bool invalidate;
+  bool uploading;
+  int32_t id;
+  int32_t cuid;
+
+  BtContextHandle btContext;
+
+  PieceStorageHandle pieceStorage;
+
+  PeerHandle peer;
+
+  BtMessageValidatorHandle validator;
+  BtEventListeners listeners;
+  const Logger* logger;
+public:
+  AbstractBtMessage():sendingInProgress(false),
+		      invalidate(false),
+		      uploading(false),
+		      id(0),
+		      cuid(0),
+		      btContext(0),
+		      pieceStorage(0),
+		      peer(0),
+		      validator(0),
+		      logger(LogFactory::getInstance())
+		      
+  {}
+
+  virtual bool isSendingInProgress() {
+    return sendingInProgress;
+  }
+
+  void setSendingInProgress(bool sendingInProgress) {
+    this->sendingInProgress = sendingInProgress;
+  }
+
+  virtual bool isInvalidate() {
+    return invalidate;
+  }
+
+  void setInvalidate(bool invalidate) {
+    this->invalidate = invalidate;
+  }
+
+  virtual bool isUploading() {
+    return uploading;
+  }
+
+  void setUploading(bool uploading) {
+    this->uploading = uploading;
+  }
+
+  virtual int32_t getId() {
+    return id;
+  }
+
+  int32_t getCuid() const {
+    return cuid;
+  }
+
+  void setCuid(int32_t cuid) {
+    this->cuid = cuid;
+  }
+
+  PeerHandle getPeer() const {
+    return peer;
+  }
+
+  void setPeer(const PeerHandle& peer) {
+    this->peer = peer;
+  }
+
+  virtual void doReceivedAction() {}
+
+  virtual bool validate(Errors& errors) {
+    if(validator.get()) {
+      return validator->validate(errors);
+    } else {
+      return true;
+    }
+  }
+  
+  virtual void onQueued() {}
+
+  virtual void handleEvent(const BtEventHandle& event) {
+    for(BtEventListeners::iterator itr = listeners.begin();
+	itr != listeners.end(); ++itr) {
+      (*itr)->handleEvent(event);
+    }
+  }
+
+  void addEventListener(const BtEventListenerHandle& listener) {
+    listeners.push_back(listener);
+  }
+
+  void setBtMessageValidator(const BtMessageValidatorHandle& validator) {
+    this->validator = validator;
+  }
+
+  BtMessageValidatorHandle getBtMessageValidator() const {
+    return validator;
+  }
+
+  void setBtContext(const BtContextHandle& btContext) {
+    this->btContext = btContext;
+    this->pieceStorage = PIECE_STORAGE(btContext);
+  }
+
+  BtContextHandle getBtContext() const {
+    return btContext;
+  }
+
+};
+
+typedef SharedHandle<AbstractBtMessage> AbstractBtMessageHandle;
+
+#endif // _D_ABSTRACT_BT_MESSAGE_H_

+ 6 - 3
src/BitfieldMan.cc

@@ -38,7 +38,7 @@
 
 BitfieldMan::BitfieldMan(int blockLength, long long int totalLength)
   :blockLength(blockLength), totalLength(totalLength), filterBitfield(0),
-   filterEnabled(false) {
+   filterEnabled(false), randomizer(0) {
   if(blockLength > 0 && totalLength > 0) {
     blocks = totalLength/blockLength+(totalLength%blockLength ? 1 : 0);
     bitfieldLength = blocks/8+(blocks%8 ? 1 : 0);
@@ -49,7 +49,7 @@ BitfieldMan::BitfieldMan(int blockLength, long long int totalLength)
   }
 }
 
-BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan) {
+BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan):randomizer(0) {
   blockLength = bitfieldMan.blockLength;
   totalLength = bitfieldMan.totalLength;
   blocks = bitfieldMan.blocks;
@@ -65,6 +65,7 @@ BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan) {
   } else {
     filterBitfield = 0;
   }
+  this->randomizer = bitfieldMan.randomizer;
 }
 
 BitfieldMan::~BitfieldMan() {
@@ -106,7 +107,9 @@ int
 BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield,
 				     int bitfieldLength) const
 {
-  int byte = (int)(((double)bitfieldLength)*random()/(RAND_MAX+1.0));
+  int byte = (int)(((double)bitfieldLength)*
+		   randomizer->getRandomNumber()/
+		   (randomizer->getMaxRandomNumber()+1.0));
 
   unsigned char lastMask = 0;
   int lastByteLength = totalLength%(blockLength*8);

+ 13 - 0
src/BitfieldMan.h

@@ -36,6 +36,7 @@
 #define _D_BITFIELD_MAN_H_
 
 #include "common.h"
+#include "Randomizer.h"
 #include <deque>
 
 typedef deque<int> BlockIndexes;
@@ -50,6 +51,8 @@ private:
   int bitfieldLength;
   int blocks;
   bool filterEnabled;
+  RandomizerHandle randomizer;
+
   int countSetBit(const unsigned char* bitfield, int len) const;
   int getNthBitIndex(const unsigned char bit, int nth) const;
   int getMissingIndexRandomly(const unsigned char* bitfield, int len) const;
@@ -176,6 +179,8 @@ public:
    */
   int countBlock() const;
 
+  int getMaxIndex() const { return blocks-1; }
+
   void setBitfield(const unsigned char* bitfield, int bitfieldLength);
 
   void clearAllBit();
@@ -202,6 +207,14 @@ public:
    * affected by filter
    */
   long long int getFilteredCompletedLength() const;
+
+  void setRandomizer(const RandomizerHandle& randomizer) {
+    this->randomizer = randomizer;
+  }
+
+  RandomizerHandle getRandomizer() const {
+    return randomizer;
+  }
 };
 
 #endif // _D_BITFIELD_MAN_H_

+ 40 - 0
src/BitfieldManFactory.cc

@@ -0,0 +1,40 @@
+/* <!-- 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 "BitfieldManFactory.h"
+#include "SimpleRandomizer.h"
+
+RandomizerHandle BitfieldManFactory::defaultRandomizer = SimpleRandomizer::getInstance();
+
+BitfieldManFactory::BitfieldManFactory():randomizer(defaultRandomizer) {}

+ 85 - 0
src/BitfieldManFactory.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_BITFIELD_MAN_FACTORY_H_
+#define _D_BITFIELD_MAN_FACTORY_H_
+
+#include "common.h"
+#include "Randomizer.h"
+#include "BitfieldMan.h"
+
+class BitfieldManFactory;
+
+typedef SharedHandle<BitfieldManFactory> BitfieldManFactoryHandle;
+
+class BitfieldManFactory {
+private:
+  static RandomizerHandle defaultRandomizer;
+  RandomizerHandle randomizer;
+
+  BitfieldManFactory();
+public:
+  ~BitfieldManFactory() {}
+
+  static BitfieldManFactoryHandle getNewFactory() {
+    BitfieldManFactoryHandle factory =
+      BitfieldManFactoryHandle(new BitfieldManFactory());
+    factory->setRandomizer(defaultRandomizer);
+    return factory;
+  }
+
+  BitfieldMan* createBitfieldMan(int blockLength, long long int totalLength) {
+    BitfieldMan* bitfieldMan = new BitfieldMan(blockLength, totalLength);
+    bitfieldMan->setRandomizer(randomizer);
+    return bitfieldMan;
+  }
+
+  static void setDefaultRandomizer(const RandomizerHandle& randomizer) {
+    defaultRandomizer = randomizer;
+  }
+
+  static RandomizerHandle getDefaultRandomizer() {
+    return defaultRandomizer;
+  }
+
+  void setRandomizer(const RandomizerHandle& randomizer) {
+    this->randomizer = randomizer;
+  }
+
+  RandomizerHandle getRandomizer() const {
+    return randomizer;
+  }
+};
+
+#endif // _D_BITFIELD_MAN_FACTORY_H_

+ 57 - 0
src/BtAbortOutstandingRequestEvent.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_BT_ABORT_OUTSTANDING_REQUEST_EVENT_H_
+#define _D_BT_ABORT_OUTSTANDING_REQUEST_EVENT_H_
+
+#include "BtEvent.h"
+
+class BtAbortOutstandingRequestEvent : public BtEvent {
+private:
+  PieceHandle piece;
+public:
+  BtAbortOutstandingRequestEvent(const PieceHandle& piece):piece(piece) {}
+
+  PieceHandle getPiece() const {
+    return piece;
+  }
+
+  void setPiece(const PieceHandle& piece) {
+    this->piece = piece;
+  }
+};
+
+typedef SharedHandle<BtAbortOutstandingRequestEvent> BtAbortOutstandingRequestEventHandle;
+
+#endif // _D_BT_ABORT_OUTSTANDING_REQUEST_EVENT_H_

+ 89 - 0
src/BtAllowedFastMessage.cc

@@ -0,0 +1,89 @@
+/* <!-- 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 "BtAllowedFastMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+
+BtAllowedFastMessageHandle BtAllowedFastMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 5) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "allowed fast", dataLength, 5);
+  }
+  uint32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "allowed fast", ID);
+  }
+  BtAllowedFastMessageHandle message = new BtAllowedFastMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  return message;
+}
+
+void BtAllowedFastMessage::doReceivedAction() {
+  if(!peer->isFastExtensionEnabled()) {
+    throw new DlAbortEx("%s received while fast extension is disabled",
+			toString().c_str());
+  }
+  peer->addPeerAllowedIndex(index);
+}
+
+uint32_t BtAllowedFastMessage::MESSAGE_LENGTH = 9;
+
+const char* BtAllowedFastMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 5, 4bytes
+     * id --- 17, 1byte
+     * piece index --- index, 4bytes
+     * total: 9bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 5, ID);
+    PeerMessageUtil::setIntParam(&msg[5], index);
+  }
+  return msg;
+}
+
+uint32_t BtAllowedFastMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+void BtAllowedFastMessage::onSendComplete() {
+  peer->addAmAllowedIndex(index);
+}
+
+string BtAllowedFastMessage::toString() const {
+  return "allowed fast index="+Util::uitos(index);
+}

+ 85 - 0
src/BtAllowedFastMessage.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_BT_ALLOWED_FAST_MESSAGE_H_
+#define _D_BT_ALLOWED_FAST_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtAllowedFastMessage;
+
+typedef SharedHandle<BtAllowedFastMessage> BtAllowedFastMessageHandle;
+
+class BtAllowedFastMessage : public SimpleBtMessage {
+private:
+  uint32_t index;
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtAllowedFastMessage(uint32_t index = 0)
+    :SimpleBtMessage(),
+     index(index),
+     msg(0) {}
+
+  virtual ~BtAllowedFastMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 17
+  };
+
+  void setIndex(uint32_t index) {
+    this->index = index;
+  }
+  uint32_t getIndex() const { return index; }
+
+  static BtAllowedFastMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  virtual void onSendComplete();
+
+};
+
+#endif // _D_BT_ALLOWED_FAST_MESSAGE_H_

+ 60 - 0
src/BtAllowedFastMessageValidator.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_BT_ALLOWED_FAST_MESSAGE_VALIDATOR_H_
+#define _D_BT_ALLOWED_FAST_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtAllowedFastMessage.h"
+
+class BtAllowedFastMessageValidator : public BtMessageValidator {
+private:
+  const BtAllowedFastMessage* message;
+  uint32_t numPiece;
+public:
+  BtAllowedFastMessageValidator(const BtAllowedFastMessage* message,
+				uint32_t numPiece):
+    message(message),
+    numPiece(numPiece) {}
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    return true;
+  }
+};
+
+typedef SharedHandle<BtAllowedFastMessageValidator> BtAllowedFastMessageValidatorHandle;
+
+#endif // _D_BT_ALLOWED_FAST_MESSAGE_VALIDATOR_H_

+ 0 - 5
src/BtAnnounce.h

@@ -99,11 +99,6 @@ public:
    * Shuffles the URLs in each announce tier.
    */
   virtual void shuffleAnnounce() = 0;
-
-  /**
-   * Returns the peer id of the client.
-   */
-  virtual string getPeerId() = 0;
 };
 
 typedef SharedHandle<BtAnnounce> BtAnnounceHandle;

+ 95 - 0
src/BtBitfieldMessage.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 "BtBitfieldMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+
+void BtBitfieldMessage::setBitfield(const unsigned char* bitfield, uint32_t bitfieldLength) {
+  if(this->bitfield == bitfield) {
+    return;
+  }
+  delete [] this->bitfield;
+
+  this->bitfieldLength = bitfieldLength;
+  this->bitfield = new unsigned char[this->bitfieldLength];
+  memcpy(this->bitfield, bitfield, this->bitfieldLength);
+}
+
+BtBitfieldMessageHandle
+BtBitfieldMessage::create(const unsigned char* data, uint32_t dataLength)
+{
+  if(dataLength <= 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be greater than %d", "bitfield", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "bitfield", ID);
+  }
+  BtBitfieldMessageHandle message = new BtBitfieldMessage();
+  message->setBitfield((unsigned char*)data+1, dataLength-1);
+  return message;
+}
+
+void BtBitfieldMessage::doReceivedAction() {
+  peer->setBitfield(bitfield, bitfieldLength);
+}
+
+const char* BtBitfieldMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1+bitfieldLength, 4bytes
+     * id --- 5, 1byte
+     * bitfield --- bitfield, len bytes
+     * total: 5+len bytes
+     */
+    msgLength = 5+bitfieldLength;
+    msg = new char[msgLength];
+    PeerMessageUtil::createPeerMessageString(msg, msgLength,
+					     1+bitfieldLength, ID);
+    memcpy(msg+5, bitfield, bitfieldLength);
+  }
+  return msg;
+}
+
+uint32_t BtBitfieldMessage::getMessageLength() {
+  getMessage();
+  return msgLength;
+}
+
+string BtBitfieldMessage::toString() const {
+  return "bitfield "+Util::toHex(bitfield, bitfieldLength);
+}

+ 98 - 0
src/BtBitfieldMessage.h

@@ -0,0 +1,98 @@
+/* <!-- 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_BITFIELD_MESSAGE_H_
+#define _D_BT_BITFIELD_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtBitfieldMessage;
+
+typedef SharedHandle<BtBitfieldMessage> BtBitfieldMessageHandle;
+
+class BtBitfieldMessage : public SimpleBtMessage {
+private:
+  unsigned char* bitfield;
+  uint32_t bitfieldLength;
+  char* msg;
+  int msgLength;
+
+  void init() {
+    bitfield = 0;
+    bitfieldLength = 0;
+    msg = 0;
+    msgLength = 0;
+  }
+public:
+  BtBitfieldMessage():SimpleBtMessage()
+  {
+    init();
+  }
+
+  BtBitfieldMessage(const unsigned char* bitfield,
+		    uint32_t bitfieldLength):SimpleBtMessage()
+  {
+    init();
+    setBitfield(bitfield, bitfieldLength);
+  }
+
+  virtual ~BtBitfieldMessage() {
+    delete [] bitfield;
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 5
+  };
+
+  void setBitfield(const unsigned char* bitfield, uint32_t bitfieldLength);
+
+  const unsigned char* getBitfield() const { return bitfield; }
+
+  uint32_t getBitfieldLength() const { return bitfieldLength; }
+
+  static BtBitfieldMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_BITFIELD_MESSAGE_H_

+ 61 - 0
src/BtBitfieldMessageValidator.h

@@ -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 --> */
+#ifndef _D_BT_BITFIELD_MESSAGE_VALIDATOR_H_
+#define _D_BT_BITFIELD_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtBitfieldMessage.h"
+
+class BtBitfieldMessageValidator : public BtMessageValidator {
+private:
+  const BtBitfieldMessage* message;
+  int numPiece;
+public:
+  BtBitfieldMessageValidator(const BtBitfieldMessage* message,
+			     int numPiece):
+    message(message),
+    numPiece(numPiece) {}
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    PeerMessageUtil::checkBitfield(message->getBitfield(),
+				   message->getBitfieldLength(),
+				   numPiece);
+    return true;
+  }
+};
+
+typedef SharedHandle<BtBitfieldMessageValidator> BtBitfieldMessageValidatorHandle;
+#endif // _D_BT_BITFIELD_MESSAGE_VALIDATOR_H_

+ 88 - 0
src/BtCancelMessage.cc

@@ -0,0 +1,88 @@
+/* <!-- 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 "BtCancelMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+
+BtCancelMessageHandle BtCancelMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 13) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "cancel", dataLength, 13);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "cancel", ID);
+  }
+  BtCancelMessageHandle message = new BtCancelMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  message->setBegin(PeerMessageUtil::getIntParam(data, 5));
+  message->setLength(PeerMessageUtil::getIntParam(data, 9));
+  return message;
+}
+
+void BtCancelMessage::doReceivedAction() {
+  BT_MESSAGE_DISPATCHER(btContext, peer)->doCancelSendingPieceAction(index, begin, length);
+}
+
+uint32_t BtCancelMessage::MESSAGE_LENGTH = 17;
+
+const char* BtCancelMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 13, 4bytes
+     * id --- 8, 1byte
+     * index --- index, 4bytes
+     * begin --- begin, 4bytes
+     * length -- length, 4bytes
+     * total: 17bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 13, ID);
+    PeerMessageUtil::setIntParam(&msg[5], index);
+    PeerMessageUtil::setIntParam(&msg[9], begin);
+    PeerMessageUtil::setIntParam(&msg[13], length);
+  }
+  return msg;
+}
+
+uint32_t BtCancelMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtCancelMessage::toString() const {
+  return "cancel index="+Util::uitos(index)+", begin="+Util::uitos(begin)+
+    ", length="+Util::uitos(length);
+}

+ 93 - 0
src/BtCancelMessage.h

@@ -0,0 +1,93 @@
+/* <!-- 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_CANCEL_MESSAGE_H_
+#define _D_BT_CANCEL_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtCancelMessage;
+
+typedef SharedHandle<BtCancelMessage> BtCancelMessageHandle;
+
+class BtCancelMessage : public SimpleBtMessage {
+private:
+  uint32_t index;
+  uint32_t begin;
+  uint32_t length;
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtCancelMessage(uint32_t index = 0, uint32_t begin = 0, uint32_t length = 0)
+    :SimpleBtMessage(),
+     index(index),
+     begin(begin),
+     length(length),
+     msg(0) {}
+
+  virtual ~BtCancelMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 8
+  };
+
+  uint32_t getIndex() const { return index; }
+
+  void setIndex(uint32_t index) { this->index = index; }
+
+  uint32_t getBegin() const { return begin; }
+
+  void setBegin(uint32_t begin) { this->begin = begin; }
+
+  uint32_t getLength() const { return length; }
+
+  void setLength(uint32_t length) { this->length = length; }
+
+  static BtCancelMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_CANCEL_MESSAGE_H_

+ 67 - 0
src/BtCancelMessageValidator.h

@@ -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 --> */
+#ifndef _D_BT_CANCEL_MESSAGE_VALIDATOR_H_
+#define _D_BT_CANCEL_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtCancelMessage.h"
+
+class BtCancelMessageValidator : public BtMessageValidator {
+private:
+  const BtCancelMessage* message;
+  uint32_t numPiece;
+  uint32_t pieceLength;
+public:
+  BtCancelMessageValidator(const BtCancelMessage* message,
+			   uint32_t numPiece,
+			   uint32_t pieceLength):
+    message(message),
+    numPiece(numPiece),
+    pieceLength(pieceLength) {}
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    PeerMessageUtil::checkBegin(message->getBegin(), pieceLength);
+    PeerMessageUtil::checkLength(message->getLength());
+    PeerMessageUtil::checkRange(message->getBegin(), message->getLength(),
+				pieceLength);
+    return true;
+  }
+};
+
+typedef SharedHandle<BtCancelMessageValidator> BtCancelMessageValidatorHandle;
+
+#endif // _D_BT_CANCEL_MESSAGE_VALIDATOR_H_

+ 78 - 0
src/BtCancelSendingPieceEvent.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_BT_CANCEL_SENDING_PIECE_EVENT_H_
+#define _D_BT_CANCEL_SENDING_PIECE_EVENT_H_
+
+#include "BtEvent.h"
+
+class BtCancelSendingPieceEvent : public BtEvent {
+private:
+  uint32_t index;
+  uint32_t begin;
+  uint32_t length;
+public:
+  BtCancelSendingPieceEvent(uint32_t index, uint32_t begin, uint32_t length):
+    index(index), begin(begin), length(length) {}
+
+  virtual ~BtCancelSendingPieceEvent() {}
+
+  void setIndex(uint32_t index) {
+    this->index = index;
+  }
+
+  uint32_t getIndex() const {
+    return index;
+  }
+
+  void setBegin(uint32_t begin) {
+    this->begin = begin;
+  }
+
+  uint32_t getBegin() const {
+    return begin;
+  }
+
+  void setLength(uint32_t length) {
+    this->length = length;
+  }
+
+  uint32_t getLength() const {
+    return length;
+  }
+};
+
+typedef SharedHandle<BtCancelSendingPieceEvent> BtCancelSendingPieceEventHandle;
+
+#endif // _D_BT_CANCEL_SENDING_PIECE_EVENT_H_

+ 87 - 0
src/BtChokeMessage.cc

@@ -0,0 +1,87 @@
+/* <!-- 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 "BtChokeMessage.h"
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+
+BtChokeMessageHandle BtChokeMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "choke", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "choke", ID);
+  }
+  BtChokeMessageHandle chokeMessage = new BtChokeMessage();
+  return chokeMessage;
+}
+
+void BtChokeMessage::doReceivedAction() {
+  peer->peerChoking = true;
+  BT_MESSAGE_DISPATCHER(btContext, peer)->doChokedAction();
+}
+
+bool BtChokeMessage::sendPredicate() const {
+  return !peer->amChoking;
+}
+
+uint32_t BtChokeMessage::MESSAGE_LENGTH = 5;
+
+const char* BtChokeMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1, 4bytes
+     * id --- 0, 1byte
+     * total: 5bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 1, ID);
+  }
+  return msg;
+}
+
+uint32_t BtChokeMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+void BtChokeMessage::onSendComplete() {
+  peer->amChoking = true;
+  BT_MESSAGE_DISPATCHER(btContext, peer)->doChokingAction();
+}
+
+string BtChokeMessage::toString() const {
+  return "choke";
+}

+ 77 - 0
src/BtChokeMessage.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_BT_CHOKE_MESSAGE_H_
+#define _D_BT_CHOKE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtChokeMessage;
+
+typedef SharedHandle<BtChokeMessage> BtChokeMessageHandle;
+
+class BtChokeMessage : public SimpleBtMessage {
+private:
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtChokeMessage():SimpleBtMessage(), msg(0) {}
+
+  virtual ~BtChokeMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 0
+  };
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  static BtChokeMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual bool sendPredicate() const;
+
+  virtual void onSendComplete();
+};
+
+#endif // _D_CHOKE_MESSAGE_H_

+ 45 - 0
src/BtChokedEvent.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_BT_CHOKED_EVENT_H_
+#define _D_BT_CHOKED_EVENT_H_
+
+#include "BtEvent.h"
+
+class BtChokedEvent : public BtEvent {
+};
+
+typedef SharedHandle<BtChokedEvent> BtChokedEventHandle;
+
+#endif // _D_BT_CHOKED_EVENT_H_

+ 45 - 0
src/BtChokingEvent.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_BT_CHOKING_EVENT_H_
+#define _D_BT_CHOKING_EVENT_H_
+
+#include "BtEvent.h"
+
+class BtChokingEvent : public BtEvent {
+};
+
+typedef SharedHandle<BtChokingEvent> BtChokingEventHandle;
+
+#endif // _D_BT_CHOKING_EVENT_H_

+ 5 - 0
src/BtContext.h

@@ -77,6 +77,11 @@ public:
   virtual int getPieceLength() const = 0;
 
   virtual int getNumPieces() const = 0;
+
+  /**
+   * Returns the peer id of localhost, 20 byte length
+   */
+  virtual const unsigned char* getPeerId() = 0;
 };
 
 typedef SharedHandle<BtContext> BtContextHandle;

+ 47 - 0
src/BtEvent.h

@@ -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 --> */
+#ifndef _D_BT_EVENT_H_
+#define _D_BT_EVENT_H_
+
+#include "common.h"
+
+class BtEvent {
+public:
+  virtual ~BtEvent() {}
+};
+
+typedef SharedHandle<BtEvent> BtEventHandle;
+
+#endif // _D_BT_EVENT_H_

+ 51 - 0
src/BtEventListener.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_BT_EVENT_LISTENER_H_
+#define _D_BT_EVENT_LISTENER_H_
+
+#include "common.h"
+#include "BtEvent.h"
+
+class BtEventListener {
+public:
+  virtual ~BtEventListener() {}
+
+  virtual void handleEvent(const BtEventHandle& event) = 0;
+};
+
+typedef SharedHandle<BtEventListener> BtEventListenerHandle;
+typedef deque<BtEventListenerHandle> BtEventListeners;
+
+#endif // _D_BT_EVENT_LISTENER_H_

+ 100 - 0
src/BtHandshakeMessage.cc

@@ -0,0 +1,100 @@
+/* <!-- 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 "BtHandshakeMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+
+const unsigned char* BtHandshakeMessage::BT_PSTR = (const unsigned char*)"BitTorrent protocol";
+
+BtHandshakeMessage::BtHandshakeMessage() {
+  init();
+}
+
+BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
+				       const unsigned char* peerId)
+{
+  init();
+  memcpy(this->infoHash, infoHash, INFO_HASH_LENGTH);
+  memcpy(this->peerId, peerId, PEER_ID_LENGTH);
+}
+
+void BtHandshakeMessage::init() {
+  msg = 0;
+  this->pstrlen = 19;
+  pstr = new unsigned char[PSTR_LENGTH];
+  reserved = new unsigned char[RESERVED_LENGTH];
+  infoHash = new unsigned char[INFO_HASH_LENGTH];
+  peerId = new unsigned char[PEER_ID_LENGTH];
+  memcpy(this->pstr, PSTR, PSTR_LENGTH);
+  memset(this->reserved, 0, RESERVED_LENGTH);
+  // fast extension
+  this->reserved[7] |= 0x04;
+}
+
+BtHandshakeMessageHandle BtHandshakeMessage::create(const unsigned char* data, uint32_t dataLength) {
+  BtHandshakeMessageHandle message = new BtHandshakeMessage();
+  message->pstrlen = data[0];
+  memcpy(message->pstr, &data[1], PSTR_LENGTH);
+  memcpy(message->reserved, &data[20], RESERVED_LENGTH);
+  memcpy(message->infoHash, &data[28], INFO_HASH_LENGTH);
+  memcpy(message->peerId, &data[48], PEER_ID_LENGTH);
+  return message;
+}
+
+const char* BtHandshakeMessage::getMessage() {
+  if(!msg) {
+    msg = new char[MESSAGE_LENGTH];
+    msg[0] = pstrlen;
+    memcpy(msg+1, pstr, PSTR_LENGTH);
+    memcpy(msg+20, reserved, RESERVED_LENGTH);
+    memcpy(msg+28, infoHash, INFO_HASH_LENGTH);
+    memcpy(msg+48, peerId, PEER_ID_LENGTH);
+  }
+  return msg;
+}
+
+uint32_t BtHandshakeMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtHandshakeMessage::toString() const {
+  return "handshake peerId="+
+    Util::urlencode(peerId, PEER_ID_LENGTH)+
+    ", reserved="+Util::toHex(reserved, RESERVED_LENGTH);
+}
+
+bool BtHandshakeMessage::isFastExtensionSupported() const {
+  return reserved[7]&0x04;
+}

+ 117 - 0
src/BtHandshakeMessage.h

@@ -0,0 +1,117 @@
+/* <!-- 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_HANDSHAKE_MESSAGE_H_
+#define _D_BT_HANDSHAKE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtHandshakeMessage;
+
+typedef SharedHandle<BtHandshakeMessage> BtHandshakeMessageHandle;
+
+class BtHandshakeMessage : public SimpleBtMessage {
+public:
+  static const uint32_t PSTR_LENGTH = 19;
+  static const unsigned char* BT_PSTR;
+  static const uint32_t RESERVED_LENGTH = 8;
+  static const uint32_t MESSAGE_LENGTH = 68;
+private:
+  uint8_t pstrlen;
+  unsigned char* pstr;
+  unsigned char* reserved;
+  unsigned char* infoHash;
+  unsigned char* peerId;
+  char* msg;
+  void init();
+public:
+  BtHandshakeMessage();
+  /**
+   * infoHash must be 20 byte length.
+   * peerId must be 20 byte length.
+   */
+  BtHandshakeMessage(const unsigned char* infoHash, const unsigned char* peerId);
+
+  static BtHandshakeMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual ~BtHandshakeMessage() {
+    delete [] msg;
+    delete [] pstr;
+    delete [] reserved;
+    delete [] infoHash;
+    delete [] peerId;
+  }
+
+  virtual int32_t getId() const { return INT32_MAX; }
+
+  virtual void doReceivedAction() {};
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  bool isFastExtensionSupported() const;
+
+  uint8_t getPstrlen() const {
+    return pstrlen;
+  }
+
+  const unsigned char* getPstr() const {
+    return pstr;
+  }
+
+  const unsigned char* getReserved() const {
+    return reserved;
+  }
+
+  const unsigned char* getInfoHash() const {
+    return infoHash;
+  }
+
+  void setInfoHash(const unsigned char* infoHash) {
+    memcpy(this->infoHash, infoHash, INFO_HASH_LENGTH);
+  }
+
+  const unsigned char* getPeerId() const {
+    return peerId;
+  }
+
+  void setPeerId(const unsigned char* peerId) {
+    memcpy(this->peerId, peerId, PEER_ID_LENGTH);
+  }
+};
+
+#endif // _D_HANDSHAKE_MESSAGE_H_

+ 75 - 0
src/BtHandshakeMessageValidator.h

@@ -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 --> */
+#ifndef _D_BT_HANDSHAKE_MESSAGE_VALIDATOR_H_
+#define _D_BT_HANDSHAKE_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtHandshakeMessage.h"
+#include "Util.h"
+
+class BtHandshakeMessageValidator : public BtMessageValidator {
+private:
+  const BtHandshakeMessage* message;
+  unsigned char infoHash[20];
+public:
+  BtHandshakeMessageValidator(const BtHandshakeMessage* message,
+			      const unsigned char* infoHash):
+    message(message)
+  {
+    memcpy(this->infoHash, infoHash, sizeof(this->infoHash));
+  }
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    if(message->getPstrlen() != 19) {
+      throw new DlAbortEx("invalid handshake pstrlen=%u",
+			  message->getPstrlen());
+    }
+    if(memcmp(BtHandshakeMessage::BT_PSTR, message->getPstr(), 19) != 0) {
+      throw new DlAbortEx("invalid handshake pstr=%s",
+			  Util::urlencode(message->getPstr(), 19).c_str());
+    }
+    if(memcmp(infoHash, message->getInfoHash(), 20) != 0) {
+      throw new DlAbortEx("invalid handshake info hash: expected:%s, actual:%s",
+			  Util::toHex(infoHash, 20).c_str(),
+			  Util::toHex(message->getInfoHash(), 20).c_str());
+    }
+    return true;
+  }
+};
+
+typedef SharedHandle<BtHandshakeMessageValidator> BtHandshakeMessageValidatorHandle;
+
+#endif // _D_BT_HANDSHAKE_MESSAGE_VALIDATOR_H_

+ 81 - 0
src/BtHaveAllMessage.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 "BtHaveAllMessage.h"
+#include "DlAbortEx.h"
+#include "PeerMessageUtil.h"
+
+BtHaveAllMessageHandle BtHaveAllMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have all", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "have all", ID);
+  }
+  BtHaveAllMessageHandle message = new BtHaveAllMessage();
+  return message;
+}
+
+void BtHaveAllMessage::doReceivedAction() {
+  if(!peer->isFastExtensionEnabled()) {
+    throw new DlAbortEx("%s received while fast extension is disabled",
+			toString().c_str());
+  }
+  peer->setAllBitfield();
+}
+
+uint32_t BtHaveAllMessage::MESSAGE_LENGTH = 5;
+
+const char* BtHaveAllMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1, 4bytes
+     * id --- 14, 1byte
+     * total: 5bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 1, ID);
+  }
+  return msg;
+}
+
+uint32_t BtHaveAllMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtHaveAllMessage::toString() const {
+  return "have all";
+}

+ 73 - 0
src/BtHaveAllMessage.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_BT_HAVE_ALL_MESSAGE_H_
+#define _D_BT_HAVE_ALL_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtHaveAllMessage;
+
+typedef SharedHandle<BtHaveAllMessage> BtHaveAllMessageHandle;
+
+class BtHaveAllMessage : public SimpleBtMessage {
+private:
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtHaveAllMessage():msg(0) {}
+
+  virtual ~BtHaveAllMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 14
+  };
+
+  static BtHaveAllMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_HAVE_ALL_MESSAGE_H_

+ 85 - 0
src/BtHaveMessage.cc

@@ -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 --> */
+#include "BtHaveMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+
+BtHaveMessageHandle BtHaveMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 5) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have", dataLength, 5);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "have", ID);
+  }
+  BtHaveMessageHandle message = new BtHaveMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  return message;
+}
+
+void BtHaveMessage::doReceivedAction() {
+  peer->updateBitfield(index, 1);
+}
+
+bool BtHaveMessage::sendPredicate() const {
+  return !peer->hasPiece(index);
+}
+
+uint32_t BtHaveMessage::MESSAGE_LENGTH = 9;
+
+const char* BtHaveMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 5, 4bytes
+     * id --- 4, 1byte
+     * piece index --- index, 4bytes
+     * total: 9bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 5, ID);
+    PeerMessageUtil::setIntParam(&msg[5], index);
+  }
+  return msg;
+}
+
+uint32_t BtHaveMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtHaveMessage::toString() const {
+  return "have index="+Util::uitos(index);
+}

+ 81 - 0
src/BtHaveMessage.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_BT_HAVE_MESSAGE_H_
+#define _D_BT_HAVE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtHaveMessage;
+
+typedef SharedHandle<BtHaveMessage> BtHaveMessageHandle;
+
+class BtHaveMessage : public SimpleBtMessage {
+private:
+  uint32_t index;
+  char* msg;
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtHaveMessage(uint32_t index = 0):index(index), msg(0) {}
+
+  virtual ~BtHaveMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 4
+  };
+
+  void setIndex(uint32_t index) {
+    this->index = index;
+  }
+
+  uint32_t getIndex() const { return index; }
+
+  static BtHaveMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual bool sendPredicate() const;
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_HAVE_MESSAGE_H_

+ 60 - 0
src/BtHaveMessageValidator.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_BT_HAVE_MESSAGE_VALIDATOR_H_
+#define _D_BT_HAVE_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtHaveMessage.h"
+#include "PeerMessageUtil.h"
+
+class BtHaveMessageValidator : public BtMessageValidator {
+private:
+  const BtHaveMessage* message;
+  int numPiece;
+public:
+  BtHaveMessageValidator(const BtHaveMessage* message,
+			 int numPiece):
+    message(message),
+    numPiece(numPiece) {}
+
+  virtual bool validate(Errors& errors) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    return true;
+  }
+
+};
+
+#endif // _D_BT_HAVE_MESSAGE_VALIDATOR_H_

+ 80 - 0
src/BtHaveNoneMessage.cc

@@ -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 --> */
+#include "BtHaveNoneMessage.h"
+#include "DlAbortEx.h"
+#include "PeerMessageUtil.h"
+
+BtHaveNoneMessageHandle BtHaveNoneMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have none", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "have none", ID);
+  }
+  BtHaveNoneMessageHandle message = new BtHaveNoneMessage();
+  return message;
+}
+
+void BtHaveNoneMessage::doReceivedAction() {
+  if(!peer->isFastExtensionEnabled()) {
+    throw new DlAbortEx("%s received while fast extension is disabled",
+			toString().c_str());
+  }
+}
+
+uint32_t BtHaveNoneMessage::MESSAGE_LENGTH = 5;
+
+const char* BtHaveNoneMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1, 4bytes
+     * id --- 15, 1byte
+     * total: 5bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 1, ID);
+  }
+  return msg;
+}
+
+uint32_t BtHaveNoneMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtHaveNoneMessage::toString() const {
+  return "have none";
+}

+ 73 - 0
src/BtHaveNoneMessage.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_BT_HAVE_NONE_MESSAGE_H_
+#define _D_BT_HAVE_NONE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtHaveNoneMessage;
+
+typedef SharedHandle<BtHaveNoneMessage> BtHaveNoneMessageHandle;
+
+class BtHaveNoneMessage : public SimpleBtMessage {
+private:
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtHaveNoneMessage():msg(0) {}
+
+  virtual ~BtHaveNoneMessage() {
+    delete []  msg;
+  }
+  
+  enum ID_t {
+    ID = 15
+  };
+  
+  static BtHaveNoneMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_HAVE_NONE_MESSAGE_H_

+ 66 - 0
src/BtInteractive.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_BT_INTERACTIVE_H_
+#define _D_BT_INTERACTIVE_H_
+
+#include "common.h"
+#include "BtMessage.h"
+
+class BtInteractive {
+public:
+  virtual ~BtInteractive() {}
+
+  virtual void initiateHandshake() = 0;
+
+  virtual BtMessageHandle receiveHandshake(bool quickReply = false) = 0;
+
+  virtual BtMessageHandle receiveAndSendHandshake() = 0;
+
+  virtual void doPostHandshakeProcessing() = 0;
+
+  virtual void doInteractionProcessing() = 0;
+
+  virtual void cancelAllPiece() = 0;
+
+  virtual void sendPendingMessage() = 0;
+
+  virtual uint32_t countPendingMessage() = 0;
+
+  virtual bool isSendingMessageInProgress() = 0;
+};
+
+typedef SharedHandle<BtInteractive> BtInteractiveHandle;
+
+#endif // _D_BT_INTERACTIVE_H_

+ 85 - 0
src/BtInterestedMessage.cc

@@ -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 --> */
+#include "BtInterestedMessage.h"
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+
+BtInterestedMessageHandle BtInterestedMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "interested", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "interested", ID);
+  }
+  BtInterestedMessageHandle message = new BtInterestedMessage();
+  return message;
+}
+
+void BtInterestedMessage::doReceivedAction() {
+  peer->peerInterested = true;
+}
+
+bool BtInterestedMessage::sendPredicate() const {
+  return !peer->amInterested;
+}
+
+uint32_t BtInterestedMessage::MESSAGE_LENGTH = 5;
+
+const char* BtInterestedMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1, 4bytes
+     * id --- 2, 1byte
+     * total: 5bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 1, ID);
+  }
+  return msg;
+}
+
+uint32_t BtInterestedMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+void BtInterestedMessage::onSendComplete() {
+  peer->amInterested = true;
+}
+
+string BtInterestedMessage::toString() const {
+  return "interested";
+}

+ 77 - 0
src/BtInterestedMessage.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_BT_INTERESTED_MESSAGE_H_
+#define _D_BT_INTERESTED_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtInterestedMessage;
+
+typedef SharedHandle<BtInterestedMessage> BtInterestedMessageHandle;
+
+class BtInterestedMessage : public SimpleBtMessage {
+private:
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtInterestedMessage():msg(0) {}
+
+  virtual ~BtInterestedMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 2
+  };
+
+  static BtInterestedMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  virtual bool sendPredicate() const;
+
+  virtual void onSendComplete();
+};
+
+#endif // _D_BT_INTERESTED_MESSAGE_H_

+ 53 - 0
src/BtKeepAliveMessage.cc

@@ -0,0 +1,53 @@
+/* <!-- 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 "BtKeepAliveMessage.h"
+
+uint32_t BtKeepAliveMessage::MESSAGE_LENGTH = 4;
+
+const char* BtKeepAliveMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 0, 4bytes
+     * total: 4bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    memset(msg, 0, MESSAGE_LENGTH);
+  }
+  return msg;
+}
+
+uint32_t BtKeepAliveMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}

+ 73 - 0
src/BtKeepAliveMessage.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_BT_KEEP_ALIVE_MESSAGE_H_
+#define _D_BT_KEEP_ALIVE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtKeepAliveMessage;
+
+typedef SharedHandle<BtKeepAliveMessage> BtKeepAliveMessageHandle;
+
+class BtKeepAliveMessage : public SimpleBtMessage {
+private:
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtKeepAliveMessage():msg(0) {}
+
+  virtual ~BtKeepAliveMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 99
+  };
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction() {}
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const {
+    return "keep alive";
+  }
+};
+
+#endif // _D_BT_KEEP_ALIVE_MESSAGE_H_

+ 72 - 0
src/BtMessage.h

@@ -0,0 +1,72 @@
+/* <!-- 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_MESSAGE_H_
+#define _D_BT_MESSAGE_H_
+
+#include "common.h"
+#include "Piece.h"
+#include "BtMessageValidator.h"
+#include "BtEvent.h"
+
+class BtMessage {
+public:
+  virtual ~BtMessage() {}
+
+  virtual bool isSendingInProgress() = 0;
+
+  virtual bool isInvalidate() = 0;
+
+  virtual bool isUploading() = 0;
+
+  virtual int32_t getId() = 0;
+
+  virtual void doReceivedAction() = 0;
+
+  virtual void send() = 0;
+
+  virtual bool validate(Errors& errors) = 0;
+
+  virtual void handleEvent(const BtEventHandle& event) = 0;
+
+  virtual void onQueued() = 0;
+
+  virtual string toString() const = 0;
+
+};
+
+typedef SharedHandle<BtMessage> BtMessageHandle;
+typedef deque<BtMessageHandle> BtMessages;
+
+#endif // _D_BT_MESSAGE_H_

+ 82 - 0
src/BtMessageDispatcher.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_BT_MESSAGE_DISPATCHER_H_
+#define _D_BT_MESSAGE_DISPATCHER_H_
+
+#include "common.h"
+#include "Piece.h"
+#include "BtMessage.h"
+#include "RequestSlot.h"
+
+class BtMessageDispatcher {
+public:
+  virtual ~BtMessageDispatcher() {}
+
+  virtual void addMessageToQueue(const BtMessageHandle& btMessage) = 0;
+
+  virtual void addMessageToQueue(const BtMessages& btMessages) = 0;
+
+  virtual void sendMessages() = 0;
+
+  virtual void doCancelSendingPieceAction(uint32_t index, uint32_t begin, uint32_t blockLength) = 0;
+
+  virtual void doCancelSendingPieceAction(const PieceHandle& piece) = 0;
+
+  virtual void doAbortOutstandingRequestAction(const PieceHandle& piece) = 0;
+
+  virtual void doChokedAction() = 0;
+
+  virtual void doChokingAction() = 0;
+
+  virtual void checkRequestSlotAndDoNecessaryThing() = 0;
+
+  virtual bool isSendingInProgress() = 0;
+
+  virtual uint32_t countMessageInQueue() = 0;
+
+  virtual uint32_t countOutstandingRequest() = 0;
+
+  virtual bool isOutstandingRequest(uint32_t index, uint32_t blockIndex) = 0;
+
+  virtual RequestSlot getOutstandingRequest(uint32_t index, uint32_t begin, uint32_t blockLength) = 0;
+
+  virtual void removeOutstandingRequest(const RequestSlot& slot) = 0;
+
+  virtual void addOutstandingRequest(const RequestSlot& slot) = 0;
+};
+
+typedef SharedHandle<BtMessageDispatcher> BtMessageDispatcherHandle;
+
+#endif // _D_BT_MESSAGE_DISPATCHER_H_

+ 53 - 0
src/BtMessageFactory.cc

@@ -0,0 +1,53 @@
+/* <!-- 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 "BtMessageFactory.h"
+#include "DefaultBtMessageFactory.h"
+
+void BtMessageFactory::registerFactory(const string& key,
+				       const BtMessageFactoryPrerequisiteHandle& prereq) {
+  prerequisiteMap.erase(key);
+  BtMessageFactoryPrerequisiteMap::value_type p(key, prereq);
+  prerequisiteMap.insert(p);
+}
+
+static BtMessageFactory::BtMessageFactoryHandle getNewFactory(const string& key) {
+  DefaultBtMessageFactoryHandle factory = new DefaultBtMessageFactory();
+  BtMessageFactoryPrerequisiteMap::iterator itr = prerequisiteMap.find(key);
+  if(prerequisiteMap.end() != itr) {
+    // TODO set prerequisite objects to factory here
+  }
+  return factory;
+}
+

+ 91 - 0
src/BtMessageFactory.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_BT_MESSAGE_FACTORY_H_
+#define _D_BT_MESSAGE_FACTORY_H_
+
+#include "common.h"
+#include "BtMessage.h"
+#include "Piece.h"
+
+class BtMessageFactory {
+public:
+  virtual ~BtMessageFactory() {}
+
+  virtual BtMessageHandle
+  createBtMessage(const unsigned char* msg, uint32_t msgLength) = 0;
+
+  virtual BtMessageHandle
+  createHandshakeMessage(const unsigned char* msg, uint32_t msgLength) = 0;
+
+  virtual BtMessageHandle
+  createHandshakeMessage(const unsigned char* infoHash,
+			 const unsigned char* peerId) = 0;
+
+  virtual BtMessageHandle
+  createRequestMessage(const PieceHandle& piece, uint32_t blockIndex) = 0;
+
+  virtual BtMessageHandle
+  createCancelMessage(uint32_t index, uint32_t begin, uint32_t length) = 0;
+
+  virtual BtMessageHandle
+  createPieceMessage(uint32_t index, uint32_t begin, uint32_t length) = 0;
+
+  virtual BtMessageHandle createHaveMessage(uint32_t index) = 0;
+
+  virtual BtMessageHandle createChokeMessage() = 0;
+
+  virtual BtMessageHandle createUnchokeMessage() = 0;
+  
+  virtual BtMessageHandle createInterestedMessage() = 0;
+
+  virtual BtMessageHandle createNotInterestedMessage() = 0;
+
+  virtual BtMessageHandle createBitfieldMessage() = 0;
+
+  virtual BtMessageHandle createKeepAliveMessage() = 0;
+  
+  virtual BtMessageHandle createHaveAllMessage() = 0;
+
+  virtual BtMessageHandle createHaveNoneMessage() = 0;
+
+  virtual BtMessageHandle
+  createRejectMessage(uint32_t index, uint32_t begin, uint32_t length) = 0;
+
+  virtual BtMessageHandle createAllowedFastMessage(uint32_t index) = 0;
+};
+
+typedef SharedHandle<BtMessageFactory> BtMessageFactoryHandle;
+
+#endif // _D_BT_MESSAGE_FACTORY_H_

+ 54 - 0
src/BtMessageReceiver.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_BT_MESSAGE_RECEIVER_H_
+#define _D_BT_MESSAGE_RECEIVER_H_
+
+#include "common.h"
+#include "BtMessage.h"
+
+class BtMessageReceiver {
+public:
+  virtual ~BtMessageReceiver() {}
+
+  virtual BtMessageHandle receiveHandshake(bool quickReply = false) = 0;
+
+  virtual BtMessageHandle receiveAndSendHandshake() = 0;
+
+  virtual BtMessageHandle receiveMessage() = 0;
+};
+
+typedef SharedHandle<BtMessageReceiver> BtMessageReceiverHandle;
+
+#endif // _D_BT_MESSAGE_RECEIVER_H_

+ 52 - 0
src/BtMessageValidator.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_BT_MESSAGE_VALIDATOR_H_
+#define _D_BT_MESSAGE_VALIDATOR_H_
+
+#include "common.h"
+#include "BtMessage.h"
+
+typedef Strings Errors;
+
+class BtMessageValidator {
+public:
+  virtual ~BtMessageValidator() {}
+
+  virtual bool validate(Errors& errors) = 0;
+};
+
+typedef SharedHandle<BtMessageValidator> BtMessageValidatorHandle;
+
+#endif // _D_BT_MESSAGE_VALIDATOR_H_

+ 85 - 0
src/BtNotInterestedMessage.cc

@@ -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 --> */
+#include "BtNotInterestedMessage.h"
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+
+BtNotInterestedMessageHandle BtNotInterestedMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "not interested", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "not interested", ID);
+  }
+  BtNotInterestedMessageHandle message = new BtNotInterestedMessage();
+  return message;
+}
+
+void BtNotInterestedMessage::doReceivedAction() {
+  peer->peerInterested = false;
+}
+
+bool BtNotInterestedMessage::sendPredicate() const {
+  return peer->amInterested;
+}
+
+uint32_t BtNotInterestedMessage::MESSAGE_LENGTH = 5;
+
+const char* BtNotInterestedMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1, 4bytes
+     * id --- 3, 1byte
+     * total: 5bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 1, ID);
+  }
+  return msg;
+}
+
+uint32_t BtNotInterestedMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+void BtNotInterestedMessage::onSendComplete() {
+  peer->amInterested = false;
+}
+
+string BtNotInterestedMessage::toString() const {
+  return "not interested";
+}

+ 77 - 0
src/BtNotInterestedMessage.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_BT_NOT_INTERESTED_MESSAGE_H_
+#define _D_BT_NOT_INTERESTED_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtNotInterestedMessage;
+
+typedef SharedHandle<BtNotInterestedMessage> BtNotInterestedMessageHandle;
+
+class BtNotInterestedMessage : public SimpleBtMessage {
+private:
+  char* msg;
+  
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtNotInterestedMessage():msg(0) {}
+
+  virtual ~BtNotInterestedMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 3
+  };
+
+  static BtNotInterestedMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  virtual bool sendPredicate() const;
+
+  virtual void onSendComplete();
+};
+
+#endif // _D_BT_NOT_INTERESTED_MESSAGE_H_

+ 283 - 0
src/BtPieceMessage.cc

@@ -0,0 +1,283 @@
+/* <!-- 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 "BtPieceMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "message.h"
+#include "DlAbortEx.h"
+#include "BtChokingEvent.h"
+#include "BtCancelSendingPieceEvent.h"
+
+void BtPieceMessage::setBlock(const unsigned char* block, uint32_t blockLength) {
+  delete [] this->block;
+  this->blockLength = blockLength;
+  this->block = new char[this->blockLength];
+  memcpy(this->block, block, this->blockLength);
+}
+
+BtPieceMessageHandle BtPieceMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength <= 9) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be greater than %d", "piece", dataLength, 9);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "piece", ID);
+  }
+  BtPieceMessageHandle message = new BtPieceMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  message->setBegin(PeerMessageUtil::getIntParam(data, 5));
+  message->setBlock(data+9, dataLength-9);
+  return message;
+}
+
+void BtPieceMessage::doReceivedAction() {
+  RequestSlot slot =
+    BT_MESSAGE_DISPATCHER(btContext, peer)->getOutstandingRequest(index,
+								  begin,
+								  blockLength);
+  peer->updateDownloadLength(blockLength);
+  if(!RequestSlot::isNull(slot)) {
+    peer->snubbing = false;
+    peer->updateLatency(slot.getLatencyInMillis());
+    PieceHandle piece = pieceStorage->getPiece(index);
+    uint64_t offset =
+      ((uint64_t)index)*btContext->getPieceLength()+begin;
+    logger->debug("CUID#%d - Piece received. index=%u, begin=%u, length=%u, offset=%llu, blockIndex=%u",
+		  cuid, index, begin, blockLength, offset, slot.getBlockIndex());
+    pieceStorage->getDiskAdaptor()->writeData(block,
+					      blockLength,
+					      offset);
+    piece->completeBlock(slot.getBlockIndex());
+    BT_MESSAGE_DISPATCHER(btContext, peer)->removeOutstandingRequest(slot);
+    if(piece->pieceComplete()) {
+      if(checkPieceHash(piece)) {
+	onNewPiece(piece);
+      } else {
+	onWrongPiece(piece);
+      }
+    }
+  }
+}
+
+uint32_t BtPieceMessage::MESSAGE_HEADER_LENGTH = 13;
+
+const char* BtPieceMessage::getMessageHeader() {
+  if(!msgHeader) {
+    /**
+     * len --- 9+blockLength, 4bytes
+     * id --- 7, 1byte
+     * index --- index, 4bytes
+     * begin --- begin, 4bytes
+     * total: 13bytes
+     */
+    msgHeader = new char[MESSAGE_HEADER_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msgHeader, MESSAGE_HEADER_LENGTH,
+					     9+blockLength, ID);
+    PeerMessageUtil::setIntParam(&msgHeader[5], index);
+    PeerMessageUtil::setIntParam(&msgHeader[9], begin);
+  }
+  return msgHeader;
+}
+
+uint32_t BtPieceMessage::getMessageHeaderLength() {
+  return MESSAGE_HEADER_LENGTH;
+}
+
+void BtPieceMessage::send() {
+  if(invalidate) {
+    return;
+  }
+  if(!headerSent) {
+    if(!sendingInProgress) {
+      logger->info(MSG_SEND_PEER_MESSAGE,
+		   cuid, peer->ipaddr.c_str(), peer->port,
+		   toString().c_str());
+      getMessageHeader();
+      leftDataLength = getMessageHeaderLength();
+      sendingInProgress = true;
+    }
+    uint32_t writtenLength
+      = PEER_CONNECTION(btContext, peer)->sendMessage(msgHeader+getMessageHeaderLength()-leftDataLength,
+				    leftDataLength);
+    if(writtenLength == leftDataLength) {
+      headerSent = true;
+      leftDataLength = blockLength;
+    } else {
+      leftDataLength -= writtenLength;
+    }
+  }
+  if(headerSent) {
+    sendingInProgress = false;
+    uint64_t pieceDataOffset =
+      ((uint64_t)index)*btContext->getPieceLength()+begin+blockLength-leftDataLength;
+    uint32_t writtenLength =
+      sendPieceData(pieceDataOffset, leftDataLength);
+    peer->updateUploadLength(writtenLength);
+    if(writtenLength < leftDataLength) {
+      sendingInProgress = true;
+    }
+    leftDataLength -= writtenLength;
+  }
+}
+
+uint32_t BtPieceMessage::sendPieceData(uint64_t offset, uint32_t length) const {
+  uint32_t BUF_SIZE = 256;
+  char buf[BUF_SIZE];
+  int32_t iteration = length/BUF_SIZE;
+  uint32_t writtenLength = 0;
+  for(int32_t i = 0; i < iteration; i++) {
+    if(pieceStorage->getDiskAdaptor()->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
+      throw new DlAbortEx("Failed to read data from disk.");
+    }
+    uint32_t ws = PEER_CONNECTION(btContext, peer)->sendMessage(buf, BUF_SIZE);
+    writtenLength += ws;
+    if(ws != BUF_SIZE) {
+      return writtenLength;
+    }
+  }
+
+  int32_t rem = length%BUF_SIZE;
+  if(rem > 0) {
+    if(pieceStorage->getDiskAdaptor()->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
+      throw new DlAbortEx("Failed to read data from disk.");
+    }
+    uint32_t ws = PEER_CONNECTION(btContext, peer)->sendMessage(buf, rem);
+    writtenLength += ws;
+  }
+  return writtenLength;
+}
+
+string BtPieceMessage::toString() const {
+  return "piece index="+Util::uitos(index)+", begin="+Util::uitos(begin)+
+    ", length="+Util::uitos(blockLength);
+}
+
+bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) {
+  uint64_t offset =
+    ((uint64_t)piece->getIndex())*btContext->getPieceLength();
+  return pieceStorage->getDiskAdaptor()->sha1Sum(offset, piece->getLength()) ==
+    btContext->getPieceHash(piece->getIndex());
+}
+
+void BtPieceMessage::onNewPiece(const PieceHandle& piece) {
+  logger->info(MSG_GOT_NEW_PIECE, cuid, piece->getIndex());
+  pieceStorage->completePiece(piece);
+  pieceStorage->advertisePiece(cuid, piece->getIndex());
+}
+
+void BtPieceMessage::onWrongPiece(const PieceHandle& piece) {
+  logger->error(MSG_GOT_WRONG_PIECE, cuid, piece->getIndex());
+  erasePieceOnDisk(piece);
+  piece->clearAllBlock();
+  BT_REQUEST_FACTORY(btContext, peer)->removeTargetPiece(piece);
+}
+
+void BtPieceMessage::erasePieceOnDisk(const PieceHandle& piece) {
+  int32_t BUFSIZE = 4096;
+  char buf[BUFSIZE];
+  memset(buf, 0, BUFSIZE);
+  uint64_t offset =
+    ((uint64_t)piece->getIndex())*btContext->getPieceLength();
+  for(int32_t i = 0; i < piece->getLength()/BUFSIZE; i++) {
+    pieceStorage->getDiskAdaptor()->writeData(buf, BUFSIZE, offset);
+    offset += BUFSIZE;
+  }
+  int32_t r = piece->getLength()%BUFSIZE;
+  if(r > 0) {
+    pieceStorage->getDiskAdaptor()->writeData(buf, r, offset);
+  }
+}
+
+bool BtPieceMessage::BtChokingEventListener::canHandle(const BtEventHandle& event) {
+  BtChokingEvent* intEvent = dynamic_cast<BtChokingEvent*>(event.get());
+  return intEvent != 0;
+}
+
+void BtPieceMessage::BtChokingEventListener::handleEventInternal(const BtEventHandle& event) {
+  message->handleChokingEvent(event);
+}
+
+void BtPieceMessage::handleChokingEvent(const BtEventHandle& event) {
+  if(!invalidate &&
+     !sendingInProgress &&
+     !peer->isInAmAllowedIndexSet(index)) {
+    logger->debug("CUID#%d - Reject piece message in queue because"
+		  " the peer has been choked. index=%d, begin=%d, length=%d",
+		  cuid,
+		  index,
+		  begin,
+		  blockLength);
+
+    if(peer->isFastExtensionEnabled()) {
+      BtMessageHandle rej =
+	BT_MESSAGE_FACTORY(btContext, peer)->createRejectMessage(index,
+								  begin,
+								  blockLength);
+      BT_MESSAGE_DISPATCHER(btContext, peer)->addMessageToQueue(rej);
+    }
+    invalidate = true;
+  }
+}
+
+bool BtPieceMessage::BtCancelSendingPieceEventListener::canHandle(const BtEventHandle& event) {
+  BtCancelSendingPieceEvent* intEvent = dynamic_cast<BtCancelSendingPieceEvent*>(event.get());
+  return intEvent != 0;
+}
+
+void BtPieceMessage::BtCancelSendingPieceEventListener::handleEventInternal(const BtEventHandle& event) {
+  message->handleCancelSendingPieceEvent(event);
+}
+
+void BtPieceMessage::handleCancelSendingPieceEvent(const BtEventHandle& event) {
+  BtCancelSendingPieceEvent* intEvent = (BtCancelSendingPieceEvent*)(event.get());
+  if(!invalidate &&
+     !sendingInProgress &&
+     index == intEvent->getIndex() &&
+     begin == intEvent->getBegin() &&
+     blockLength == intEvent->getLength()) {
+    logger->debug("CUID#%d - Reject piece message in queue because cancel"
+		  " message received. index=%d, begin=%d, length=%d",
+		  cuid, index, begin, blockLength);
+    if(peer->isFastExtensionEnabled()) {
+      BtMessageHandle rej =
+	BT_MESSAGE_FACTORY(btContext, peer)->createRejectMessage(index,
+								  begin,
+								  blockLength);
+      BT_MESSAGE_DISPATCHER(btContext, peer)->addMessageToQueue(rej);
+    }
+    invalidate = true;
+  } 
+}

+ 154 - 0
src/BtPieceMessage.h

@@ -0,0 +1,154 @@
+/* <!-- 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_PIECE_MESSAGE_H_
+#define _D_BT_PIECE_MESSAGE_H_
+
+#include "AbstractBtMessage.h"
+#include "BtContext.h"
+#include "PieceStorage.h"
+#include "BtEvent.h"
+#include "AbstractBtEventListener.h"
+
+class BtPieceMessage;
+
+typedef SharedHandle<BtPieceMessage> BtPieceMessageHandle;
+
+class BtPieceMessage : public AbstractBtMessage {
+private:
+  uint32_t index;
+  uint32_t begin;
+  uint32_t blockLength;
+  char* block;
+  uint32_t leftDataLength;
+  bool headerSent;
+  char* msgHeader;
+
+  static uint32_t MESSAGE_HEADER_LENGTH;
+
+  bool checkPieceHash(const PieceHandle& piece);
+
+  void onNewPiece(const PieceHandle& piece);
+
+  void onWrongPiece(const PieceHandle& piece);
+
+  void erasePieceOnDisk(const PieceHandle& piece);
+
+  uint32_t sendPieceData(uint64_t offset, uint32_t length) const;
+
+  class BtChokingEventListener : public AbstractBtEventListener {
+  private:
+    BtPieceMessage* message;
+  public:
+    BtChokingEventListener(BtPieceMessage* message):message(message) {}
+
+    virtual bool canHandle(const BtEventHandle& btEvent);
+
+    virtual void handleEventInternal(const BtEventHandle& btEvent);
+  };
+
+  typedef SharedHandle<BtChokingEventListener> BtChokingEventListenerHandle;
+
+  class BtCancelSendingPieceEventListener : public AbstractBtEventListener {
+  private:
+    BtPieceMessage* message;
+  public:
+    BtCancelSendingPieceEventListener(BtPieceMessage* message):message(message) {}
+
+    virtual bool canHandle(const BtEventHandle& btEvent);
+
+    virtual void handleEventInternal(const BtEventHandle& btEvent);
+  };
+
+  typedef SharedHandle<BtCancelSendingPieceEventListener> BtCancelSendingPieceEventListenerHandle;
+public:
+  BtPieceMessage(uint32_t index = 0, uint32_t begin = 0, uint32_t blockLength = 0)
+    :index(index),
+     begin(begin),
+     blockLength(blockLength),
+     block(0),
+     leftDataLength(0),
+     headerSent(false),
+     msgHeader(0)
+  {
+    uploading = true;
+    addEventListener(new BtChokingEventListener(this));
+    addEventListener(new BtCancelSendingPieceEventListener(this));
+  }
+
+  virtual ~BtPieceMessage() {
+    delete [] msgHeader;
+    delete []  block;
+  }
+
+  enum ID_t {
+    ID = 7
+  };
+
+  uint32_t getIndex() const { return index; }
+
+  void setIndex(uint32_t index) { this->index = index; }
+
+  uint32_t getBegin() const { return begin; }
+
+  void setBegin(uint32_t begin) { this->begin = begin; }
+
+  const char* getBlock() const { return block; }
+
+  void setBlock(const unsigned char* block, uint32_t blockLength);
+
+  uint32_t getBlockLength() const { return blockLength; }
+
+  void setBlockLength(uint32_t blockLength) { this->blockLength = blockLength; }
+
+  static BtPieceMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  const char* getMessageHeader();
+
+  uint32_t getMessageHeaderLength();
+
+  virtual void send();
+
+  virtual string toString() const;
+
+  void handleChokingEvent(const BtEventHandle& event);
+  
+  void handleCancelSendingPieceEvent(const BtEventHandle& event);
+};
+
+#endif // _D_BT_PIECE_MESSAGE_H_

+ 64 - 0
src/BtPieceMessageValidator.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_BT_PIECE_MESSAGE_VALIDATOR_H_
+#define _D_BT_PIECE_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtPieceMessage.h"
+
+class BtPieceMessageValidator : public BtMessageValidator {
+private:
+  const BtPieceMessage* message;
+  uint32_t numPiece;
+  uint32_t pieceLength;
+public:
+  BtPieceMessageValidator(const BtPieceMessage* message,
+			  uint32_t numPiece,
+			  uint32_t pieceLength):
+    message(message),
+    numPiece(numPiece),
+    pieceLength(pieceLength) {}
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    PeerMessageUtil::checkBegin(message->getBegin(), pieceLength);
+    return true;
+  }
+};
+
+typedef SharedHandle<BtPieceMessageValidator> BtPieceMessageValidatorHandle;
+
+#endif // _D_BT_PIECE_MESSAGE_VALIDATOR_H_

+ 56 - 0
src/BtPortMessage.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 "BtPortMessage.h"
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+#include "Util.h"
+
+BtPortMessageHandle BtPortMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 3) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "port", dataLength, 3);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "piece", ID);
+  }
+  BtPortMessageHandle message = new BtPortMessage();
+  message->setPort(PeerMessageUtil::getShortIntParam(data, 1));
+  return message;
+}
+
+string BtPortMessage::toString() const {
+  return "port port="+Util::uitos(port);
+}

+ 72 - 0
src/BtPortMessage.h

@@ -0,0 +1,72 @@
+/* <!-- 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_PORT_MESSAGE_H_
+#define _D_BT_PORT_MESSAGE_H_
+
+#include "AbstractBtMessage.h"
+
+class BtPortMessage;
+
+typedef SharedHandle<BtPortMessage> BtPortMessageHandle;
+
+class BtPortMessage : public AbstractBtMessage {
+private:
+  uint16_t port;
+public:
+  BtPortMessage(uint16_t port = 0):port(port) {}
+
+  virtual ~BtPortMessage() {}
+
+  enum ID_t {
+    ID = 9
+  };
+
+  uint16_t getPort() const { return port; }
+
+  void setPort(uint16_t port) { this->port = port; }
+
+  virtual int32_t getId() const { return ID; }
+
+  static BtPortMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual void doReceivedAction() {
+    logger->info("DHT is not supported yet.");
+  }
+  virtual void send() {}
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_PORT_MESSAGE_H_

+ 30 - 0
src/BtRegistry.cc

@@ -40,6 +40,7 @@ PieceStorageMap BtRegistry::pieceStorageMap;
 BtAnnounceMap BtRegistry::btAnnounceMap;
 BtRuntimeMap BtRegistry::btRuntimeMap;
 BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
+PeerObjectClusterRegistry BtRegistry::peerObjectClusterRegistry;
 
 PeerStorageHandle BtRegistry::getPeerStorage(const string& key) {
   PeerStorageMap::iterator itr = peerStorageMap.find(key);
@@ -70,6 +71,7 @@ BtRegistry::getPieceStorage(const string& key) {
 bool
 BtRegistry::registerPieceStorage(const string& key,
 				 const PieceStorageHandle& pieceStorage) {
+  pieceStorageMap.erase(key);
   PieceStorageMap::value_type p(key, pieceStorage);
   pair<PieceStorageMap::iterator, bool> retval = pieceStorageMap.insert(p);
   return retval.second;
@@ -128,3 +130,31 @@ BtRegistry::registerBtProgressInfoFile(const string& key,
     btProgressInfoFileMap.insert(p);
   return retval.second;
 }
+
+PeerObjectClusterHandle
+BtRegistry::getPeerObjectCluster(const string& key)
+{
+  return peerObjectClusterRegistry.getHandle(key);
+}
+
+void
+BtRegistry::registerPeerObjectCluster(const string& key,
+				      const PeerObjectClusterHandle& cluster)
+{
+  peerObjectClusterRegistry.registerHandle(key, cluster);
+}
+
+void
+BtRegistry::unregisterPeerObjectCluster(const string& key)
+{
+  peerObjectClusterRegistry.unregisterHandle(key);
+}
+
+void BtRegistry::clear() {
+  peerStorageMap.clear();
+  pieceStorageMap.clear();
+  btAnnounceMap.clear();
+  btRuntimeMap.clear();
+  btProgressInfoFileMap.clear();
+  peerObjectClusterRegistry.clear();
+}

+ 39 - 0
src/BtRegistry.h

@@ -41,6 +41,8 @@
 #include "BtAnnounce.h"
 #include "BtRuntime.h"
 #include "BtProgressInfoFile.h"
+#include "PeerObject.h"
+#include "HandleRegistry.h"
 #include <map>
 
 typedef map<string, PeerStorageHandle> PeerStorageMap;
@@ -49,6 +51,11 @@ typedef map<string, BtAnnounceHandle> BtAnnounceMap;
 typedef map<string, BtRuntimeHandle> BtRuntimeMap;
 typedef map<string, BtProgressInfoFileHandle> BtProgressInfoFileMap;
 
+// for BtMessageFactory
+typedef HandleRegistry<string, PeerObject> PeerObjectCluster;
+typedef SharedHandle<PeerObjectCluster> PeerObjectClusterHandle;
+typedef HandleRegistry<string, PeerObjectCluster> PeerObjectClusterRegistry;
+
 class BtRegistry {
 private:
   BtRegistry() {}
@@ -58,6 +65,7 @@ private:
   static BtAnnounceMap btAnnounceMap;
   static BtRuntimeMap btRuntimeMap;
   static BtProgressInfoFileMap btProgressInfoFileMap;
+  static PeerObjectClusterRegistry peerObjectClusterRegistry;
 public:
   static PeerStorageHandle getPeerStorage(const string& key);
   static bool registerPeerStorage(const string& key,
@@ -78,6 +86,19 @@ public:
   static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
   static bool registerBtProgressInfoFile(const string& key,
 					 const BtProgressInfoFileHandle& btProgressInfoFile);
+
+  // for PeerObject
+  static PeerObjectClusterHandle
+  getPeerObjectCluster(const string& key);
+
+  static void
+  registerPeerObjectCluster(const string& key,
+			    const PeerObjectClusterHandle& cluster);
+
+  static void
+  unregisterPeerObjectCluster(const string& key);
+
+  static void clear();
 };
 
 #define PEER_STORAGE(btContext) \
@@ -95,4 +116,22 @@ BtRegistry::getBtRuntime(btContext->getInfoHashAsString())
 #define BT_PROGRESS_INFO_FILE(btContext) \
 BtRegistry::getBtProgressInfoFile(btContext->getInfoHashAsString())
 
+#define PEER_OBJECT_CLUSTER(btContext) \
+BtRegistry::getPeerObjectCluster(btContext->getInfoHashAsString())
+
+#define PEER_OBJECT(btContext, peer) \
+PEER_OBJECT_CLUSTER(btContext)->getHandle(peer->getId())
+
+#define BT_MESSAGE_DISPATCHER(btContext, peer) \
+PEER_OBJECT(btContext, peer)->btMessageDispatcher
+
+#define BT_MESSAGE_FACTORY(btContext, peer) \
+PEER_OBJECT(btContext, peer)->btMessageFactory
+
+#define BT_REQUEST_FACTORY(btContext, peer) \
+PEER_OBJECT(btContext, peer)->btRequestFactory
+
+#define PEER_CONNECTION(btContext, peer) \
+PEER_OBJECT(btContext, peer)->peerConnection
+
 #endif // _D_BT_REGISTRY_H_

+ 101 - 0
src/BtRejectMessage.cc

@@ -0,0 +1,101 @@
+/* <!-- 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 "BtRejectMessage.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+
+BtRejectMessageHandle BtRejectMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 13) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "reject", dataLength, 13);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "reject", ID);
+  }
+  BtRejectMessageHandle message = new BtRejectMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  message->setBegin(PeerMessageUtil::getIntParam(data, 5));
+  message->setLength(PeerMessageUtil::getIntParam(data, 9));
+  return message;
+}
+
+void BtRejectMessage::doReceivedAction() {
+  if(!peer->isFastExtensionEnabled()) {
+    throw new DlAbortEx("%s received while fast extension is disabled.",
+			toString().c_str());
+  }
+  // TODO Current implementation does not close a connection even if
+  // a request for this reject message has never sent.
+  RequestSlot slot =
+    BT_MESSAGE_DISPATCHER(btContext, peer)->getOutstandingRequest(index, begin, length);
+  if(RequestSlot::isNull(slot)) {
+    //throw new DlAbortEx("reject recieved, but it is not in the request slots.");
+  } else {
+    BT_MESSAGE_DISPATCHER(btContext, peer)->removeOutstandingRequest(slot);
+  }
+
+}
+
+uint32_t BtRejectMessage::MESSAGE_LENGTH = 17;
+
+const char* BtRejectMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 13, 4bytes
+     * id --- 16, 1byte
+     * index --- index, 4bytes
+     * begin --- begin, 4bytes
+     * length -- length, 4bytes
+     * total: 17bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 13, ID);
+    PeerMessageUtil::setIntParam(&msg[5], index);
+    PeerMessageUtil::setIntParam(&msg[9], begin);
+    PeerMessageUtil::setIntParam(&msg[13], length);
+  }
+  return msg;
+}
+
+uint32_t BtRejectMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtRejectMessage::toString() const {
+  return "reject index="+Util::uitos(index)+", begin="+Util::uitos(begin)+
+    ", length="+Util::uitos(length);
+}

+ 88 - 0
src/BtRejectMessage.h

@@ -0,0 +1,88 @@
+/* <!-- 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_REJECT_MESSAGE_H_
+#define _D_BT_REJECT_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtRejectMessage;
+
+typedef SharedHandle<BtRejectMessage> BtRejectMessageHandle;
+
+class BtRejectMessage : public SimpleBtMessage {
+private:
+  uint32_t index;
+  uint32_t begin;
+  uint32_t length;
+  char* msg;
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtRejectMessage(uint32_t index = 0, uint32_t begin = 0, uint32_t length = 0)
+    :index(index),
+     begin(begin),
+     length(length),
+     msg(0) {}
+
+  virtual ~BtRejectMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 16
+  };
+
+  uint32_t getIndex() const { return index; }
+  void setIndex(uint32_t index) { this->index = index; }
+
+  uint32_t getBegin() const { return begin; }
+  void setBegin(uint32_t begin) { this->begin = begin; }
+
+  uint32_t getLength() const { return length; }
+  void setLength(uint32_t length) { this->length = length; }
+
+  static BtRejectMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_REJECT_MESSAGE_H_

+ 68 - 0
src/BtRejectMessageValidator.h

@@ -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 --> */
+#ifndef _D_BT_REJECT_MESSAGE_VALIDATOR_H_
+#define _D_BT_REJECT_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtRejectMessage.h"
+
+class BtRejectMessageValidator : public BtMessageValidator {
+private:
+  const BtRejectMessage* message;
+  uint32_t numPiece;
+  uint32_t pieceLength;
+public:
+  BtRejectMessageValidator(const BtRejectMessage* message,
+			   uint32_t numPiece,
+			   uint32_t pieceLength):
+    message(message),
+    numPiece(numPiece),
+    pieceLength(pieceLength) {}
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    PeerMessageUtil::checkBegin(message->getBegin(), pieceLength);
+    PeerMessageUtil::checkLength(message->getLength());
+    PeerMessageUtil::checkRange(message->getBegin(),
+				message->getLength(),
+				pieceLength);
+    return true;
+  }
+};
+
+typedef SharedHandle<BtRejectMessageValidator> BtRejectMessageValidatorHandle;
+
+#endif // _D_BT_REJECT_MESSAGE_VALIDATOR_H_

+ 72 - 0
src/BtRequestFactory.h

@@ -0,0 +1,72 @@
+/* <!-- 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_REQUEST_FACTORY_H_
+#define _D_BT_REQUEST_FACTORY_H_
+
+#include "common.h"
+#include "BtMessage.h"
+#include "Piece.h"
+
+class BtRequestFactory {
+public:
+  virtual ~BtRequestFactory() {}
+
+  virtual void addTargetPiece(const PieceHandle& piece) = 0;
+
+  virtual void removeTargetPiece(const PieceHandle& piece) = 0;
+
+  virtual void removeAllTargetPiece() = 0;
+
+  virtual int countTargetPiece() = 0;
+
+  virtual void removeCompletedPiece() = 0;
+
+  /**
+   * Creates RequestMessage objects associated to the pieces added by
+   * addTargetPiece() and returns them.
+   * The number of objects returned is capped by max.
+   */
+  virtual BtMessages createRequestMessages(int max) = 0;
+
+  /**
+   * Use this method in end game mode.
+   *
+   */
+  virtual BtMessages createRequestMessagesOnEndGame(int max) = 0;
+};
+
+typedef SharedHandle<BtRequestFactory> BtRequestFactoryHandle;
+
+#endif // _D_BT_REQUEST_FACTORY_H_

+ 129 - 0
src/BtRequestMessage.cc

@@ -0,0 +1,129 @@
+/* <!-- 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 "BtRequestMessage.h"
+#include "PeerInteraction.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+#include "BtAbortOutstandingRequestEvent.h"
+
+BtRequestMessageHandle BtRequestMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 13) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "request", dataLength, 13);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "request", ID);
+  }
+  BtRequestMessageHandle message = new BtRequestMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  message->setBegin(PeerMessageUtil::getIntParam(data, 5));
+  message->setLength(PeerMessageUtil::getIntParam(data, 9));
+  return message;
+}
+
+void BtRequestMessage::doReceivedAction() {
+  if(pieceStorage->hasPiece(index) &&
+     (!peer->amChoking ||
+      peer->amChoking && peer->isInAmAllowedIndexSet(index))) {
+    BtMessageHandle msg =
+      BT_MESSAGE_FACTORY(btContext, peer)->createPieceMessage(index,
+							       begin,
+							       length);
+    BT_MESSAGE_DISPATCHER(btContext, peer)->addMessageToQueue(msg);
+  } else {
+    if(peer->isFastExtensionEnabled()) {
+      BtMessageHandle msg =
+	BT_MESSAGE_FACTORY(btContext, peer)->createRejectMessage(index,
+								  begin,
+								  length);
+      BT_MESSAGE_DISPATCHER(btContext, peer)->addMessageToQueue(msg);
+    }
+  }
+}
+
+uint32_t BtRequestMessage::MESSAGE_LENGTH = 17;
+
+const char* BtRequestMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 13, 4bytes
+     * id --- 6, 1byte
+     * index --- index, 4bytes
+     * begin --- begin, 4bytes
+     * length --- length, 4bytes
+     * total: 17bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 13, ID);
+    PeerMessageUtil::setIntParam(&msg[5], index);
+    PeerMessageUtil::setIntParam(&msg[9], begin);
+    PeerMessageUtil::setIntParam(&msg[13], length);
+  }
+  return msg;
+}
+
+uint32_t BtRequestMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtRequestMessage::toString() const {
+  return "request index="+Util::uitos(index)+", begin="+Util::uitos(begin)+
+    ", length="+Util::uitos(length);
+}
+
+void BtRequestMessage::onQueued() {
+  RequestSlot requestSlot(index, begin, length, blockIndex);
+  BT_MESSAGE_DISPATCHER(btContext, peer)->addOutstandingRequest(requestSlot);
+}
+
+bool BtRequestMessage::BtAbortOutstandingRequestEventListener::canHandle(const BtEventHandle& event) {
+  BtAbortOutstandingRequestEvent* intEvent = dynamic_cast<BtAbortOutstandingRequestEvent*>(event.get());
+  return intEvent != 0;
+}
+
+void BtRequestMessage::BtAbortOutstandingRequestEventListener::handleEventInternal(const BtEventHandle& event) {
+  message->handleAbortOutstandingRequestEvent(event);
+}
+
+void BtRequestMessage::handleAbortOutstandingRequestEvent(const BtEventHandle& event) {
+  BtAbortOutstandingRequestEvent* intEvent = (BtAbortOutstandingRequestEvent*)event.get();
+  if(index == intEvent->getPiece()->getIndex() &&
+     !invalidate &&
+     !sendingInProgress) {
+    invalidate = true;
+  }
+}

+ 117 - 0
src/BtRequestMessage.h

@@ -0,0 +1,117 @@
+/* <!-- 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_REQUEST_MESSAGE_H_
+#define _D_BT_REQUEST_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+#include "BtContext.h"
+#include "PieceStorage.h"
+#include "AbstractBtEventListener.h"
+
+class BtRequestMessage;
+
+typedef SharedHandle<BtRequestMessage> BtRequestMessageHandle;
+
+class BtRequestMessage : public SimpleBtMessage {
+private:
+  uint32_t index;
+  uint32_t begin;
+  uint32_t length;
+  uint32_t blockIndex;
+  char* msg;
+
+  static uint32_t MESSAGE_LENGTH;
+
+  class BtAbortOutstandingRequestEventListener : public AbstractBtEventListener {
+  private:
+    BtRequestMessage* message;
+  public:
+    BtAbortOutstandingRequestEventListener(BtRequestMessage* message):message(message) {}
+
+    virtual bool canHandle(const BtEventHandle& event);
+
+    virtual void handleEventInternal(const BtEventHandle& event);
+  };
+
+  typedef SharedHandle<BtAbortOutstandingRequestEventListener> BtAbortOutstandingRequestEventListenerHandle;
+public:
+  BtRequestMessage(uint32_t index = 0,
+		   uint32_t begin = 0,
+		   uint32_t length = 0,
+		   uint32_t blockIndex = 0)
+    :index(index),
+     begin(begin),
+     length(length),
+     blockIndex(blockIndex),
+     msg(0)
+  {
+    addEventListener(new BtAbortOutstandingRequestEventListener(this));
+  }
+
+  virtual ~BtRequestMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 6
+  };
+
+  uint32_t getIndex() const { return index; }
+  void setIndex(uint32_t index) { this->index = index; }
+  uint32_t getBegin() const { return begin; }
+  void setBegin(uint32_t begin) { this->begin = begin; }
+  uint32_t getLength() const { return length; }
+  void setLength(uint32_t length) { this->length = length; }
+  uint32_t getBlockIndex() const { return blockIndex; }
+  void setBlockIndex(uint32_t blockIndex) { this->blockIndex = blockIndex; }
+
+  static BtRequestMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  virtual void onQueued();
+
+  virtual void handleAbortOutstandingRequestEvent(const BtEventHandle& event);
+};
+
+#endif // _D_BT_REQUEST_MESSAGE_H_

+ 68 - 0
src/BtRequestMessageValidator.h

@@ -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 --> */
+#ifndef _D_BT_REQUEST_MESSAGE_VALIDATOR_H_
+#define _D_BT_REQUEST_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtRequestMessage.h"
+
+class BtRequestMessageValidator : public BtMessageValidator {
+private:
+  const BtRequestMessage* message;
+  uint32_t numPiece;
+  uint32_t pieceLength;
+public:
+  BtRequestMessageValidator(const BtRequestMessage* message,
+			   uint32_t numPiece,
+			   uint32_t pieceLength):
+    message(message),
+    numPiece(numPiece),
+    pieceLength(pieceLength) {}
+
+  virtual bool validate(Errors& error) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    PeerMessageUtil::checkBegin(message->getBegin(), pieceLength);
+    PeerMessageUtil::checkLength(message->getLength());
+    PeerMessageUtil::checkRange(message->getBegin(),
+				message->getLength(),
+				pieceLength);
+    return true;
+  }
+};
+
+typedef SharedHandle<BtRequestMessageValidator> BtRequestMessageValidatorHandle;
+
+#endif // _D_BT_REQUEST_MESSAGE_VALIDATOR_H_

+ 78 - 0
src/BtSuggestPieceMessage.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 "BtSuggestPieceMessage.h"
+#include "PeerInteraction.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+
+BtSuggestPieceMessageHandle BtSuggestPieceMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 5) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "suggest piece", dataLength, 5);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "suggest piece", ID);
+  }
+  BtSuggestPieceMessageHandle message = new BtSuggestPieceMessage();
+  message->setIndex(PeerMessageUtil::getIntParam(data, 1));
+  return message;
+}
+
+uint32_t BtSuggestPieceMessage::MESSAGE_LENGTH = 9;
+
+const char* BtSuggestPieceMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 5, 4bytes
+     * id --- 13, 1byte
+     * piece index --- index, 4bytes
+     * total: 9bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 5, ID);
+    PeerMessageUtil::setIntParam(&msg[5], index);
+  }
+  return msg;
+}
+
+uint32_t BtSuggestPieceMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+string BtSuggestPieceMessage::toString() const {
+  return "suggest piece index="+Util::uitos(index);
+}

+ 81 - 0
src/BtSuggestPieceMessage.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_BT_SUGGEST_PIECE_MESSAGE_H_
+#define _D_BT_SUGGEST_PIECE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtSuggestPieceMessage;
+
+typedef SharedHandle<BtSuggestPieceMessage> BtSuggestPieceMessageHandle;
+
+class BtSuggestPieceMessage : public SimpleBtMessage {
+private:
+  uint32_t index;
+  char* msg;
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtSuggestPieceMessage():index(0), msg(0) {}
+
+  virtual ~BtSuggestPieceMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 13
+  };
+
+  void setIndex(uint32_t index) {
+    this->index = index;
+  }
+
+  uint32_t getIndex() const { return index; }
+
+  static BtSuggestPieceMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction() {
+    // TODO Current implementation ignores this message.
+  }
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+};
+
+#endif // _D_BT_SUGGEST_PIECE_MESSAGE_H_

+ 60 - 0
src/BtSuggestPieceMessageValidator.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_BT_SUGGEST_PIECE_MESSAGE_VALIDATOR_H_
+#define _D_BT_SUGGEST_PIECE_MESSAGE_VALIDATOR_H_
+
+#include "BtMessageValidator.h"
+#include "BtSuggestPieceMessage.h"
+
+class BtSuggestPieceMessageValidator : public BtMessageValidator {
+private:
+  const BtSuggestPieceMessage* message;
+  int numPiece;
+public:
+  BtSuggestPieceMessageValidator(const BtSuggestPieceMessage* message,
+				 int numPiece):
+    message(message),
+    numPiece(numPiece) {}
+
+  virtual bool validate(Errors& errors) {
+    // TODO
+    PeerMessageUtil::checkIndex(message->getIndex(), numPiece);
+    return true;
+  }
+
+};
+
+typedef SharedHandle<BtSuggestPieceMessageValidator> BtSuggestPieceMessageValidatorHandle;
+#endif // _D_BT_SUGGEST_PIECE_MESSAGE_VALIDATOR_H_

+ 85 - 0
src/BtUnchokeMessage.cc

@@ -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 --> */
+#include "BtUnchokeMessage.h"
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+
+BtUnchokeMessageHandle BtUnchokeMessage::create(const unsigned char* data, uint32_t dataLength) {
+  if(dataLength != 1) {
+    throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "unchoke", dataLength, 1);
+  }
+  int32_t id = PeerMessageUtil::getId(data);
+  if(id != ID) {
+    throw new DlAbortEx("invalid ID=%d for %s. It should be %d.",
+			id, "unchoke", ID);
+  }
+  BtUnchokeMessageHandle message = new BtUnchokeMessage();
+  return message;
+}
+
+void BtUnchokeMessage::doReceivedAction() {
+  peer->peerChoking = false;
+}
+
+bool BtUnchokeMessage::sendPredicate() const {
+  return peer->amChoking;
+}
+
+uint32_t BtUnchokeMessage::MESSAGE_LENGTH = 5;
+
+const char* BtUnchokeMessage::getMessage() {
+  if(!msg) {
+    /**
+     * len --- 1, 4bytes
+     * id --- 1, 1byte
+     * total: 5bytes
+     */
+    msg = new char[MESSAGE_LENGTH];
+    PeerMessageUtil::createPeerMessageString(msg, MESSAGE_LENGTH, 1, ID);
+  }
+  return msg;
+}
+
+uint32_t BtUnchokeMessage::getMessageLength() {
+  return MESSAGE_LENGTH;
+}
+
+void BtUnchokeMessage::onSendComplete() {
+  peer->amChoking = false;
+}
+
+string BtUnchokeMessage::toString() const {
+  return "unchoke";
+}

+ 76 - 0
src/BtUnchokeMessage.h

@@ -0,0 +1,76 @@
+/* <!-- 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_UNCHOKE_MESSAGE_H_
+#define _D_BT_UNCHOKE_MESSAGE_H_
+
+#include "SimpleBtMessage.h"
+
+class BtUnchokeMessage;
+
+typedef SharedHandle<BtUnchokeMessage> BtUnchokeMessageHandle;
+
+class BtUnchokeMessage : public SimpleBtMessage {
+private:
+  char* msg;
+  static uint32_t MESSAGE_LENGTH;
+public:
+  BtUnchokeMessage():msg(0) {}
+
+  virtual ~BtUnchokeMessage() {
+    delete [] msg;
+  }
+
+  enum ID_t {
+    ID = 1
+  };
+
+  static BtUnchokeMessageHandle create(const unsigned char* data, uint32_t dataLength);
+
+  virtual int32_t getId() const { return ID; }
+
+  virtual void doReceivedAction();
+
+  virtual const char* getMessage();
+
+  virtual uint32_t getMessageLength();
+
+  virtual string toString() const;
+
+  virtual bool sendPredicate() const;
+
+  virtual void onSendComplete();
+};
+
+#endif // _D_BT_UNCHOKE_MESSAGE_H_

+ 1 - 8
src/DefaultBtAnnounce.cc

@@ -62,7 +62,6 @@ DefaultBtAnnounce::DefaultBtAnnounce(BtContextHandle btContext,
 {
   prevAnnounceTime.setTimeInSec(0);
   key = generateKey();
-  peerId = generatePeerId();
   logger = LogFactory::getInstance();
 }
 
@@ -73,12 +72,6 @@ string DefaultBtAnnounce::generateKey() const {
   return Util::randomAlpha(8);
 }
 
-string DefaultBtAnnounce::generatePeerId() const {
-  string peerId = "-aria2-";
-  peerId += Util::randomAlpha(20-peerId.size());
-  return peerId;
-}
-
 bool DefaultBtAnnounce::isDefaultAnnounceReady() {
   return (trackers == 0 && prevAnnounceTime.elapsed(minInterval));
 }
@@ -131,7 +124,7 @@ string DefaultBtAnnounce::getAnnounceUrl() {
   string url = announceList.getAnnounce()+"?"+
     "info_hash="+Util::torrentUrlencode(btContext->getInfoHash(),
 					btContext->getInfoHashLength())+"&"+
-    "peer_id="+peerId+"&"+
+    "peer_id="+Util::torrentUrlencode(btContext->getPeerId(), 20)+"&"+
     "port="+Util::itos(btRuntime->getListenPort())+"&"+
     "uploaded="+Util::llitos(stat.getSessionUploadLength())+"&"+
     "downloaded="+Util::llitos(stat.getSessionDownloadLength())+"&"+

+ 1 - 6
src/DefaultBtAnnounce.h

@@ -60,7 +60,6 @@ private:
   string trackerId;
   string key;
   int trackerNumTry;
-  string peerId;
   const Option* option;
   Logger* logger;
   BtRuntimeHandle btRuntime;
@@ -112,11 +111,7 @@ public:
 
   virtual void shuffleAnnounce();
 
-  string generateKey() const;
-  
-  string generatePeerId() const;
-
-  virtual string getPeerId() { return peerId; }
+  string generateKey() const;  
 };
 
 #endif // _D_DEFAULT_BT_ANNOUNCE_H_

+ 6 - 0
src/DefaultBtContext.cc

@@ -45,6 +45,12 @@ DefaultBtContext::DefaultBtContext() {}
 
 DefaultBtContext::~DefaultBtContext() {}
 
+string DefaultBtContext::generatePeerId() const {
+  string peerId = "-aria2-";
+  peerId += Util::randomAlpha(20-peerId.size());
+  return peerId;
+}
+
 const unsigned char* DefaultBtContext::getInfoHash() const {
   return infoHash;
 }

+ 10 - 0
src/DefaultBtContext.h

@@ -55,6 +55,7 @@ private:
   int pieceLength;
   string name;
   int numPieces;
+  string peerId;
   AnnounceTiers announceTiers;
 
   void clear();
@@ -92,6 +93,15 @@ private:
   virtual int getPieceLength() const;
   
   virtual int getNumPieces() const;
+
+  virtual const unsigned char* getPeerId() {
+    if(peerId == "") {
+      peerId = generatePeerId();
+    }
+    return (const unsigned char*)peerId.c_str();
+  }
+
+  string generatePeerId() const;
 };
 
 #endif // _D_DEFAULT_BT_CONTEXT_H_

+ 307 - 0
src/DefaultBtInteractive.cc

@@ -0,0 +1,307 @@
+/* <!-- 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 "DefaultBtInteractive.h"
+#include "prefs.h"
+#include "message.h"
+#include "BtHandshakeMessage.h"
+#include "Util.h"
+#include "BtKeepAliveMessage.h"
+#include "BtChokeMessage.h"
+#include "BtUnchokeMessage.h"
+#include "DlAbortEx.h"
+
+void DefaultBtInteractive::initiateHandshake() {
+  BtMessageHandle message =
+    BT_MESSAGE_FACTORY(btContext, peer)->
+    createHandshakeMessage(btContext->getInfoHash(),
+			   btContext->getPeerId());
+  dispatcher->addMessageToQueue(message);
+  dispatcher->sendMessages();
+}
+
+BtMessageHandle DefaultBtInteractive::receiveHandshake(bool quickReply) {
+    BtHandshakeMessageHandle message =
+      btMessageReceiver->receiveHandshake(quickReply);
+    if(message.isNull()) {
+      return 0;
+    }
+    peer->setPeerId(message->getPeerId());
+    logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
+		 peer->ipaddr.c_str(), peer->port,
+		 message->toString().c_str());
+    return message;
+}
+
+BtMessageHandle DefaultBtInteractive::receiveAndSendHandshake() {
+  return receiveHandshake(true);
+}
+
+void DefaultBtInteractive::doPostHandshakeProcessing() {
+  // TODO where is the valid place to rest haveCheckTime?
+  haveCheckPoint.reset();
+  keepAliveCheckPoint.reset();
+  floodingCheckPoint.reset();
+  addBitfieldMessageToQueue();
+  addAllowedFastMessageToQueue();  
+}
+
+void DefaultBtInteractive::addBitfieldMessageToQueue() {
+  BtMessageFactoryHandle factory = BT_MESSAGE_FACTORY(btContext, peer);
+  if(peer->isFastExtensionEnabled()) {
+    if(pieceStorage->downloadFinished()) {
+      dispatcher->addMessageToQueue(factory->createHaveAllMessage());
+    } else if(pieceStorage->getCompletedLength() > 0) {
+      dispatcher->addMessageToQueue(factory->createBitfieldMessage());
+    } else {
+      dispatcher->addMessageToQueue(factory->createHaveNoneMessage());
+    }
+  } else {
+    if(pieceStorage->getCompletedLength() > 0) {
+      dispatcher->addMessageToQueue(factory->createBitfieldMessage());
+    }
+  }
+}
+
+void DefaultBtInteractive::addAllowedFastMessageToQueue() {
+  if(peer->isFastExtensionEnabled()) {
+    Integers fastSet = Util::computeFastSet(peer->ipaddr,
+					    btContext->getInfoHash(),
+					    btContext->getNumPieces(),
+					    allowedFastSetSize);
+    for(Integers::const_iterator itr = fastSet.begin();
+	itr != fastSet.end(); itr++) {
+      dispatcher->addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->
+				    createAllowedFastMessage(*itr));
+    }
+  }
+}
+
+void DefaultBtInteractive::decideChoking() {
+  if(peer->shouldBeChoking()) {
+    if(!peer->amChoking) {
+      dispatcher->addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->
+				    createChokeMessage());
+    }
+  } else {
+    if(peer->amChoking) {
+      dispatcher->addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->
+				    createUnchokeMessage());
+    }
+  }
+}
+
+void DefaultBtInteractive::checkHave() {
+  BtMessageFactoryHandle factory = BT_MESSAGE_FACTORY(btContext, peer);
+  Integers indexes =
+    pieceStorage->getAdvertisedPieceIndexes(cuid, haveCheckPoint);
+  haveCheckPoint.reset();
+  if(indexes.size() >= 20) {
+    if(peer->isFastExtensionEnabled() && pieceStorage->downloadFinished()) {
+      dispatcher->addMessageToQueue(factory->createHaveAllMessage());
+    } else {
+      dispatcher->addMessageToQueue(factory->createBitfieldMessage());
+    }
+  } else {
+    for(Integers::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
+      dispatcher->addMessageToQueue(factory->createHaveMessage(*itr));
+    }
+  }
+}
+
+void DefaultBtInteractive::sendKeepAlive() {
+  if(keepAliveCheckPoint.elapsed(option->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL))) {
+    if(dispatcher->countMessageInQueue() == 0) {
+      dispatcher->addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->createKeepAliveMessage());
+      dispatcher->sendMessages();
+    }
+    keepAliveCheckPoint.reset();
+  }
+}
+
+void DefaultBtInteractive::receiveMessages() {
+  for(int i = 0; i < 50; i++) {
+    int maxSpeedLimit = option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT);
+    if(maxSpeedLimit > 0) {
+      TransferStat stat = peerStorage->calculateStat();
+      if(maxSpeedLimit < stat.downloadSpeed) {
+	break;
+      }
+    }
+    BtMessageHandle message = btMessageReceiver->receiveMessage();
+    if(message.isNull()) {
+      break;
+    }
+    logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
+		 peer->ipaddr.c_str(), peer->port,
+		 message->toString().c_str());
+    message->doReceivedAction();
+
+    switch(message->getId()) {
+    case BtKeepAliveMessage::ID:
+      floodingStat.incKeepAliveCount();
+      break;
+    case BtChokeMessage::ID:
+      if(!peer->peerChoking) {
+	floodingStat.incChokeUnchokeCount();
+      }
+      break;
+    case BtUnchokeMessage::ID:
+      if(peer->peerChoking) {
+	floodingStat.incChokeUnchokeCount();
+      }
+      break;
+    }
+  }
+}
+
+void DefaultBtInteractive::decideInterest() {
+  if(!pieceStorage->hasMissingPiece(peer)) {
+    if(peer->amInterested) {
+      logger->debug("CUID#%d - Not interested in the peer", cuid);
+      dispatcher->
+	addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->
+			  createNotInterestedMessage());
+    }
+  } else {
+    if(!peer->amInterested) {
+      logger->debug("CUID#%d - Interested in the peer", cuid);
+      dispatcher->
+	addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->
+			  createInterestedMessage());
+    }
+  }
+}
+
+void DefaultBtInteractive::fillPiece(int maxPieceNum) {
+  if(pieceStorage->hasMissingPiece(peer)) {
+    if(peer->peerChoking) {
+      dispatcher->doChokedAction();
+      if(peer->isFastExtensionEnabled()) {
+	while(btRequestFactory->countTargetPiece() < maxPieceNum) {
+	  PieceHandle piece = pieceStorage->getMissingFastPiece(peer);
+	  if(piece.isNull()) {
+	    break;
+	  } else {
+	    btRequestFactory->addTargetPiece(piece);
+	  }
+	}
+      }
+    } else {
+      while(btRequestFactory->countTargetPiece() < maxPieceNum) {
+	PieceHandle piece = pieceStorage->getMissingPiece(peer);
+	if(piece.isNull()) {
+	  break;
+	} else {
+	  btRequestFactory->addTargetPiece(piece);
+	}
+      }
+    }
+  }
+}
+
+void DefaultBtInteractive::addRequests() {
+  uint32_t MAX_PENDING_REQUEST;
+  if(peer->getLatency() < 500) {
+    MAX_PENDING_REQUEST = 24;
+  } else if(peer->getLatency() < 1500) {
+    MAX_PENDING_REQUEST = 12;
+  } else {
+    MAX_PENDING_REQUEST = 6;
+  }
+  uint32_t pieceNum;
+  if(pieceStorage->isEndGame()) {
+    pieceNum = 1;
+  } else {
+    uint32_t blocks = DIV_FLOOR(btContext->getPieceLength(), BLOCK_LENGTH);
+    pieceNum = DIV_FLOOR(MAX_PENDING_REQUEST, blocks);
+  }
+  fillPiece(pieceNum);
+
+  uint32_t reqNumToCreate =
+    MAX_PENDING_REQUEST <= dispatcher->countOutstandingRequest() ?
+    0 : MAX_PENDING_REQUEST-dispatcher->countOutstandingRequest();
+  if(reqNumToCreate > 0) {
+    //logger->debug("CUID#%d - %u requets to go.", cuid, reqNumToCreate);
+    BtMessages requests;
+    if(pieceStorage->isEndGame()) {
+      requests = btRequestFactory->createRequestMessagesOnEndGame(reqNumToCreate);
+    } else {
+      requests = btRequestFactory->createRequestMessages(reqNumToCreate);
+    }
+    dispatcher->addMessageToQueue(requests);
+  }
+}
+
+void DefaultBtInteractive::cancelAllPiece() {
+  btRequestFactory->removeAllTargetPiece();
+}
+
+void DefaultBtInteractive::sendPendingMessage() {
+  dispatcher->sendMessages();
+}
+
+void DefaultBtInteractive::detectMessageFlooding() {
+  if(floodingCheckPoint.elapsed(FLOODING_CHECK_INTERVAL)) {
+    if(floodingStat.getChokeUnchokeCount() >= 2 ||
+       floodingStat.getKeepAliveCount() >= 2) {
+      throw new DlAbortEx("Flooding detected.");
+    } else {
+      floodingStat.reset();
+    }
+    floodingCheckPoint.reset();
+  }
+}
+
+void DefaultBtInteractive::doInteractionProcessing() {
+  decideChoking();
+
+  detectMessageFlooding();
+
+  dispatcher->checkRequestSlotAndDoNecessaryThing();
+
+  checkHave();
+
+  sendKeepAlive();
+
+  receiveMessages();
+  
+  btRequestFactory->removeCompletedPiece();
+
+  decideInterest();
+  if(!pieceStorage->downloadFinished()) {
+    addRequests();
+  }
+  sendPendingMessage();
+}

+ 195 - 0
src/DefaultBtInteractive.h

@@ -0,0 +1,195 @@
+/* <!-- 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_DEFAULT_BT_INTERACTIVE_H_
+#define _D_DEFAULT_BT_INTERACTIVE_H_
+
+#include "BtInteractive.h"
+#include "Peer.h"
+#include "BtContext.h"
+#include "PieceStorage.h"
+#include "PeerStorage.h"
+#include "BtMessageReceiver.h"
+#include "BtMessageDispatcher.h"
+#include "BtRequestFactory.h"
+#include "PeerConnection.h"
+#include "BtRegistry.h"
+#include "Logger.h"
+#include "LogFactory.h"
+#include "TimeA2.h"
+
+class FloodingStat {
+private:
+  uint32_t chokeUnchokeCount;
+  uint32_t keepAliveCount;
+public:
+  FloodingStat():chokeUnchokeCount(0), keepAliveCount(0) {}
+  
+  void incChokeUnchokeCount() {
+    if(chokeUnchokeCount < UINT32_MAX) {
+      chokeUnchokeCount++;
+    }
+  }
+
+  void incKeepAliveCount() {
+    if(keepAliveCount < UINT32_MAX) {
+      keepAliveCount++;
+    }
+  }
+
+  uint32_t getChokeUnchokeCount() const {
+    return chokeUnchokeCount;
+  }
+
+  uint32_t getKeepAliveCount() const {
+    return keepAliveCount;
+  }
+
+  void reset() {
+    chokeUnchokeCount = 0;
+    keepAliveCount = 0;
+  }
+};
+
+class DefaultBtInteractive : public BtInteractive {
+private:
+  int32_t cuid;
+  PeerHandle peer;
+  BtContextHandle btContext;
+  PeerStorageHandle peerStorage;
+  PieceStorageHandle pieceStorage;
+  BtMessageReceiverHandle btMessageReceiver;
+  BtMessageDispatcherHandle dispatcher;
+  BtRequestFactoryHandle btRequestFactory;
+  PeerConnectionHandle peerConnection;
+  const Logger* logger;
+  uint32_t allowedFastSetSize;
+  Time haveCheckPoint;
+  Time keepAliveCheckPoint;
+  Time floodingCheckPoint;
+  FloodingStat floodingStat;
+  const Option* option;
+
+  static const uint32_t FLOODING_CHECK_INTERVAL = 5;
+
+  void addBitfieldMessageToQueue();
+  void addAllowedFastMessageToQueue();
+  void decideChoking();
+  void checkHave();
+  void sendKeepAlive();
+  void decideInterest();
+  void fillPiece(int maxPieceNum);
+  void addRequests();
+  void detectMessageFlooding();
+public:
+  DefaultBtInteractive():peer(0),
+			 btContext(0),
+			 peerStorage(0),
+			 pieceStorage(0),
+			 btMessageReceiver(0),
+			 dispatcher(0),
+			 btRequestFactory(0),
+			 peerConnection(0),
+			 logger(LogFactory::getInstance()),
+			 allowedFastSetSize(10)
+  {
+    logger->debug("DefaultBtInteractive instantiated.");
+  }
+
+  virtual ~DefaultBtInteractive() {
+    logger->debug("DefaultBtInteractive deleted.");
+  }
+
+  virtual void initiateHandshake();
+
+  virtual BtMessageHandle receiveHandshake(bool quickReply = false);
+
+  virtual BtMessageHandle receiveAndSendHandshake();
+
+  virtual void doPostHandshakeProcessing();
+
+  virtual void doInteractionProcessing();
+
+  virtual void cancelAllPiece();
+
+  virtual void sendPendingMessage();
+
+  void receiveMessages();
+
+  virtual uint32_t countPendingMessage() {
+    return dispatcher->countMessageInQueue();
+  }
+  
+  virtual bool isSendingMessageInProgress() {
+    return dispatcher->isSendingInProgress();
+  }
+
+  void setCuid(int32_t cuid) {
+    this->cuid = cuid;
+  }
+
+  void setPeer(const PeerHandle& peer) {
+    this->peer = peer;
+  }
+
+  void setBtContext(const BtContextHandle& btContext) {
+    this->btContext = btContext;
+    this->peerStorage = PEER_STORAGE(btContext);
+    this->pieceStorage = PIECE_STORAGE(btContext);
+  }
+
+  void setBtMessageReceiver(const BtMessageReceiverHandle& receiver) {
+    this->btMessageReceiver = receiver;
+  }
+
+  void setDispatcher(const BtMessageDispatcherHandle& dispatcher) {
+    this->dispatcher = dispatcher;
+  }
+
+  void setBtRequestFactory(const BtRequestFactoryHandle& factory) {
+    this->btRequestFactory = factory;
+  }
+
+  void setPeerConnection(const PeerConnectionHandle& peerConnection) {
+    this->peerConnection  = peerConnection;
+  }
+
+  void setOption(const Option* option) {
+    this->option = option;
+  }
+};
+
+typedef SharedHandle<DefaultBtInteractive> DefaultBtInteractiveHandle;
+
+#endif // _D_DEFAULT_BT_INTERACTIVE_H_

+ 214 - 0
src/DefaultBtMessageDispatcher.cc

@@ -0,0 +1,214 @@
+/* <!-- 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 "DefaultBtMessageDispatcher.h"
+#include "BtRegistry.h"
+#include "prefs.h"
+#include "BtAbortOutstandingRequestEvent.h"
+#include "BtCancelSendingPieceEvent.h"
+#include "BtChokedEvent.h"
+#include "BtChokingEvent.h"
+#include "BtRegistry.h"
+#include "BtMessageFactory.h"
+
+void DefaultBtMessageDispatcher::addMessageToQueue(const BtMessageHandle& btMessage)
+{
+  btMessage->onQueued();
+  messageQueue.push_back(btMessage);
+}
+
+void DefaultBtMessageDispatcher::addMessageToQueue(const BtMessages& btMessages)
+{
+  for(BtMessages::const_iterator itr = btMessages.begin(); itr != btMessages.end(); itr++) {
+    addMessageToQueue(*itr);
+  }
+}
+
+
+void DefaultBtMessageDispatcher::sendMessages() {
+  BtMessages tempQueue;
+  int32_t uploadLimit = option->getAsInt(PREF_MAX_UPLOAD_LIMIT);
+  while(messageQueue.size() > 0) {
+    BtMessageHandle msg = messageQueue.front();
+    messageQueue.pop_front();
+    if(uploadLimit > 0) {
+      TransferStat stat = peerStorage->calculateStat();
+      if(uploadLimit < stat.getUploadSpeed() &&
+	 msg->isUploading() && !msg->isSendingInProgress()) {
+	tempQueue.push_back(msg);
+	continue;
+      }
+    }
+    msg->send();
+    if(msg->isSendingInProgress()) {
+      messageQueue.push_front(msg);
+      break;
+    }
+  }
+  copy(tempQueue.begin(), tempQueue.end(), back_inserter(messageQueue));
+}
+
+// Cancel sending piece message to peer.
+void DefaultBtMessageDispatcher::doCancelSendingPieceAction(uint32_t index, uint32_t begin, uint32_t blockLength)
+{
+  BtCancelSendingPieceEventHandle event =
+    new BtCancelSendingPieceEvent(index, begin, blockLength);
+
+  BtMessages tempQueue = messageQueue;
+  for(BtMessages::iterator itr = tempQueue.begin(); itr != tempQueue.end(); itr++) {
+    (*itr)->handleEvent(event);
+  }
+}
+
+// Cancel sending piece message to peer.
+// TODO Is this method really necessary?
+void DefaultBtMessageDispatcher::doCancelSendingPieceAction(const PieceHandle& piece)
+{
+}
+
+// localhost cancels outstanding download requests to the peer.
+void DefaultBtMessageDispatcher::doAbortOutstandingRequestAction(const PieceHandle& piece) {
+  for(RequestSlots::iterator itr = requestSlots.begin();
+      itr != requestSlots.end();) {
+    RequestSlot& slot = *itr;
+    if(slot.getIndex() == piece->getIndex()) {
+      logger->debug("CUID#%d - Deleting request slot index=%d, blockIndex=%d",
+		    cuid,
+		    slot.getIndex(),
+		    slot.getBlockIndex());
+      piece->cancelBlock(slot.getBlockIndex());
+      itr = requestSlots.erase(itr);
+    } else {
+      itr++;
+    }
+  }
+
+  BtAbortOutstandingRequestEventHandle event =
+    new BtAbortOutstandingRequestEvent(piece);
+
+  BtMessages tempQueue = messageQueue;
+  for(BtMessages::iterator itr = tempQueue.begin(); itr != tempQueue.end(); ++itr) {
+    (*itr)->handleEvent(event);
+  }  
+}
+
+// localhost received choke message from the peer.
+void DefaultBtMessageDispatcher::doChokedAction()
+{
+  for(RequestSlots::iterator itr = requestSlots.begin();
+      itr != requestSlots.end();) {
+    RequestSlot& slot = *itr;
+    logger->debug("CUID#%d - Deleting request slot index=%d, blockIndex=%d"
+		  " because localhost got choked.",
+		  cuid,
+		  slot.getIndex(),
+		  slot.getBlockIndex());
+    PieceHandle piece = pieceStorage->getPiece(slot.getIndex());
+    piece->cancelBlock(slot.getBlockIndex());
+    itr = requestSlots.erase(itr);
+  }
+
+  BtChokedEventHandle event = new BtChokedEvent();
+
+  BtMessages tempQueue = messageQueue;
+  for(BtMessages::iterator itr = tempQueue.begin(); itr != tempQueue.end(); ++itr) {
+    (*itr)->handleEvent(event);
+  }
+}
+
+// localhost dispatched choke message to the peer.
+void DefaultBtMessageDispatcher::doChokingAction()
+{
+  BtChokingEventHandle event = new BtChokingEvent();
+
+  BtMessages tempQueue = messageQueue;
+  for(BtMessages::iterator itr = tempQueue.begin(); itr != tempQueue.end(); ++itr) {
+    (*itr)->handleEvent(event);
+  }
+}
+
+void DefaultBtMessageDispatcher::checkRequestSlotAndDoNecessaryThing()
+{
+  for(RequestSlots::iterator itr = requestSlots.begin();
+      itr != requestSlots.end();) {
+    RequestSlot& slot = *itr;
+    PieceHandle piece = pieceStorage->getPiece(slot.getIndex());
+    if(slot.isTimeout(option->getAsInt(PREF_BT_REQUEST_TIMEOUT))) {
+      logger->debug("CUID#%d - Deleting request slot blockIndex=%d"
+		    " because of time out",
+		    cuid,
+		    slot.getBlockIndex());
+      piece->cancelBlock(slot.getBlockIndex());
+      peer->snubbing = true;
+      itr = requestSlots.erase(itr);
+    } else if(piece->hasBlock(slot.getBlockIndex())) {
+      logger->debug("CUID#%d - Deleting request slot blockIndex=%d because"
+		    " the block has been acquired.",
+		    cuid,
+		    slot.getBlockIndex());
+      addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->
+			createCancelMessage(slot.getIndex(),
+					    slot.getBegin(),
+					    slot.getLength()));
+      itr = requestSlots.erase(itr);
+    } else {
+      itr++;
+    }
+  }
+}
+
+bool DefaultBtMessageDispatcher::isSendingInProgress()
+{
+  if(messageQueue.size() > 0) {
+    return messageQueue.front()->isSendingInProgress();
+  } else {
+    return false;
+  }
+}
+
+uint32_t DefaultBtMessageDispatcher::countOutstandingRequest()
+{
+  return requestSlots.size();
+}
+
+bool DefaultBtMessageDispatcher::isOutstandingRequest(uint32_t index, uint32_t blockIndex) {
+  for(RequestSlots::const_iterator itr = requestSlots.begin();
+      itr != requestSlots.end(); itr++) {
+    const RequestSlot& slot = *itr;
+    if(slot.getIndex() == index && slot.getBlockIndex() == blockIndex) {
+      return true;
+    }
+  }
+  return false;
+}

+ 163 - 0
src/DefaultBtMessageDispatcher.h

@@ -0,0 +1,163 @@
+/* <!-- 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_DEFAULT_BT_MESSAGE_DISPATCHER_H_
+#define _D_DEFAULT_BT_MESSAGE_DISPATCHER_H_
+
+#include "BtMessageDispatcher.h"
+#include "BtContext.h"
+#include "PeerStorage.h"
+#include "PieceStorage.h"
+#include "RequestSlot.h"
+#include "BtMessage.h"
+#include "Peer.h"
+#include "Option.h"
+#include "LogFactory.h"
+#include "Logger.h"
+#include "BtRegistry.h"
+
+class DefaultBtMessageDispatcher : public BtMessageDispatcher {
+private:
+  int32_t cuid;
+  BtMessages messageQueue;
+  RequestSlots requestSlots;
+  BtContextHandle btContext;
+  PeerStorageHandle peerStorage;
+  PieceStorageHandle pieceStorage;
+  PeerHandle peer;
+  const Option* option;
+  const Logger* logger;
+public:
+  DefaultBtMessageDispatcher():
+    cuid(0),
+    btContext(0),
+    peerStorage(0),
+    pieceStorage(0),
+    peer(0),
+    option(0),
+    logger(LogFactory::getInstance())
+  {
+    logger->debug("DefaultBtMessageDispatcher::instantiated");
+  }
+
+  virtual ~DefaultBtMessageDispatcher()
+  {
+    logger->debug("DefaultBtMessageDispatcher::deleted");
+  }
+
+  virtual void addMessageToQueue(const BtMessageHandle& btMessage);
+
+  virtual void addMessageToQueue(const BtMessages& btMessages);
+
+  virtual void sendMessages();
+
+  virtual void doCancelSendingPieceAction(uint32_t index, uint32_t begin, uint32_t blockLength);
+
+  virtual void doCancelSendingPieceAction(const PieceHandle& piece);
+
+  virtual void doAbortOutstandingRequestAction(const PieceHandle& piece);
+
+  virtual void doChokedAction();
+
+  virtual void doChokingAction();
+
+  virtual void checkRequestSlotAndDoNecessaryThing();
+
+  virtual bool isSendingInProgress();
+
+  virtual uint32_t countMessageInQueue() {
+    return messageQueue.size();
+  }
+
+  virtual uint32_t countOutstandingRequest();
+
+  virtual bool isOutstandingRequest(uint32_t index, uint32_t blockIndex);
+
+  virtual RequestSlot getOutstandingRequest(uint32_t index, uint32_t begin, uint32_t blockLength) {
+    for(RequestSlots::iterator itr = requestSlots.begin();
+	itr != requestSlots.end(); itr++) {
+      if(itr->getIndex() == index &&
+	 itr->getBegin() == begin &&
+	 itr->getLength() == blockLength) {
+	return *itr;
+      }
+    }
+    return RequestSlot::nullSlot;
+  }
+
+  virtual void removeOutstandingRequest(const RequestSlot& slot) {
+    RequestSlots temp;
+    remove_copy(requestSlots.begin(), requestSlots.end(), back_inserter(temp), slot);
+    requestSlots = temp;
+  }
+
+  virtual void addOutstandingRequest(const RequestSlot& requestSlot) {
+    if(!isOutstandingRequest(requestSlot.getIndex(), requestSlot.getBlockIndex())) {
+      requestSlots.push_back(requestSlot);
+    }
+  }
+
+  BtMessages& getMessageQueue() {
+    return messageQueue;
+  }
+
+  void setOption(const Option* option) {
+    this->option = option;
+  }
+
+  const Option* getOption() const {
+    return option;
+  }
+
+  RequestSlots& getRequestSlots() {
+    return requestSlots;
+  }
+
+  void setPeer(const PeerHandle& peer) {
+    this->peer = peer;
+  }
+
+  void setBtContext(const BtContextHandle& btContext) {
+    this->btContext = btContext;
+    this->pieceStorage = PIECE_STORAGE(btContext);
+    this->peerStorage = PEER_STORAGE(btContext);
+  }
+
+  void setCuid(int32_t cuid) {
+    this->cuid = cuid;
+  }
+};
+
+typedef SharedHandle<DefaultBtMessageDispatcher> DefaultBtMessageDispatcherHandle;
+#endif // _D_DEFAULT_BT_MESSAGE_DISPATCHER_H_

+ 347 - 0
src/DefaultBtMessageFactory.cc

@@ -0,0 +1,347 @@
+/* <!-- 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 "DefaultBtMessageFactory.h"
+#include "DlAbortEx.h"
+#include "PeerMessageUtil.h"
+#include "BtKeepAliveMessage.h"
+#include "BtChokeMessage.h"
+#include "BtUnchokeMessage.h"
+#include "BtInterestedMessage.h"
+#include "BtNotInterestedMessage.h"
+#include "BtHaveMessage.h"
+#include "BtHaveMessageValidator.h"
+#include "BtBitfieldMessage.h"
+#include "BtBitfieldMessageValidator.h"
+#include "BtRequestMessage.h"
+#include "BtRequestMessageValidator.h"
+#include "BtCancelMessage.h"
+#include "BtCancelMessageValidator.h"
+#include "BtPieceMessage.h"
+#include "BtPieceMessageValidator.h"
+#include "BtPortMessage.h"
+#include "BtHaveAllMessage.h"
+#include "BtHaveNoneMessage.h"
+#include "BtRejectMessage.h"
+#include "BtRejectMessageValidator.h"
+#include "BtSuggestPieceMessage.h"
+#include "BtSuggestPieceMessageValidator.h"
+#include "BtAllowedFastMessage.h"
+#include "BtAllowedFastMessageValidator.h"
+#include "BtHandshakeMessage.h"
+#include "BtHandshakeMessageValidator.h"
+
+BtMessageHandle
+DefaultBtMessageFactory::createBtMessage(const unsigned char* data, uint32_t dataLength)
+{
+  AbstractBtMessageHandle msg(0);
+  if(dataLength == 0) {
+    // keep-alive
+    msg = new BtKeepAliveMessage();
+  } else {
+    int32_t id = PeerMessageUtil::getId(data);
+    switch(id) {
+    case BtChokeMessage::ID:
+      msg = BtChokeMessage::create(data, dataLength);
+      break;
+    case BtUnchokeMessage::ID:
+      msg = BtUnchokeMessage::create(data, dataLength);
+      break;
+    case BtInterestedMessage::ID:
+      msg = BtInterestedMessage::create(data, dataLength);
+      break;
+    case BtNotInterestedMessage::ID:
+      msg = BtNotInterestedMessage::create(data, dataLength);
+      break;
+    case BtHaveMessage::ID:
+      msg = BtHaveMessage::create(data, dataLength);
+      msg->setBtMessageValidator(new BtHaveMessageValidator((BtHaveMessage*)msg.get(),
+							    btContext->getNumPieces()));
+      break;
+    case BtBitfieldMessage::ID:
+      msg = BtBitfieldMessage::create(data, dataLength);
+      msg->setBtMessageValidator(new BtBitfieldMessageValidator((BtBitfieldMessage*)msg.get(),
+								btContext->getNumPieces()));
+      break;
+    case BtRequestMessage::ID: {
+      BtRequestMessageHandle temp = BtRequestMessage::create(data, dataLength);
+      BtMessageValidatorHandle validator =
+	new BtRequestMessageValidator(temp.get(),
+				      btContext->getNumPieces(),
+				      pieceStorage->getPieceLength(temp->getIndex()));
+      temp->setBtMessageValidator(validator);
+      msg = temp;
+      break;
+    }
+    case BtCancelMessage::ID: {
+      BtCancelMessageHandle temp = BtCancelMessage::create(data, dataLength);
+      BtMessageValidatorHandle validator =
+	new BtCancelMessageValidator(temp.get(),
+				     btContext->getNumPieces(),
+				     pieceStorage->getPieceLength(temp->getIndex()));
+      temp->setBtMessageValidator(validator);
+      msg = temp;
+      break;
+    }
+    case BtPieceMessage::ID: {
+      BtPieceMessageHandle temp = BtPieceMessage::create(data, dataLength);
+      BtMessageValidatorHandle validator =
+	new BtPieceMessageValidator(temp.get(),
+				    btContext->getNumPieces(),
+				    pieceStorage->getPieceLength(temp->getIndex()));
+      temp->setBtMessageValidator(validator);
+      msg = temp;
+      break;
+    }
+    case BtPortMessage::ID:
+      msg = BtPortMessage::create(data, dataLength);
+      break;
+    case BtHaveAllMessage::ID:
+      msg = BtHaveAllMessage::create(data, dataLength);
+      break;
+    case BtHaveNoneMessage::ID:
+      msg = BtHaveNoneMessage::create(data, dataLength);
+      break;
+    case BtRejectMessage::ID: {
+      BtRejectMessageHandle temp = BtRejectMessage::create(data, dataLength);
+      BtMessageValidatorHandle validator =
+	new BtRejectMessageValidator(temp.get(),
+				     btContext->getNumPieces(),
+				     pieceStorage->getPieceLength(temp->getIndex()));
+      temp->setBtMessageValidator(validator);
+      msg = temp;
+      break;
+    }
+    case BtSuggestPieceMessage::ID: {
+      BtSuggestPieceMessageHandle temp = BtSuggestPieceMessage::create(data, dataLength);
+      BtMessageValidatorHandle validator =
+	new BtSuggestPieceMessageValidator(temp.get(),
+					   btContext->getNumPieces());
+      temp->setBtMessageValidator(validator);
+      msg = temp;
+      break;
+    }
+    case BtAllowedFastMessage::ID: {
+      BtAllowedFastMessageHandle temp = BtAllowedFastMessage::create(data, dataLength);
+      BtMessageValidatorHandle validator =
+	new BtAllowedFastMessageValidator(temp.get(),
+					  btContext->getNumPieces());
+      temp->setBtMessageValidator(validator);
+      msg = temp;
+      break;
+    }
+    default:
+      throw new DlAbortEx("Invalid message id. id = %d", id);
+    }
+  }
+  setCommonProperty(msg);
+  return msg;
+}
+
+void DefaultBtMessageFactory::setCommonProperty(const AbstractBtMessageHandle& msg) {
+  msg->setCuid(cuid);
+  msg->setPeer(peer);
+  msg->setBtContext(btContext);  
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createHandshakeMessage(const unsigned char* data, uint32_t dataLength)
+{
+  BtHandshakeMessageHandle msg = BtHandshakeMessage::create(data, dataLength);
+  BtMessageValidatorHandle validator =
+    new BtHandshakeMessageValidator(msg.get(),
+				    btContext->getInfoHash());
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createHandshakeMessage(const unsigned char* infoHash,
+						const unsigned char* peerId)
+{
+  BtHandshakeMessageHandle msg = new BtHandshakeMessage(infoHash, peerId);
+  BtMessageValidatorHandle validator =
+    new BtHandshakeMessageValidator(msg.get(),
+				    btContext->getInfoHash());
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createRequestMessage(const PieceHandle& piece, uint32_t blockIndex)
+{
+  BtRequestMessageHandle msg =
+    new BtRequestMessage(piece->getIndex(),
+			 blockIndex*piece->getBlockLength(),
+			 piece->getBlockLength(blockIndex),
+			 blockIndex);
+  BtMessageValidatorHandle validator =
+    new BtRequestMessageValidator(msg.get(),
+				  btContext->getNumPieces(),
+				  pieceStorage->getPieceLength(msg->getIndex()));
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createCancelMessage(uint32_t index, uint32_t begin, uint32_t length)
+{
+  BtCancelMessageHandle msg = new BtCancelMessage(index, begin, length);
+  BtMessageValidatorHandle validator =
+    new BtCancelMessageValidator(msg.get(),
+				 btContext->getNumPieces(),
+				 pieceStorage->getPieceLength(index));
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createPieceMessage(uint32_t index, uint32_t begin, uint32_t length)
+{
+  BtPieceMessageHandle msg = new BtPieceMessage(index, begin, length);
+  BtMessageValidatorHandle validator =
+    new BtPieceMessageValidator(msg.get(),
+				btContext->getNumPieces(),
+				pieceStorage->getPieceLength(index));
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createHaveMessage(uint32_t index)
+{
+  BtHaveMessageHandle msg = new BtHaveMessage(index);
+  msg->setBtMessageValidator(new BtHaveMessageValidator(msg.get(),
+							btContext->getNumPieces()));
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createChokeMessage()
+{
+  BtChokeMessageHandle msg = new BtChokeMessage();
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createUnchokeMessage()
+{
+  BtUnchokeMessageHandle msg = new BtUnchokeMessage();
+  setCommonProperty(msg);
+  return msg;
+}
+ 
+BtMessageHandle
+DefaultBtMessageFactory::createInterestedMessage()
+{
+  BtInterestedMessageHandle msg = new BtInterestedMessage();
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createNotInterestedMessage()
+{
+  BtNotInterestedMessageHandle msg = new BtNotInterestedMessage();
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createBitfieldMessage()
+{
+  BtBitfieldMessageHandle msg =
+    new BtBitfieldMessage(pieceStorage->getBitfield(),
+			  pieceStorage->getBitfieldLength());
+  msg->setBtMessageValidator(new BtBitfieldMessageValidator(msg.get(),
+							    btContext->getNumPieces()));
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createKeepAliveMessage()
+{
+  BtKeepAliveMessageHandle msg = new BtKeepAliveMessage();
+  setCommonProperty(msg);
+  return msg;
+} 
+
+BtMessageHandle
+DefaultBtMessageFactory::createHaveAllMessage()
+{
+  BtHaveAllMessageHandle msg = new BtHaveAllMessage();
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createHaveNoneMessage()
+{
+  BtHaveNoneMessageHandle msg = new BtHaveNoneMessage();
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createRejectMessage(uint32_t index, uint32_t begin, uint32_t length)
+{
+  BtRejectMessageHandle msg = new BtRejectMessage(index, begin, length);
+  BtMessageValidatorHandle validator =
+    new BtRejectMessageValidator(msg.get(),
+				 btContext->getNumPieces(),
+				 pieceStorage->getPieceLength(index));
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}
+
+BtMessageHandle
+DefaultBtMessageFactory::createAllowedFastMessage(uint32_t index)
+{
+  BtAllowedFastMessageHandle msg = new BtAllowedFastMessage(index);
+  BtMessageValidatorHandle validator =
+    new BtAllowedFastMessageValidator(msg.get(),
+				      btContext->getNumPieces());
+  msg->setBtMessageValidator(validator);
+  setCommonProperty(msg);
+  return msg;
+}

+ 131 - 0
src/DefaultBtMessageFactory.h

@@ -0,0 +1,131 @@
+/* <!-- 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_DEFAULT_BT_MESSAGE_FACTORY_H_
+#define _D_DEFAULT_BT_MESSAGE_FACTORY_H_
+
+#include "BtMessageFactory.h"
+#include "Peer.h"
+#include "AbstractBtMessage.h"
+#include "BtRegistry.h"
+
+class DefaultBtMessageFactory : public BtMessageFactory {
+private:
+  int32_t cuid;
+  BtContextHandle btContext;
+  PieceStorageHandle pieceStorage;
+  PeerHandle peer;
+
+  void setCommonProperty(const AbstractBtMessageHandle& msg);
+public:
+  DefaultBtMessageFactory():cuid(0),
+			    btContext(0),
+			    pieceStorage(0),
+			    peer(0)
+  {
+    LogFactory::getInstance()->debug("DefaultBtMessageFactory::instantiated");
+  }
+
+  virtual ~DefaultBtMessageFactory()
+  {
+    LogFactory::getInstance()->debug("DefaultBtMessageFactory::deleted");
+  }
+
+  virtual BtMessageHandle
+  createBtMessage(const unsigned char* msg, uint32_t msgLength);
+
+  virtual BtMessageHandle
+  createHandshakeMessage(const unsigned char* msg, uint32_t msgLength);
+
+  virtual BtMessageHandle
+  createHandshakeMessage(const unsigned char* infoHash,
+			 const unsigned char* peerId);
+
+  virtual BtMessageHandle
+  createRequestMessage(const PieceHandle& piece, uint32_t blockIndex);
+
+  virtual BtMessageHandle
+  createCancelMessage(uint32_t index, uint32_t begin, uint32_t length);
+
+  virtual BtMessageHandle
+  createPieceMessage(uint32_t index, uint32_t begin, uint32_t length);
+
+  virtual BtMessageHandle createHaveMessage(uint32_t index);
+
+  virtual BtMessageHandle createChokeMessage();
+
+  virtual BtMessageHandle createUnchokeMessage();
+  
+  virtual BtMessageHandle createInterestedMessage();
+
+  virtual BtMessageHandle createNotInterestedMessage();
+
+  virtual BtMessageHandle createBitfieldMessage();
+
+  virtual BtMessageHandle createKeepAliveMessage();
+  
+  virtual BtMessageHandle createHaveAllMessage();
+
+  virtual BtMessageHandle createHaveNoneMessage();
+
+  virtual BtMessageHandle
+  createRejectMessage(uint32_t index, uint32_t begin, uint32_t length);
+
+  virtual BtMessageHandle createAllowedFastMessage(uint32_t index);
+
+  void setPeer(const PeerHandle& peer) {
+    this->peer = peer;
+  }
+
+  PeerHandle getPeer() const {
+    return peer;
+  }
+
+  void setBtContext(const BtContextHandle& btContext) {
+    this->btContext = btContext;
+    this->pieceStorage = PIECE_STORAGE(btContext);
+  }
+
+  BtContextHandle getBtContext() const {
+    return btContext;
+  }
+
+  void setCuid(int32_t cuid) {
+    this->cuid = cuid;
+  }
+};
+
+typedef SharedHandle<DefaultBtMessageFactory> DefaultBtMessageFactoryHandle;
+
+#endif // _D_DEFAULT_BT_MESSAGE_FACTORY_H_

+ 95 - 0
src/DefaultBtMessageReceiver.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 "DefaultBtMessageReceiver.h"
+#include "BtHandshakeMessage.h"
+
+BtMessageHandle DefaultBtMessageReceiver::receiveHandshake(bool quickReply) {
+  unsigned char data[BtHandshakeMessage::MESSAGE_LENGTH];
+  uint32_t dataLength = sizeof(data);
+  bool retval = peerConnection->receiveHandshake(data, dataLength);
+  // To handle tracker's NAT-checking feature
+  if(!handshakeSent && quickReply && dataLength >= 48) {
+    handshakeSent = true;
+    // check info_hash
+    if(memcmp(btContext->getInfoHash(), &data[28], INFO_HASH_LENGTH) == 0) {
+      sendHandshake();
+    }
+  }
+  if(!retval) {
+    return 0;
+  }
+  BtHandshakeMessageHandle msg =
+    BT_MESSAGE_FACTORY(btContext, peer)->createHandshakeMessage(data, dataLength);
+  Errors errors;
+  if(msg->validate(errors)) {
+    if(msg->isFastExtensionSupported()) {
+      peer->setFastExtensionEnabled(true);
+      logger->info("CUID#%d - Fast extension enabled.", cuid);
+    }
+  } else {
+    // TODO throw exception here based on errors
+  }
+  return msg;
+}
+
+BtMessageHandle DefaultBtMessageReceiver::receiveAndSendHandshake() {
+  return receiveHandshake(true);
+}
+
+void DefaultBtMessageReceiver::sendHandshake() {
+  BtHandshakeMessageHandle msg =
+    BT_MESSAGE_FACTORY(btContext, peer)->createHandshakeMessage(btContext->getInfoHash(),
+								 btContext->getPeerId());
+  dispatcher->addMessageToQueue(msg);
+  dispatcher->sendMessages();
+}
+
+BtMessageHandle DefaultBtMessageReceiver::receiveMessage() {
+  unsigned char data[MAX_PAYLOAD_LEN];
+  uint32_t dataLength = 0;
+  if(!peerConnection->receiveMessage(data, dataLength)) {
+    return 0;
+  }
+  BtMessageHandle msg =
+    BT_MESSAGE_FACTORY(btContext, peer)->createBtMessage(data, dataLength);
+  Errors errors;
+  if(msg->validate(errors)) {
+    return msg;
+  } else {
+    // TODO throw exception here based on errors;
+    return 0;
+  }
+}
+

+ 120 - 0
src/DefaultBtMessageReceiver.h

@@ -0,0 +1,120 @@
+/* <!-- 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_DEFAULT_BT_MESSAGE_RECEIVER_H_
+#define _D_DEFAULT_BT_MESSAGE_RECEIVER_H_
+
+#include "BtMessageReceiver.h"
+#include "BtContext.h"
+#include "BtRegistry.h"
+#include "Peer.h"
+#include "PeerConnection.h"
+#include "BtMessageDispatcher.h"
+#include "Logger.h"
+#include "LogFactory.h"
+
+class DefaultBtMessageReceiver : public BtMessageReceiver {
+private:
+  int32_t cuid;
+  bool handshakeSent;
+  BtContextHandle btContext;
+  PeerHandle peer;
+  PeerConnectionHandle peerConnection;
+  BtMessageDispatcherHandle dispatcher;
+  const Logger* logger;
+
+  void sendHandshake();
+public:
+  DefaultBtMessageReceiver():cuid(0),
+			     handshakeSent(false),
+			     btContext(0),
+			     peer(0),
+			     peerConnection(0),
+			     dispatcher(0),
+			     logger(LogFactory::getInstance())
+  {
+    logger->debug("DefaultBtMessageReceiver::instantiated");
+  }
+
+  virtual ~DefaultBtMessageReceiver()
+  {
+    logger->debug("DefaultBtMessageReceiver::deleted");
+  }
+
+  virtual BtMessageHandle receiveHandshake(bool quickReply = false);
+
+  virtual BtMessageHandle receiveAndSendHandshake();
+
+  virtual BtMessageHandle receiveMessage();
+
+  void setCuid(int32_t cuid) {
+    this->cuid = cuid;
+  }
+
+  int32_t getCuid() const {
+    return cuid;
+  }
+
+  void setPeerConnection(const PeerConnectionHandle& peerConnection) {
+    this->peerConnection = peerConnection;
+  }
+
+  PeerConnectionHandle getPeerConnection() const {
+    return peerConnection;
+  }
+
+  void setBtContext(const BtContextHandle& btContext) {
+    this->btContext = btContext;
+  }
+
+  BtContextHandle getBtContext() const {
+    return btContext;
+  }
+
+  void setPeer(const PeerHandle& peer) {
+    this->peer = peer;
+  }
+
+  PeerHandle getPeer() const {
+    return peer;
+  }
+
+  void setDispatcher(const BtMessageDispatcherHandle& dispatcher) {
+    this->dispatcher = dispatcher;
+  }
+};
+
+typedef SharedHandle<DefaultBtMessageReceiver> DefaultBtMessageReceiverHandle;
+
+#endif // _D_DEFAULT_BT_MESSAGE_RECEIVER_H_

+ 99 - 0
src/DefaultBtRequestFactory.cc

@@ -0,0 +1,99 @@
+/* <!-- 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 "DefaultBtRequestFactory.h"
+
+void DefaultBtRequestFactory::removeCompletedPiece() {
+  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end();) {
+    PieceHandle& piece = *itr;
+    if(piece->pieceComplete()) {
+      dispatcher->doAbortOutstandingRequestAction(piece);
+      itr = pieces.erase(itr);
+    } else {
+      itr++;
+    }
+  }
+}
+
+void DefaultBtRequestFactory::removeTargetPiece(const PieceHandle& piece) {
+  Pieces temp;
+  remove_copy(pieces.begin(), pieces.end(), back_inserter(temp), piece);
+  pieces = temp;
+  dispatcher->doAbortOutstandingRequestAction(piece);
+  pieceStorage->cancelPiece(piece);
+}
+
+void DefaultBtRequestFactory::removeAllTargetPiece() {
+  for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
+    dispatcher->doAbortOutstandingRequestAction(*itr);
+    pieceStorage->cancelPiece(*itr);
+  }
+  pieces.clear();
+}
+
+BtMessages DefaultBtRequestFactory::createRequestMessages(int max) {
+  BtMessages requests;
+  for(Pieces::iterator itr = pieces.begin();
+      itr != pieces.end() && requests.size() < (size_t)max; itr++) {
+    PieceHandle& piece = *itr;
+    int blockIndex;
+    while(requests.size() < (size_t)max &&
+	  (blockIndex = piece->getMissingUnusedBlockIndex()) != -1) {
+      requests.push_back(BT_MESSAGE_FACTORY(btContext, peer)->
+			 createRequestMessage(piece, blockIndex));
+    }
+  }
+  return requests;
+}
+
+BtMessages DefaultBtRequestFactory::createRequestMessagesOnEndGame(int max) {
+  BtMessages requests;
+  for(Pieces::iterator itr = pieces.begin();
+      itr != pieces.end() && requests.size() < (size_t)max; itr++) {
+    PieceHandle& piece = *itr;
+    BlockIndexes missingBlockIndexes = piece->getAllMissingBlockIndexes();
+    random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end());
+    for(BlockIndexes::const_iterator bitr = missingBlockIndexes.begin();
+	bitr != missingBlockIndexes.end() && requests.size() < (size_t)max;
+	bitr++) {
+      int blockIndex = *bitr;
+      if(!dispatcher->isOutstandingRequest(piece->getIndex(),
+					   blockIndex)) {
+	requests.push_back(BT_MESSAGE_FACTORY(btContext, peer)->
+			   createRequestMessage(piece, blockIndex));
+      }
+    }
+  }
+  return requests;
+}

+ 125 - 0
src/DefaultBtRequestFactory.h

@@ -0,0 +1,125 @@
+/* <!-- 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_DEFAULT_BT_REQUEST_FACTORY_H_
+#define _D_DEFAULT_BT_REQUEST_FACTORY_H_
+
+#include "BtRequestFactory.h"
+#include "BtContext.h"
+#include "PieceStorage.h"
+#include "Piece.h"
+#include "Peer.h"
+#include "BtMessageDispatcher.h"
+#include "BtRegistry.h"
+#include "LogFactory.h"
+
+class DefaultBtRequestFactory : public BtRequestFactory {
+private:
+  int cuid;
+  BtContextHandle btContext;
+  PieceStorageHandle pieceStorage;
+  PeerHandle peer;
+  BtMessageDispatcherHandle dispatcher;
+  Pieces pieces;
+public:
+  DefaultBtRequestFactory():
+    cuid(0),
+    btContext(0),
+    pieceStorage(0),
+    peer(0),
+    dispatcher(0)
+  {
+    LogFactory::getInstance()->debug("DefaultBtRequestFactory::instantiated");
+  }
+
+  virtual ~DefaultBtRequestFactory()
+  {
+    LogFactory::getInstance()->debug("DefaultBtRequestFactory::deleted");
+  }
+
+  virtual void addTargetPiece(const PieceHandle& piece) {
+    pieces.push_back(piece);
+  }
+
+  virtual void removeTargetPiece(const PieceHandle& piece);
+
+  virtual void removeAllTargetPiece();
+
+  virtual int countTargetPiece() {
+    return pieces.size();
+  }
+
+  virtual void removeCompletedPiece();
+
+  virtual BtMessages createRequestMessages(int max);
+
+  virtual BtMessages createRequestMessagesOnEndGame(int max);
+
+  Pieces& getTargetPieces() {
+    return pieces;
+  }
+
+  void setCuid(int32_t cuid) {
+    this->cuid = cuid;
+  }
+
+  int32_t getCuid() const {
+    return cuid;
+  }
+
+  void setBtContext(const BtContextHandle& btContext) {
+    this->btContext = btContext;
+    this->pieceStorage = PIECE_STORAGE(btContext);
+  }
+
+  BtContextHandle getBtContext() const {
+    return btContext;
+  }
+
+  PeerHandle getPeer() const {
+    return peer;
+  }
+
+  void setPeer(const PeerHandle& peer) {
+    this->peer = peer;
+  }
+
+  void setBtMessageDispatcher(const BtMessageDispatcherHandle& dispatcher) {
+    this->dispatcher = dispatcher;
+  }
+};
+
+typedef SharedHandle<DefaultBtRequestFactory> DefaultBtRequestFactoryHandle;
+
+#endif // _D_DEFAULT_BT_REQUEST_FACTORY_H_

+ 3 - 8
src/DefaultPeerStorage.cc

@@ -36,14 +36,11 @@
 #include "LogFactory.h"
 #include "BtRegistry.h"
 
-extern PeerHandle nullPeer;
-
 DefaultPeerStorage::DefaultPeerStorage(BtContextHandle btContext,
 				       const Option* option):
   btContext(btContext),
   option(option),
   maxPeerListSize(MAX_PEER_LIST_SIZE),
-  peerEntryIdCounter(0),
   btRuntime(BT_RUNTIME(btContext)),
   removedPeerSessionDownloadLength(0),
   removedPeerSessionUploadLength(0)
@@ -59,8 +56,6 @@ bool DefaultPeerStorage::addPeer(const PeerHandle& peer) {
     if(peers.size() >= (size_t)maxPeerListSize) {
       deleteUnusedPeer(peers.size()-maxPeerListSize+1);
     }
-    ++peerEntryIdCounter;
-    peer->entryId = peerEntryIdCounter;
     peers.push_back(peer);
     return true;
   } else {
@@ -100,7 +95,7 @@ PeerHandle DefaultPeerStorage::getUnusedPeer() {
   Peers::const_iterator itr = find_if(peers.begin(), peers.end(),
 				      FindFinePeer());
   if(itr == peers.end()) {
-    return nullPeer;
+    return 0;
   } else {
     return *itr;
   }
@@ -123,7 +118,7 @@ PeerHandle DefaultPeerStorage::getPeer(const string& ipaddr,
   Peers::const_iterator itr = find_if(peers.begin(), peers.end(),
 				      FindPeer(ipaddr, port));
   if(itr == peers.end()) {
-    return nullPeer;
+    return 0;
   } else {
     return *itr;
   }
@@ -134,7 +129,7 @@ int DefaultPeerStorage::countPeer() const {
 }
 
 bool DefaultPeerStorage::isPeerAvailable() {
-  return getUnusedPeer() != nullPeer;
+  return !getUnusedPeer().isNull();
 }
 
 Peers DefaultPeerStorage::getActivePeers() {

+ 0 - 1
src/DefaultPeerStorage.h

@@ -50,7 +50,6 @@ private:
   const Option* option;
   Peers peers;
   int maxPeerListSize;
-  int peerEntryIdCounter;
   Logger* logger;
   BtRuntimeHandle btRuntime;
   long long int removedPeerSessionDownloadLength;

+ 52 - 62
src/DefaultPieceStorage.cc

@@ -42,6 +42,7 @@
 #include "MultiDiskWriter.h"
 #include "PreAllocationDiskWriter.h"
 #include "DlAbortEx.h"
+#include "BitfieldManFactory.h"
 
 DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option):
   btContext(btContext),
@@ -49,13 +50,16 @@ DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option
   endGamePieceNum(END_GAME_PIECE_NUM),
   option(option)
 {
-  bitfieldMan = new BitfieldMan(btContext->getPieceLength(),
-				btContext->getTotalLength());
+  bitfieldMan =
+    BitfieldManFactory::getNewFactory()->
+    createBitfieldMan(btContext->getPieceLength(),
+		      btContext->getTotalLength());
   logger = LogFactory::getInstance();
 }
 
 DefaultPieceStorage::~DefaultPieceStorage() {
   delete bitfieldMan;
+  delete diskAdaptor;
 }
 
 bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) {
@@ -79,15 +83,15 @@ int DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
   return index;
 }
 
-Piece DefaultPieceStorage::checkOutPiece(int index) {
+PieceHandle DefaultPieceStorage::checkOutPiece(int index) {
   if(index == -1) {
-    return Piece::nullPiece;
+    return 0;
   }
   bitfieldMan->setUseBit(index);
 
-  Piece piece = findUsedPiece(index);
-  if(Piece::isNull(piece)) {
-    Piece piece(index, bitfieldMan->getBlockLength(index));
+  PieceHandle piece = findUsedPiece(index);
+  if(piece.isNull()) {
+    piece = new Piece(index, bitfieldMan->getBlockLength(index));
     addUsedPiece(piece);
     return piece;
   } else {
@@ -95,8 +99,26 @@ Piece DefaultPieceStorage::checkOutPiece(int index) {
   }
 }
 
-void DefaultPieceStorage::addUsedPiece(const Piece& piece) {
-  // TODO ? if nullPiece
+/**
+ * Newly instantiated piece is not added to usedPieces.
+ * Because it is waste of memory and there is no chance to use them later.
+ */
+PieceHandle DefaultPieceStorage::getPiece(int index) {
+  if(0 <= index && index <= bitfieldMan->getMaxIndex()) {
+    PieceHandle piece = findUsedPiece(index);
+    if(piece.isNull()) {
+      piece = new Piece(index, bitfieldMan->getBlockLength(index));
+      if(hasPiece(index)) {
+	piece->setAllBlock();
+      }
+    }
+    return piece;
+  } else {
+    return 0;
+  }
+}
+
+void DefaultPieceStorage::addUsedPiece(const PieceHandle& piece) {
   usedPieces.push_back(piece);
 }
 
@@ -106,23 +128,23 @@ private:
 public:
   FindPiece(int index):index(index) {}
 
-  bool operator()(const Piece& piece) {
-    return piece.getIndex() == index;
+  bool operator()(const PieceHandle& piece) {
+    return piece->getIndex() == index;
   }
 };
 
-Piece DefaultPieceStorage::findUsedPiece(int index) const {
+PieceHandle DefaultPieceStorage::findUsedPiece(int index) const {
   Pieces::const_iterator itr = find_if(usedPieces.begin(),
 				       usedPieces.end(),
 				       FindPiece(index));
   if(itr == usedPieces.end()) {
-    return Piece::nullPiece;
+    return 0;
   } else {
     return *itr;
   }
 }
 
-Piece DefaultPieceStorage::getMissingPiece(const PeerHandle& peer) {
+PieceHandle DefaultPieceStorage::getMissingPiece(const PeerHandle& peer) {
   int index = getMissingPieceIndex(peer);
   return checkOutPiece(index);
 }
@@ -149,13 +171,13 @@ int DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
   return index;
 }
 
-Piece DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) {
+PieceHandle DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) {
   int index = getMissingFastPieceIndex(peer);
   return checkOutPiece(index);
 }
 
-void DefaultPieceStorage::deleteUsedPiece(const Piece& piece) {
-  if(Piece::isNull(piece)) {
+void DefaultPieceStorage::deleteUsedPiece(const PieceHandle& piece) {
+  if(piece.isNull()) {
     return;
   }
   Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(), piece);
@@ -185,12 +207,12 @@ int DefaultPieceStorage::deleteUsedPiecesByFillRate(int fillRate,
   int deleted = 0;
   for(Pieces::iterator itr = usedPieces.begin();
       itr != usedPieces.end() && deleted < toDelete;) {
-    Piece& piece = *itr;
-    if(!bitfieldMan->isUseBitSet(piece.getIndex()) &&
-       piece.countCompleteBlock() <= piece.countBlock()*(fillRate/100.0)) {
+    PieceHandle& piece = *itr;
+    if(!bitfieldMan->isUseBitSet(piece->getIndex()) &&
+       piece->countCompleteBlock() <= piece->countBlock()*(fillRate/100.0)) {
       logger->debug("Deleting used piece index=%d, fillRate(%%)=%d<=%d",
-		    piece.getIndex(),
-		    (piece.countCompleteBlock()*100)/piece.countBlock(),
+		    piece->getIndex(),
+		    (piece->countCompleteBlock()*100)/piece->countBlock(),
 		    fillRate);
       itr = usedPieces.erase(itr);
       deleted++;
@@ -201,8 +223,8 @@ int DefaultPieceStorage::deleteUsedPiecesByFillRate(int fillRate,
   return deleted;
 }
 
-void DefaultPieceStorage::completePiece(const Piece& piece) {
-  if(Piece::isNull(piece)) {
+void DefaultPieceStorage::completePiece(const PieceHandle& piece) {
+  if(piece.isNull()) {
     return;
   }
   deleteUsedPiece(piece);
@@ -212,8 +234,8 @@ void DefaultPieceStorage::completePiece(const Piece& piece) {
   if(downloadFinished()) {
     return;
   }
-  bitfieldMan->setBit(piece.getIndex());
-  bitfieldMan->unsetUseBit(piece.getIndex());
+  bitfieldMan->setBit(piece->getIndex());
+  bitfieldMan->unsetUseBit(piece->getIndex());
   if(downloadFinished()) {
     diskAdaptor->onDownloadComplete();
     if(isSelectiveDownloadingMode()) {
@@ -235,50 +257,18 @@ void DefaultPieceStorage::finishSelectiveDownloadingMode() {
 }
 
 // not unittested
-void DefaultPieceStorage::cancelPiece(const Piece& piece) {
-  if(Piece::isNull(piece)) {
+void DefaultPieceStorage::cancelPiece(const PieceHandle& piece) {
+  if(piece.isNull()) {
     return;
   }
-  updatePiece(piece);
-  bitfieldMan->unsetUseBit(piece.getIndex());
+  bitfieldMan->unsetUseBit(piece->getIndex());
   if(!isEndGame()) {
-    if(piece.countCompleteBlock() == 0) {
+    if(piece->countCompleteBlock() == 0) {
       deleteUsedPiece(piece);
     }
   }
 }
 
-// not unittested
-void DefaultPieceStorage::updatePiece(const Piece& piece) {
-  if(Piece::isNull(piece)) {
-    return;
-  }
-  Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
-			      piece);
-  if(itr != usedPieces.end()) {
-    *itr = piece;
-  }
-}
-
-// not unittested
-void DefaultPieceStorage::syncPiece(Piece& piece) {
-  if(Piece::isNull(piece)) {
-    return;
-  }
-  Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
-			      piece);
-  if(itr != usedPieces.end()) {
-    piece = *itr;
-    return;
-  } else {
-    // hasPiece(piece.getIndex()) is true, then set all bit of
-    // piece.bitfield to 1
-    if(hasPiece(piece.getIndex())) {
-      piece.setAllBlock();
-    }
-  }
-}
-
 bool DefaultPieceStorage::hasPiece(int index) {
   return bitfieldMan->isBitSet(index);
 }

+ 12 - 11
src/DefaultPieceStorage.h

@@ -77,29 +77,26 @@ private:
 
   int getMissingPieceIndex(const PeerHandle& peer);
   int getMissingFastPieceIndex(const PeerHandle& peer);
-  Piece checkOutPiece(int index);
-  void addUsedPiece(const Piece& piece);
-  Piece findUsedPiece(int index) const;
+  PieceHandle checkOutPiece(int index);
   int deleteUsedPiecesByFillRate(int fillRate, int toDelete);
   void reduceUsedPieces(int delMax);
-  void deleteUsedPiece(const Piece& piece);
+  void deleteUsedPiece(const PieceHandle& piece);
+  PieceHandle findUsedPiece(int index) const;
 public:
   DefaultPieceStorage(BtContextHandle btContext, const Option* option);
   virtual ~DefaultPieceStorage();
 
   virtual bool hasMissingPiece(const PeerHandle& peer);
 
-  virtual Piece getMissingPiece(const PeerHandle& peer);
+  virtual PieceHandle getMissingPiece(const PeerHandle& peer);
 
-  virtual Piece getMissingFastPiece(const PeerHandle& peer);
+  virtual PieceHandle getMissingFastPiece(const PeerHandle& peer);
 
-  virtual void completePiece(const Piece& piece);
+  virtual PieceHandle getPiece(int index);
 
-  virtual void cancelPiece(const Piece& piece);
+  virtual void completePiece(const PieceHandle& piece);
 
-  virtual void updatePiece(const Piece& piece);
-
-  virtual void syncPiece(Piece& piece);
+  virtual void cancelPiece(const PieceHandle& piece);
 
   virtual bool hasPiece(int index);
 
@@ -153,6 +150,10 @@ public:
 
   virtual void removeAdvertisedPiece(int elapsed);
 
+  /**
+   * This method is made private for test purpose only.
+   */
+  void addUsedPiece(const PieceHandle& piece);
 };
 
 #endif // _D_DEFAULT_PIECE_STORAGE_H_

+ 18 - 0
src/DownloadEngineFactory.cc

@@ -107,6 +107,24 @@ DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
   BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(),
 					 btProgressInfoFile);
 
+  BtRegistry::registerPeerObjectCluster(btContext->getInfoHashAsString(),
+					new PeerObjectCluster());
+
+  /*
+  DefaultBtMessageFactoryAdaptorHandle factoryAdaptor =
+    new DefaultBtMessageFactoryAdaptor();
+  BtRegistry::registerBtMessageFactoryAdaptor(btContext->getInfoHashAsString(),
+					      factoryAdaptor);
+
+  BtMessageFactoryClusterHandle factoryCluster = new BtMessageFactoryCluster();
+  BtRegistry::registerBtMessageFactoryCluster(btContext->getInfoHashAsString(),
+					      factoryCluster);
+
+  BtMessageDispatcherClusterHandle dispatcherCluster =
+    new BtMessageDispatcherCluster();
+  BtRegistry::registerBtMessageDispatcherCluster(btContext->getInfoHashAsString(),
+						 dispatcherCluster);
+  */
   te->setBtContext(btContext);
   // initialize file storage
   pieceStorage->initStorage();

+ 73 - 0
src/HandleRegistry.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_HANDLE_REGISTRY_H_
+#define _D_HANDLE_REGISTRY_H_
+
+#include "SharedHandle.h"
+#include <map>
+
+using namespace std;
+
+template<typename K, typename T>
+class HandleRegistry {
+  typedef map<K, SharedHandle<T> > HandleMap;
+private:
+  HandleMap handleMap;
+public:
+  void registerHandle(const K& key, const SharedHandle<T>& obj) {
+    unregisterHandle(key);
+    typename HandleMap::value_type p(key, obj);
+    handleMap.insert(p);
+  }
+
+  void unregisterHandle(const K& key) {
+    handleMap.erase(key);
+  }
+
+  SharedHandle<T> getHandle(const K& key) {
+    typename HandleMap::const_iterator itr = handleMap.find(key);
+    if(itr == handleMap.end()) {
+      return 0;
+    } else {
+      return itr->second;
+    }
+  }
+
+  void clear() {
+    handleMap.clear();
+  }
+};
+
+#endif // _D_HANDLE_REGISTRY_H_

+ 54 - 2
src/Makefile.am

@@ -49,13 +49,18 @@ SRCS =  Socket.h\
 	NullLogger.h\
 	TimeA2.cc TimeA2.h\
 	SharedHandle.h\
+	HandleRegistry.h\
 	FeatureConfig.cc FeatureConfig.h\
 	DownloadEngineFactory.cc DownloadEngineFactory.h\
 	RequestInfo.h\
 	UrlRequestInfo.cc UrlRequestInfo.h\
 	SpeedCalc.cc SpeedCalc.h\
 	PeerStat.h\
-	BitfieldMan.cc BitfieldMan.h
+	BitfieldMan.cc BitfieldMan.h\
+	BitfieldManFactory.cc BitfieldManFactory.h\
+	Randomizer.h\
+	SimpleRandomizer.cc SimpleRandomizer.h
+#	debug_new.cpp
 
 if ENABLE_ASYNC_DNS
 SRCS += NameResolver.cc NameResolver.h
@@ -138,7 +143,54 @@ SRCS += MetaEntry.h\
 	BtRuntime.h\
 	BtProgressInfoFile.h\
 	DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
-	BtContextAwareCommand.cc BtContextAwareCommand.h
+	BtContextAwareCommand.cc BtContextAwareCommand.h\
+	BtMessage.h\
+	AbstractBtMessage.h\
+	SimpleBtMessage.cc SimpleBtMessage.h\
+	BtAllowedFastMessage.cc BtAllowedFastMessage.h\
+	BtBitfieldMessage.cc BtBitfieldMessage.h\
+	BtCancelMessage.cc BtCancelMessage.h\
+	BtChokeMessage.cc BtChokeMessage.h\
+	BtHaveAllMessage.cc BtHaveAllMessage.h\
+	BtHaveMessage.cc BtHaveMessage.h\
+	BtHaveNoneMessage.cc BtHaveNoneMessage.h\
+	BtInterestedMessage.cc BtInterestedMessage.h\
+	BtKeepAliveMessage.cc BtKeepAliveMessage.h\
+	BtNotInterestedMessage.cc BtNotInterestedMessage.h\
+	BtPieceMessage.cc BtPieceMessage.h\
+	BtPortMessage.cc BtPortMessage.h\
+	BtRejectMessage.cc BtRejectMessage.h\
+	BtRequestMessage.cc BtRequestMessage.h\
+	BtSuggestPieceMessage.cc BtSuggestPieceMessage.h\
+	BtUnchokeMessage.cc BtUnchokeMessage.h\
+	BtHandshakeMessage.cc BtHandshakeMessage.h\
+	BtMessageValidator.h\
+	BtAllowedFastMessageValidator.h\
+	BtBitfieldMessageValidator.h\
+	BtCancelMessageValidator.h\
+	BtHaveMessageValidator.h\
+	BtPieceMessageValidator.h\
+	BtRejectMessageValidator.h\
+	BtRequestMessageValidator.h\
+	BtSuggestPieceMessageValidator.h\
+	BtHandshakeMessageValidator.h\
+	BtMessageFactory.h\
+	DefaultBtMessageFactory.cc DefaultBtMessageFactory.h\
+	BtMessageDispatcher.h\
+	DefaultBtMessageDispatcher.cc DefaultBtMessageDispatcher.h\
+	BtMessageReceiver.h\
+	DefaultBtMessageReceiver.cc DefaultBtMessageReceiver.h\
+	BtRequestFactory.h\
+	DefaultBtRequestFactory.cc DefaultBtRequestFactory.h\
+	BtEvent.h\
+	BtEventListener.h\
+	BtCancelSendingPieceEvent.h\
+	BtAbortOutstandingRequestEvent.h\
+	BtChokedEvent.h\
+	BtChokingEvent.h\
+	BtInteractive.h\
+	DefaultBtInteractive.cc DefaultBtInteractive.h\
+	PeerObject.h
 endif # ENABLE_BITTORRENT
 
 if ENABLE_METALINK

+ 165 - 20
src/Makefile.in

@@ -115,7 +115,54 @@ bin_PROGRAMS = aria2c$(EXEEXT)
 @ENABLE_BITTORRENT_TRUE@	BtRuntime.h\
 @ENABLE_BITTORRENT_TRUE@	BtProgressInfoFile.h\
 @ENABLE_BITTORRENT_TRUE@	DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
-@ENABLE_BITTORRENT_TRUE@	BtContextAwareCommand.cc BtContextAwareCommand.h
+@ENABLE_BITTORRENT_TRUE@	BtContextAwareCommand.cc BtContextAwareCommand.h\
+@ENABLE_BITTORRENT_TRUE@	BtMessage.h\
+@ENABLE_BITTORRENT_TRUE@	AbstractBtMessage.h\
+@ENABLE_BITTORRENT_TRUE@	SimpleBtMessage.cc SimpleBtMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtAllowedFastMessage.cc BtAllowedFastMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtBitfieldMessage.cc BtBitfieldMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtCancelMessage.cc BtCancelMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtChokeMessage.cc BtChokeMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtHaveAllMessage.cc BtHaveAllMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtHaveMessage.cc BtHaveMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtHaveNoneMessage.cc BtHaveNoneMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtInterestedMessage.cc BtInterestedMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtKeepAliveMessage.cc BtKeepAliveMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtNotInterestedMessage.cc BtNotInterestedMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtPieceMessage.cc BtPieceMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtPortMessage.cc BtPortMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtRejectMessage.cc BtRejectMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtRequestMessage.cc BtRequestMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtSuggestPieceMessage.cc BtSuggestPieceMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtUnchokeMessage.cc BtUnchokeMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtHandshakeMessage.cc BtHandshakeMessage.h\
+@ENABLE_BITTORRENT_TRUE@	BtMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtAllowedFastMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtBitfieldMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtCancelMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtHaveMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtPieceMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtRejectMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtRequestMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtSuggestPieceMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtHandshakeMessageValidator.h\
+@ENABLE_BITTORRENT_TRUE@	BtMessageFactory.h\
+@ENABLE_BITTORRENT_TRUE@	DefaultBtMessageFactory.cc DefaultBtMessageFactory.h\
+@ENABLE_BITTORRENT_TRUE@	BtMessageDispatcher.h\
+@ENABLE_BITTORRENT_TRUE@	DefaultBtMessageDispatcher.cc DefaultBtMessageDispatcher.h\
+@ENABLE_BITTORRENT_TRUE@	BtMessageReceiver.h\
+@ENABLE_BITTORRENT_TRUE@	DefaultBtMessageReceiver.cc DefaultBtMessageReceiver.h\
+@ENABLE_BITTORRENT_TRUE@	BtRequestFactory.h\
+@ENABLE_BITTORRENT_TRUE@	DefaultBtRequestFactory.cc DefaultBtRequestFactory.h\
+@ENABLE_BITTORRENT_TRUE@	BtEvent.h\
+@ENABLE_BITTORRENT_TRUE@	BtEventListener.h\
+@ENABLE_BITTORRENT_TRUE@	BtCancelSendingPieceEvent.h\
+@ENABLE_BITTORRENT_TRUE@	BtAbortOutstandingRequestEvent.h\
+@ENABLE_BITTORRENT_TRUE@	BtChokedEvent.h\
+@ENABLE_BITTORRENT_TRUE@	BtChokingEvent.h\
+@ENABLE_BITTORRENT_TRUE@	BtInteractive.h\
+@ENABLE_BITTORRENT_TRUE@	DefaultBtInteractive.cc DefaultBtInteractive.h\
+@ENABLE_BITTORRENT_TRUE@	PeerObject.h
 
 @ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
 @ENABLE_METALINK_TRUE@	MetalinkEntry.cc MetalinkEntry.h\
@@ -178,16 +225,19 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	AbstractDiskWriter.cc AbstractDiskWriter.h File.cc File.h \
 	Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \
 	messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \
-	TimeA2.cc TimeA2.h SharedHandle.h FeatureConfig.cc \
-	FeatureConfig.h DownloadEngineFactory.cc \
+	TimeA2.cc TimeA2.h SharedHandle.h HandleRegistry.h \
+	FeatureConfig.cc FeatureConfig.h DownloadEngineFactory.cc \
 	DownloadEngineFactory.h RequestInfo.h UrlRequestInfo.cc \
 	UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \
-	BitfieldMan.cc BitfieldMan.h NameResolver.cc NameResolver.h \
-	MetaEntry.h Data.cc Data.h Dictionary.cc Dictionary.h List.cc \
-	List.h MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
-	ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \
-	PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
-	PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
+	BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \
+	BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \
+	SimpleRandomizer.h debug_new.cpp NameResolver.cc \
+	NameResolver.h MetaEntry.h Data.cc Data.h Dictionary.cc \
+	Dictionary.h List.cc List.h MetaFileUtil.cc MetaFileUtil.h \
+	MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \
+	PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \
+	PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \
+	PeerInitiateConnectionCommand.cc \
 	PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
 	PeerInteractionCommand.h Peer.cc Peer.h \
 	TorrentDownloadEngine.cc TorrentDownloadEngine.h \
@@ -231,9 +281,38 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	DefaultBtAnnounce.h BtRegistry.cc BtRegistry.h BtRuntime.h \
 	BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \
 	DefaultBtProgressInfoFile.h BtContextAwareCommand.cc \
-	BtContextAwareCommand.h Metalinker.cc Metalinker.h \
-	MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \
-	MetalinkResource.h MetalinkProcessor.h \
+	BtContextAwareCommand.h BtMessage.h AbstractBtMessage.h \
+	SimpleBtMessage.cc SimpleBtMessage.h BtAllowedFastMessage.cc \
+	BtAllowedFastMessage.h BtBitfieldMessage.cc \
+	BtBitfieldMessage.h BtCancelMessage.cc BtCancelMessage.h \
+	BtChokeMessage.cc BtChokeMessage.h BtHaveAllMessage.cc \
+	BtHaveAllMessage.h BtHaveMessage.cc BtHaveMessage.h \
+	BtHaveNoneMessage.cc BtHaveNoneMessage.h \
+	BtInterestedMessage.cc BtInterestedMessage.h \
+	BtKeepAliveMessage.cc BtKeepAliveMessage.h \
+	BtNotInterestedMessage.cc BtNotInterestedMessage.h \
+	BtPieceMessage.cc BtPieceMessage.h BtPortMessage.cc \
+	BtPortMessage.h BtRejectMessage.cc BtRejectMessage.h \
+	BtRequestMessage.cc BtRequestMessage.h \
+	BtSuggestPieceMessage.cc BtSuggestPieceMessage.h \
+	BtUnchokeMessage.cc BtUnchokeMessage.h BtHandshakeMessage.cc \
+	BtHandshakeMessage.h BtMessageValidator.h \
+	BtAllowedFastMessageValidator.h BtBitfieldMessageValidator.h \
+	BtCancelMessageValidator.h BtHaveMessageValidator.h \
+	BtPieceMessageValidator.h BtRejectMessageValidator.h \
+	BtRequestMessageValidator.h BtSuggestPieceMessageValidator.h \
+	BtHandshakeMessageValidator.h BtMessageFactory.h \
+	DefaultBtMessageFactory.cc DefaultBtMessageFactory.h \
+	BtMessageDispatcher.h DefaultBtMessageDispatcher.cc \
+	DefaultBtMessageDispatcher.h BtMessageReceiver.h \
+	DefaultBtMessageReceiver.cc DefaultBtMessageReceiver.h \
+	BtRequestFactory.h DefaultBtRequestFactory.cc \
+	DefaultBtRequestFactory.h BtEvent.h BtEventListener.h \
+	BtCancelSendingPieceEvent.h BtAbortOutstandingRequestEvent.h \
+	BtChokedEvent.h BtChokingEvent.h BtInteractive.h \
+	DefaultBtInteractive.cc DefaultBtInteractive.h PeerObject.h \
+	Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
+	MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
 	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \
 	MetalinkRequestInfo.cc MetalinkRequestInfo.h
 @ENABLE_ASYNC_DNS_TRUE@am__objects_1 = NameResolver.$(OBJEXT)
@@ -297,7 +376,30 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 @ENABLE_BITTORRENT_TRUE@	DefaultBtAnnounce.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	BtRegistry.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	DefaultBtProgressInfoFile.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@	BtContextAwareCommand.$(OBJEXT)
+@ENABLE_BITTORRENT_TRUE@	BtContextAwareCommand.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	SimpleBtMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtAllowedFastMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtBitfieldMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtCancelMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtChokeMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtHaveAllMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtHaveMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtHaveNoneMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtInterestedMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtKeepAliveMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtNotInterestedMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtPieceMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtPortMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtRejectMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtRequestMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtSuggestPieceMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtUnchokeMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	BtHandshakeMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	DefaultBtMessageFactory.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	DefaultBtMessageDispatcher.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	DefaultBtMessageReceiver.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	DefaultBtRequestFactory.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	DefaultBtInteractive.$(OBJEXT)
 @ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	MetalinkEntry.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	MetalinkResource.$(OBJEXT) \
@@ -326,8 +428,9 @@ am__objects_4 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 	CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \
 	FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \
 	UrlRequestInfo.$(OBJEXT) SpeedCalc.$(OBJEXT) \
-	BitfieldMan.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
-	$(am__objects_3)
+	BitfieldMan.$(OBJEXT) BitfieldManFactory.$(OBJEXT) \
+	SimpleRandomizer.$(OBJEXT) debug_new.$(OBJEXT) \
+	$(am__objects_1) $(am__objects_2) $(am__objects_3)
 am_libaria2c_a_OBJECTS = $(am__objects_4)
 libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
 am__installdirs = "$(DESTDIR)$(bindir)"
@@ -525,12 +628,14 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
 	AbstractDiskWriter.cc AbstractDiskWriter.h File.cc File.h \
 	Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \
 	messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \
-	TimeA2.cc TimeA2.h SharedHandle.h FeatureConfig.cc \
-	FeatureConfig.h DownloadEngineFactory.cc \
+	TimeA2.cc TimeA2.h SharedHandle.h HandleRegistry.h \
+	FeatureConfig.cc FeatureConfig.h DownloadEngineFactory.cc \
 	DownloadEngineFactory.h RequestInfo.h UrlRequestInfo.cc \
 	UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \
-	BitfieldMan.cc BitfieldMan.h $(am__append_1) $(am__append_2) \
-	$(am__append_3)
+	BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \
+	BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \
+	SimpleRandomizer.h debug_new.cpp $(am__append_1) \
+	$(am__append_2) $(am__append_3)
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
@@ -547,7 +652,7 @@ AM_CPPFLAGS = -Wall\
 all: all-am
 
 .SUFFIXES:
-.SUFFIXES: .cc .o .obj
+.SUFFIXES: .cc .cpp .o .obj
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
 	@for dep in $?; do \
 	  case '$(am__configure_deps)' in \
@@ -624,9 +729,27 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnounceList.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMan.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtBitfieldMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtCancelMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtChokeMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtContextAwareCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHandshakeMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveAllMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveNoneMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtInterestedMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtKeepAliveMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtNotInterestedMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPieceMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtPortMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRegistry.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRejectMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRequestMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtSuggestPieceMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtUnchokeMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ByteArrayDiskWriter.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CancelMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChokeMessage.Po@am__quote@
@@ -639,7 +762,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Data.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounce.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtContext.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtInteractive.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageDispatcher.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageReceiver.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtRequestFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerStorage.Po@am__quote@
@@ -712,8 +840,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Segment.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentMan.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleBtMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimplePeerMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleRandomizer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketCore.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalc.Po@am__quote@
@@ -729,6 +859,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UrlRequestInfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug_new.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
 
 .cc.o:
@@ -744,6 +875,20 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 uninstall-info-am:
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)

+ 50 - 1
src/Peer.cc

@@ -33,8 +33,33 @@
  */
 /* copyright --> */
 #include "Peer.h"
+#include "BitfieldManFactory.h"
+#include "Util.h"
 
-PeerHandle nullPeer = PeerHandle(new Peer("", 0, 0, 0));
+Peer::Peer(string ipaddr, int port, int pieceLength, long long int totalLength):
+  ipaddr(ipaddr),
+  port(port),
+  error(0),
+  sessionUploadLength(0),
+  sessionDownloadLength(0),
+  pieceLength(pieceLength),
+  active(false)
+{
+  resetStatus();
+  this->bitfield = BitfieldManFactory::getNewFactory()->
+    createBitfieldMan(pieceLength, totalLength);
+  string idSeed = ipaddr+":"+Util::itos(port);
+  id = Util::simpleMessageDigest(idSeed);
+}
+
+/*
+Peer::Peer():entryId(0), ipaddr(""), port(0), bitfield(0),
+       sessionUploadLength(0), sessionDownloadLength(0),
+       pieceLength(0)
+{
+  resetStatus();
+}
+*/
 
 void Peer::updateBitfield(int index, int operation) {
   if(operation == 1) {
@@ -74,6 +99,8 @@ void Peer::resetStatus() {
   fastExtensionEnabled = false;
   latency = DEFAULT_LATENCY;
   fastSet.clear();
+  peerAllowedIndexSet.clear();
+  amAllowedIndexSet.clear();
   peerStat.reset();
 }
 
@@ -87,6 +114,28 @@ void Peer::addFastSetIndex(int index) {
   }
 }
 
+bool Peer::isInPeerAllowedIndexSet(int index) const {
+  return find(peerAllowedIndexSet.begin(), peerAllowedIndexSet.end(),
+	      index) != peerAllowedIndexSet.end();
+}
+
+void Peer::addPeerAllowedIndex(int index) {
+  if(!isInPeerAllowedIndexSet(index)) {
+    peerAllowedIndexSet.push_back(index);
+  }
+}
+
+bool Peer::isInAmAllowedIndexSet(int index) const {
+  return find(amAllowedIndexSet.begin(), amAllowedIndexSet.end(),
+	      index) != amAllowedIndexSet.end();
+}
+
+void Peer::addAmAllowedIndex(int index) {
+  if(!isInAmAllowedIndexSet(index)) {
+    amAllowedIndexSet.push_back(index);
+  }
+}
+
 void Peer::setAllBitfield() {
   bitfield->setAllBit();
 }

+ 22 - 23
src/Peer.h

@@ -51,7 +51,6 @@ class Peer {
   friend bool operator==(const Peer& p1, const Peer& p2);
   friend bool operator!=(const Peer& p1, const Peer& p2);
 public:
-  int entryId;
   string ipaddr;
   int port;
   bool amChoking;
@@ -65,42 +64,32 @@ public:
   bool optUnchoking;
   bool snubbing;
 private:
-  char peerId[PEER_ID_LENGTH];
+  unsigned char peerId[PEER_ID_LENGTH];
   BitfieldMan* bitfield;
   bool fastExtensionEnabled;
   // allowed fast indexes that peer has sent by Allowed Fast message
   Integers fastSet;
+  // fast index set which a peer has sent to localhost.
+  Integers peerAllowedIndexSet;
+  // fast index set which localhost has sent to a peer.
+  Integers amAllowedIndexSet;
   PeerStat peerStat;
   long long int sessionUploadLength;
   long long int sessionDownloadLength;
   int pieceLength;
   int latency;
   bool active;
+  string id;
 public:
-  Peer(string ipaddr, int port, int pieceLength, long long int totalLength):
-    entryId(0), ipaddr(ipaddr), port(port), error(0),
-    sessionUploadLength(0), sessionDownloadLength(0),
-    pieceLength(pieceLength), active(false)
-  {
-    resetStatus();
-    this->bitfield = new BitfieldMan(pieceLength, totalLength);
-  }
-
-  Peer():entryId(0), ipaddr(""), port(0), bitfield(0),
-	 sessionUploadLength(0), sessionDownloadLength(0),
-	 pieceLength(0)
-  {
-    resetStatus();
-  }
+  Peer(string ipaddr, int port, int pieceLength, long long int totalLength);
 
   ~Peer() {
-    if(bitfield != NULL) {
-      delete bitfield;
-    }
+    delete bitfield;
   }
 
   bool operator==(const Peer& p) {
-    return ipaddr == p.ipaddr && port == p.port;
+    //return ipaddr == p.ipaddr && port == p.port;
+    return id == p.id;
   }
   
   bool operator!=(const Peer& p) {
@@ -161,10 +150,10 @@ public:
     return active;
   }
 
-  void setPeerId(const char* peerId) {
+  void setPeerId(const unsigned char* peerId) {
     memcpy(this->peerId, peerId, PEER_ID_LENGTH);
   }
-  const char* getPeerId() const { return this->peerId; }
+  const unsigned char* getPeerId() const { return this->peerId; }
   
   void setBitfield(const unsigned char* bitfield, int bitfieldLength) {
     this->bitfield->setBitfield(bitfield, bitfieldLength);
@@ -189,6 +178,12 @@ public:
   bool isInFastSet(int index) const;
   int countFastSet() const { return fastSet.size(); }
 
+  void addPeerAllowedIndex(int index);
+  bool isInPeerAllowedIndexSet(int index) const;
+
+  void addAmAllowedIndex(int index);
+  bool isInAmAllowedIndexSet(int index) const;
+
   bool shouldBeChoking() const;
 
   bool hasPiece(int index) const;
@@ -197,6 +192,10 @@ public:
 
   void updateLatency(int latency);
   int getLatency() const { return latency; }
+
+  const string& getId() const {
+    return id;
+  }
 };
 
 typedef SharedHandle<Peer> PeerHandle;

+ 25 - 22
src/PeerConnection.cc

@@ -38,9 +38,10 @@
 #include "PeerMessageUtil.h"
 #include "Util.h"
 #include "LogFactory.h"
+#include "BtHandshakeMessage.h"
 #include <netinet/in.h>
 
-PeerConnection::PeerConnection(int cuid,
+PeerConnection::PeerConnection(int32_t cuid,
 			       const SocketHandle& socket,
 			       const Option* op)
   :cuid(cuid),
@@ -55,24 +56,26 @@ PeerConnection::PeerConnection(int cuid,
 
 PeerConnection::~PeerConnection() {}
 
-int PeerConnection::sendMessage(const char* msg, int length) {
-  int writtenLength = 0;
+uint32_t PeerConnection::sendMessage(const unsigned char* data, uint32_t dataLength) {
+  uint32_t writtenLength = 0;
   if(socket->isWritable(0)) {
-    socket->writeData(msg, length);
-    writtenLength += length;
+    // TODO fix this
+    socket->writeData((const char*)data, dataLength);
+    writtenLength += dataLength;
   }
   return writtenLength;
 }
 
-bool PeerConnection::receiveMessage(char* msg, int& length) {
+bool PeerConnection::receiveMessage(unsigned char* data, uint32_t& dataLength) {
   if(!socket->isReadable(0)) {
     return false;
   }
   if(resbufLength == 0 && lenbufLength != 4) {
     // read payload size, 4-byte integer
-    int remain = 4-lenbufLength;
-    int temp = remain;
-    socket->readData(lenbuf+lenbufLength, temp);
+    uint32_t remain = 4-lenbufLength;
+    uint32_t temp = remain;
+    // TODO fix this
+    socket->readData((char*)lenbuf+lenbufLength, (int&)temp);
     if(temp == 0) {
       // we got EOF
       throw new DlAbortEx(EX_EOF_FROM_PEER);
@@ -83,7 +86,7 @@ bool PeerConnection::receiveMessage(char* msg, int& length) {
       return false;
     }
     //payloadLen = ntohl(nPayloadLen);
-    int payloadLength = ntohl(*((int*)lenbuf));
+    uint32_t payloadLength = ntohl(*((uint32_t*)lenbuf));
     if(payloadLength > MAX_PAYLOAD_LEN || payloadLength < 0) {
       throw new DlAbortEx("max payload length exceeded or invalid. length = %d",
 			  payloadLength);
@@ -91,9 +94,9 @@ bool PeerConnection::receiveMessage(char* msg, int& length) {
     currentPayloadLength = payloadLength;
   }
   // we have currentPayloadLen-resbufLen bytes to read
-  int remaining = currentPayloadLength-resbufLength;
+  uint32_t remaining = currentPayloadLength-resbufLength;
   if(remaining > 0) {
-    socket->readData(resbuf+resbufLength, remaining);
+    socket->readData((char*)resbuf+resbufLength, (int&)remaining);
     if(remaining == 0) {
       // we got EOF
       throw new DlAbortEx(EX_EOF_FROM_PEER);
@@ -107,19 +110,19 @@ bool PeerConnection::receiveMessage(char* msg, int& length) {
   resbufLength = 0;
   lenbufLength = 0;
 
-  memcpy(msg, resbuf, currentPayloadLength);
-  length = currentPayloadLength;
+  memcpy(data, resbuf, currentPayloadLength);
+  dataLength = currentPayloadLength;
   return true;
 }
 
-bool PeerConnection::receiveHandshake(char* msg, int& length) {
+bool PeerConnection::receiveHandshake(unsigned char* data, uint32_t& dataLength) {
   if(!socket->isReadable(0)) {
-    length = 0;
+    dataLength = 0;
     return false;
   }
-  int remain = HANDSHAKE_MESSAGE_LENGTH-resbufLength;
-  int temp = remain;
-  socket->readData(resbuf+resbufLength, temp);
+  uint32_t remain = BtHandshakeMessage::MESSAGE_LENGTH-resbufLength;
+  uint32_t temp = remain;
+  socket->readData((char*)resbuf+resbufLength, (int&)temp);
   if(temp == 0) {
     // we got EOF
     throw new DlAbortEx(EX_EOF_FROM_PEER);
@@ -132,9 +135,9 @@ bool PeerConnection::receiveHandshake(char* msg, int& length) {
   }
   resbufLength += temp;
   // we got whole handshake payload
-  int writeLength = resbufLength > length ? length : resbufLength;
-  memcpy(msg, resbuf, writeLength);
-  length = writeLength;
+  uint32_t writeLength = resbufLength > dataLength ? dataLength : resbufLength;
+  memcpy(data, resbuf, writeLength);
+  dataLength = writeLength;
   if(retval) {
     resbufLength = 0;
   }

+ 21 - 10
src/PeerConnection.h

@@ -38,7 +38,6 @@
 #include "Option.h"
 #include "Socket.h"
 #include "Logger.h"
-#include "PeerMessage.h"
 #include "common.h"
 
 // we assume maximum length of incoming message is "piece" message with 16KB
@@ -47,32 +46,44 @@
 
 class PeerConnection {
 private:
-  int cuid;
+  int32_t cuid;
   SocketHandle socket;
   const Option* option;
   const Logger* logger;
 
   char resbuf[MAX_PAYLOAD_LEN];
-  int resbufLength;
-  int currentPayloadLength;
-  char lenbuf[4];
-  int lenbufLength;
+  uint32_t resbufLength;
+  uint32_t currentPayloadLength;
+  unsigned char lenbuf[4];
+  uint32_t lenbufLength;
 
 public:
-  PeerConnection(int cuid, const SocketHandle& socket, const Option* op);
+  PeerConnection(int32_t cuid, const SocketHandle& socket, const Option* op);
   ~PeerConnection();
   
   // Returns the number of bytes written
-  int sendMessage(const char* msg, int length);
+  uint32_t sendMessage(const unsigned char* data, uint32_t dataLength);
+  uint32_t sendMessage(const char* msg, int length) {
+    return sendMessage((const unsigned char*)msg, (uint32_t)length);
+  }
+
+  bool receiveMessage(unsigned char* data, uint32_t& dataLength);
+  bool receiveMessage(char* msg, int& length) {
+    return receiveMessage((unsigned char*)msg, (uint32_t&)length);
+  }
 
-  bool receiveMessage(char* msg, int& length);
   /**
    * Returns true if a handshake message is fully received, otherwise returns
    * false.
    * In both cases, 'msg' is filled with received bytes and the filled length
    * is assigned to 'length'.
    */
-  bool receiveHandshake(char* msg, int& length);
+  bool receiveHandshake(unsigned char* data, uint32_t& dataLength);
+  bool receiveHandshake(char* msg, int& length) {
+    return receiveHandshake((unsigned char*)msg, (uint32_t&)length);
+  }
 };
 
+typedef SharedHandle<PeerConnection> PeerConnectionHandle;
+
 #endif // _D_PEER_CONNECTION_H_

+ 29 - 25
src/PeerInteraction.cc

@@ -123,8 +123,8 @@ void PeerInteraction::rejectPieceMessageInQueue(int index, int begin, int length
 
 void PeerInteraction::onChoked() {
   for(Pieces::iterator itr = pieces.begin(); itr != pieces.end();) {
-    Piece& piece = *itr;
-    if(!peer->isInFastSet(piece.getIndex())) {
+    PieceHandle& piece = *itr;
+    if(!peer->isInFastSet(piece->getIndex())) {
       abortPiece(piece);
       itr = pieces.erase(itr);
     } else {
@@ -140,20 +140,20 @@ void PeerInteraction::abortAllPieces() {
   }
 }
 
-void PeerInteraction::abortPiece(Piece& piece) {
-  if(!Piece::isNull(piece)) {
+void PeerInteraction::abortPiece(const PieceHandle& piece) {
+  if(!piece.isNull()) {
     int size = messageQueue.size();
     for(int i = 0; i < size; i++) {
       messageQueue.at(i)->onAbortPiece(piece);
     }
     for(RequestSlots::iterator itr = requestSlots.begin();
 	itr != requestSlots.end();) {
-      if(itr->getIndex() == piece.getIndex()) {
+      if(itr->getIndex() == piece->getIndex()) {
 	logger->debug("CUID#%d - Deleting request slot blockIndex=%d"
 		      " because piece was canceled",
 		      cuid,
 		      itr->getBlockIndex());
-	piece.cancelBlock(itr->getBlockIndex());
+	piece->cancelBlock(itr->getBlockIndex());
 	itr = requestSlots.erase(itr);
       } else {
 	itr++;
@@ -181,14 +181,14 @@ void PeerInteraction::checkRequestSlot() {
 		    " because of time out",
 		    cuid,
 		    slot.getBlockIndex());
-      Piece& piece = getDownloadPiece(slot.getIndex());
-      piece.cancelBlock(slot.getBlockIndex());
+      PieceHandle piece = getDownloadPiece(slot.getIndex());
+      piece->cancelBlock(slot.getBlockIndex());
       itr = requestSlots.erase(itr);
       peer->snubbing = true;
     } else {
-      Piece piece = getDownloadPiece(slot.getIndex());
-      if(piece.hasBlock(slot.getBlockIndex()) ||
-	 pieceStorage->hasPiece(piece.getIndex())) {
+      PieceHandle piece = getDownloadPiece(slot.getIndex());
+      if(piece->hasBlock(slot.getBlockIndex()) ||
+	 pieceStorage->hasPiece(piece->getIndex())) {
 	logger->debug("CUID#%d - Deleting request slot blockIndex=%d because"
 		      " the block has been acquired.", cuid,
 		      slot.getBlockIndex());
@@ -275,15 +275,19 @@ PeerMessageHandle PeerInteraction::receiveMessage() {
 }
 
 void PeerInteraction::syncPiece() {
+  /*
   for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
     pieceStorage->syncPiece(*itr);
   }
+  */
 }
 
 void PeerInteraction::updatePiece() {
+  /*
   for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
     pieceStorage->updatePiece(*itr);
   }
+  */
 }
 
 void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
@@ -297,8 +301,8 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
       onChoked();
       if(peer->isFastExtensionEnabled()) {
 	while((int)pieces.size() < pieceNum) {
-	  Piece piece = pieceStorage->getMissingFastPiece(peer);
-	  if(Piece::isNull(piece)) {
+	  PieceHandle piece = pieceStorage->getMissingFastPiece(peer);
+	  if(piece.isNull()) {
 	    break;
 	  } else {
 	    pieces.push_back(piece);
@@ -307,8 +311,8 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
       }
     } else {
       while((int)pieces.size() < pieceNum) {
-	Piece piece = pieceStorage->getMissingPiece(peer);
-	if(Piece::isNull(piece)) {
+	PieceHandle piece = pieceStorage->getMissingPiece(peer);
+	if(piece.isNull()) {
 	  break;
 	} else {
 	  pieces.push_back(piece);
@@ -325,8 +329,8 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
 void PeerInteraction::addRequests() {
   // Abort downloading of completed piece.
   for(Pieces::iterator itr = pieces.begin(); itr != pieces.end();) {
-    Piece& piece = *itr;
-    if(piece.pieceComplete()) {
+    PieceHandle& piece = *itr;
+    if(piece->pieceComplete()) {
       abortPiece(piece);
       itr = pieces.erase(itr);
     } else {
@@ -350,16 +354,16 @@ void PeerInteraction::addRequests() {
   }
   getNewPieceAndSendInterest(pieceNum);
   for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
-    Piece& piece = *itr;
+    PieceHandle& piece = *itr;
     if(pieceStorage->isEndGame()) {
-      BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes();
+      BlockIndexes missingBlockIndexes = piece->getAllMissingBlockIndexes();
       random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end());
       int count = countRequestSlot();
       for(BlockIndexes::const_iterator bitr = missingBlockIndexes.begin();
 	  bitr != missingBlockIndexes.end() && count < MAX_PENDING_REQUEST;
 	  bitr++) {
 	int blockIndex = *bitr;
-	if(!isInRequestSlot(piece.getIndex(), blockIndex)) {
+	if(!isInRequestSlot(piece->getIndex(), blockIndex)) {
 	  addMessage(peerMessageFactory->createRequestMessage(piece,
 							      blockIndex));
 	  count++;
@@ -367,7 +371,7 @@ void PeerInteraction::addRequests() {
       }
     } else {
       while(countRequestSlot() < MAX_PENDING_REQUEST) {
-	int blockIndex = piece.getMissingUnusedBlockIndex();
+	int blockIndex = piece->getMissingUnusedBlockIndex();
 	if(blockIndex == -1) {
 	  break;
 	}
@@ -385,7 +389,7 @@ void PeerInteraction::addRequests() {
 void PeerInteraction::sendHandshake() {
   PeerMessageHandle handle =
     peerMessageFactory->createHandshakeMessage(btContext->getInfoHash(),
-					       btAnnounce->getPeerId().c_str());
+					       (const char*)btContext->getPeerId());
   addMessage(handle);
   sendMessages();
 }
@@ -420,9 +424,9 @@ void PeerInteraction::sendAllowedFast() {
   }
 }
 
-Piece& PeerInteraction::getDownloadPiece(int index) {
+PieceHandle PeerInteraction::getDownloadPiece(int index) {
   for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
-    if(itr->getIndex() == index) {
+    if((*itr)->getIndex() == index) {
       return *itr;
     }
   }
@@ -431,7 +435,7 @@ Piece& PeerInteraction::getDownloadPiece(int index) {
 
 bool PeerInteraction::hasDownloadPiece(int index) const {
   for(Pieces::const_iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
-    if(itr->getIndex() == index) {
+    if((*itr)->getIndex() == index) {
       return true;
     }
   }

+ 2 - 3
src/PeerInteraction.h

@@ -48,7 +48,6 @@
 #define REQUEST_TIME_OUT 60
 #define ALLOWED_FAST_SET_SIZE 10
 
-typedef deque<RequestSlot> RequestSlots;
 typedef deque<PeerMessageHandle> MessageQueue;
 
 class PeerInteraction {
@@ -85,7 +84,7 @@ public:
   void rejectPieceMessageInQueue(int index, int begin, int length);
   void rejectAllPieceMessageInQueue();
   void onChoked();
-  void abortPiece(Piece& piece);
+  void abortPiece(const PieceHandle& piece);
   void abortAllPieces();
 
   bool isSendingMessageInProgress() const;
@@ -104,7 +103,7 @@ public:
   // If the piece which this object has is nullPiece, then throws an exception.
   // So before calling this function, call hasDownloadPiece and make sure
   // this has valid piece, not nullPiece.
-  Piece& getDownloadPiece(int index);
+  PieceHandle getDownloadPiece(int index);
   
   bool isInFastSet(int index) const;
 

+ 86 - 183
src/PeerInteractionCommand.cc

@@ -35,15 +35,17 @@
 #include "PeerInteractionCommand.h"
 #include "PeerInitiateConnectionCommand.h"
 #include "PeerMessageUtil.h"
-#include "HandshakeMessage.h"
-#include "KeepAliveMessage.h"
-#include "ChokeMessage.h"
-#include "UnchokeMessage.h"
-#include "HaveMessage.h"
+#include "DefaultBtInteractive.h"
 #include "DlAbortEx.h"
 #include "Util.h"
 #include "message.h"
 #include "prefs.h"
+#include "DefaultBtMessageDispatcher.h"
+#include "DefaultBtMessageReceiver.h"
+#include "DefaultBtRequestFactory.h"
+#include "DefaultBtMessageFactory.h"
+#include "DefaultBtInteractive.h"
+#include "PeerConnection.h"
 #include <algorithm>
 
 PeerInteractionCommand::PeerInteractionCommand(int cuid,
@@ -52,196 +54,133 @@ PeerInteractionCommand::PeerInteractionCommand(int cuid,
 					       const BtContextHandle& btContext,
 					       const SocketHandle& s,
 					       int sequence)
-  :PeerAbstractCommand(cuid, p, e, btContext, s), sequence(sequence) {
+  :PeerAbstractCommand(cuid, p, e, btContext, s),
+   sequence(sequence),
+   btInteractive(0)
+{
+  // TODO move following bunch of processing to separate method, like init()
   if(sequence == INITIATOR_SEND_HANDSHAKE) {
     disableReadCheckSocket();
     setWriteCheckSocket(socket);
     setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
   }
-  peerInteraction = new PeerInteraction(cuid, peer, socket, e->option,
-					btContext);
+  PeerConnectionHandle peerConnection =
+    new PeerConnection(cuid, socket, e->option);
+
+  DefaultBtMessageDispatcherHandle dispatcher = new DefaultBtMessageDispatcher();
+  dispatcher->setCuid(cuid);
+  dispatcher->setPeer(peer);
+  dispatcher->setBtContext(btContext);
+  dispatcher->setOption(e->option);
+
+  DefaultBtMessageReceiverHandle receiver = new DefaultBtMessageReceiver();
+  receiver->setCuid(cuid);
+  receiver->setPeer(peer);
+  receiver->setBtContext(btContext);
+  receiver->setPeerConnection(peerConnection);
+  receiver->setDispatcher(dispatcher);
+
+  DefaultBtRequestFactoryHandle reqFactory = new DefaultBtRequestFactory();
+  reqFactory->setCuid(cuid);
+  reqFactory->setPeer(peer);
+  reqFactory->setBtContext(btContext);
+  reqFactory->setBtMessageDispatcher(dispatcher);
+
+  DefaultBtInteractiveHandle btInteractive = new DefaultBtInteractive();
+  btInteractive->setCuid(cuid);
+  btInteractive->setPeer(peer);
+  btInteractive->setBtContext(btContext);
+  btInteractive->setBtMessageReceiver(receiver);
+  btInteractive->setDispatcher(dispatcher);
+  btInteractive->setBtRequestFactory(reqFactory);
+  btInteractive->setPeerConnection(peerConnection);
+  btInteractive->setOption(e->option);
+  this->btInteractive = btInteractive;
+
+  DefaultBtMessageFactoryHandle factory = new DefaultBtMessageFactory();
+  factory->setCuid(cuid);
+  factory->setBtContext(btContext);
+  factory->setPeer(peer);
+
+  PeerObjectHandle peerObject = new PeerObject();
+  peerObject->btMessageDispatcher = dispatcher;
+  peerObject->btMessageFactory = factory;
+  peerObject->btRequestFactory = reqFactory;
+  peerObject->peerConnection = peerConnection;
+
+  PEER_OBJECT_CLUSTER(btContext)->registerHandle(peer->getId(), peerObject);
+
   setUploadLimit(e->option->getAsInt(PREF_MAX_UPLOAD_LIMIT));
-  chokeUnchokeCount = 0;
-  haveCount = 0;
-  keepAliveCount = 0;
   peer->activate();
 }
 
 PeerInteractionCommand::~PeerInteractionCommand() {
-  delete peerInteraction;
   peer->deactivate();
+  PEER_OBJECT_CLUSTER(btContext)->unregisterHandle(peer->getId());
+							  
+  logger->debug("CUID#%d - unregistered message factory using ID:%s",
+		cuid, peer->getId().c_str());
 }
 
 bool PeerInteractionCommand::executeInternal() {
+  setReadCheckSocket(socket);
   disableWriteCheckSocket();
   setUploadLimitCheck(false);
   setNoCheck(false);
-
   switch(sequence) {
   case INITIATOR_SEND_HANDSHAKE:
     if(!socket->isWritable(0)) {
+      disableReadCheckSocket();
       setWriteCheckSocket(socket);
       break;
     }
     socket->setBlockingMode();
-    setReadCheckSocket(socket);
-    setTimeout(e->option->getAsInt(PREF_TIMEOUT));
-    peerInteraction->sendHandshake();
+    setTimeout(e->option->getAsInt(PREF_BT_TIMEOUT));
+    btInteractive->initiateHandshake();
     sequence = INITIATOR_WAIT_HANDSHAKE;
     break;
   case INITIATOR_WAIT_HANDSHAKE: {
-    if(peerInteraction->countMessageInQueue() > 0) {
-      peerInteraction->sendMessages();
-      if(peerInteraction->countMessageInQueue() > 0) {
+    if(btInteractive->countPendingMessage() > 0) {
+      btInteractive->sendPendingMessage();
+      if(btInteractive->countPendingMessage() > 0) {
 	break;
       }
     }
-    PeerMessageHandle handshakeMessage =
-      peerInteraction->receiveHandshake();
-    if(handshakeMessage.get() == 0) {
+    BtMessageHandle handshakeMessage = btInteractive->receiveHandshake();
+    if(handshakeMessage.isNull()) {
       break;
     }
-    peer->setPeerId(((HandshakeMessage*)handshakeMessage.get())->peerId);
-    logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
-		 peer->ipaddr.c_str(), peer->port,
-		 handshakeMessage->toString().c_str());
-    haveCheckTime.reset();
-    peerInteraction->sendBitfield();
-    peerInteraction->sendAllowedFast();
+    btInteractive->doPostHandshakeProcessing();
     sequence = WIRED;
     break;
   }
   case RECEIVER_WAIT_HANDSHAKE: {
-    PeerMessageHandle handshakeMessage =
-      peerInteraction->receiveHandshake(true);
-    if(handshakeMessage.get() == 0) {
+    BtMessageHandle handshakeMessage = btInteractive->receiveAndSendHandshake();
+    if(handshakeMessage.isNull()) {
       break;
     }
-    peer->setPeerId(((HandshakeMessage*)handshakeMessage.get())->peerId);
-    logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
-		 peer->ipaddr.c_str(), peer->port,
-		 handshakeMessage->toString().c_str());
-    haveCheckTime.reset();
-    peerInteraction->sendBitfield();
-    peerInteraction->sendAllowedFast();
+    btInteractive->doPostHandshakeProcessing();
     sequence = WIRED;    
     break;
   }
   case WIRED:
-    peerInteraction->syncPiece();
-    decideChoking();
+    btInteractive->doInteractionProcessing();
 
-    if(periodicExecPoint.elapsedInMillis(500)) {
-      periodicExecPoint.reset();
-      detectMessageFlooding();
-      peerInteraction->checkRequestSlot();
-      checkHave();
-      sendKeepAlive();
-    }
-    receiveMessages();
-
-    peerInteraction->addRequests();
-
-    peerInteraction->sendMessages();
     break;
   }
-  if(peerInteraction->countMessageInQueue() > 0) {
-    if(peerInteraction->isSendingMessageInProgress()) {
-      setUploadLimitCheck(true);
-    }
+  if(btInteractive->countPendingMessage() > 0) {
     setNoCheck(true);
   }
-  e->commands.push_back(this);
-  return false;
-}
-
-#define FLOODING_CHECK_INTERVAL 5
-
-void PeerInteractionCommand::detectMessageFlooding() {
-  if(freqCheckPoint.elapsed(FLOODING_CHECK_INTERVAL)) {
-    if(chokeUnchokeCount*1.0/FLOODING_CHECK_INTERVAL >= 0.4
-       //|| haveCount*1.0/elapsed >= 20.0
-       || keepAliveCount*1.0/FLOODING_CHECK_INTERVAL >= 1.0) {
-      throw new DlAbortEx("Flooding detected.");
-    } else {
-      chokeUnchokeCount = 0;
-      haveCount = 0;
-      keepAliveCount = 0;
-      freqCheckPoint.reset();
+  int maxSpeedLimit = e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT);
+  if(maxSpeedLimit > 0) {
+    TransferStat stat = peerStorage->calculateStat();
+    if(maxSpeedLimit < stat.downloadSpeed) {
+      disableReadCheckSocket();
+      setNoCheck(true);
     }
   }
-}
-
-/*
-void PeerInteractionCommand::checkLongTimePeerChoking() {
-  if(pieceStorage->downloadFinished()) {
-    return;
-  }    
-  if(peer->amInterested && peer->peerChoking) {
-    if(chokeCheckPoint.elapsed(MAX_PEER_CHOKING_INTERVAL)) {
-      logger->info("CUID#%d - The peer is choking too long.", cuid);
-      peer->snubbing = true;
-    }
-  } else {
-    chokeCheckPoint.reset();
-  }
-}
-*/
-
-void PeerInteractionCommand::decideChoking() {
-  if(peer->shouldBeChoking()) {
-    if(!peer->amChoking) {
-      peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				  createChokeMessage());
-    }
-  } else {
-    if(peer->amChoking) {
-      peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				  createUnchokeMessage());
-    }
-  }
-}
-
-void PeerInteractionCommand::receiveMessages() {
-  for(int i = 0; i < 50; i++) {
-    int maxSpeedLimit = e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT);
-    if(maxSpeedLimit > 0) {
-      TransferStat stat = peerStorage->calculateStat();
-      if(maxSpeedLimit < stat.downloadSpeed) {
-	disableReadCheckSocket();
-	setNoCheck(true);
-	break;
-      }
-    }
-
-    PeerMessageHandle message = peerInteraction->receiveMessage();
-    if(message.get() == NULL) {
-      return;
-    }
-    logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
-		 peer->ipaddr.c_str(), peer->port,
-		 message->toString().c_str());
-    // to detect flooding
-    switch(message->getId()) {
-    case KeepAliveMessage::ID:
-      keepAliveCount++;
-      break;
-    case ChokeMessage::ID:
-      if(!peer->peerChoking) {
-	chokeUnchokeCount++;
-      }
-      break;
-    case UnchokeMessage::ID:
-      if(peer->peerChoking) {
-	chokeUnchokeCount++;
-      }
-      break;
-    case HaveMessage::ID:
-      haveCount++;
-      break;
-    }
-    message->receivedAction();
-  }
+  e->commands.push_back(this);
+  return false;
 }
 
 // TODO this method removed when PeerBalancerCommand is implemented
@@ -266,42 +205,6 @@ bool PeerInteractionCommand::prepareForRetry(int wait) {
 }
 
 void PeerInteractionCommand::onAbort(Exception* ex) {
-  peerInteraction->abortAllPieces();
+  btInteractive->cancelAllPiece();
   PeerAbstractCommand::onAbort(ex);
 }
-
-void PeerInteractionCommand::sendKeepAlive() {
-  if(keepAliveCheckPoint.elapsed(KEEP_ALIVE_INTERVAL)) {
-    if(peerInteraction->countMessageInQueue() == 0) {
-      peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				  createKeepAliveMessage());
-      peerInteraction->sendMessages();
-    }
-    keepAliveCheckPoint.reset();
-  }
-}
-
-void PeerInteractionCommand::checkHave() {
-  Integers indexes =
-    pieceStorage->getAdvertisedPieceIndexes(cuid, haveCheckTime);
-  haveCheckTime.reset();
-  if(indexes.size() >= 20) {
-    if(peer->isFastExtensionEnabled()) {
-      if(pieceStorage->downloadFinished()) {
-	peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				    createHaveAllMessage());
-      } else {
-	peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				    createBitfieldMessage());
-      }
-    } else {
-      peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				  createBitfieldMessage());
-    }
-  } else {
-    for(Integers::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
-      peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
-				  createHaveMessage(*itr));
-    }
-  }
-}

+ 6 - 27
src/PeerInteractionCommand.h

@@ -36,45 +36,24 @@
 #define _D_PEER_INTERACTION_COMMAND_H_
 
 #include "PeerAbstractCommand.h"
-#include "PeerConnection.h"
-#include "PeerInteraction.h"
-#include "TimeA2.h"
-
-using namespace std;
-
-#define MAX_PEER_CHOKING_INTERVAL (1*60)
-#define KEEP_ALIVE_INTERVAL 120
+#include "BtInteractive.h"
 
 class PeerInteractionCommand : public PeerAbstractCommand {
 private:
   int sequence;
-  PeerInteraction* peerInteraction;
- 
-  Time keepAliveCheckPoint;
-  //Time chokeCheckPoint;
-  Time freqCheckPoint;
-  Time haveCheckTime;
-  Time periodicExecPoint;
-  int chokeUnchokeCount;
-  int haveCount;
-  int keepAliveCount;
-  void receiveMessages();
-  void detectMessageFlooding();
-  void checkLongTimePeerChoking();
-  void detectTimeoutAndDuplicateBlock();
-  void decideChoking();
-  void sendKeepAlive();
-  void checkHave();
+  BtInteractiveHandle btInteractive;
 protected:
   bool executeInternal();
   bool prepareForRetry(int wait);
   bool prepareForNextPeer(int wait);
   void onAbort(Exception* ex);
 public:
-  PeerInteractionCommand(int cuid, const PeerHandle& peer,
+  PeerInteractionCommand(int cuid,
+			 const PeerHandle& peer,
 			 TorrentDownloadEngine* e,
 			 const BtContextHandle& btContext,
-			 const SocketHandle& s, int sequence);
+			 const SocketHandle& s,
+			 int sequence);
 
   ~PeerInteractionCommand();
 

+ 1 - 0
src/PeerMessage.cc

@@ -39,6 +39,7 @@ PeerMessage::PeerMessage()
   :inProgress(false),
    invalidate(false),
    uploading(false),
+   peer(0),
    btContext(0),
    peerStorage(0),
    pieceStorage(0)

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