Selaa lähdekoodia

2006-07-30 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	* src/TorrentMan.h:
	(advertisePiece): Updated doc.
	(getAdvertisedPieceIndexes): Updated doc.
	(removeAdvertisedPiece); New function.
	
	* src/TorrentMan.cc
	(FindElapsedHave): New function object.
	(removeAdvertisedPiece): New function.

	* src/HaveEraseCommand.h: New class.
	* src/HaveEraseCommand.cc: New class.

	* src/FeatureConfig.h: New class.
	* src/FeatureConfig.cc: New class.
	
	* src/Request.h
	(defaultPorts): Removed.
	* src/Request.cc
	(FeatureConfig.h): Included.
	(Request): Removed the statements related to defaultPorts.
	(parseUrl): Removed metalinkEnabled. Use FeatureConfig instead.
	A default port number is now retrieved from FeatureConfig.
	
	* src/main.cc
	(HaveEraseCommand.h): Included.
	(showVersion): Added the output of feature list.
	(main): Added HaveEraseCommand to command queue in BitTorrent
	downloading.
	
	* src/PeerInteractionCommand.h
	(chokeCheckPoint): Commented out.
	(periodicExecPoint): New variable.
	* src/PeerInteractionCommand.cc
	(executeInternal): Following methods are now called in at least 
every
	0.5 seconds to reduce CPU usage:
	detectMessageFlooding(), peerInteraction->checkRequestSlot(),
	checkHave(), sendKeepAlive().
	(checkLongTimePeerChoking): Commented out.

	* src/BitfieldMan.h
	(getNthBitIndex): Changed the method signature.
	(getMissingIndexRandomly): Changed the method signature.
	* src/BitfieldMan.cc
	(getNthBitIndex): Rewritten
	(getMissingIndexRandomly): Rewritten.
	(hasMissingPiece): Rewritten.
	(getMissingIndex): Refactored.
	(getMissingUnusedIndex); Refactored.
	(getMissingIndex): Refactored.
Tatsuhiro Tsujikawa 19 vuotta sitten
vanhempi
commit
928465b7bc

+ 52 - 0
ChangeLog

@@ -1,3 +1,55 @@
+2006-07-30  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	* src/TorrentMan.h:
+	(advertisePiece): Updated doc.
+	(getAdvertisedPieceIndexes): Updated doc.
+	(removeAdvertisedPiece); New function.
+	
+	* src/TorrentMan.cc
+	(FindElapsedHave): New function object.
+	(removeAdvertisedPiece): New function.
+
+	* src/HaveEraseCommand.h: New class.
+	* src/HaveEraseCommand.cc: New class.
+
+	* src/FeatureConfig.h: New class.
+	* src/FeatureConfig.cc: New class.
+	
+	* src/Request.h
+	(defaultPorts): Removed.
+	* src/Request.cc
+	(FeatureConfig.h): Included.
+	(Request): Removed the statements related to defaultPorts.
+	(parseUrl): Removed metalinkEnabled. Use FeatureConfig instead.
+	A default port number is now retrieved from FeatureConfig.
+	
+	* src/main.cc
+	(HaveEraseCommand.h): Included.
+	(showVersion): Added the output of feature list.
+	(main): Added HaveEraseCommand to command queue in BitTorrent
+	downloading.
+	
+	* src/PeerInteractionCommand.h
+	(chokeCheckPoint): Commented out.
+	(periodicExecPoint): New variable.
+	* src/PeerInteractionCommand.cc
+	(executeInternal): Following methods are now called in at least every
+	0.5 seconds to reduce CPU usage:
+	detectMessageFlooding(), peerInteraction->checkRequestSlot(),
+	checkHave(), sendKeepAlive().
+	(checkLongTimePeerChoking): Commented out.
+
+	* src/BitfieldMan.h
+	(getNthBitIndex): Changed the method signature.
+	(getMissingIndexRandomly): Changed the method signature.
+	* src/BitfieldMan.cc
+	(getNthBitIndex): Rewritten
+	(getMissingIndexRandomly): Rewritten.
+	(hasMissingPiece): Rewritten.
+	(getMissingIndex): Refactored.
+	(getMissingUnusedIndex); Refactored.
+	(getMissingIndex): Refactored.
+	
 2006-07-27  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	* src/PeerMessage.h

+ 28 - 60
src/BitfieldMan.cc

@@ -74,45 +74,36 @@ int BitfieldMan::countSetBit(const unsigned char* bitfield, int len) const {
   return count;
 }
 
-int BitfieldMan::getNthBitIndex(const unsigned char* bitfield, int len, int nth) const {
+int BitfieldMan::getNthBitIndex(const unsigned char bitfield, int nth) const {
   int index = -1;
-  for(int i = 0; i < len && index == -1; i++) {
-    unsigned char bit = bitfield[i];
-    for(int bs = 7; bs >= 0; bs--) {
-      unsigned char mask = 1 << bs;
-      if(bit & mask) {
-	nth--;
-	if(nth == 0) {
-	  index = i*8+7-bs;
-	  break;
-	}
+  for(int bs = 7; bs >= 0; bs--) {
+    unsigned char mask = 1 << bs;
+    if(bitfield & mask) {
+      nth--;
+      if(nth == 0) {
+	index = 7-bs;
+	break;
       }
     }
   }
   return index;
 }
 
-int BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, int len, int randMax) const {
-  int nth = 1+(int)(((double)randMax)*random()/(RAND_MAX+1.0));
+int
+BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield,
+				     int bitfieldLength) const
+{
+  int byte = (int)(((double)bitfieldLength)*random()/(RAND_MAX+1.0));
 
-  int count = 0;
-  int size = sizeof(unsigned int);
-  for(int i = 0; i < len/size; i++) {
-    int temp = Util::countBit(*(unsigned int*)&bitfield[i*size]);
-    if(nth <= count+temp) {
-      int t = i*size*8+getNthBitIndex(&bitfield[i*size], size, nth-count);
-      return t;
-    } else {
-      count += temp;
+  for(int i = 0; i < bitfieldLength; i++) {
+    unsigned char mask = 0xff;
+    if(bitfield[byte]&mask) {
+      int index = byte*8+getNthBitIndex(bitfield[byte], 1);
+      return index;
     }
-  }
-  for(int i = len-len%size; i < len; i++) {
-    int temp = Util::countBit((unsigned int)bitfield[i]);
-    if(nth <= count+temp) {
-      int t = i*8+getNthBitIndex(&bitfield[i], 1, nth-count);
-      return t;      
-    } else {
-      count += temp;
+    byte++;
+    if(byte == bitfieldLength) {
+      byte = 0;
     }
   }
   return -1;
@@ -122,28 +113,17 @@ bool BitfieldMan::hasMissingPiece(const unsigned char* peerBitfield, int length)
   if(bitfieldLength != length) {
     return false;
   }
-  unsigned char* tempBitfield = new unsigned char[bitfieldLength];
+  bool retval = false;
   for(int i = 0; i < bitfieldLength; i++) {
-    tempBitfield[i] = peerBitfield[i] & ~bitfield[i];
+    unsigned char temp = peerBitfield[i] & ~bitfield[i];
     if(filterEnabled) {
-      tempBitfield[i] &= filterBitfield[i];
+      temp &= filterBitfield[i];
     }
-  }
-  bool retval = false;
-  int size = sizeof(unsigned int);
-  for(int i = 0; i < length/size; i++) {
-    if(Util::countBit(*(unsigned int*)&tempBitfield[i*size]) > 0) {
-      retval = true;
-      break;
-    }
-  }
-  for(int i = length-length%size; i < length && retval == false; i++) {
-    if(Util::countBit((unsigned int)tempBitfield[i]) > 0) {
+    if(temp&0xff) {
       retval = true;
       break;
     }
   }
-  delete [] tempBitfield;
   return retval;
 }
 
@@ -158,11 +138,7 @@ int BitfieldMan::getMissingIndex(const unsigned char* peerBitfield, int length)
       tempBitfield[i] &= filterBitfield[i];
     }
   }
-  int max = countSetBit(tempBitfield, bitfieldLength);
-  int index = -1;
-  if(max > 0) {
-    index = getMissingIndexRandomly(tempBitfield, bitfieldLength, max);
-  }
+  int index = getMissingIndexRandomly(tempBitfield, bitfieldLength);
   delete [] tempBitfield;
   return index;
 }
@@ -178,11 +154,7 @@ int BitfieldMan::getMissingUnusedIndex(const unsigned char* peerBitfield, int le
       tempBitfield[i] &= filterBitfield[i];
     }
   }
-  int max = countSetBit(tempBitfield, bitfieldLength);
-  int index = -1;
-  if(max > 0) {
-    index = getMissingIndexRandomly(tempBitfield, bitfieldLength, max);
-  }
+  int index = getMissingIndexRandomly(tempBitfield, bitfieldLength);
   delete [] tempBitfield;
   return index;
 }
@@ -230,11 +202,7 @@ int BitfieldMan::getMissingIndex() const {
       tempBitfield[i] &= filterBitfield[i];
     }
   }
-  int max = countSetBit(tempBitfield, bitfieldLength);
-  int index = -1;
-  if(max > 0) {
-    index = getMissingIndexRandomly(tempBitfield, bitfieldLength, max);
-  }
+  int index = getMissingIndexRandomly(tempBitfield, bitfieldLength);
   delete [] tempBitfield;
   return index;
 }

+ 2 - 2
src/BitfieldMan.h

@@ -38,8 +38,8 @@ private:
   int blocks;
   bool filterEnabled;
   int countSetBit(const unsigned char* bitfield, int len) const;
-  int getNthBitIndex(const unsigned char* bitfield, int len, int nth) const;
-  int getMissingIndexRandomly(const unsigned char* bitfield, int len, int randMax) const;
+  int getNthBitIndex(const unsigned char bit, int nth) const;
+  int getMissingIndexRandomly(const unsigned char* bitfield, int len) const;
   bool isBitSetInternal(const unsigned char* bitfield, int index) const;
   bool setBitInternal(unsigned char* bitfield, int index, bool on);
   bool setFilterBit(int index);

+ 56 - 0
src/FeatureConfig.cc

@@ -0,0 +1,56 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* copyright --> */
+#include "FeatureConfig.h"
+
+string FeatureConfig::FEATURE_HTTP = "http";
+string FeatureConfig::FEATURE_HTTPS = "https";
+string FeatureConfig::FEATURE_FTP = "ftp";
+string FeatureConfig::FEATURE_BITTORRENT = "bittorrent";
+string FeatureConfig::FEATURE_METALINK = "metalink";
+
+static ProtocolPortMap::value_type defaultPortsArray[] = {
+  ProtocolPortMap::value_type(FeatureConfig::FEATURE_HTTP, 80),
+  ProtocolPortMap::value_type(FeatureConfig::FEATURE_HTTPS, 443),
+  ProtocolPortMap::value_type(FeatureConfig::FEATURE_FTP, 21),
+};
+
+ProtocolPortMap FeatureConfig::defaultPorts(&defaultPortsArray[0],
+					     &defaultPortsArray[3]);
+
+static SupportedFeatureMap::value_type supportedFeaturesArray[] = {
+  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_HTTP, true),
+#ifdef ENABLE_SSL
+  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_HTTPS, true),
+#endif // ENABLE_SSL
+  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_FTP, true),
+#ifdef ENABLE_BITTORRENT
+  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_BITTORRENT, true),
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_METALINK, true),
+#endif // ENABLE_METALINK
+};
+
+SupportedFeatureMap
+FeatureConfig::supportedFeatures(&supportedFeaturesArray[0],
+				 &supportedFeaturesArray[sizeof(supportedFeaturesArray)/sizeof(SupportedFeatureMap::value_type)]);
+

+ 80 - 0
src/FeatureConfig.h

@@ -0,0 +1,80 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* copyright --> */
+#ifndef _D_FEATURE_CONFIG_H_
+#define _D_FEATURE_CONFIG_H_
+
+#include "common.h"
+#include <map>
+
+typedef map<string, int> ProtocolPortMap;
+typedef map<string, bool> SupportedFeatureMap;
+
+class FeatureConfig {
+private:
+  static ProtocolPortMap defaultPorts;
+  static SupportedFeatureMap supportedFeatures;
+public:
+  static string FEATURE_HTTP;
+  static string FEATURE_HTTPS;
+  static string FEATURE_FTP;
+  static string FEATURE_BITTORRENT;
+  static string FEATURE_METALINK;
+
+  static int getDefaultPort(const string& protocol) {
+    if(defaultPorts.count(protocol)) {
+      return defaultPorts[protocol];
+    } else {
+      return 0;
+    }
+  }
+
+  static bool isSupported(const string& protocol) {
+    if(supportedFeatures.count(protocol)) {
+      return supportedFeatures[protocol];
+    } else {
+      return false;
+    }
+  }
+  
+  static string getConfigurationSummary() {
+    string protos[] = {
+      FEATURE_HTTP,
+      FEATURE_HTTPS,
+      FEATURE_FTP,
+      FEATURE_BITTORRENT,
+      FEATURE_METALINK
+    };
+    string summary;
+    for(int i = 0; i < (int)(sizeof(protos)/sizeof(string)); i++) {
+      summary += protos[i];
+      if(isSupported(protos[i])) {
+	summary += ": yes";
+      } else {
+	summary += ": no";
+      }
+      summary += "\n";
+    }
+    return summary;
+  }
+};
+
+#endif // _D_FEATURE_CONFIG_H_

+ 34 - 0
src/HaveEraseCommand.cc

@@ -0,0 +1,34 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* copyright --> */
+#include "HaveEraseCommand.h"
+
+bool HaveEraseCommand::execute() {
+  if(e->torrentMan->isHalt()) {
+    return true;
+  }
+  if(cp.elapsed(interval)) {
+    cp.reset();
+    e->torrentMan->removeAdvertisedPiece(5);
+  }
+  e->commands.push_back(this);
+  return false;
+}

+ 44 - 0
src/HaveEraseCommand.h

@@ -0,0 +1,44 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* copyright --> */
+#ifndef _D_HAVE_ERASE_COMMAND_H_
+#define _D_HAVE_ERASE_COMMAND_H_
+
+#include "Command.h"
+#include "TorrentDownloadEngine.h"
+
+class HaveEraseCommand : public Command {
+private:
+  TorrentDownloadEngine* e;
+  Time cp;
+  int interval;
+public:
+  HaveEraseCommand(int cuid, TorrentDownloadEngine* e, int interval)
+    :Command(cuid),
+     e(e),
+     interval(interval) {}
+
+  virtual ~HaveEraseCommand() {}
+
+  virtual bool execute();
+};
+
+#endif // _D_HAVE_ERASE_COMMAND_H_

+ 6 - 4
src/Makefile.am

@@ -51,7 +51,8 @@ SRCS =  Socket.h\
 	LogFactory.cc LogFactory.h\
 	NullLogger.h\
 	Time.cc Time.h\
-	SharedHandle.h
+	SharedHandle.h\
+	FeatureConfig.cc FeatureConfig.h
 
 if ENABLE_BITTORRENT
 SRCS += MetaEntry.h\
@@ -106,7 +107,8 @@ SRCS += MetaEntry.h\
 	AllowedFastMessage.cc AllowedFastMessage.h\
 	SuggestPieceMessage.cc SuggestPieceMessage.h\
 	SimplePeerMessage.cc SimplePeerMessage.h\
-	PeerMessageFactory.cc PeerMessageFactory.h
+	PeerMessageFactory.cc PeerMessageFactory.h\
+	HaveEraseCommand.cc HaveEraseCommand.h
 endif # ENABLE_BITTORRENT
 
 if ENABLE_METALINK
@@ -121,8 +123,8 @@ noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@
-#aria2c_LDFLAGS = -pg
+aria2c_LDFLAGS = -pg
 AM_CPPFLAGS =  -Wall\
 	-I../lib -I../intl -I$(top_srcdir)/intl\
 	@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
-	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@# -pg
+	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg

+ 21 - 15
src/Makefile.in

@@ -90,7 +90,8 @@ bin_PROGRAMS = aria2c$(EXEEXT)
 @ENABLE_BITTORRENT_TRUE@	AllowedFastMessage.cc AllowedFastMessage.h\
 @ENABLE_BITTORRENT_TRUE@	SuggestPieceMessage.cc SuggestPieceMessage.h\
 @ENABLE_BITTORRENT_TRUE@	SimplePeerMessage.cc SimplePeerMessage.h\
-@ENABLE_BITTORRENT_TRUE@	PeerMessageFactory.cc PeerMessageFactory.h
+@ENABLE_BITTORRENT_TRUE@	PeerMessageFactory.cc PeerMessageFactory.h\
+@ENABLE_BITTORRENT_TRUE@	HaveEraseCommand.cc HaveEraseCommand.h
 
 @ENABLE_METALINK_TRUE@am__append_2 = Metalinker.cc Metalinker.h\
 @ENABLE_METALINK_TRUE@	MetalinkEntry.cc MetalinkEntry.h\
@@ -154,12 +155,13 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	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 Time.cc Time.h \
-	SharedHandle.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 TorrentMan.cc \
-	TorrentMan.h PeerConnection.cc PeerConnection.h \
-	PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
-	PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
+	SharedHandle.h FeatureConfig.cc FeatureConfig.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 TorrentMan.cc TorrentMan.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 BitfieldMan.cc \
 	BitfieldMan.h TorrentDownloadEngine.cc TorrentDownloadEngine.h \
@@ -188,9 +190,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	RejectMessage.h AllowedFastMessage.cc AllowedFastMessage.h \
 	SuggestPieceMessage.cc SuggestPieceMessage.h \
 	SimplePeerMessage.cc SimplePeerMessage.h PeerMessageFactory.cc \
-	PeerMessageFactory.h Metalinker.cc Metalinker.h \
-	MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \
-	MetalinkResource.h MetalinkProcessor.h \
+	PeerMessageFactory.h HaveEraseCommand.cc HaveEraseCommand.h \
+	Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
+	MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
 	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h
 @ENABLE_BITTORRENT_TRUE@am__objects_1 = Data.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	Dictionary.$(OBJEXT) List.$(OBJEXT) \
@@ -238,7 +240,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 @ENABLE_BITTORRENT_TRUE@	AllowedFastMessage.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	SuggestPieceMessage.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	SimplePeerMessage.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@	PeerMessageFactory.$(OBJEXT)
+@ENABLE_BITTORRENT_TRUE@	PeerMessageFactory.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	HaveEraseCommand.$(OBJEXT)
 @ENABLE_METALINK_TRUE@am__objects_2 = Metalinker.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	MetalinkEntry.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	MetalinkResource.$(OBJEXT) \
@@ -266,7 +269,7 @@ am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 	PreAllocationDiskWriter.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
 	File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \
 	CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) Time.$(OBJEXT) \
-	$(am__objects_1) $(am__objects_2)
+	FeatureConfig.$(OBJEXT) $(am__objects_1) $(am__objects_2)
 am_libaria2c_a_OBJECTS = $(am__objects_3)
 libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
 am__installdirs = "$(DESTDIR)$(bindir)"
@@ -455,17 +458,18 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
 	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 Time.cc Time.h \
-	SharedHandle.h $(am__append_1) $(am__append_2)
+	SharedHandle.h FeatureConfig.cc FeatureConfig.h \
+	$(am__append_1) $(am__append_2)
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@
 
-#aria2c_LDFLAGS = -pg
+aria2c_LDFLAGS = -pg
 AM_CPPFLAGS = -Wall\
 	-I../lib -I../intl -I$(top_srcdir)/intl\
 	@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
-	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@# -pg
+	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg
 
 all: all-am
 
@@ -563,6 +567,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DiskAdaptor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpDownloadCommand.Po@am__quote@
@@ -572,6 +577,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelResponseCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HandshakeMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveAllMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveEraseCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveNoneMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpConnection.Po@am__quote@

+ 10 - 4
src/PeerInteractionCommand.cc

@@ -115,14 +115,18 @@ bool PeerInteractionCommand::executeInternal() {
   case WIRED:
     peerInteraction->syncPiece();
     decideChoking();
+
+    if(periodicExecPoint.elapsedInMillis(500)) {
+      periodicExecPoint.reset();
+      detectMessageFlooding();
+      peerInteraction->checkRequestSlot();
+      checkHave();
+      sendKeepAlive();
+    }
     receiveMessages();
-    detectMessageFlooding();
 
-    peerInteraction->checkRequestSlot();
     peerInteraction->addRequests();
-    checkHave();
     peerInteraction->sendMessages(e->getUploadSpeed());
-    sendKeepAlive();
     break;
   }
   if(peerInteraction->countMessageInQueue() > 0) {
@@ -152,6 +156,7 @@ void PeerInteractionCommand::detectMessageFlooding() {
   }
 }
 
+/*
 void PeerInteractionCommand::checkLongTimePeerChoking() {
   if(e->torrentMan->downloadComplete()) {
     return;
@@ -165,6 +170,7 @@ void PeerInteractionCommand::checkLongTimePeerChoking() {
     chokeCheckPoint.reset();
   }
 }
+*/
 
 void PeerInteractionCommand::decideChoking() {
   if(peer->shouldBeChoking()) {

+ 2 - 1
src/PeerInteractionCommand.h

@@ -38,9 +38,10 @@ private:
   PeerInteraction* peerInteraction;
  
   Time keepAliveCheckPoint;
-  Time chokeCheckPoint;
+  //Time chokeCheckPoint;
   Time freqCheckPoint;
   Time haveCheckTime;
+  Time periodicExecPoint;
   int chokeUnchokeCount;
   int haveCount;
   int keepAliveCount;

+ 4 - 14
src/Request.cc

@@ -21,14 +21,9 @@
 /* copyright --> */
 #include "Request.h"
 #include "Util.h"
+#include "FeatureConfig.h"
 
 Request::Request():port(0), tryCount(0), isTorrent(false) {
-  defaultPorts["http"] = 80;
-#ifdef ENABLE_SSL
-  // for SSL
-  defaultPorts["https"] = 443;
-#endif // ENABLE_SSL
-  defaultPorts["ftp"] = 21;
   seg.sp = 0;
   seg.ep = 0;
   seg.ds = 0;
@@ -56,16 +51,11 @@ bool Request::redirectUrl(const string& url) {
 }
 
 bool Request::parseUrl(const string& url) {
-#ifdef ENABLE_METALINK
-  bool metalinkEnabled = true;
-#else
-  bool metalinkEnabled = false;
-#endif
-
   string tempUrl;
   string::size_type sharpIndex = url.find("#");
   if(sharpIndex != string::npos) {
-    if(metalinkEnabled && url.find(METALINK_MARK) == sharpIndex) {
+    if(FeatureConfig::isSupported(FeatureConfig::FEATURE_METALINK) &&
+       url.find(METALINK_MARK) == sharpIndex) {
       tempUrl = url.substr(sharpIndex+strlen(METALINK_MARK));
     } else {
       tempUrl = url.substr(0, sharpIndex);
@@ -92,7 +82,7 @@ bool Request::parseUrl(const string& url) {
   if(hp == string::npos) return false;
   protocol = tempUrl.substr(0, hp);
   int defPort;
-  if((defPort = defaultPorts[protocol]) == 0) {
+  if((defPort = FeatureConfig::getDefaultPort(protocol)) == 0) {
     return false;
   }
   hp += 3;

+ 0 - 1
src/Request.h

@@ -57,7 +57,6 @@ private:
   int port;
   string dir;
   string file;
-  map<string, int> defaultPorts;
   int tryCount;
   int trackerEvent;
   bool parseUrl(const string& url);

+ 30 - 1
src/TorrentMan.cc

@@ -660,7 +660,9 @@ void TorrentMan::advertisePiece(int cuid, int index) {
 
 PieceIndexes
 TorrentMan::getAdvertisedPieceIndexes(int myCuid,
-				      const Time& lastCheckTime) const {
+				      const Time& lastCheckTime
+				      ) const
+{
   PieceIndexes indexes;
   for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
     const Haves::value_type& have = *itr;
@@ -674,3 +676,30 @@ TorrentMan::getAdvertisedPieceIndexes(int myCuid,
   }
   return indexes;
 }
+
+class FindElapsedHave
+{
+private:
+  int elapsed;
+public:
+  FindElapsedHave(int elapsed):elapsed(elapsed) {}
+
+  bool operator()(const HaveEntry& have) {
+    if(have.registeredTime.elapsed(elapsed)) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+};
+  
+void
+TorrentMan::removeAdvertisedPiece(int elapsed)
+{
+  Haves::iterator itr = find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
+  if(itr != haves.end()) {
+    logger->debug("Removed %d have entries.", haves.end()-itr);
+    haves.erase(itr, haves.end());
+  }
+}
+

+ 6 - 0
src/TorrentMan.h

@@ -176,9 +176,15 @@ public:
 
   string getPieceHash(int index) const;
 
+  // Addes piece index to advertise to other commands. They send have message
+  // based on this information.
   void advertisePiece(int cuid, int index);
 
+  // Returns piece index which is not advertised by the caller command and
+  // newer than lastCheckTime.
   PieceIndexes getAdvertisedPieceIndexes(int myCuid, const Time& lastCheckTime) const;
+  // Removes have entry if specified seconds have elapsed since its registration.
+  void removeAdvertisedPiece(int elapsed);
 
   long long int getTotalLength() const { return totalLength; }
   void setTotalLength(long long int length) { totalLength = length; }

+ 7 - 0
src/main.cc

@@ -29,6 +29,7 @@
 #include "Util.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "prefs.h"
+#include "FeatureConfig.h"
 
 #ifdef ENABLE_BITTORRENT
 # include "TorrentConsoleDownloadEngine.h"
@@ -37,6 +38,7 @@
 # include "TorrentAutoSaveCommand.h"
 # include "TrackerWatcherCommand.h"
 # include "TrackerUpdateCommand.h"
+# include "HaveEraseCommand.h"
 # include "ByteArrayDiskWriter.h"
 # include "PeerChokeCommand.h"
 #endif // ENABLE_BITTORRENT
@@ -129,6 +131,9 @@ void showVersion() {
   cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl;
   cout << "Copyright (C) 2006 Tatsuhiro Tsujikawa" << endl;
   cout << endl;
+  cout << "**Configuration**" << endl;
+  cout << FeatureConfig::getConfigurationSummary();
+  cout << endl;
   cout <<
     _("This program is free software; you can redistribute it and/or modify\n"
       "it under the terms of the GNU General Public License as published by\n"
@@ -881,6 +886,8 @@ int main(int argc, char* argv[]) {
 							op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
       te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(),
 						  10, te));
+      te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(),
+						  te, 10));
       te->run();
       
       if(te->torrentMan->downloadComplete()) {

+ 73 - 0
test/BitfieldManTest.cc

@@ -11,6 +11,7 @@ class BitfieldManTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testGetFirstMissingUnusedIndex);
   CPPUNIT_TEST(testIsAllBitSet);
   CPPUNIT_TEST(testFilter);
+  CPPUNIT_TEST(testGetMissingIndex);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -22,6 +23,7 @@ public:
   void testGetFirstMissingUnusedIndex();
   void testIsAllBitSet();
   void testFilter();
+  void testGetMissingIndex();
 };
 
 
@@ -136,3 +138,74 @@ void BitfieldManTest::testFilter() {
   btman2.enableFilter();
   CPPUNIT_ASSERT_EQUAL((long long int)31, btman2.getFilteredTotalLength());
 }
+
+void BitfieldManTest::testGetMissingIndex() {
+  srandom(100);
+
+  BitfieldMan bt1(1024, 1024*256);
+
+  unsigned char bitArray[] = {
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+  };
+  CPPUNIT_ASSERT_EQUAL(80, bt1.getMissingIndex(bitArray, 32));
+
+  unsigned char bitArray2[] = {
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0x00, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+  };
+
+  CPPUNIT_ASSERT_EQUAL(80, bt1.getMissingIndex(bitArray2, 32));
+
+  unsigned char bitArray3[] = {
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x0f,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+  };
+
+  CPPUNIT_ASSERT_EQUAL(60, bt1.getMissingIndex(bitArray3, 32));
+
+  unsigned char bitArray4[] = {
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+  };
+
+  CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingIndex(bitArray4, 32));
+
+  unsigned char bitArray5[] = {
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+  };
+
+  CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingIndex(bitArray5, 32));
+
+}

+ 42 - 0
test/FeatureConfigTest.cc

@@ -0,0 +1,42 @@
+#include "FeatureConfig.h"
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FeatureConfigTest:public CppUnit::TestFixture {
+
+  CPPUNIT_TEST_SUITE(FeatureConfigTest);
+  CPPUNIT_TEST(testGetDefaultPort);
+  CPPUNIT_TEST(testIsSupported);
+  CPPUNIT_TEST(testGetConfigurationSummary);
+  CPPUNIT_TEST_SUITE_END();
+  
+public:
+  void testGetDefaultPort();
+  void testIsSupported();
+  void testGetConfigurationSummary();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FeatureConfigTest);
+
+void FeatureConfigTest::testGetDefaultPort() {
+  CPPUNIT_ASSERT_EQUAL(80, FeatureConfig::getDefaultPort("http"));
+  CPPUNIT_ASSERT_EQUAL(443, FeatureConfig::getDefaultPort("https"));
+  CPPUNIT_ASSERT_EQUAL(21, FeatureConfig::getDefaultPort("ftp"));
+}
+
+void FeatureConfigTest::testIsSupported() {
+  CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::isSupported("http"));
+  CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::isSupported("https"));
+  CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::isSupported("ftp"));
+  CPPUNIT_ASSERT_EQUAL(false, FeatureConfig::isSupported("ftps"));
+}
+
+void FeatureConfigTest::testGetConfigurationSummary() {
+  CPPUNIT_ASSERT_EQUAL(string("http: yes\n")
+		       +"https: yes\n"
+		       +"ftp: yes\n"
+		       +"bittorrent: yes\n"
+		       +"metalink: yes\n",
+		       FeatureConfig::getConfigurationSummary());
+}

+ 2 - 1
test/Makefile.am

@@ -34,7 +34,8 @@ aria2c_SOURCES = AllTest.cc\
 	SuggestPieceMessageTest.cc\
 	Xml2MetalinkProcessorTest.cc\
 	MetalinkerTest.cc\
-	MetalinkEntryTest.cc
+	MetalinkEntryTest.cc\
+	FeatureConfigTest.cc
 #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
 #aria2c_LDFLAGS = ${CPPUNIT_LIBS}
 

+ 4 - 2
test/Makefile.in

@@ -73,7 +73,7 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestTest.$(OBJEXT) \
 	RejectMessageTest.$(OBJEXT) AllowedFastMessageTest.$(OBJEXT) \
 	SuggestPieceMessageTest.$(OBJEXT) \
 	Xml2MetalinkProcessorTest.$(OBJEXT) MetalinkerTest.$(OBJEXT) \
-	MetalinkEntryTest.$(OBJEXT)
+	MetalinkEntryTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT)
 aria2c_OBJECTS = $(am_aria2c_OBJECTS)
 am__DEPENDENCIES_1 =
 aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1)
@@ -255,7 +255,8 @@ aria2c_SOURCES = AllTest.cc\
 	SuggestPieceMessageTest.cc\
 	Xml2MetalinkProcessorTest.cc\
 	MetalinkerTest.cc\
-	MetalinkEntryTest.cc
+	MetalinkEntryTest.cc\
+	FeatureConfigTest.cc
 
 #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
 #aria2c_LDFLAGS = ${CPPUNIT_LIBS}
@@ -328,6 +329,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DataTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriterTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DictionaryTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfigTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveAllMessageTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveMessageTest.Po@am__quote@

+ 8 - 0
test/PeerMessageUtilTest.cc

@@ -1,4 +1,12 @@
 #include "PeerMessageUtil.h"
+#include "UnchokeMessage.h"
+#include "InterestedMessage.h"
+#include "NotInterestedMessage.h"
+#include "HaveMessage.h"
+#include "BitfieldMessage.h"
+#include "RequestMessage.h"
+#include "PieceMessage.h"
+#include "CancelMessage.h"
 #include <netinet/in.h>
 #include <string>
 #include <cppunit/extensions/HelperMacros.h>