mirror of https://github.com/aria2/aria2
Added new class SendMessageQueue that includes PendingMessages
and RequestSlotMan. * src/SendMessageQueue.h: New class. * src/SendMessageQueue.cc: New class. * src/PendingMessage.h: Added new member variable blockIndex and its accessors. (createRequestMessage): Updated. * src/PendingMessage.cc (createRequestMessage): Updated. * src/PeerInteractionCommand.cc (executeInternal): Updated with SendMessageQueue. (checkLongTimePeerChoking): Updated with SendMessageQueue. (receiveMessage): Updated with SendMessageQueue. (deletePendingPieceMessage): Removed. (getNewPieceAndSendInterest): Updated with SendMessageQueue. (sendInterest): Updated with SendMessageQueue. (createRequestPendingMessage): Updated with SendMessageQueue. (sendMessages): Updated with SendMessageQueue. (onAbort): Updated with SendMessageQueue. (keepAlive): Updated with SendMessageQueue. (beforeSocketCheck): Updated SendMessageQueue. * src/PeerInteractionCommand (sendMessages): Shuffle missingBLockIndexes before using it. Added its own timeout for peer connection. * src/PeerAbstractCommand.h: Added member variable timeout and its setter. * src/prefs.h: Added PREF_PEER_CONNECTION_TIMEOUT. * src/PeerInteractionCommand.cc (PeerInteractionCommand): Added setTimeout() call. (executeInternal): Added setTimeout() call. * src/PeerAbstractCommand.cc (PeerAbstractCommand): Added timeout. (isTimeoutDetected): Updated. * src/main.cc (main): Added PREF_PEER_CONNECTION_TIMEOUT entry to option. Added *simple* message flooding checker. * src/PeerInteractionCommand.cc (executeInternal): Added detectMessageFlooding() call. (detectMessageFlooding): New function. (receiveMessage): Count up CHOKE, UNCHOKE, HAVE message. (beforeSocketCheck): Added detectMessageFlooding() call. * src/PeerInteractionCommand.h: Added sendMessageQueue, chokeUnchokeCount, haveCount, detectMessageFlooding(). Removed deletePendingPieceMessage(), getRequestSlot(), deleteRequestSlot(), deleteAllRequestSlot(). * src/PeerInteractionCommand.cc (beforeSocketCheck): Added checkLongTimePeerChoking() call. * src/RequestSlotMan.h: Renamed deleteTimeoutRequestSlot(). * src/TorrentMan.cc (addPeer): Delete at most MAX_PEER_LIST_SIZE peers if duplicate == false. The parameter "uploaded" and "downloaded" in the tracker request are the size since the client sent the "started" event to the tracker. * src/TorrentMan.cc (setup): Assigned saved downloaded Size and uploaded size to preDownloadedSize, preUploadedSize respectively. * src/TorrentMan.h: Added preDownloadedSize, preUploadedSize, getSessionDownloadedSize(), getSessionUploadedSize(). * src/TrackerInitCommand.cc (execute): Use getSessionDownloadedSize(), getSessionUploadedSize() instead of getDownloadedSize(), getUploadedSize(). * src/PendingMessage.cc (processMessage): Do not send request message if the peer is choking the client. * src/TrackerUpdateCommand.cc (execute): Check wtheher minInterval is less than interval.pull/1/head
parent
4892b40945
commit
e1f24adc40
88
ChangeLog
88
ChangeLog
|
@ -1,3 +1,81 @@
|
||||||
|
2006-03-28 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
|
Added new class SendMessageQueue that includes PendingMessages and
|
||||||
|
RequestSlotMan.
|
||||||
|
|
||||||
|
* src/SendMessageQueue.h: New class.
|
||||||
|
* src/SendMessageQueue.cc: New class.
|
||||||
|
* src/PendingMessage.h: Added new member variable blockIndex and its
|
||||||
|
accessors.
|
||||||
|
(createRequestMessage): Updated.
|
||||||
|
* src/PendingMessage.cc (createRequestMessage): Updated.
|
||||||
|
* src/PeerInteractionCommand.cc (executeInternal): Updated with
|
||||||
|
SendMessageQueue.
|
||||||
|
(checkLongTimePeerChoking): Updated with SendMessageQueue.
|
||||||
|
(receiveMessage): Updated with SendMessageQueue.
|
||||||
|
(deletePendingPieceMessage): Removed.
|
||||||
|
(getNewPieceAndSendInterest): Updated with SendMessageQueue.
|
||||||
|
(sendInterest): Updated with SendMessageQueue.
|
||||||
|
(createRequestPendingMessage): Updated with SendMessageQueue.
|
||||||
|
(sendMessages): Updated with SendMessageQueue.
|
||||||
|
(onAbort): Updated with SendMessageQueue.
|
||||||
|
(keepAlive): Updated with SendMessageQueue.
|
||||||
|
(beforeSocketCheck): Updated SendMessageQueue.
|
||||||
|
|
||||||
|
* src/PeerInteractionCommand (sendMessages): Shuffle
|
||||||
|
missingBLockIndexes before using it.
|
||||||
|
|
||||||
|
Added its own timeout for peer connection.
|
||||||
|
|
||||||
|
* src/PeerAbstractCommand.h: Added member variable timeout and its
|
||||||
|
setter.
|
||||||
|
* src/prefs.h: Added PREF_PEER_CONNECTION_TIMEOUT.
|
||||||
|
* src/PeerInteractionCommand.cc (PeerInteractionCommand):
|
||||||
|
Added setTimeout() call.
|
||||||
|
(executeInternal): Added setTimeout() call.
|
||||||
|
* src/PeerAbstractCommand.cc (PeerAbstractCommand):
|
||||||
|
Added timeout.
|
||||||
|
(isTimeoutDetected): Updated.
|
||||||
|
* src/main.cc (main): Added PREF_PEER_CONNECTION_TIMEOUT entry to
|
||||||
|
option.
|
||||||
|
|
||||||
|
Added *simple* message flooding checker.
|
||||||
|
|
||||||
|
* src/PeerInteractionCommand.cc (executeInternal):
|
||||||
|
Added detectMessageFlooding() call.
|
||||||
|
(detectMessageFlooding): New function.
|
||||||
|
(receiveMessage): Count up CHOKE, UNCHOKE, HAVE message.
|
||||||
|
(beforeSocketCheck): Added detectMessageFlooding() call.
|
||||||
|
* src/PeerInteractionCommand.h: Added sendMessageQueue,
|
||||||
|
chokeUnchokeCount, haveCount, detectMessageFlooding().
|
||||||
|
Removed deletePendingPieceMessage(), getRequestSlot(),
|
||||||
|
deleteRequestSlot(), deleteAllRequestSlot().
|
||||||
|
|
||||||
|
* src/PeerInteractionCommand.cc (beforeSocketCheck):
|
||||||
|
Added checkLongTimePeerChoking() call.
|
||||||
|
|
||||||
|
* src/RequestSlotMan.h: Renamed deleteTimeoutRequestSlot().
|
||||||
|
|
||||||
|
* src/TorrentMan.cc (addPeer): Delete at most MAX_PEER_LIST_SIZE peers
|
||||||
|
if duplicate == false.
|
||||||
|
|
||||||
|
The parameter "uploaded" and "downloaded" in the tracker request are
|
||||||
|
the size since the client sent the "started" event to the tracker.
|
||||||
|
|
||||||
|
* src/TorrentMan.cc (setup): Assigned saved downloaded Size and
|
||||||
|
uploaded size to preDownloadedSize, preUploadedSize respectively.
|
||||||
|
* src/TorrentMan.h: Added preDownloadedSize, preUploadedSize,
|
||||||
|
getSessionDownloadedSize(), getSessionUploadedSize().
|
||||||
|
* src/TrackerInitCommand.cc (execute): Use getSessionDownloadedSize(),
|
||||||
|
getSessionUploadedSize() instead of getDownloadedSize(),
|
||||||
|
getUploadedSize().
|
||||||
|
|
||||||
|
* src/PendingMessage.cc (processMessage): Do not send request message
|
||||||
|
if the peer is choking the client.
|
||||||
|
|
||||||
|
* src/TrackerUpdateCommand.cc (execute): Check wtheher minInterval is
|
||||||
|
less than interval.
|
||||||
|
|
||||||
2006-03-27 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2006-03-27 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
* configure.in: Added gnutls support. Added several CPP macros.
|
* configure.in: Added gnutls support. Added several CPP macros.
|
||||||
|
@ -28,24 +106,20 @@
|
||||||
* src/InitiateConnectionCommandFactory.cc: Replaced HAVE_LIBSSL with
|
* src/InitiateConnectionCommandFactory.cc: Replaced HAVE_LIBSSL with
|
||||||
ENABLE_SSL.
|
ENABLE_SSL.
|
||||||
* src/Request.cc: Replaced HAVE_LIBSSL with ENABLE_SSL.
|
* src/Request.cc: Replaced HAVE_LIBSSL with ENABLE_SSL.
|
||||||
* src/RequestSlotMan.cc:
|
* src/RequestSlotMan.cc (deleteCompletedRequestSlot):
|
||||||
(deleteCompletedRequestSlot)
|
|
||||||
If a piece is already acquired by another command, delete the request
|
If a piece is already acquired by another command, delete the request
|
||||||
slots for the piece.
|
slots for the piece.
|
||||||
* src/TrackerUpdateCommand.cc:
|
* src/TrackerUpdateCommand.cc (execute):
|
||||||
(execute)
|
|
||||||
Changed log level of MSG_TRACKER_WARNING_MESSAGE from info to warn.
|
Changed log level of MSG_TRACKER_WARNING_MESSAGE from info to warn.
|
||||||
Added a check whether peer list is null.
|
Added a check whether peer list is null.
|
||||||
Fixed the bug that causes sending completed event to the tracker
|
Fixed the bug that causes sending completed event to the tracker
|
||||||
several times.
|
several times.
|
||||||
* src/TrackerInitCommand.cc:
|
* src/TrackerInitCommand.cc (execute):
|
||||||
(execute)
|
|
||||||
Fixed the bug that causes sending completed event to the tracker
|
Fixed the bug that causes sending completed event to the tracker
|
||||||
several times.
|
several times.
|
||||||
* src/AbstractDiskWriter.{h,cc}: Removed direct dependency on OpenSSL
|
* src/AbstractDiskWriter.{h,cc}: Removed direct dependency on OpenSSL
|
||||||
by using messageDigest.h.
|
by using messageDigest.h.
|
||||||
|
|
||||||
|
|
||||||
2006-03-26 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
2006-03-26 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||||
|
|
||||||
* PeerConnection.cc: Replaced log message "keep-alive" with
|
* PeerConnection.cc: Replaced log message "keep-alive" with
|
||||||
|
|
4
TODO
4
TODO
|
@ -10,3 +10,7 @@
|
||||||
* no-compact peers format
|
* no-compact peers format
|
||||||
* Add port range command-line option
|
* Add port range command-line option
|
||||||
* Add max peers command-line option
|
* Add max peers command-line option
|
||||||
|
* Distinguish seeder from leecher
|
||||||
|
* time out for connecting peers
|
||||||
|
* ignore incoming connection from localhost.
|
||||||
|
* do not connect to localhost
|
||||||
|
|
|
@ -77,7 +77,8 @@ SRCS = Socket.cc Socket.h\
|
||||||
TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
|
TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
|
||||||
Directory.cc Directory.h\
|
Directory.cc Directory.h\
|
||||||
TrackerWatcherCommand.cc TrackerWatcherCommand.h\
|
TrackerWatcherCommand.cc TrackerWatcherCommand.h\
|
||||||
messageDigest.h
|
messageDigest.h\
|
||||||
|
SendMessageQueue.cc SendMessageQueue.h
|
||||||
noinst_LIBRARIES = libaria2c.a
|
noinst_LIBRARIES = libaria2c.a
|
||||||
libaria2c_a_SOURCES = $(SRCS)
|
libaria2c_a_SOURCES = $(SRCS)
|
||||||
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
|
||||||
|
|
|
@ -97,7 +97,8 @@ am__objects_1 = Socket.$(OBJEXT) SocketCore.$(OBJEXT) \
|
||||||
PeerListenCommand.$(OBJEXT) PendingMessage.$(OBJEXT) \
|
PeerListenCommand.$(OBJEXT) PendingMessage.$(OBJEXT) \
|
||||||
PeerMessage.$(OBJEXT) Piece.$(OBJEXT) RequestSlot.$(OBJEXT) \
|
PeerMessage.$(OBJEXT) Piece.$(OBJEXT) RequestSlot.$(OBJEXT) \
|
||||||
RequestSlotMan.$(OBJEXT) TorrentAutoSaveCommand.$(OBJEXT) \
|
RequestSlotMan.$(OBJEXT) TorrentAutoSaveCommand.$(OBJEXT) \
|
||||||
Directory.$(OBJEXT) TrackerWatcherCommand.$(OBJEXT)
|
Directory.$(OBJEXT) TrackerWatcherCommand.$(OBJEXT) \
|
||||||
|
SendMessageQueue.$(OBJEXT)
|
||||||
am_libaria2c_a_OBJECTS = $(am__objects_1)
|
am_libaria2c_a_OBJECTS = $(am__objects_1)
|
||||||
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
|
||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
|
@ -324,7 +325,8 @@ SRCS = Socket.cc Socket.h\
|
||||||
TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
|
TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
|
||||||
Directory.cc Directory.h\
|
Directory.cc Directory.h\
|
||||||
TrackerWatcherCommand.cc TrackerWatcherCommand.h\
|
TrackerWatcherCommand.cc TrackerWatcherCommand.h\
|
||||||
messageDigest.h
|
messageDigest.h\
|
||||||
|
SendMessageQueue.cc SendMessageQueue.h
|
||||||
|
|
||||||
noinst_LIBRARIES = libaria2c.a
|
noinst_LIBRARIES = libaria2c.a
|
||||||
libaria2c_a_SOURCES = $(SRCS)
|
libaria2c_a_SOURCES = $(SRCS)
|
||||||
|
@ -458,6 +460,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlotMan.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlotMan.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentMan.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentMan.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentSplitter.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentSplitter.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SendMessageQueue.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitor.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@
|
||||||
|
|
|
@ -38,7 +38,7 @@ PeerAbstractCommand::PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEn
|
||||||
}
|
}
|
||||||
this->checkPoint.tv_sec = 0;
|
this->checkPoint.tv_sec = 0;
|
||||||
this->checkPoint.tv_usec = 0;
|
this->checkPoint.tv_usec = 0;
|
||||||
|
timeout = e->option->getAsInt(PREF_TIMEOUT);
|
||||||
e->torrentMan->connections++;
|
e->torrentMan->connections++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ bool PeerAbstractCommand::isTimeoutDetected() {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
long long int elapsed = Util::difftv(now, checkPoint);
|
long long int elapsed = Util::difftv(now, checkPoint);
|
||||||
if(elapsed >= e->option->getAsLLInt(PREF_TIMEOUT)*1000000) {
|
if(elapsed >= ((long long int)timeout)*1000000) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -32,11 +32,12 @@ private:
|
||||||
void updateCheckPoint();
|
void updateCheckPoint();
|
||||||
bool isTimeoutDetected();
|
bool isTimeoutDetected();
|
||||||
struct timeval checkPoint;
|
struct timeval checkPoint;
|
||||||
|
int timeout;
|
||||||
protected:
|
protected:
|
||||||
TorrentDownloadEngine* e;
|
TorrentDownloadEngine* e;
|
||||||
Socket* socket;
|
Socket* socket;
|
||||||
Peer* peer;
|
Peer* peer;
|
||||||
|
void setTimeout(int timeout) { this->timeout = timeout; }
|
||||||
virtual bool prepareForNextPeer(int wait);
|
virtual bool prepareForNextPeer(int wait);
|
||||||
virtual bool prepareForRetry(int wait);
|
virtual bool prepareForRetry(int wait);
|
||||||
virtual void onAbort(Exception* ex);
|
virtual void onAbort(Exception* ex);
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "DlAbortEx.h"
|
#include "DlAbortEx.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
#include "prefs.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer,
|
PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer,
|
||||||
TorrentDownloadEngine* e,
|
TorrentDownloadEngine* e,
|
||||||
|
@ -33,21 +35,26 @@ PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer,
|
||||||
if(sequence == INITIATOR_SEND_HANDSHAKE) {
|
if(sequence == INITIATOR_SEND_HANDSHAKE) {
|
||||||
setReadCheckSocket(NULL);
|
setReadCheckSocket(NULL);
|
||||||
setWriteCheckSocket(socket);
|
setWriteCheckSocket(socket);
|
||||||
|
setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
|
||||||
}
|
}
|
||||||
peerConnection = new PeerConnection(cuid, socket, e->option, e->logger,
|
peerConnection = new PeerConnection(cuid, socket, e->option, e->logger,
|
||||||
peer, e->torrentMan);
|
peer, e->torrentMan);
|
||||||
requestSlotMan = new RequestSlotMan(cuid, &pendingMessages, peerConnection,
|
sendMessageQueue = new SendMessageQueue(cuid, peerConnection, e->torrentMan,
|
||||||
e->torrentMan, e->logger);
|
e->logger);
|
||||||
piece = Piece::nullPiece;
|
piece = Piece::nullPiece;
|
||||||
keepAliveCheckPoint.tv_sec = 0;
|
keepAliveCheckPoint.tv_sec = 0;
|
||||||
keepAliveCheckPoint.tv_usec = 0;
|
keepAliveCheckPoint.tv_usec = 0;
|
||||||
chokeCheckPoint.tv_sec = 0;
|
chokeCheckPoint.tv_sec = 0;
|
||||||
chokeCheckPoint.tv_usec = 0;
|
chokeCheckPoint.tv_usec = 0;
|
||||||
|
freqCheckPoint.tv_sec = 0;
|
||||||
|
freqCheckPoint.tv_usec = 0;
|
||||||
|
chokeUnchokeCount = 0;
|
||||||
|
haveCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerInteractionCommand::~PeerInteractionCommand() {
|
PeerInteractionCommand::~PeerInteractionCommand() {
|
||||||
delete peerConnection;
|
delete peerConnection;
|
||||||
delete requestSlotMan;
|
delete sendMessageQueue;
|
||||||
e->torrentMan->unadvertisePiece(cuid);
|
e->torrentMan->unadvertisePiece(cuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +62,7 @@ bool PeerInteractionCommand::executeInternal() {
|
||||||
if(sequence == INITIATOR_SEND_HANDSHAKE) {
|
if(sequence == INITIATOR_SEND_HANDSHAKE) {
|
||||||
socket->setBlockingMode();
|
socket->setBlockingMode();
|
||||||
setReadCheckSocket(socket);
|
setReadCheckSocket(socket);
|
||||||
|
setTimeout(e->option->getAsInt(PREF_TIMEOUT));
|
||||||
}
|
}
|
||||||
setWriteCheckSocket(NULL);
|
setWriteCheckSocket(NULL);
|
||||||
|
|
||||||
|
@ -97,6 +105,7 @@ bool PeerInteractionCommand::executeInternal() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WIRED:
|
case WIRED:
|
||||||
|
detectMessageFlooding();
|
||||||
checkLongTimePeerChoking();
|
checkLongTimePeerChoking();
|
||||||
syncPiece();
|
syncPiece();
|
||||||
decideChoking();
|
decideChoking();
|
||||||
|
@ -106,19 +115,38 @@ bool PeerInteractionCommand::executeInternal() {
|
||||||
}
|
}
|
||||||
receiveMessage();
|
receiveMessage();
|
||||||
}
|
}
|
||||||
requestSlotMan->deleteTimedoutRequestSlot(piece);
|
sendMessageQueue->deleteTimeoutRequestSlot(piece);
|
||||||
requestSlotMan->deleteCompletedRequestSlot(piece);
|
sendMessageQueue->deleteCompletedRequestSlot(piece);
|
||||||
sendInterest();
|
sendInterest();
|
||||||
sendMessages();
|
sendMessages();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(pendingMessages.size() > 0) {
|
if(sendMessageQueue->countPendingMessage() > 0) {
|
||||||
setWriteCheckSocket(socket);
|
setWriteCheckSocket(socket);
|
||||||
}
|
}
|
||||||
e->commands.push(this);
|
e->commands.push(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PeerInteractionCommand::detectMessageFlooding() {
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
if(freqCheckPoint.tv_sec == 0 && freqCheckPoint.tv_usec == 0) {
|
||||||
|
freqCheckPoint = now;
|
||||||
|
} else {
|
||||||
|
if(Util::difftv(now, freqCheckPoint) >= 5*1000000) {
|
||||||
|
if(chokeUnchokeCount*1.0/(Util::difftv(now, freqCheckPoint)/1000000) >= 0.3
|
||||||
|
|| haveCount*1.0/(Util::difftv(now, freqCheckPoint)/1000000) >= 20.0) {
|
||||||
|
throw new DlAbortEx("flooding detected.");
|
||||||
|
} else {
|
||||||
|
chokeUnchokeCount = 0;
|
||||||
|
haveCount = 0;
|
||||||
|
freqCheckPoint = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PeerInteractionCommand::checkLongTimePeerChoking() {
|
void PeerInteractionCommand::checkLongTimePeerChoking() {
|
||||||
if(e->torrentMan->downloadComplete()) {
|
if(e->torrentMan->downloadComplete()) {
|
||||||
return;
|
return;
|
||||||
|
@ -152,21 +180,21 @@ void PeerInteractionCommand::decideChoking() {
|
||||||
if(e->torrentMan->downloadComplete()) {
|
if(e->torrentMan->downloadComplete()) {
|
||||||
if(peer->amChocking && peer->peerInterested) {
|
if(peer->amChocking && peer->peerInterested) {
|
||||||
PendingMessage pendingMessage(PeerMessage::UNCHOKE, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::UNCHOKE, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(peer->shouldChoke()) {
|
if(peer->shouldChoke()) {
|
||||||
if(!peer->amChocking) {
|
if(!peer->amChocking) {
|
||||||
PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
}
|
}
|
||||||
} else if(peer->amChocking && peer->peerInterested) {
|
} else if(peer->amChocking && peer->peerInterested) {
|
||||||
PendingMessage pendingMessage(PeerMessage::UNCHOKE, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::UNCHOKE, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
} else if(!peer->peerInterested) {
|
} else if(!peer->peerInterested) {
|
||||||
PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,10 +211,15 @@ void PeerInteractionCommand::receiveMessage() {
|
||||||
case PeerMessage::KEEP_ALIVE:
|
case PeerMessage::KEEP_ALIVE:
|
||||||
break;
|
break;
|
||||||
case PeerMessage::CHOKE:
|
case PeerMessage::CHOKE:
|
||||||
|
if(!peer->peerChoking) {
|
||||||
|
chokeUnchokeCount++;
|
||||||
|
}
|
||||||
peer->peerChoking = true;
|
peer->peerChoking = true;
|
||||||
requestSlotMan->deleteAllRequestSlot(piece);
|
|
||||||
break;
|
break;
|
||||||
case PeerMessage::UNCHOKE:
|
case PeerMessage::UNCHOKE:
|
||||||
|
if(peer->peerChoking) {
|
||||||
|
chokeUnchokeCount++;
|
||||||
|
}
|
||||||
peer->peerChoking = false;
|
peer->peerChoking = false;
|
||||||
break;
|
break;
|
||||||
case PeerMessage::INTERESTED:
|
case PeerMessage::INTERESTED:
|
||||||
|
@ -196,6 +229,7 @@ void PeerInteractionCommand::receiveMessage() {
|
||||||
peer->peerInterested = false;
|
peer->peerInterested = false;
|
||||||
break;
|
break;
|
||||||
case PeerMessage::HAVE:
|
case PeerMessage::HAVE:
|
||||||
|
haveCount++;
|
||||||
peer->updateBitfield(message->getIndex(), 1);
|
peer->updateBitfield(message->getIndex(), 1);
|
||||||
break;
|
break;
|
||||||
case PeerMessage::BITFIELD:
|
case PeerMessage::BITFIELD:
|
||||||
|
@ -209,16 +243,16 @@ void PeerInteractionCommand::receiveMessage() {
|
||||||
message->getLength(),
|
message->getLength(),
|
||||||
e->torrentMan->pieceLength,
|
e->torrentMan->pieceLength,
|
||||||
peerConnection);
|
peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
e->torrentMan->addUploadedSize(message->getLength());
|
e->torrentMan->addUploadedSize(message->getLength());
|
||||||
e->torrentMan->addDeltaUpload(message->getLength());
|
e->torrentMan->addDeltaUpload(message->getLength());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PeerMessage::CANCEL:
|
case PeerMessage::CANCEL:
|
||||||
deletePendingMessage(message);
|
sendMessageQueue->deletePendingPieceMessage(message);
|
||||||
break;
|
break;
|
||||||
case PeerMessage::PIECE: {
|
case PeerMessage::PIECE: {
|
||||||
RequestSlot slot = requestSlotMan->getCorrespoindingRequestSlot(message);
|
RequestSlot slot = sendMessageQueue->getCorrespoindingRequestSlot(message);
|
||||||
peer->addPeerUpload(message->getBlockLength());
|
peer->addPeerUpload(message->getBlockLength());
|
||||||
if(!Piece::isNull(piece) && !RequestSlot::isNull(slot)) {
|
if(!Piece::isNull(piece) && !RequestSlot::isNull(slot)) {
|
||||||
long long int offset =
|
long long int offset =
|
||||||
|
@ -229,7 +263,7 @@ void PeerInteractionCommand::receiveMessage() {
|
||||||
message->getBlockLength(),
|
message->getBlockLength(),
|
||||||
offset);
|
offset);
|
||||||
piece.completeBlock(slot.getBlockIndex());
|
piece.completeBlock(slot.getBlockIndex());
|
||||||
requestSlotMan->deleteRequestSlot(slot);
|
sendMessageQueue->deleteRequestSlot(slot);
|
||||||
e->torrentMan->updatePiece(piece);
|
e->torrentMan->updatePiece(piece);
|
||||||
e->logger->debug("CUID#%d - setting piece bit index=%d", cuid,
|
e->logger->debug("CUID#%d - setting piece bit index=%d", cuid,
|
||||||
slot.getBlockIndex());
|
slot.getBlockIndex());
|
||||||
|
@ -252,27 +286,6 @@ void PeerInteractionCommand::receiveMessage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerInteractionCommand::deletePendingMessage(PeerMessage* cancelMessage) {
|
|
||||||
for(PendingMessages::iterator itr = pendingMessages.begin();
|
|
||||||
itr != pendingMessages.end();) {
|
|
||||||
PendingMessage& pendingMessage = *itr;
|
|
||||||
if(pendingMessage.getPeerMessageId() == PeerMessage::PIECE &&
|
|
||||||
pendingMessage.getIndex() == cancelMessage->getIndex() &&
|
|
||||||
pendingMessage.getBegin() == cancelMessage->getBegin() &&
|
|
||||||
pendingMessage.getLength() == cancelMessage->getLength() &&
|
|
||||||
!pendingMessage.isInProgress()) {
|
|
||||||
e->logger->debug("CUID#%d - deleting pending piece message because cancel message received. index=%d, begin=%d, length=%d",
|
|
||||||
cuid,
|
|
||||||
pendingMessage.getIndex(),
|
|
||||||
pendingMessage.getBegin(),
|
|
||||||
pendingMessage.getLength());
|
|
||||||
itr = pendingMessages.erase(itr);
|
|
||||||
} else {
|
|
||||||
itr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerInteractionCommand::onGotNewPiece() {
|
void PeerInteractionCommand::onGotNewPiece() {
|
||||||
e->logger->info(MSG_GOT_NEW_PIECE, cuid, piece.getIndex());
|
e->logger->info(MSG_GOT_NEW_PIECE, cuid, piece.getIndex());
|
||||||
e->torrentMan->completePiece(piece);
|
e->torrentMan->completePiece(piece);
|
||||||
|
@ -305,15 +318,16 @@ bool PeerInteractionCommand::prepareForRetry(int wait) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Piece PeerInteractionCommand::getNewPieceAndSendInterest() {
|
Piece PeerInteractionCommand::getNewPieceAndSendInterest() {
|
||||||
|
sendMessageQueue->cancelAllRequest();
|
||||||
Piece piece = e->torrentMan->getMissingPiece(peer);
|
Piece piece = e->torrentMan->getMissingPiece(peer);
|
||||||
if(Piece::isNull(piece)) {
|
if(Piece::isNull(piece)) {
|
||||||
e->logger->debug("CUID#%d - try to send not-interested", cuid);
|
e->logger->debug("CUID#%d - try to send not-interested", cuid);
|
||||||
PendingMessage pendingMessage(PeerMessage::NOT_INTERESTED, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::NOT_INTERESTED, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
} else {
|
} else {
|
||||||
e->logger->debug("CUID#%d - try to send interested", cuid);
|
e->logger->debug("CUID#%d - try to send interested", cuid);
|
||||||
PendingMessage pendingMessage(PeerMessage::INTERESTED, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::INTERESTED, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
}
|
}
|
||||||
return piece;
|
return piece;
|
||||||
}
|
}
|
||||||
|
@ -323,8 +337,7 @@ void PeerInteractionCommand::sendInterest() {
|
||||||
// retrive new piece from TorrentMan
|
// retrive new piece from TorrentMan
|
||||||
piece = getNewPieceAndSendInterest();
|
piece = getNewPieceAndSendInterest();
|
||||||
} else if(peer->peerChoking) {
|
} else if(peer->peerChoking) {
|
||||||
// TODO separate method is better
|
sendMessageQueue->cancelAllRequest(piece);
|
||||||
requestSlotMan->deleteAllRequestSlot(piece);
|
|
||||||
e->torrentMan->cancelPiece(piece);
|
e->torrentMan->cancelPiece(piece);
|
||||||
piece = Piece::nullPiece;
|
piece = Piece::nullPiece;
|
||||||
} else if(piece.pieceComplete()) {
|
} else if(piece.pieceComplete()) {
|
||||||
|
@ -334,35 +347,26 @@ void PeerInteractionCommand::sendInterest() {
|
||||||
|
|
||||||
void PeerInteractionCommand::createRequestPendingMessage(int blockIndex) {
|
void PeerInteractionCommand::createRequestPendingMessage(int blockIndex) {
|
||||||
PendingMessage pendingMessage =
|
PendingMessage pendingMessage =
|
||||||
PendingMessage::createRequestMessage(piece.getIndex(),
|
PendingMessage::createRequestMessage(piece, blockIndex, peerConnection);
|
||||||
blockIndex*piece.getBlockLength(),
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
piece.getBlockLength(blockIndex),
|
|
||||||
peerConnection);
|
|
||||||
pendingMessages.push_back(pendingMessage);
|
|
||||||
RequestSlot requestSlot(piece.getIndex(),
|
|
||||||
blockIndex*piece.getBlockLength(),
|
|
||||||
piece.getBlockLength(blockIndex),
|
|
||||||
blockIndex);
|
|
||||||
requestSlotMan->addRequestSlot(requestSlot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerInteractionCommand::sendMessages() {
|
void PeerInteractionCommand::sendMessages() {
|
||||||
if(!Piece::isNull(piece) && !peer->peerChoking) {
|
if(!Piece::isNull(piece) && !peer->peerChoking) {
|
||||||
if(e->torrentMan->isEndGame()) {
|
if(e->torrentMan->isEndGame()) {
|
||||||
BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes();
|
BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes();
|
||||||
if(requestSlotMan->isEmpty()) {
|
if(sendMessageQueue->countRequestSlot() == 0) {
|
||||||
|
random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end());
|
||||||
|
int count = 0;
|
||||||
for(PieceIndexes::const_iterator itr = missingBlockIndexes.begin();
|
for(PieceIndexes::const_iterator itr = missingBlockIndexes.begin();
|
||||||
itr != missingBlockIndexes.end(); itr++) {
|
itr != missingBlockIndexes.end() && count < 6; itr++, count++) {
|
||||||
createRequestPendingMessage(*itr);
|
createRequestPendingMessage(*itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = requestSlotMan->countRequestSlot(); i <= 5; i++) {
|
for(int i = sendMessageQueue->countRequestSlot(); i < 6; i++) {
|
||||||
int blockIndex = piece.getMissingUnusedBlockIndex();
|
int blockIndex = piece.getMissingUnusedBlockIndex();
|
||||||
if(blockIndex == -1) {
|
if(blockIndex == -1) {
|
||||||
if(requestSlotMan->isEmpty()) {
|
|
||||||
piece = Piece::nullPiece;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
e->torrentMan->updatePiece(piece);
|
e->torrentMan->updatePiece(piece);
|
||||||
|
@ -371,18 +375,11 @@ void PeerInteractionCommand::sendMessages() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(PendingMessages::iterator itr = pendingMessages.begin(); itr != pendingMessages.end();) {
|
sendMessageQueue->send();
|
||||||
if(itr->processMessage()) {
|
|
||||||
itr = pendingMessages.erase(itr);
|
|
||||||
} else {
|
|
||||||
//setWriteCheckSocket(socket);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerInteractionCommand::onAbort(Exception* ex) {
|
void PeerInteractionCommand::onAbort(Exception* ex) {
|
||||||
requestSlotMan->deleteAllRequestSlot(piece);
|
sendMessageQueue->cancelAllRequest(piece);
|
||||||
e->torrentMan->cancelPiece(piece);
|
e->torrentMan->cancelPiece(piece);
|
||||||
PeerAbstractCommand::onAbort(ex);
|
PeerAbstractCommand::onAbort(ex);
|
||||||
}
|
}
|
||||||
|
@ -394,7 +391,7 @@ void PeerInteractionCommand::keepAlive() {
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
if(Util::difftv(now, keepAliveCheckPoint) >= (long long int)120*1000000) {
|
if(Util::difftv(now, keepAliveCheckPoint) >= (long long int)120*1000000) {
|
||||||
if(pendingMessages.empty()) {
|
if(sendMessageQueue->countPendingMessage() == 0) {
|
||||||
peerConnection->sendKeepAlive();
|
peerConnection->sendKeepAlive();
|
||||||
}
|
}
|
||||||
keepAliveCheckPoint = now;
|
keepAliveCheckPoint = now;
|
||||||
|
@ -405,20 +402,22 @@ void PeerInteractionCommand::keepAlive() {
|
||||||
void PeerInteractionCommand::beforeSocketCheck() {
|
void PeerInteractionCommand::beforeSocketCheck() {
|
||||||
if(sequence == WIRED) {
|
if(sequence == WIRED) {
|
||||||
e->torrentMan->unadvertisePiece(cuid);
|
e->torrentMan->unadvertisePiece(cuid);
|
||||||
|
detectMessageFlooding();
|
||||||
|
checkLongTimePeerChoking();
|
||||||
|
|
||||||
PieceIndexes indexes = e->torrentMan->getAdvertisedPieceIndexes(cuid);
|
PieceIndexes indexes = e->torrentMan->getAdvertisedPieceIndexes(cuid);
|
||||||
if(indexes.size() >= 20) {
|
if(indexes.size() >= 20) {
|
||||||
PendingMessage pendingMessage(PeerMessage::BITFIELD, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::BITFIELD, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
} else {
|
} else {
|
||||||
if(pendingMessages.size() == 0) {
|
if(sendMessageQueue->countPendingMessage() == 0) {
|
||||||
for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
|
for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
|
||||||
peerConnection->sendHave(*itr);
|
peerConnection->sendHave(*itr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
|
for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
|
||||||
PendingMessage pendingMessage = PendingMessage::createHaveMessage(*itr, peerConnection);
|
PendingMessage pendingMessage = PendingMessage::createHaveMessage(*itr, peerConnection);
|
||||||
pendingMessages.push_back(pendingMessage);
|
sendMessageQueue->addPendingMessage(pendingMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
|
|
||||||
#include "PeerAbstractCommand.h"
|
#include "PeerAbstractCommand.h"
|
||||||
#include "PeerConnection.h"
|
#include "PeerConnection.h"
|
||||||
#include "PendingMessage.h"
|
#include "SendMessageQueue.h"
|
||||||
#include "RequestSlotMan.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -33,12 +32,15 @@ class PeerInteractionCommand : public PeerAbstractCommand {
|
||||||
private:
|
private:
|
||||||
int sequence;
|
int sequence;
|
||||||
PeerConnection* peerConnection;
|
PeerConnection* peerConnection;
|
||||||
RequestSlotMan* requestSlotMan;
|
SendMessageQueue* sendMessageQueue;
|
||||||
PendingMessages pendingMessages;
|
|
||||||
Piece piece;
|
Piece piece;
|
||||||
struct timeval keepAliveCheckPoint;
|
struct timeval keepAliveCheckPoint;
|
||||||
struct timeval chokeCheckPoint;
|
struct timeval chokeCheckPoint;
|
||||||
|
struct timeval freqCheckPoint;
|
||||||
|
int chokeUnchokeCount;
|
||||||
|
int haveCount;
|
||||||
void receiveMessage();
|
void receiveMessage();
|
||||||
|
void detectMessageFlooding();
|
||||||
void checkLongTimePeerChoking();
|
void checkLongTimePeerChoking();
|
||||||
void syncPiece();
|
void syncPiece();
|
||||||
void detectTimeoutAndDuplicateBlock();
|
void detectTimeoutAndDuplicateBlock();
|
||||||
|
@ -46,10 +48,6 @@ private:
|
||||||
void sendInterest();
|
void sendInterest();
|
||||||
void sendMessages();
|
void sendMessages();
|
||||||
void createRequestPendingMessage(int blockIndex);
|
void createRequestPendingMessage(int blockIndex);
|
||||||
void deletePendingMessage(PeerMessage* cancelMessage);
|
|
||||||
const RequestSlot& getRequestSlot(int index, int begin, int length) const;
|
|
||||||
bool deleteRequestSlot(const RequestSlot& slot);
|
|
||||||
void deleteAllRequestSlot();
|
|
||||||
bool checkPieceHash(const Piece& piece);
|
bool checkPieceHash(const Piece& piece);
|
||||||
void erasePieceOnDisk(const Piece& piece);
|
void erasePieceOnDisk(const Piece& piece);
|
||||||
void keepAlive();
|
void keepAlive();
|
||||||
|
|
|
@ -59,9 +59,9 @@ bool PeerListenCommand::execute() {
|
||||||
Socket* peerSocket = NULL;
|
Socket* peerSocket = NULL;
|
||||||
try {
|
try {
|
||||||
peerSocket = socket->acceptConnection();
|
peerSocket = socket->acceptConnection();
|
||||||
if(e->torrentMan->connections < MAX_PEERS) {
|
|
||||||
pair<string, int> peerInfo;
|
pair<string, int> peerInfo;
|
||||||
peerSocket->getPeerInfo(peerInfo);
|
peerSocket->getPeerInfo(peerInfo);
|
||||||
|
if(e->torrentMan->connections < MAX_PEERS) {
|
||||||
Peer* peer = new Peer(peerInfo.first, peerInfo.second,
|
Peer* peer = new Peer(peerInfo.first, peerInfo.second,
|
||||||
e->torrentMan->pieceLength,
|
e->torrentMan->pieceLength,
|
||||||
e->torrentMan->totalSize);
|
e->torrentMan->totalSize);
|
||||||
|
|
|
@ -72,7 +72,9 @@ bool PendingMessage::processMessage() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PeerMessage::REQUEST:
|
case PeerMessage::REQUEST:
|
||||||
|
if(!peerConnection->getPeer()->peerChoking) {
|
||||||
peerConnection->sendRequest(index, begin, length);
|
peerConnection->sendRequest(index, begin, length);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PeerMessage::CANCEL:
|
case PeerMessage::CANCEL:
|
||||||
peerConnection->sendCancel(index, begin, length);
|
peerConnection->sendCancel(index, begin, length);
|
||||||
|
@ -83,11 +85,14 @@ bool PendingMessage::processMessage() {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingMessage PendingMessage::createRequestMessage(int index, int begin, int length, PeerConnection* peerConnection) {
|
PendingMessage PendingMessage::createRequestMessage(const Piece& piece,
|
||||||
|
int blockIndex,
|
||||||
|
PeerConnection* peerConnection) {
|
||||||
PendingMessage pendingMessage(PeerMessage::REQUEST, peerConnection);
|
PendingMessage pendingMessage(PeerMessage::REQUEST, peerConnection);
|
||||||
pendingMessage.setIndex(index);
|
pendingMessage.setIndex(piece.getIndex());
|
||||||
pendingMessage.setBegin(begin);
|
pendingMessage.setBegin(blockIndex*piece.getBlockLength());
|
||||||
pendingMessage.setLength(length);
|
pendingMessage.setLength(piece.getBlockLength(blockIndex));
|
||||||
|
pendingMessage.setBlockIndex(blockIndex);
|
||||||
return pendingMessage;
|
return pendingMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ private:
|
||||||
int index;
|
int index;
|
||||||
int begin;
|
int begin;
|
||||||
int length;
|
int length;
|
||||||
|
int blockIndex;
|
||||||
long long int pieceDataOffset;
|
long long int pieceDataOffset;
|
||||||
int leftPieceDataLength;
|
int leftPieceDataLength;
|
||||||
bool inProgress;
|
bool inProgress;
|
||||||
|
@ -58,9 +59,11 @@ public:
|
||||||
int getBegin() const { return begin; }
|
int getBegin() const { return begin; }
|
||||||
void setLength(int length) { this->length = length; }
|
void setLength(int length) { this->length = length; }
|
||||||
int getLength() const { return length; }
|
int getLength() const { return length; }
|
||||||
|
void setBlockIndex(int blockIndex) { this->blockIndex = blockIndex; }
|
||||||
|
int getBlockIndex() const { return blockIndex; }
|
||||||
bool processMessage();
|
bool processMessage();
|
||||||
|
|
||||||
static PendingMessage createRequestMessage(int index, int begin, int length, PeerConnection* peerConnection);
|
static PendingMessage createRequestMessage(const Piece& piece, int blockIndex, PeerConnection* peerConnection);
|
||||||
static PendingMessage createCancelMessage(int index, int begin, int length, PeerConnection* peerConnection);
|
static PendingMessage createCancelMessage(int index, int begin, int length, PeerConnection* peerConnection);
|
||||||
static PendingMessage createPieceMessage(int index, int begin, int length, int pieceLength, PeerConnection* peerConnection);
|
static PendingMessage createPieceMessage(int index, int begin, int length, int pieceLength, PeerConnection* peerConnection);
|
||||||
static PendingMessage createHaveMessage(int index, PeerConnection* peerConnectioin);
|
static PendingMessage createHaveMessage(int index, PeerConnection* peerConnectioin);
|
||||||
|
|
|
@ -48,7 +48,7 @@ void RequestSlotMan::deleteAllRequestSlot(Piece& piece) {
|
||||||
requestSlots.clear();
|
requestSlots.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestSlotMan::deleteTimedoutRequestSlot(Piece& piece) {
|
void RequestSlotMan::deleteTimeoutRequestSlot(Piece& piece) {
|
||||||
for(RequestSlots::iterator itr = requestSlots.begin();
|
for(RequestSlots::iterator itr = requestSlots.begin();
|
||||||
itr != requestSlots.end();) {
|
itr != requestSlots.end();) {
|
||||||
if(itr->isTimeout(timeout)) {
|
if(itr->isTimeout(timeout)) {
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
void deleteRequestSlot(const RequestSlot& requestSlot);
|
void deleteRequestSlot(const RequestSlot& requestSlot);
|
||||||
void deleteAllRequestSlot(Piece& piece);
|
void deleteAllRequestSlot(Piece& piece);
|
||||||
|
|
||||||
void deleteTimedoutRequestSlot(Piece& piece);
|
void deleteTimeoutRequestSlot(Piece& piece);
|
||||||
void deleteCompletedRequestSlot(const Piece& piece);
|
void deleteCompletedRequestSlot(const Piece& piece);
|
||||||
|
|
||||||
RequestSlot getCorrespoindingRequestSlot(const PeerMessage* pieceMessage) const;
|
RequestSlot getCorrespoindingRequestSlot(const PeerMessage* pieceMessage) const;
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* <!-- 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 "SendMessageQueue.h"
|
||||||
|
|
||||||
|
SendMessageQueue::SendMessageQueue(int cuid, PeerConnection* peerConnection,
|
||||||
|
TorrentMan* torrentMan,
|
||||||
|
const Logger* logger)
|
||||||
|
:cuid(cuid), logger(logger) {
|
||||||
|
requestSlotMan = new RequestSlotMan(cuid, &pendingMessages, peerConnection,
|
||||||
|
torrentMan, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendMessageQueue::~SendMessageQueue() {
|
||||||
|
delete requestSlotMan;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::send() {
|
||||||
|
for(PendingMessages::iterator itr = pendingMessages.begin();
|
||||||
|
itr != pendingMessages.end();) {
|
||||||
|
if(itr->processMessage()) {
|
||||||
|
itr = pendingMessages.erase(itr);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::addPendingMessage(const PendingMessage& pendingMessage) {
|
||||||
|
pendingMessages.push_back(pendingMessage);
|
||||||
|
if(pendingMessage.getPeerMessageId() == PeerMessage::REQUEST) {
|
||||||
|
RequestSlot requestSlot(pendingMessage.getIndex(),
|
||||||
|
pendingMessage.getBegin(),
|
||||||
|
pendingMessage.getLength(),
|
||||||
|
pendingMessage.getBlockIndex());
|
||||||
|
requestSlotMan->addRequestSlot(requestSlot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::deletePendingPieceMessage(const PeerMessage* cancelMessage) {
|
||||||
|
for(PendingMessages::iterator itr = pendingMessages.begin();
|
||||||
|
itr != pendingMessages.end();) {
|
||||||
|
PendingMessage& pendingMessage = *itr;
|
||||||
|
if(pendingMessage.getPeerMessageId() == PeerMessage::PIECE &&
|
||||||
|
pendingMessage.getIndex() == cancelMessage->getIndex() &&
|
||||||
|
pendingMessage.getBegin() == cancelMessage->getBegin() &&
|
||||||
|
pendingMessage.getLength() == cancelMessage->getLength() &&
|
||||||
|
!pendingMessage.isInProgress()) {
|
||||||
|
logger->debug("CUID#%d - deleting pending piece message because cancel message received. index=%d, begin=%d, length=%d",
|
||||||
|
cuid,
|
||||||
|
pendingMessage.getIndex(),
|
||||||
|
pendingMessage.getBegin(),
|
||||||
|
pendingMessage.getLength());
|
||||||
|
itr = pendingMessages.erase(itr);
|
||||||
|
} else {
|
||||||
|
itr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::deletePendingRequestMessage() {
|
||||||
|
for(PendingMessages::iterator itr = pendingMessages.begin();
|
||||||
|
itr != pendingMessages.end();) {
|
||||||
|
PendingMessage& pendingMessage = *itr;
|
||||||
|
if(pendingMessage.getPeerMessageId() == PeerMessage::REQUEST) {
|
||||||
|
itr = pendingMessages.erase(itr);
|
||||||
|
} else {
|
||||||
|
itr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::deleteRequestSlot(const RequestSlot& requestSlot) {
|
||||||
|
requestSlotMan->deleteRequestSlot(requestSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::deleteTimeoutRequestSlot(Piece& piece) {
|
||||||
|
requestSlotMan->deleteTimeoutRequestSlot(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::deleteCompletedRequestSlot(const Piece& piece) {
|
||||||
|
requestSlotMan->deleteCompletedRequestSlot(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestSlot SendMessageQueue::getCorrespoindingRequestSlot(const PeerMessage* pieceMessage) const {
|
||||||
|
return requestSlotMan->getCorrespoindingRequestSlot(pieceMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::cancelAllRequest() {
|
||||||
|
cancelAllRequest(Piece::nullPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendMessageQueue::cancelAllRequest(Piece& piece) {
|
||||||
|
deletePendingRequestMessage();
|
||||||
|
requestSlotMan->deleteAllRequestSlot(Piece::nullPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendMessageQueue::countPendingMessage() const {
|
||||||
|
return pendingMessages.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendMessageQueue::countRequestSlot() const {
|
||||||
|
return requestSlotMan->countRequestSlot();
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* <!-- 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_SEND_MESSAGE_QUEUE_H_
|
||||||
|
#define _D_SEND_MESSAGE_QUEUE_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "RequestSlotMan.h"
|
||||||
|
|
||||||
|
class SendMessageQueue {
|
||||||
|
private:
|
||||||
|
int cuid;
|
||||||
|
RequestSlotMan* requestSlotMan;
|
||||||
|
PendingMessages pendingMessages;
|
||||||
|
const Logger* logger;
|
||||||
|
public:
|
||||||
|
SendMessageQueue(int cuid, PeerConnection* peerConnection,
|
||||||
|
TorrentMan* torrentMan, const Logger* logger);
|
||||||
|
~SendMessageQueue();
|
||||||
|
|
||||||
|
void send();
|
||||||
|
|
||||||
|
void addPendingMessage(const PendingMessage& pendingMessage);
|
||||||
|
void deletePendingPieceMessage(const PeerMessage* cancelMessage);
|
||||||
|
void deletePendingRequestMessage();
|
||||||
|
|
||||||
|
void deleteRequestSlot(const RequestSlot& requestSlot);
|
||||||
|
void deleteTimeoutRequestSlot(Piece& piece);
|
||||||
|
void deleteCompletedRequestSlot(const Piece& piece);
|
||||||
|
RequestSlot getCorrespoindingRequestSlot(const PeerMessage* pieceMessage) const;
|
||||||
|
|
||||||
|
void cancelAllRequest();
|
||||||
|
void cancelAllRequest(Piece& piece);
|
||||||
|
|
||||||
|
int countPendingMessage() const;
|
||||||
|
int countRequestSlot() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _D_SEND_MESSAGE_QUEUE_H_
|
|
@ -36,6 +36,7 @@
|
||||||
TorrentMan::TorrentMan():bitfield(NULL),
|
TorrentMan::TorrentMan():bitfield(NULL),
|
||||||
peerEntryIdCounter(0), cuidCounter(0),
|
peerEntryIdCounter(0), cuidCounter(0),
|
||||||
downloadedSize(0), uploadedSize(0),
|
downloadedSize(0), uploadedSize(0),
|
||||||
|
preDownloadedSize(0), preUploadedSize(0),
|
||||||
deltaDownload(0), deltaUpload(0),
|
deltaDownload(0), deltaUpload(0),
|
||||||
storeDir("."),
|
storeDir("."),
|
||||||
multiFileTopDir(NULL),
|
multiFileTopDir(NULL),
|
||||||
|
@ -74,12 +75,7 @@ bool TorrentMan::addPeer(Peer* peer, bool duplicate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(peers.size() >= MAX_PEER_LIST_SIZE) {
|
deleteOldErrorPeers(MAX_PEER_LIST_SIZE);
|
||||||
deleteOldErrorPeers(100);
|
|
||||||
if(peers.size() >= MAX_PEER_LIST_SIZE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
|
for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
|
||||||
Peer* p = *itr;
|
Peer* p = *itr;
|
||||||
if(p->ipaddr == peer->ipaddr && p->port == peer->port) {
|
if(p->ipaddr == peer->ipaddr && p->port == peer->port) {
|
||||||
|
@ -455,6 +451,8 @@ void TorrentMan::read(FILE* file) {
|
||||||
if(fread(&uploadedSize, sizeof(uploadedSize), 1, file) < 1) {
|
if(fread(&uploadedSize, sizeof(uploadedSize), 1, file) < 1) {
|
||||||
throw new DlAbortEx(strerror(errno));
|
throw new DlAbortEx(strerror(errno));
|
||||||
}
|
}
|
||||||
|
preDownloadedSize = downloadedSize;
|
||||||
|
preUploadedSize = uploadedSize;
|
||||||
delete [] savedBitfield;
|
delete [] savedBitfield;
|
||||||
} catch(Exception* ex) {
|
} catch(Exception* ex) {
|
||||||
delete [] savedBitfield;
|
delete [] savedBitfield;
|
||||||
|
|
|
@ -74,6 +74,8 @@ private:
|
||||||
int cuidCounter;
|
int cuidCounter;
|
||||||
long long int downloadedSize;
|
long long int downloadedSize;
|
||||||
long long int uploadedSize;
|
long long int uploadedSize;
|
||||||
|
long long int preDownloadedSize;
|
||||||
|
long long int preUploadedSize;
|
||||||
int deltaDownload;
|
int deltaDownload;
|
||||||
int deltaUpload;
|
int deltaUpload;
|
||||||
int fileMode;
|
int fileMode;
|
||||||
|
@ -186,6 +188,13 @@ public:
|
||||||
long long int getUploadedSize() const { return uploadedSize; }
|
long long int getUploadedSize() const { return uploadedSize; }
|
||||||
void setUploadedSize(long long int size) { uploadedSize = size; }
|
void setUploadedSize(long long int size) { uploadedSize = size; }
|
||||||
|
|
||||||
|
long long int getSessionDownloadedSize() const {
|
||||||
|
return downloadedSize-preDownloadedSize;
|
||||||
|
}
|
||||||
|
long long int getSessionUploadedSize() const {
|
||||||
|
return uploadedSize-preUploadedSize;
|
||||||
|
}
|
||||||
|
|
||||||
void setFileMode(int mode) {
|
void setFileMode(int mode) {
|
||||||
fileMode = mode;
|
fileMode = mode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,8 @@ bool TrackerInitCommand::execute() {
|
||||||
"info_hash="+Util::urlencode(e->torrentMan->getInfoHash(), 20)+"&"+
|
"info_hash="+Util::urlencode(e->torrentMan->getInfoHash(), 20)+"&"+
|
||||||
"peer_id="+e->torrentMan->peerId+"&"+
|
"peer_id="+e->torrentMan->peerId+"&"+
|
||||||
"port="+Util::itos(e->torrentMan->getPort())+"&"+
|
"port="+Util::itos(e->torrentMan->getPort())+"&"+
|
||||||
"uploaded="+Util::llitos(e->torrentMan->getUploadedSize())+"&"+
|
"uploaded="+Util::llitos(e->torrentMan->getSessionUploadedSize())+"&"+
|
||||||
"downloaded="+Util::llitos(e->torrentMan->getDownloadedSize())+"&"+
|
"downloaded="+Util::llitos(e->torrentMan->getSessionDownloadedSize())+"&"+
|
||||||
"left="+(e->torrentMan->totalSize-e->torrentMan->getDownloadedSize() <= 0
|
"left="+(e->torrentMan->totalSize-e->torrentMan->getDownloadedSize() <= 0
|
||||||
? "0" : Util::llitos(e->torrentMan->totalSize-e->torrentMan->getDownloadedSize()))+"&"+
|
? "0" : Util::llitos(e->torrentMan->totalSize-e->torrentMan->getDownloadedSize()))+"&"+
|
||||||
"compact=1";
|
"compact=1";
|
||||||
|
|
|
@ -62,6 +62,9 @@ bool TrackerUpdateCommand::execute() {
|
||||||
e->torrentMan->minInterval = minInterval->toInt();
|
e->torrentMan->minInterval = minInterval->toInt();
|
||||||
e->logger->debug("CUID#%d - min interval:%d", cuid, e->torrentMan->minInterval);
|
e->logger->debug("CUID#%d - min interval:%d", cuid, e->torrentMan->minInterval);
|
||||||
}
|
}
|
||||||
|
if(e->torrentMan->minInterval > e->torrentMan->interval) {
|
||||||
|
e->torrentMan->minInterval = e->torrentMan->interval;
|
||||||
|
}
|
||||||
Data* complete = (Data*)response->get("complete");
|
Data* complete = (Data*)response->get("complete");
|
||||||
if(complete != NULL) {
|
if(complete != NULL) {
|
||||||
e->torrentMan->complete = complete->toInt();
|
e->torrentMan->complete = complete->toInt();
|
||||||
|
|
|
@ -242,6 +242,7 @@ int main(int argc, char* argv[]) {
|
||||||
Option* op = new Option();
|
Option* op = new Option();
|
||||||
op->put(PREF_RETRY_WAIT, "5");
|
op->put(PREF_RETRY_WAIT, "5");
|
||||||
op->put(PREF_TIMEOUT, "60");
|
op->put(PREF_TIMEOUT, "60");
|
||||||
|
op->put(PREF_PEER_CONNECTION_TIMEOUT, "30");
|
||||||
op->put(PREF_MIN_SEGMENT_SIZE, "1048576");// 1M
|
op->put(PREF_MIN_SEGMENT_SIZE, "1048576");// 1M
|
||||||
op->put(PREF_MAX_TRIES, "5");
|
op->put(PREF_MAX_TRIES, "5");
|
||||||
op->put(PREF_HTTP_PROXY_METHOD, V_TUNNEL);
|
op->put(PREF_HTTP_PROXY_METHOD, V_TUNNEL);
|
||||||
|
|
|
@ -83,5 +83,10 @@
|
||||||
// values: true | false
|
// values: true | false
|
||||||
#define PREF_HTTP_PROXY_AUTH_ENABLED "http_proxy_auth_enabled"
|
#define PREF_HTTP_PROXY_AUTH_ENABLED "http_proxy_auth_enabled"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BitTorrent related preferences
|
||||||
|
*/
|
||||||
|
// values: 1*digit
|
||||||
|
#define PREF_PEER_CONNECTION_TIMEOUT "peer_connection_timeout"
|
||||||
|
|
||||||
#endif // _D_PREFS_H_
|
#endif // _D_PREFS_H_
|
||||||
|
|
Loading…
Reference in New Issue