diff --git a/ChangeLog b/ChangeLog index 20a1ffea..55043eb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,58 @@ +2006-06-22 Tatsuhiro Tsujikawa + + 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 * src/TorrentMan.cc (setupInternal1): Fixed peerId generation bug. diff --git a/src/ChokeMessage.cc b/src/ChokeMessage.cc index c2313b4f..c57de0c6 100644 --- a/src/ChokeMessage.cc +++ b/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(); } diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc index 42d64240..b8d3fee9 100644 --- a/src/PeerConnection.cc +++ b/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; } diff --git a/src/PeerInteraction.cc b/src/PeerInteraction.cc index 93031501..d2e1ea75 100644 --- a/src/PeerInteraction.cc +++ b/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); diff --git a/src/PeerInteraction.h b/src/PeerInteraction.h index a6b239ea..f3e9ff7d 100644 --- a/src/PeerInteraction.h +++ b/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); diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index e6b75b2a..89d536fd 100644 --- a/src/PeerInteractionCommand.cc +++ b/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(); diff --git a/src/SocketCore.cc b/src/SocketCore.cc index f557ff94..acac581b 100644 --- a/src/SocketCore.cc +++ b/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() { diff --git a/src/SocketCore.h b/src/SocketCore.h index e1b54464..06cdf0dd 100644 --- a/src/SocketCore.h +++ b/src/SocketCore.h @@ -104,6 +104,8 @@ public: */ void establishConnection(const string& host, int port); + void setNonBlockingMode() const; + /** * Makes this socket blocking mode. */ diff --git a/src/TorrentMan.cc b/src/TorrentMan.cc index 22ac23d0..d4cb74bb 100644 --- a/src/TorrentMan.cc +++ b/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; diff --git a/src/TorrentMan.h b/src/TorrentMan.h index 13a7d303..d4b888c2 100644 --- a/src/TorrentMan.h +++ b/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; diff --git a/src/TrackerWatcherCommand.cc b/src/TrackerWatcherCommand.cc index 4ad394e6..3b6c1d50 100644 --- a/src/TrackerWatcherCommand.cc +++ b/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; } diff --git a/src/Util.cc b/src/Util.cc index afe5b0dd..7bdfcac8 100644 --- a/src/Util.cc +++ b/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; +} diff --git a/src/Util.h b/src/Util.h index e7827ef3..69ad6d1d 100644 --- a/src/Util.h +++ b/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_ diff --git a/test/UtilTest.cc b/test/UtilTest.cc index e7960eaa..2081d0a7 100644 --- a/test/UtilTest.cc +++ b/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)); +}