Переглянути джерело

2009-07-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Disconnect seeder if client is also in seed state.
	* src/BtBitfieldMessage.cc
	* src/BtHaveAllMessage.cc
	* src/BtHaveMessage.cc
	* src/message.h
	* test/BtBitfieldMessageTest.cc
	* test/BtHaveAllMessageTest.cc
	* test/BtHaveMessageTest.cc
	* test/MockPieceStorage.h
Tatsuhiro Tsujikawa 16 роки тому
батько
коміт
5f966f6327

+ 12 - 0
ChangeLog

@@ -1,3 +1,15 @@
+2009-07-07  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Disconnect seeder if client is also in seed state.
+	* src/BtBitfieldMessage.cc
+	* src/BtHaveAllMessage.cc
+	* src/BtHaveMessage.cc
+	* src/message.h
+	* test/BtBitfieldMessageTest.cc
+	* test/BtHaveAllMessageTest.cc
+	* test/BtHaveMessageTest.cc
+	* test/MockPieceStorage.h
+
 2009-07-06  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Keep CreateRequestCommand in queue when no segment is available so

+ 3 - 0
src/BtBitfieldMessage.cc

@@ -73,6 +73,9 @@ BtBitfieldMessage::create(const unsigned char* data, size_t dataLength)
 void BtBitfieldMessage::doReceivedAction() {
   pieceStorage->updatePieceStats(bitfield, bitfieldLength, peer->getBitfield());
   peer->setBitfield(bitfield, bitfieldLength);
+  if(peer->isSeeder() && pieceStorage->downloadFinished()) {
+    throw DL_ABORT_EX(MSG_GOOD_BYE_SEEDER);
+  }
 }
 
 const unsigned char* BtBitfieldMessage::getMessage() {

+ 4 - 0
src/BtHaveAllMessage.cc

@@ -37,6 +37,7 @@
 #include "Peer.h"
 #include "StringFormat.h"
 #include "PieceStorage.h"
+#include "message.h"
 
 namespace aria2 {
 
@@ -59,6 +60,9 @@ void BtHaveAllMessage::doReceivedAction()
 				   peer->getBitfieldLength());
   peer->setAllBitfield();
   pieceStorage->addPieceStats(peer->getBitfield(), peer->getBitfieldLength());
+  if(peer->isSeeder() && pieceStorage->downloadFinished()) {
+    throw DL_ABORT_EX(MSG_GOOD_BYE_SEEDER);
+  }
 }
 
 } // namespace aria2

+ 5 - 0
src/BtHaveMessage.cc

@@ -35,6 +35,8 @@
 #include "BtHaveMessage.h"
 #include "Peer.h"
 #include "PieceStorage.h"
+#include "message.h"
+#include "DlAbortEx.h"
 
 namespace aria2 {
 
@@ -50,6 +52,9 @@ void BtHaveMessage::doReceivedAction()
 {
   peer->updateBitfield(getIndex(), 1);
   pieceStorage->addPieceStats(getIndex());
+  if(peer->isSeeder() && pieceStorage->downloadFinished()) {
+    throw DL_ABORT_EX(MSG_GOOD_BYE_SEEDER);
+  }
 }
 
 } // namespace aria2

+ 1 - 0
src/message.h

@@ -172,6 +172,7 @@
 				   " file. Skipping.")
 #define MSG_GID_NOT_PROVIDED "GID is not provided."
 #define MSG_CANNOT_PARSE_XML_RPC_REQUEST "Failed to parse xml-rpc request."
+#define MSG_GOOD_BYE_SEEDER "Client is in seed state: Good Bye Seeder;)"
 
 #define EX_TIME_OUT _("Timeout.")
 #define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.")

+ 43 - 2
test/BtBitfieldMessageTest.cc

@@ -1,10 +1,14 @@
 #include "BtBitfieldMessage.h"
+
+#include <cstring>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "PeerMessageUtil.h"
 #include "Util.h"
 #include "Peer.h"
 #include "MockPieceStorage.h"
-#include <cstring>
-#include <cppunit/extensions/HelperMacros.h>
+#include "DlAbortEx.h"
 
 namespace aria2 {
 
@@ -14,6 +18,7 @@ class BtBitfieldMessageTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testGetMessage);
   CPPUNIT_TEST(testDoReceivedAction);
+  CPPUNIT_TEST(testDoReceivedAction_goodByeSeeder);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -25,6 +30,7 @@ public:
   void testCreate();
   void testGetMessage();
   void testDoReceivedAction();
+  void testDoReceivedAction_goodByeSeeder();
   void testToString();
 };
 
@@ -87,6 +93,41 @@ void BtBitfieldMessageTest::testDoReceivedAction() {
 							peer->getBitfieldLength()));
 }
 
+void BtBitfieldMessageTest::testDoReceivedAction_goodByeSeeder()
+{
+  SharedHandle<Peer> peer(new Peer("ip", 6000));
+  peer->allocateSessionResource(1024, 1024);
+  BtBitfieldMessage msg;
+  msg.setPeer(peer);
+  SharedHandle<MockPieceStorage> pieceStorage(new MockPieceStorage());
+  msg.setPieceStorage(pieceStorage);
+  unsigned char bitfield[] = { 0x00 };
+  msg.setBitfield(bitfield, sizeof(bitfield));
+
+  // peer is not seeder and client have not completed download
+  msg.doReceivedAction();
+
+  pieceStorage->setDownloadFinished(true);
+
+  // client completed download, but peer is not seeder
+  msg.doReceivedAction();
+
+  pieceStorage->setDownloadFinished(false);
+  bitfield[0] = 0x80;
+  msg.setBitfield(bitfield, sizeof(bitfield));
+
+  // peer is seeder, but client have not completed download
+  msg.doReceivedAction();
+
+  pieceStorage->setDownloadFinished(true);
+  try {
+    msg.doReceivedAction();
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(DlAbortEx& e) {
+    // success
+  }
+}
+
 void BtBitfieldMessageTest::testToString() {
   BtBitfieldMessage msg;
   unsigned char bitfield[] = { 0xff, 0xff };

+ 28 - 2
test/BtHaveAllMessageTest.cc

@@ -1,9 +1,13 @@
 #include "BtHaveAllMessage.h"
+
+#include <cstring>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "PeerMessageUtil.h"
 #include "Peer.h"
 #include "MockPieceStorage.h"
-#include <cstring>
-#include <cppunit/extensions/HelperMacros.h>
+#include "DlAbortEx.h"
 
 namespace aria2 {
 
@@ -13,6 +17,7 @@ class BtHaveAllMessageTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testGetMessage);
   CPPUNIT_TEST(testDoReceivedAction);
+  CPPUNIT_TEST(testDoReceivedAction_goodByeSeeder);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -23,6 +28,7 @@ public:
   void testCreate();
   void testGetMessage();
   void testDoReceivedAction();
+  void testDoReceivedAction_goodByeSeeder();
 };
 
 
@@ -80,4 +86,24 @@ void BtHaveAllMessageTest::testDoReceivedAction() {
   } catch(...) {}
 }
 
+void BtHaveAllMessageTest::testDoReceivedAction_goodByeSeeder()
+{
+  BtHaveAllMessage msg;
+  SharedHandle<Peer> peer(new Peer("ip", 6000));
+  peer->allocateSessionResource(1024, 1024);
+  peer->setFastExtensionEnabled(true);
+  msg.setPeer(peer);
+  SharedHandle<MockPieceStorage> pieceStorage(new MockPieceStorage());
+  msg.setPieceStorage(pieceStorage);
+
+  pieceStorage->setDownloadFinished(true);
+
+  try {
+    msg.doReceivedAction();
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(DlAbortEx& e) {
+    // success
+  }
+}
+
 } // namespace aria2

+ 41 - 2
test/BtHaveMessageTest.cc

@@ -1,9 +1,13 @@
 #include "BtHaveMessage.h"
+
+#include <cstring>
+
+#include <cppunit/extensions/HelperMacros.h>
+
 #include "PeerMessageUtil.h"
 #include "Peer.h"
 #include "MockPieceStorage.h"
-#include <cstring>
-#include <cppunit/extensions/HelperMacros.h>
+#include "DlAbortEx.h"
 
 namespace aria2 {
 
@@ -13,6 +17,7 @@ class BtHaveMessageTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testGetMessage);
   CPPUNIT_TEST(testDoReceivedAction);
+  CPPUNIT_TEST(testDoReceivedAction_goodByeSeeder);
   CPPUNIT_TEST(testToString);
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -24,6 +29,7 @@ public:
   void testCreate();
   void testGetMessage();
   void testDoReceivedAction();
+  void testDoReceivedAction_goodByeSeeder();
   void testToString();
 };
 
@@ -80,6 +86,39 @@ void BtHaveMessageTest::testDoReceivedAction() {
 
   CPPUNIT_ASSERT(peer->hasPiece(msg.getIndex()));
 }
+
+void BtHaveMessageTest::testDoReceivedAction_goodByeSeeder()
+{
+  SharedHandle<Peer> peer(new Peer("ip", 6000));
+  peer->allocateSessionResource(1024, 2*1024);
+  BtHaveMessage msg;
+  msg.setIndex(0);
+  msg.setPeer(peer);
+  SharedHandle<MockPieceStorage> pieceStorage(new MockPieceStorage());
+  msg.setPieceStorage(pieceStorage);
+
+  // peer is not seeder and client have not completed download
+  msg.doReceivedAction();
+
+  pieceStorage->setDownloadFinished(true);
+
+  // client have completed download but, peer is not seeder
+  msg.doReceivedAction();
+
+  msg.setIndex(1);
+  pieceStorage->setDownloadFinished(false);
+
+  // peer is a seeder but client have not completed download
+  msg.doReceivedAction();
+
+  pieceStorage->setDownloadFinished(true);
+  try {
+    msg.doReceivedAction();
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(DlAbortEx& e) {
+    // success
+  }
+}
   
 void BtHaveMessageTest::testToString() {
   BtHaveMessage msg;

+ 8 - 1
test/MockPieceStorage.h

@@ -23,6 +23,7 @@ private:
   SharedHandle<DiskAdaptor> diskAdaptor;
   std::deque<size_t> pieceLengthList;
   std::deque<SharedHandle<Piece> > inFlightPieces;
+  bool _downloadFinished;
   bool _allDownloadFinished;
 public:
   MockPieceStorage():totalLength(0),
@@ -32,6 +33,7 @@ public:
 		     bitfieldMan(0),
 		     selectiveDownloadingMode(false),
 		     endGame(false),
+		     _downloadFinished(false),
 		     _allDownloadFinished(false) {}
 
   virtual ~MockPieceStorage() {}
@@ -133,7 +135,12 @@ public:
   virtual void clearFileFilter() {}
 
   virtual bool downloadFinished() {
-    return false;
+    return _downloadFinished;
+  }
+
+  void setDownloadFinished(bool f)
+  {
+    _downloadFinished = f;
   }
 
   virtual bool allDownloadFinished() {