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.
pull/1/head
Tatsuhiro Tsujikawa 2006-06-22 15:26:18 +00:00
parent 70ff0c0b3b
commit d02d80d9e9
14 changed files with 130 additions and 24 deletions

View File

@ -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> 2006-06-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/TorrentMan.cc (setupInternal1): Fixed peerId generation bug. * src/TorrentMan.cc (setupInternal1): Fixed peerId generation bug.

View File

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

View File

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

View File

@ -35,7 +35,8 @@ PeerInteraction::PeerInteraction(int cuid,
:cuid(cuid), :cuid(cuid),
uploadLimit(0), uploadLimit(0),
torrentMan(torrentMan), torrentMan(torrentMan),
peer(peer) { peer(peer),
quickReplied(false) {
peerConnection = new PeerConnection(cuid, socket, op); peerConnection = new PeerConnection(cuid, socket, op);
logger = LogFactory::getInstance(); logger = LogFactory::getInstance();
} }
@ -285,10 +286,19 @@ int PeerInteraction::countRequestSlot() const {
return requestSlots.size(); return requestSlots.size();
} }
HandshakeMessage* PeerInteraction::receiveHandshake() { HandshakeMessage* PeerInteraction::receiveHandshake(bool quickReply) {
char msg[HANDSHAKE_MESSAGE_LENGTH]; char msg[HANDSHAKE_MESSAGE_LENGTH];
int msgLength = 0; int msgLength = HANDSHAKE_MESSAGE_LENGTH;
if(!peerConnection->receiveHandshake(msg, msgLength)) { 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; return NULL;
} }
HandshakeMessage* handshakeMessage = createHandshakeMessage(msg, msgLength); HandshakeMessage* handshakeMessage = createHandshakeMessage(msg, msgLength);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -456,3 +456,18 @@ int Util::countBit(unsigned int n) {
return count; 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;
}

View File

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

View File

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