Browse Source

2006-06-22 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	To make a listening socket non-block:
	
	* src/SocketCore.h
	(setNonBlockingMode): New function.
	* src/SocketCore.cc
	(setNonBlockingMode): New function.
	(beginListen): Added a call to setNonBlockingMode().
	(acceptConnection): Call setNonBlockingMode().
	(setBlockingMode): Updated.

	To handle tracker's NAT-checking:
	
	* src/PeerConnection.cc
	(receiveHandshake): 'msg' param is filled with received data and
	its length is assigned to 'length' param, even if all handshake
	message is not yet received.
	* src/PeerInteractionCommand.cc
	(executeInternal): Use peerInteraction->receiveHandshake(true) 
when
	a new peer connects to localhost.
	A call to peerInteraction->sendHandshake() was removed because 
	it is called from peerInteraction->receiveHandshake(true).
	* src/PeerInteraction.h
	(quickReplied): New variable.
	(receiveHandshake): Added an argument.
	* src/PeerInteraction.cc
	(PeerInteraction): Added the initialization of quickReplied.
	(receiveHandshake): Send handshake message as soon as the info 
hash
	in a handshake message from a peer is correct.

	
	To change the random part of peer id and key parameter:

	* src/TorrentMan.h
	(key): New variable.
	* src/TorrentMan.cc
	(setupInternal1): Use Util::randomAlpha() to generate random 
part
	of peer id, which is now "-aria2-"+13 alphabet 
characters([A-Za-z]).
	key is also generated by Util::randomAlpha() and it is now 8 
character
	long.
	* src/Util.h
	(randomAlpha): New function.
	* src/Util.cc
	(randomAlpha): New function.
	* src/TrackerWatcherCommand.cc
	(execute): In a tracker request: Use torrentMan->key as key 
parameter.
	Added no_peer_id=1.
	
	Set snubbing flag to false when a choke message is received from 
a
	snubbed peer.

	* src/ChokeMessage.cc
	(receivedAction): Set snubbing flag to false.
Tatsuhiro Tsujikawa 19 years ago
parent
commit
d02d80d9e9

+ 55 - 0
ChangeLog

@@ -1,3 +1,58 @@
+2006-06-22  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	To make a listening socket non-block:
+	
+	* src/SocketCore.h
+	(setNonBlockingMode): New function.
+	* src/SocketCore.cc
+	(setNonBlockingMode): New function.
+	(beginListen): Added a call to setNonBlockingMode().
+	(acceptConnection): Call setNonBlockingMode().
+	(setBlockingMode): Updated.
+
+	To handle tracker's NAT-checking:
+	
+	* src/PeerConnection.cc
+	(receiveHandshake): 'msg' param is filled with received data and
+	its length is assigned to 'length' param, even if all handshake
+	message is not yet received.
+	* src/PeerInteractionCommand.cc
+	(executeInternal): Use peerInteraction->receiveHandshake(true) when
+	a new peer connects to localhost.
+	A call to peerInteraction->sendHandshake() was removed because 
+	it is called from peerInteraction->receiveHandshake(true).
+	* src/PeerInteraction.h
+	(quickReplied): New variable.
+	(receiveHandshake): Added an argument.
+	* src/PeerInteraction.cc
+	(PeerInteraction): Added the initialization of quickReplied.
+	(receiveHandshake): Send handshake message as soon as the info hash
+	in a handshake message from a peer is correct.
+
+	
+	To change the random part of peer id and key parameter:
+
+	* src/TorrentMan.h
+	(key): New variable.
+	* src/TorrentMan.cc
+	(setupInternal1): Use Util::randomAlpha() to generate random part
+	of peer id, which is now "-aria2-"+13 alphabet characters([A-Za-z]).
+	key is also generated by Util::randomAlpha() and it is now 8 character
+	long.
+	* src/Util.h
+	(randomAlpha): New function.
+	* src/Util.cc
+	(randomAlpha): New function.
+	* src/TrackerWatcherCommand.cc
+	(execute): In a tracker request: Use torrentMan->key as key parameter.
+	Added no_peer_id=1.
+	
+	Set snubbing flag to false when a choke message is received from a
+	snubbed peer.
+
+	* src/ChokeMessage.cc
+	(receivedAction): Set snubbing flag to false.
+	
 2006-06-18  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	* src/TorrentMan.cc (setupInternal1): Fixed peerId generation bug.

+ 1 - 0
src/ChokeMessage.cc

@@ -40,6 +40,7 @@ ChokeMessage* ChokeMessage::create(const char* data, int dataLength) {
 
 void ChokeMessage::receivedAction() {
   peer->peerChoking = true;
+  peer->snubbing = false;
   peerInteraction->onChoked();
 }
 

+ 13 - 7
src/PeerConnection.cc

@@ -101,6 +101,7 @@ bool PeerConnection::receiveMessage(char* msg, int& length) {
 
 bool PeerConnection::receiveHandshake(char* msg, int& length) {
   if(!socket->isReadable(0)) {
+    length = 0;
     return false;
   }
   int remain = HANDSHAKE_MESSAGE_LENGTH-resbufLength;
@@ -110,14 +111,19 @@ bool PeerConnection::receiveHandshake(char* msg, int& length) {
     // we got EOF
     throw new DlAbortEx(EX_EOF_FROM_PEER);
   }
+  bool retval;
   if(remain != temp) {
-    resbufLength += temp;
-    return false;
+    retval = false;
+  } else {
+    retval = true;
   }
+  resbufLength += temp;
   // we got whole handshake payload
-  resbufLength = 0;
-
-  memcpy(msg, resbuf, HANDSHAKE_MESSAGE_LENGTH);
-  length = HANDSHAKE_MESSAGE_LENGTH;
-  return true;
+  int writeLength = resbufLength > length ? length : resbufLength;
+  memcpy(msg, resbuf, writeLength);
+  length = writeLength;
+  if(retval) {
+    resbufLength = 0;
+  }
+  return retval;
 }

+ 14 - 4
src/PeerInteraction.cc

@@ -35,7 +35,8 @@ PeerInteraction::PeerInteraction(int cuid,
   :cuid(cuid),
    uploadLimit(0),
    torrentMan(torrentMan),
-   peer(peer) {
+   peer(peer),
+   quickReplied(false) {
   peerConnection = new PeerConnection(cuid, socket, op);
   logger = LogFactory::getInstance();
 }
@@ -285,10 +286,19 @@ int PeerInteraction::countRequestSlot() const {
   return requestSlots.size();
 }
 
-HandshakeMessage* PeerInteraction::receiveHandshake() {
+HandshakeMessage* PeerInteraction::receiveHandshake(bool quickReply) {
   char msg[HANDSHAKE_MESSAGE_LENGTH];
-  int msgLength = 0;
-  if(!peerConnection->receiveHandshake(msg, msgLength)) {
+  int msgLength = HANDSHAKE_MESSAGE_LENGTH;
+  bool retval = peerConnection->receiveHandshake(msg, msgLength);
+  // To handle tracker's NAT-checking feature
+  if(!quickReplied && quickReply && msgLength >= 48) {
+    quickReplied = true;
+    // check info_hash
+    if(memcmp(torrentMan->getInfoHash(), &msg[28], INFO_HASH_LENGTH) == 0) {
+      sendHandshake();
+    }
+  }
+  if(!retval) {
     return NULL;
   }
   HandshakeMessage* handshakeMessage = createHandshakeMessage(msg, msgLength);

+ 3 - 2
src/PeerInteraction.h

@@ -62,8 +62,9 @@ private:
   Pieces pieces;
   // allowed fast piece indexes that local client has sent
   Integers fastSet;
+  bool quickReplied;
   const Logger* logger;
-  
+
   void getNewPieceAndSendInterest(int pieceNum);
   PeerMessage* createPeerMessage(const char* msg, int msgLength);
   HandshakeMessage* createHandshakeMessage(const char* msg, int msgLength);
@@ -116,7 +117,7 @@ public:
   void sendAllowedFast();
 
   PeerMessage* receiveMessage();
-  HandshakeMessage* receiveHandshake();
+  HandshakeMessage* receiveHandshake(bool quickReply = false);
 
   RequestMessage* createRequestMessage(int index, int blockIndex);
   CancelMessage* createCancelMessage(int index, int begin, int length);

+ 2 - 2
src/PeerInteractionCommand.cc

@@ -89,7 +89,8 @@ bool PeerInteractionCommand::executeInternal() {
     break;
   }
   case RECEIVER_WAIT_HANDSHAKE: {
-    HandshakeMessage* handshakeMessage = peerInteraction->receiveHandshake();
+    HandshakeMessage* handshakeMessage =
+      peerInteraction->receiveHandshake(true);
     if(handshakeMessage == NULL) {
       break;
     }
@@ -98,7 +99,6 @@ bool PeerInteractionCommand::executeInternal() {
 		 peer->ipaddr.c_str(), peer->port,
 		 handshakeMessage->toString().c_str());
     delete handshakeMessage;
-    peerInteraction->sendHandshake();
     haveCheckTime.reset();
     peerInteraction->sendBitfield();
     peerInteraction->sendAllowedFast();

+ 11 - 3
src/SocketCore.cc

@@ -93,6 +93,8 @@ void SocketCore::beginListen(int port) {
   if(listen(sockfd, 1) == -1) {
     throw new DlAbortEx(EX_SOCKET_LISTEN, strerror(errno));
   }
+
+  setNonBlockingMode();
 }
 
 SocketCore* SocketCore::acceptConnection() const {
@@ -166,16 +168,22 @@ void SocketCore::establishConnection(const string& host, int port) {
     freeaddrinfo(res);
   }
   // make socket non-blocking mode
-  int flags = fcntl(sockfd, F_GETFL, 0);
-  fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
+  setNonBlockingMode();
   if(connect(sockfd, (struct sockaddr*)&sockaddr, (socklen_t)sizeof(sockaddr)) == -1 && errno != EINPROGRESS) {
     throw new DlAbortEx(EX_SOCKET_CONNECT, host.c_str(), strerror(errno));
   }
 }
 
+void SocketCore::setNonBlockingMode() const {
+  int flags = fcntl(sockfd, F_GETFL, 0);
+  // TODO add error handling
+  fcntl(sockfd, F_SETFL, flags|O_NONBLOCK);
+}
+
 void SocketCore::setBlockingMode() const {
   int flags = fcntl(sockfd, F_GETFL, 0);
-  fcntl(sockfd, F_SETFL, flags&~O_NONBLOCK);
+  // TODO add error handling
+  fcntl(sockfd, F_SETFL, flags&(~O_NONBLOCK));
 }
 
 void SocketCore::closeConnection() {

+ 2 - 0
src/SocketCore.h

@@ -104,6 +104,8 @@ public:
    */
   void establishConnection(const string& host, int port);
 
+  void setNonBlockingMode() const;
+
   /**
    * Makes this socket blocking mode.
    */

+ 2 - 4
src/TorrentMan.cc

@@ -399,10 +399,8 @@ void TorrentMan::readFileEntry(FileEntries& fileEntries, Directory** pTopDir, co
 
 void TorrentMan::setupInternal1(const string& metaInfoFile) {
   peerId = "-aria2-";
-  int randomSize = 20-peerId.size();
-  for(int i = 0; i < randomSize; i++) {
-    peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0)));
-  }
+  peerId += Util::randomAlpha(20-peerId.size());
+  key = Util::randomAlpha(8);
 
   uploadLength = 0;
   downloadLength = 0;

+ 1 - 0
src/TorrentMan.h

@@ -109,6 +109,7 @@ public:
   int pieces;
   // TODO type char* would be better
   string peerId;
+  string key;
   string announce;
   string trackerId;
   string name;

+ 3 - 2
src/TrackerWatcherCommand.cc

@@ -87,8 +87,9 @@ bool TrackerWatcherCommand::execute() {
       "left="+(e->torrentMan->getTotalLength()-e->torrentMan->getDownloadLength() <= 0
 	       ? "0" : Util::llitos(e->torrentMan->getTotalLength()-e->torrentMan->getDownloadLength()))+"&"+
       "compact=1"+"&"+
-      "key="+e->torrentMan->peerId+"&"+
-      "numwant="+Util::itos(numWant);
+      "key="+e->torrentMan->key+"&"+
+      "numwant="+Util::itos(numWant)+"&"+
+      "no_peer_id=1";
     if(!event.empty()) {
       url += string("&")+"event="+event;
     }

+ 15 - 0
src/Util.cc

@@ -456,3 +456,18 @@ int Util::countBit(unsigned int n) {
 
   return count;
 }
+
+string Util::randomAlpha(int length) {
+  string str;
+  for(int i = 0; i < length; i++) {
+    int index = (int)(((double)52)*random()/(RAND_MAX+1.0));
+    char ch;
+    if(index < 26) {
+      ch = (char)('A'+index);
+    } else {
+      ch = (char)('a'+index-26);
+    }
+    str += ch;
+  }
+  return str;
+}

+ 2 - 0
src/Util.h

@@ -86,6 +86,8 @@ public:
 				int pieces, int fastSetSize);
 
   static int countBit(unsigned int);
+
+  static string randomAlpha(int length);
 };
 
 #endif // _D_UTIL_H_

+ 6 - 0
test/UtilTest.cc

@@ -16,6 +16,7 @@ class UtilTest:public CppUnit::TestFixture {
   // may be moved to other helper class in the future.
   CPPUNIT_TEST(testGetContentDispositionFilename);
   CPPUNIT_TEST(testComputeFastSet);
+  CPPUNIT_TEST(testRandomAlpha);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -32,6 +33,7 @@ public:
   void testComputeFastSet();
   // may be moved to other helper class in the future.
   void testGetContentDispositionFilename();
+  void testRandomAlpha();
 };
 
 
@@ -208,3 +210,7 @@ void UtilTest::testComputeFastSet() {
   Integers ansSet2(&ans2[0], &ans2[10]);
   CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet2.begin()));
 }
+
+void UtilTest::testRandomAlpha() {
+  CPPUNIT_ASSERT_EQUAL(string("rUopvKRn"), Util::randomAlpha(8));
+}