From d018b3a609a9e6eb5f2adb550b39452254daa8c6 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 18 May 2006 17:08:29 +0000 Subject: [PATCH] 2006-05-18 Tatsuhiro Tsujikawa To remove a wait from download loop: * src/DownloadEngine.cc (run): Comment out shortSleep. To rewrite the message handling: * src/CancelMessage.h: Derived from SimplePeerMessage. (msg): New variable. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/CancelMessage.cc (create): New function. (receivedAction): Replaced deleteRequestMessageInQueue with rejectPieceMessageInQueue. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/BitfieldMessage.h: Derived from SimplePeerMessage. (msg): New variable. (msgLength): New variable. (~BitfieldMessage): Deleted msg. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/BitfieldMessage.cc (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/ChokeMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPredicate): New function. (onSendComplete): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. (create): New function. * src/ChokeMessage.cc (create): New function. (send): Removed. (sendPredicate): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/KeepAliveMessage.h: Derived from SimplePeerMessage. (msg): New variable. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/KeepAliveMessage.cc (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/PortMessage.h (create): New function. (receivedAction): Updated log message. * src/PortMessage.cc: New file. * src/UnchokeMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPredicate): New function. (onSendComplete): New function. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/UnchokeMessage.cc (create): New function. (send): Removed. (sendPredicate): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/PieceMessage.h (leftPieceDataLength): Removed. (leftDataLength): New variable. (headerSend): New variable. (pendingCount): New variable. (msgHeader): New variable. (sendPieceData): New function. (incrementPendingCount): New function. (isPendingCountMax): New function. (create): New function. (getMessageHeader): New function. (getMessageHeaderLength): New function. * src/PieceMessage.cc (create): New function. (getMessageHeader): New function. (getMessageHeaderLength): New function. (send): Rewritten. (sendPieceData): New function. * src/HaveMessage.h: Derived from SimplePeerMessage. (msg): New variable. (create): New function. (getMessage): New function. (getMessageLength): New function. * src/HaveMessage.cc (create): New function. (send): Removed. (sendPieceData): New function. (getMessage): New function. (getMessageLength): New function. * src/RequestMessage.h: Derived from SimplePeerMessage. (msg): New variable. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/RequestMessage.cc (create): New function. (receivedAction): Added the handling of fast extension. Deleted torrentMan->addUploadLength, torrentMan->addDeltaUploadLength. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/InterestedMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPredicate): New function. (onSendComplete): New function. (create): New function. (getMessage): New function. (getMessageLength): New function. * src/InterestedMessage.cc (create): New function. (send): Removed. (sendPieceData): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/NotInterestedMessage.h: Derived from SimplePeerMessage. (msg): New variable. (sendPieceData): New function. (onSendComplete): New function. (create): New function. (send): Removed. (getMessage): New function. (getMessageLength): New function. * src/NotInterestedMessage.cc (create): New function. (send): Removed. (sendPredicate): New function. (getMessage): New function. (getMessageLength): New function. (onSendComplete): New function. * src/AllowedFastMessage.h: New class. * src/AllowedFastMessage.cc: New class. * src/RejectMessage.h: New class. * src/RejectMessage.cc: New class. * src/SuggestPieceMessage.h: New class. * src/SuggestPieceMessage.cc: New class. * src/HaveAllMessage.h: New class. * src/HaveAllMessage.cc: New class. * src/HaveNoneMessage.h: New class. * src/HaveNoneMessage.cc: New class. * src/HandshakeMessage.h: Derived from SimplePeerMessage. (msg): New variable. (reserved): New variable. (create): New function. (getId): New function. (receivedAction): New function. (getMessage): New function. (getMessageLength): New function. (isFastExtensionSupported): New function. * src/HandshakeMessage.cc (HandshakeMessage): Moved here from HandshakeMessage.h. (create): New function. (getMessage): New function. (getMessageLength): New function. (toString): Added the output of reserved field. (check): Added const qualifier. (isFastExtensionSupported): New function. * src/PeerMessageUtil.h (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createHaveMessage): Removed. (createBitfieldMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createPortMessage): Removed. (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createHaveMessage): Removed. (createBitfieldMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createKeepAliveMessage): Removed. (createHandshakeMessage): Removed. (setIntParam): New function. (createPeerMessageString): New function. * src/PeerMessageUtil.cc (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createHaveMessage): Removed. (createBitfieldMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createPortMessage): Removed. (createRequestMessage): Removed. (createCancelMessage): Removed. (createPieceMessage): Removed. (createHaveMessage): Removed. (createChokeMessage): Removed. (createUnchokeMessage): Removed. (createInterestedMessage): Removed. (createNotInterestedMessage): Removed. (createBitfieldMessage): Removed. (createKeepAliveMessage): Removed. (createHandshakeMessage): Removed. (setIntParam): New function. (createPeerMessageString): New function. * src/PeerConnection.h (peer): Removed. (torrentMan): Removed. (createNLengthMessage): Removed. (setIntParam): Removed. (writeOutgoingMessageLog): Removed all overloaded functions. (PeerConnection): Deleted peer and torrentMan from its arguments. (sendMessage): New function. (sendHandshake): Removed. (sendKeepAlive): Removed. (sendChoke): Removed. (sendUnchoke): Removed. (sendInterested): Removed. (sendNotInterested): Removed. (sendHave): Removed. (sendBitfield): Removed. (sendRequest): Removed. (sendPiece): Removed. (sendPieceHeader): Removed. (sendPieceData): Removed. (sendCancel): Removed. (getPeer): Removed. * src/PeerConnection.cc (PeerConnection): Deleted peer and torrentMan from its arguments. (sendHandshake): Removed. (sendKeepAlive): Removed. (createNLengthMessage): Removed. (setIntParam): Removed. (writeOutgoingMessageLog): Removed all overloaded functions. (sendChoke): Removed. (sendUnchoke): Removed. (sendInterested): Removed. (sendNotInterested): Removed. (sendHave): Removed. (sendBitfield): Removed. (sendRequest): Removed. (sendPiece): Removed. (sendPieceHeader): Removed. (sendPieceData): Removed. (sendMessage): New function. (sendCancel): Removed. * src/PeerInteractionCommand.cc (PeerInteractionCommand): Call setUploadLimit. (executeInternal): Call setUploadLimit. Added the handling of "inProgress" state of handshake message. Call sendBitfield() or sendAllowdFast() instead of deprecated sendNow(). (keepAlive): Call addMessage and sendMessage instead of deprecated sendNow(). (beforeSocketCheck): Call addMessage instead of deprecated trySendNow() * src/TorrentMan.h (PEER_ID_LENGTH): New definition. (hasAllPieces): New function. * src/TorrentMan.cc (getMissingPiece): Added the handling of fast extension. (cancelPiece): Call updatePiece(). (hasAllPieces): New function. * src/PeerInteraction.h (fastSet): New variable. (getNewPieceAndSendInterest): Changed the return type to void. (send): Renamed as sendMessages. (deleteAllRequestSlot): Removed. (deleteRequestMessageInQueue): Renamed as rejectPieceMessageInQueue. (cancelAllRequest): Removed all overloaded functions. (deleteAllRequestSlot): Removed. (deletePieceMessageInQueue): Renamed as rejectAllPieceMessageInQueue. (rejectPieceMessageInQueue): New function. (rejectAllPieceMessageInQueue): New function. (onChoked): New function. (isSendingMessageInProgress): New function. (getCorrespondingRequestSlot): Changed its arguments. (isInFastSet): New function. (addFastSetIndex): New function. (addRequests): New function. (sendNow): Removed. (trySendNow): Removed. (sendBitfield): New function. (sendAllowdFast): New function. (createHaveAllMessage): New function. (createHaveNoneMessage): New function. (createRejectMessage): New function. (createAllowedFastMessage): New function. * src/PeerInteraction.cc (send): Renamed as sendMessages. (sendMessages): New function. (MsgPushBack): New class. (isSendingMessageInProgress): New function. (deletePieceMessageInQueue): Renamed as rejectAllPieceMessageInQueue. (rejectAllPieceMessageInQueue): New function. Added the handling of fast extension. (deleteRequestMessageInQueue): Renamed as rejectPieceMessageInQueue. (rejectPieceMessageInQueue): New function. Added the handling of fast extension. (deleteRequestSlot): Replaced for loop with std::find. (onChoked): New function. (deleteAllRequestSlot): Removed. (abortPiece): Rewirtten. (deleteTimeoutRequestSlot): Updated log messages. (getCorrespondingRequestSlot): Changed its arguments. (cancelAllRequest): Removed all overloaded functions. (receiveHandshake): Added the check to see whether an incoming peer supports fast extension. (createHandshakeMessage): Use HandshakeMessage::create instead of PeerMessageUtil. (createPeerMessage): Use create() of each message class instead of PeerMessageUtil. HaveAllMessage, HaveNoneMessage, RejectMessage, SuggestPieceMessage, AllowedFastMessage were added. (getNewPieceAndSendInterest): Changed its return value type to void. Added the handling of fast extension. (addRequests): New function. (sendNow): Removed. (sendHandshake): Rewritten. (trySendNow): Removed. (sendBitfield): New function. (sendAllowdFast): New function. (isInFastSet): New function. (addFastSetIndex): New function. (createRequestMessage): Use RequestMessage::create instead of PeerMessageUtil. (createCancelMessage): Use CancelMessage::create instead of PeerMessageUtil. (createPieceMessage): Use PieceMessage::create instead of PeerMessageUtil. (createHaveMessage): Use HaveMessage::create instead of PeerMessageUtil. (createChokeMessage): Use ChokeMessage::create instead of PeerMessageUtil. (createUnchokeMessage): Use UnchokeMessage::create instead of PeerMessageUtil. (createInterestedMessage): Use InterestedMessage::create instead of PeerMessageUtil. (createNotInterestedMessage): Use NotInterestedMessage::create instead of PeerMessageUtil. (createBitfieldMessage): Use BitfieldMessage::create instead of PeerMessageUtil. (createKeepAliveMessage): Use KeepAliveMessage::create instead of PeerMessageUtil. (createHaveAllMessage): New function. (createHaveNoneMessage): New function. (createRejectMessage): New function. (createAllowedFastMessage: New function. * src/Util.h (sha1Sum): New function. (computeFastSet): New function. * src/Util.cc (sha1Sum): New function. (computeFastSet): New function. * src/Peer.h (fastExtensionEnabled): New variable. (fastSet): New variable. (setAllBitfield): New function. (setFastExtensionEnabled): New function. (isFastExtensionEnabled): New function. (addFastSetIndex): New function. (getFastSet): New function. (isInFastSet): New function. (countFastSet): New function. * src/Peer.cc (isInFastSet): New function. (addFastSetIndex): New function. (setAllBitfield): New function. * src/AbstractCommand.cc (execute): Changed the procedure of checking sockets. * src/PeerAbstractCommand.cc (PeerAbstractCommand): Added the initialization for uploadLimitCheck and uploadLimit. (execute): Changed the procedure of checking sockets. The upload speed checking were added. (setUploadLimit): New function. (setUploadLimitCheck): New function. * src/PeerAbstractCommand.h (setUploadLimit): New function. (setUploadLimitCheck): New function. (uploadLimit): New variable. (uploadLimitCheck): New variable. To contact a tracker regularly: * src/TrackerWatcherCommand.h (interval): New variable. (checkPoint): New variable. (TrackerWatcherCommand): Added interval argument. * src/TrackerWatcherCommand.cc (TrackerWatcherCommand): Initialized checkPoint. (execute): Now a tracker is contacted in every specified period. If peer list is not needed, send request with numwant=0. * src/TrackerUpdateCommand.cc (execute): Updated log messages. * src/DownloadEngine.cc (~DownloadEngine): Removed two asserts. (waitData): Uncommented wfds. May be a bug fix. --- ChangeLog | 418 +++++++++++++++++++++++++++++++ TODO | 5 +- src/AbstractCommand.cc | 29 ++- src/AllowedFastMessage.cc | 78 ++++++ src/AllowedFastMessage.h | 64 +++++ src/BitfieldMessage.cc | 37 ++- src/BitfieldMessage.h | 19 +- src/CancelMessage.cc | 43 +++- src/CancelMessage.h | 15 +- src/ChokeMessage.cc | 43 +++- src/ChokeMessage.h | 15 +- src/DownloadEngine.cc | 6 +- src/HandshakeMessage.cc | 45 +++- src/HandshakeMessage.h | 33 ++- src/HaveAllMessage.cc | 72 ++++++ src/HaveAllMessage.h | 48 ++++ src/HaveMessage.cc | 37 ++- src/HaveMessage.h | 14 +- src/HaveNoneMessage.cc | 71 ++++++ src/HaveNoneMessage.h | 48 ++++ src/InterestedMessage.cc | 40 ++- src/InterestedMessage.h | 16 +- src/KeepAliveMessage.cc | 15 +- src/KeepAliveMessage.h | 11 +- src/Makefile.am | 8 +- src/Makefile.in | 21 +- src/NotInterestedMessage.cc | 40 ++- src/NotInterestedMessage.h | 16 +- src/Peer.cc | 16 ++ src/Peer.h | 17 +- src/PeerAbstractCommand.cc | 27 +- src/PeerAbstractCommand.h | 4 + src/PeerConnection.cc | 275 +------------------- src/PeerConnection.h | 30 +-- src/PeerInteraction.cc | 381 +++++++++++++++++++--------- src/PeerInteraction.h | 42 ++-- src/PeerInteractionCommand.cc | 40 ++- src/PeerMessageUtil.cc | 182 +------------- src/PeerMessageUtil.h | 37 +-- src/PieceMessage.cc | 123 +++++++-- src/PieceMessage.h | 17 +- src/PortMessage.cc | 38 +++ src/PortMessage.h | 6 +- src/RejectMessage.cc | 93 +++++++ src/RejectMessage.h | 76 ++++++ src/RequestMessage.cc | 49 +++- src/RequestMessage.h | 13 +- src/SuggestPieceMessage.cc | 70 ++++++ src/SuggestPieceMessage.h | 62 +++++ src/TorrentMan.cc | 33 ++- src/TorrentMan.h | 3 + src/TrackerUpdateCommand.cc | 20 +- src/TrackerWatcherCommand.cc | 27 +- src/TrackerWatcherCommand.h | 5 +- src/UnchokeMessage.cc | 40 ++- src/UnchokeMessage.h | 17 +- src/Util.cc | 55 ++++ src/Util.h | 6 + src/main.cc | 3 +- test/AllowedFastMessageTest.cc | 59 +++++ test/BitfieldMessageTest.cc | 63 +++++ test/CancelMessageTest.cc | 67 +++++ test/ChokeMessageTest.cc | 55 ++++ test/HaveAllMessageTest.cc | 55 ++++ test/HaveMessageTest.cc | 59 +++++ test/HaveNoneMessageTest.cc | 55 ++++ test/InterestedMessageTest.cc | 55 ++++ test/Makefile.am | 16 +- test/Makefile.in | 39 ++- test/MetaFileUtilTest.cc | 16 +- test/NotInterestedMessageTest.cc | 55 ++++ test/PeerMessageUtilTest.cc | 215 +--------------- test/PieceMessageTest.cc | 69 +++++ test/RejectMessageTest.cc | 67 +++++ test/RequestMessageTest.cc | 67 +++++ test/SuggestPieceMessageTest.cc | 59 +++++ test/UnchokeMessageTest.cc | 55 ++++ test/UtilTest.cc | 33 +++ 78 files changed, 3258 insertions(+), 1015 deletions(-) create mode 100644 src/AllowedFastMessage.cc create mode 100644 src/AllowedFastMessage.h create mode 100644 src/HaveAllMessage.cc create mode 100644 src/HaveAllMessage.h create mode 100644 src/HaveNoneMessage.cc create mode 100644 src/HaveNoneMessage.h create mode 100644 src/PortMessage.cc create mode 100644 src/RejectMessage.cc create mode 100644 src/RejectMessage.h create mode 100644 src/SuggestPieceMessage.cc create mode 100644 src/SuggestPieceMessage.h create mode 100644 test/AllowedFastMessageTest.cc create mode 100644 test/BitfieldMessageTest.cc create mode 100644 test/CancelMessageTest.cc create mode 100644 test/ChokeMessageTest.cc create mode 100644 test/HaveAllMessageTest.cc create mode 100644 test/HaveMessageTest.cc create mode 100644 test/HaveNoneMessageTest.cc create mode 100644 test/InterestedMessageTest.cc create mode 100644 test/NotInterestedMessageTest.cc create mode 100644 test/PieceMessageTest.cc create mode 100644 test/RejectMessageTest.cc create mode 100644 test/RequestMessageTest.cc create mode 100644 test/SuggestPieceMessageTest.cc create mode 100644 test/UnchokeMessageTest.cc diff --git a/ChangeLog b/ChangeLog index 73cc9988..c2e5b5d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,421 @@ +2006-05-18 Tatsuhiro Tsujikawa + + To remove a wait from download loop: + + * src/DownloadEngine.cc + (run): Comment out shortSleep. + + To rewrite the message handling: + + * src/CancelMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (create): New function. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/CancelMessage.cc + (create): New function. + (receivedAction): Replaced deleteRequestMessageInQueue with + rejectPieceMessageInQueue. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/BitfieldMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (msgLength): New variable. + (~BitfieldMessage): Deleted msg. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/BitfieldMessage.cc + (create): New function. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/ChokeMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (sendPredicate): New function. + (onSendComplete): New function. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + (create): New function. + * src/ChokeMessage.cc + (create): New function. + (send): Removed. + (sendPredicate): New function. + (getMessage): New function. + (getMessageLength): New function. + (onSendComplete): New function. + * src/KeepAliveMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/KeepAliveMessage.cc + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/PortMessage.h + (create): New function. + (receivedAction): Updated log message. + * src/PortMessage.cc: New file. + * src/UnchokeMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (sendPredicate): New function. + (onSendComplete): New function. + (create): New function. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/UnchokeMessage.cc + (create): New function. + (send): Removed. + (sendPredicate): New function. + (getMessage): New function. + (getMessageLength): New function. + (onSendComplete): New function. + * src/PieceMessage.h + (leftPieceDataLength): Removed. + (leftDataLength): New variable. + (headerSend): New variable. + (pendingCount): New variable. + (msgHeader): New variable. + (sendPieceData): New function. + (incrementPendingCount): New function. + (isPendingCountMax): New function. + (create): New function. + (getMessageHeader): New function. + (getMessageHeaderLength): New function. + * src/PieceMessage.cc + (create): New function. + (getMessageHeader): New function. + (getMessageHeaderLength): New function. + (send): Rewritten. + (sendPieceData): New function. + * src/HaveMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (create): New function. + (getMessage): New function. + (getMessageLength): New function. + * src/HaveMessage.cc + (create): New function. + (send): Removed. + (sendPieceData): New function. + (getMessage): New function. + (getMessageLength): New function. + * src/RequestMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (create): New function. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/RequestMessage.cc + (create): New function. + (receivedAction): Added the handling of fast extension. + Deleted torrentMan->addUploadLength, torrentMan->addDeltaUploadLength. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/InterestedMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (sendPredicate): New function. + (onSendComplete): New function. + (create): New function. + (getMessage): New function. + (getMessageLength): New function. + * src/InterestedMessage.cc + (create): New function. + (send): Removed. + (sendPieceData): New function. + (getMessage): New function. + (getMessageLength): New function. + (onSendComplete): New function. + * src/NotInterestedMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (sendPieceData): New function. + (onSendComplete): New function. + (create): New function. + (send): Removed. + (getMessage): New function. + (getMessageLength): New function. + * src/NotInterestedMessage.cc + (create): New function. + (send): Removed. + (sendPredicate): New function. + (getMessage): New function. + (getMessageLength): New function. + (onSendComplete): New function. + * src/AllowedFastMessage.h: New class. + * src/AllowedFastMessage.cc: New class. + * src/RejectMessage.h: New class. + * src/RejectMessage.cc: New class. + * src/SuggestPieceMessage.h: New class. + * src/SuggestPieceMessage.cc: New class. + * src/HaveAllMessage.h: New class. + * src/HaveAllMessage.cc: New class. + * src/HaveNoneMessage.h: New class. + * src/HaveNoneMessage.cc: New class. + * src/HandshakeMessage.h: Derived from SimplePeerMessage. + (msg): New variable. + (reserved): New variable. + (create): New function. + (getId): New function. + (receivedAction): New function. + (getMessage): New function. + (getMessageLength): New function. + (isFastExtensionSupported): New function. + * src/HandshakeMessage.cc + (HandshakeMessage): Moved here from HandshakeMessage.h. + (create): New function. + (getMessage): New function. + (getMessageLength): New function. + (toString): Added the output of reserved field. + (check): Added const qualifier. + (isFastExtensionSupported): New function. + * src/PeerMessageUtil.h + (createChokeMessage): Removed. + (createUnchokeMessage): Removed. + (createInterestedMessage): Removed. + (createNotInterestedMessage): Removed. + (createHaveMessage): Removed. + (createBitfieldMessage): Removed. + (createRequestMessage): Removed. + (createCancelMessage): Removed. + (createPieceMessage): Removed. + (createPortMessage): Removed. + (createChokeMessage): Removed. + (createUnchokeMessage): Removed. + (createInterestedMessage): Removed. + (createNotInterestedMessage): Removed. + (createHaveMessage): Removed. + (createBitfieldMessage): Removed. + (createRequestMessage): Removed. + (createCancelMessage): Removed. + (createPieceMessage): Removed. + (createKeepAliveMessage): Removed. + (createHandshakeMessage): Removed. + (setIntParam): New function. + (createPeerMessageString): New function. + * src/PeerMessageUtil.cc + (createChokeMessage): Removed. + (createUnchokeMessage): Removed. + (createInterestedMessage): Removed. + (createNotInterestedMessage): Removed. + (createHaveMessage): Removed. + (createBitfieldMessage): Removed. + (createRequestMessage): Removed. + (createCancelMessage): Removed. + (createPieceMessage): Removed. + (createPortMessage): Removed. + (createRequestMessage): Removed. + (createCancelMessage): Removed. + (createPieceMessage): Removed. + (createHaveMessage): Removed. + (createChokeMessage): Removed. + (createUnchokeMessage): Removed. + (createInterestedMessage): Removed. + (createNotInterestedMessage): Removed. + (createBitfieldMessage): Removed. + (createKeepAliveMessage): Removed. + (createHandshakeMessage): Removed. + (setIntParam): New function. + (createPeerMessageString): New function. + * src/PeerConnection.h + (peer): Removed. + (torrentMan): Removed. + (createNLengthMessage): Removed. + (setIntParam): Removed. + (writeOutgoingMessageLog): Removed all overloaded functions. + (PeerConnection): Deleted peer and torrentMan from its arguments. + (sendMessage): New function. + (sendHandshake): Removed. + (sendKeepAlive): Removed. + (sendChoke): Removed. + (sendUnchoke): Removed. + (sendInterested): Removed. + (sendNotInterested): Removed. + (sendHave): Removed. + (sendBitfield): Removed. + (sendRequest): Removed. + (sendPiece): Removed. + (sendPieceHeader): Removed. + (sendPieceData): Removed. + (sendCancel): Removed. + (getPeer): Removed. + * src/PeerConnection.cc + (PeerConnection): Deleted peer and torrentMan from its arguments. + (sendHandshake): Removed. + (sendKeepAlive): Removed. + (createNLengthMessage): Removed. + (setIntParam): Removed. + (writeOutgoingMessageLog): Removed all overloaded functions. + (sendChoke): Removed. + (sendUnchoke): Removed. + (sendInterested): Removed. + (sendNotInterested): Removed. + (sendHave): Removed. + (sendBitfield): Removed. + (sendRequest): Removed. + (sendPiece): Removed. + (sendPieceHeader): Removed. + (sendPieceData): Removed. + (sendMessage): New function. + (sendCancel): Removed. + * src/PeerInteractionCommand.cc + (PeerInteractionCommand): Call setUploadLimit. + (executeInternal): Call setUploadLimit. + Added the handling of "inProgress" state of handshake message. + Call sendBitfield() or sendAllowdFast() instead of deprecated + sendNow(). + (keepAlive): Call addMessage and sendMessage instead of deprecated + sendNow(). + (beforeSocketCheck): Call addMessage instead of deprecated trySendNow() + * src/TorrentMan.h + (PEER_ID_LENGTH): New definition. + (hasAllPieces): New function. + * src/TorrentMan.cc + (getMissingPiece): Added the handling of fast extension. + (cancelPiece): Call updatePiece(). + (hasAllPieces): New function. + * src/PeerInteraction.h + (fastSet): New variable. + (getNewPieceAndSendInterest): Changed the return type to void. + (send): Renamed as sendMessages. + (deleteAllRequestSlot): Removed. + (deleteRequestMessageInQueue): Renamed as rejectPieceMessageInQueue. + (cancelAllRequest): Removed all overloaded functions. + (deleteAllRequestSlot): Removed. + (deletePieceMessageInQueue): Renamed as rejectAllPieceMessageInQueue. + (rejectPieceMessageInQueue): New function. + (rejectAllPieceMessageInQueue): New function. + (onChoked): New function. + (isSendingMessageInProgress): New function. + (getCorrespondingRequestSlot): Changed its arguments. + (isInFastSet): New function. + (addFastSetIndex): New function. + (addRequests): New function. + (sendNow): Removed. + (trySendNow): Removed. + (sendBitfield): New function. + (sendAllowdFast): New function. + (createHaveAllMessage): New function. + (createHaveNoneMessage): New function. + (createRejectMessage): New function. + (createAllowedFastMessage): New function. + * src/PeerInteraction.cc + (send): Renamed as sendMessages. + (sendMessages): New function. + (MsgPushBack): New class. + (isSendingMessageInProgress): New function. + (deletePieceMessageInQueue): Renamed as rejectAllPieceMessageInQueue. + (rejectAllPieceMessageInQueue): New function. + Added the handling of fast extension. + (deleteRequestMessageInQueue): Renamed as rejectPieceMessageInQueue. + (rejectPieceMessageInQueue): New function. + Added the handling of fast extension. + (deleteRequestSlot): Replaced for loop with std::find. + (onChoked): New function. + (deleteAllRequestSlot): Removed. + (abortPiece): Rewirtten. + (deleteTimeoutRequestSlot): Updated log messages. + (getCorrespondingRequestSlot): Changed its arguments. + (cancelAllRequest): Removed all overloaded functions. + (receiveHandshake): Added the check to see whether an incoming peer + supports fast extension. + (createHandshakeMessage): Use HandshakeMessage::create instead of + PeerMessageUtil. + (createPeerMessage): Use create() of each message class instead of + PeerMessageUtil. + HaveAllMessage, HaveNoneMessage, RejectMessage, SuggestPieceMessage, + AllowedFastMessage were added. + (getNewPieceAndSendInterest): Changed its return value type to void. + Added the handling of fast extension. + (addRequests): New function. + (sendNow): Removed. + (sendHandshake): Rewritten. + (trySendNow): Removed. + (sendBitfield): New function. + (sendAllowdFast): New function. + (isInFastSet): New function. + (addFastSetIndex): New function. + (createRequestMessage): Use RequestMessage::create instead of + PeerMessageUtil. + (createCancelMessage): Use CancelMessage::create instead of + PeerMessageUtil. + (createPieceMessage): Use PieceMessage::create instead of + PeerMessageUtil. + (createHaveMessage): Use HaveMessage::create instead of + PeerMessageUtil. + (createChokeMessage): Use ChokeMessage::create instead of + PeerMessageUtil. + (createUnchokeMessage): Use UnchokeMessage::create instead of + PeerMessageUtil. + (createInterestedMessage): Use InterestedMessage::create instead of + PeerMessageUtil. + (createNotInterestedMessage): Use NotInterestedMessage::create instead + of PeerMessageUtil. + (createBitfieldMessage): Use BitfieldMessage::create instead of + PeerMessageUtil. + (createKeepAliveMessage): Use KeepAliveMessage::create instead of + PeerMessageUtil. + (createHaveAllMessage): New function. + (createHaveNoneMessage): New function. + (createRejectMessage): New function. + (createAllowedFastMessage: New function. + * src/Util.h + (sha1Sum): New function. + (computeFastSet): New function. + * src/Util.cc + (sha1Sum): New function. + (computeFastSet): New function. + * src/Peer.h + (fastExtensionEnabled): New variable. + (fastSet): New variable. + (setAllBitfield): New function. + (setFastExtensionEnabled): New function. + (isFastExtensionEnabled): New function. + (addFastSetIndex): New function. + (getFastSet): New function. + (isInFastSet): New function. + (countFastSet): New function. + * src/Peer.cc + (isInFastSet): New function. + (addFastSetIndex): New function. + (setAllBitfield): New function. + + * src/AbstractCommand.cc (execute): Changed the procedure of checking + sockets. + * src/PeerAbstractCommand.cc + (PeerAbstractCommand): Added the initialization for uploadLimitCheck + and uploadLimit. + (execute): Changed the procedure of checking sockets. The upload speed + checking were added. + (setUploadLimit): New function. + (setUploadLimitCheck): New function. + * src/PeerAbstractCommand.h + (setUploadLimit): New function. + (setUploadLimitCheck): New function. + (uploadLimit): New variable. + (uploadLimitCheck): New variable. + + To contact a tracker regularly: + + * src/TrackerWatcherCommand.h (interval): New variable. + (checkPoint): New variable. + (TrackerWatcherCommand): Added interval argument. + * src/TrackerWatcherCommand.cc + (TrackerWatcherCommand): Initialized checkPoint. + (execute): Now a tracker is contacted in every specified period. + If peer list is not needed, send request with numwant=0. + + * src/TrackerUpdateCommand.cc + (execute): Updated log messages. + + * src/DownloadEngine.cc + (~DownloadEngine): Removed two asserts. + (waitData): Uncommented wfds. May be a bug fix. + 2006-05-10 Tatsuhiro Tsujikawa * src/PeerInteractionCommand.h diff --git a/TODO b/TODO index 857676c9..84f49741 100644 --- a/TODO +++ b/TODO @@ -14,5 +14,6 @@ * Add Mainline-compatible DHT support * Add Message stream encryption support * Add announce-list support -* Add fast extension -* Refacturing HttpConnection and FtpConnection \ No newline at end of file +* Refacturing HttpConnection and FtpConnection +* HTTP/FTP downloading regression test +* Fast extension test \ No newline at end of file diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 03983842..3954dd9d 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -72,25 +72,28 @@ bool AbstractCommand::isTimeoutDetected() { bool AbstractCommand::execute() { try { - if(checkSocketIsReadable && !readCheckTarget->isReadable(0) - || checkSocketIsWritable && !writeCheckTarget->isWritable(0)) { + if(checkSocketIsReadable && readCheckTarget->isReadable(0) || + checkSocketIsWritable && writeCheckTarget->isWritable(0) || + !checkSocketIsReadable && !checkSocketIsWritable) { + + updateCheckPoint(); + Segment seg = { 0, 0, 0, false }; + if(e->segmentMan->downloadStarted) { + // get segment information in order to set Range header. + if(!e->segmentMan->getSegment(seg, cuid)) { + // no segment available + logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid); + return true; + } + } + return executeInternal(seg); + } else { if(isTimeoutDetected()) { throw new DlRetryEx(EX_TIME_OUT); } e->commands.push_back(this); return false; } - updateCheckPoint(); - Segment seg = { 0, 0, 0, false }; - if(e->segmentMan->downloadStarted) { - // get segment information in order to set Range header. - if(!e->segmentMan->getSegment(seg, cuid)) { - // no segment available - logger->info(MSG_NO_SEGMENT_AVAILABLE, cuid); - return true; - } - } - return executeInternal(seg); } catch(DlAbortEx* err) { logger->error(MSG_DOWNLOAD_ABORTED, err, cuid); onAbort(err); diff --git a/src/AllowedFastMessage.cc b/src/AllowedFastMessage.cc new file mode 100644 index 00000000..f3d7c711 --- /dev/null +++ b/src/AllowedFastMessage.cc @@ -0,0 +1,78 @@ +/* */ +#include "AllowedFastMessage.h" +#include "PeerInteraction.h" +#include "PeerMessageUtil.h" +#include "Util.h" +#include "DlAbortEx.h" + +AllowedFastMessage* AllowedFastMessage::create(const char* data, int dataLength) { + if(dataLength != 5) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "allowed fast", dataLength, 5); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "allowed fast", ID); + } + AllowedFastMessage* allowedFastMessage = new AllowedFastMessage(); + allowedFastMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + return allowedFastMessage; +} + +void AllowedFastMessage::receivedAction() { + if(!peer->isFastExtensionEnabled()) { + throw new DlAbortEx("%s received while fast extension is disabled", + toString().c_str()); + } + peer->addFastSetIndex(index); +} + +const char* AllowedFastMessage::getMessage() { + if(!inProgress) { + /** + * len --- 5, 4bytes + * id --- 17, 1byte + * piece index --- index, 4bytes + * total: 9bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, ID); + PeerMessageUtil::setIntParam(&msg[5], index); + } + return msg; +} + +int AllowedFastMessage::getMessageLength() { + return sizeof(msg); +} + +void AllowedFastMessage::onSendComplete() { + peerInteraction->addFastSetIndex(index); +} + +void AllowedFastMessage::check() const { + PeerMessageUtil::checkIndex(index, pieces); +} + +string AllowedFastMessage::toString() const { + return "allowed fast index="+Util::itos(index); +} diff --git a/src/AllowedFastMessage.h b/src/AllowedFastMessage.h new file mode 100644 index 00000000..0d4f1666 --- /dev/null +++ b/src/AllowedFastMessage.h @@ -0,0 +1,64 @@ +/* */ +#ifndef _D_ALLOWED_FAST_MESSAGE_H_ +#define _D_ALLOWED_FAST_MESSAGE_H_ + +#include "SimplePeerMessage.h" + +class AllowedFastMessage : public SimplePeerMessage { +private: + int index; + // for check + int pieces; + char msg[9]; +protected: + virtual void onSendComplete(); +public: + AllowedFastMessage():SimplePeerMessage(), index(0), pieces(0) {} + + virtual ~AllowedFastMessage() {} + + enum ID { + ID = 17 + }; + + void setIndex(int index) { + this->index = index; + } + int getIndex() const { return index; } + + void setPieces(int pieces) { + this->pieces = pieces; + } + int getPieces() const { return pieces;} + + static AllowedFastMessage* create(const char* data, int dataLength); + + virtual int getId() const { return ID; } + virtual void receivedAction(); + virtual const char* getMessage(); + virtual int getMessageLength(); + virtual void check() const; + virtual string toString() const; +}; + +#endif // _D_ALLOWED_FAST_MESSAGE_H_ diff --git a/src/BitfieldMessage.cc b/src/BitfieldMessage.cc index 84a96f33..95ef3dff 100644 --- a/src/BitfieldMessage.cc +++ b/src/BitfieldMessage.cc @@ -23,6 +23,7 @@ #include "PeerInteraction.h" #include "PeerMessageUtil.h" #include "Util.h" +#include "DlAbortEx.h" void BitfieldMessage::setBitfield(const unsigned char* bitfield, int bitfieldLength) { if(this->bitfield != NULL) { @@ -33,12 +34,44 @@ void BitfieldMessage::setBitfield(const unsigned char* bitfield, int bitfieldLen memcpy(this->bitfield, bitfield, this->bitfieldLength); } +BitfieldMessage* BitfieldMessage::create(const char* data, int dataLength) { + if(dataLength <= 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be greater than %d", "bitfield", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "bitfield", ID); + } + BitfieldMessage* bitfieldMessage = new BitfieldMessage(); + bitfieldMessage->setBitfield((unsigned char*)data+1, dataLength-1); + return bitfieldMessage; +} + void BitfieldMessage::receivedAction() { peer->setBitfield(bitfield, bitfieldLength); } -void BitfieldMessage::send() { - peerInteraction->getPeerConnection()->sendBitfield(); +const char* BitfieldMessage::getMessage() { + if(!inProgress && msg == NULL) { + /** + * len --- 1+bitfieldLength, 4bytes + * id --- 5, 1byte + * bitfield --- bitfield, len bytes + * total: 5+len bytes + */ + msgLength = 5+bitfieldLength; + msg = new char[msgLength]; + PeerMessageUtil::createPeerMessageString(msg, msgLength, + 1+bitfieldLength, ID); + memcpy(msg+5, bitfield, bitfieldLength); + } + return msg; +} + +int BitfieldMessage::getMessageLength() { + getMessage(); + return msgLength; } void BitfieldMessage::check() const { diff --git a/src/BitfieldMessage.h b/src/BitfieldMessage.h index 4c7901e9..3fd19c0d 100644 --- a/src/BitfieldMessage.h +++ b/src/BitfieldMessage.h @@ -22,23 +22,29 @@ #ifndef _D_BITFIELD_MESSAGE_H_ #define _D_BITFIELD_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class BitfieldMessage : public PeerMessage { +class BitfieldMessage : public SimplePeerMessage { private: unsigned char* bitfield; int bitfieldLength; // for check int pieces; + + char* msg; + int msgLength; public: - BitfieldMessage():PeerMessage(), + BitfieldMessage():SimplePeerMessage(), bitfield(NULL), bitfieldLength(0), - pieces(0) {} + pieces(0), msg(NULL), msgLength(0) {} virtual ~BitfieldMessage() { if(bitfield != NULL) { delete [] bitfield; } + if(msg != NULL) { + delete [] msg; + } } enum ID { @@ -55,9 +61,12 @@ public: } int getPieces() const { return pieces;} + static BitfieldMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual void check() const; virtual string toString() const; }; diff --git a/src/CancelMessage.cc b/src/CancelMessage.cc index 0a452cbf..9c8ea1f7 100644 --- a/src/CancelMessage.cc +++ b/src/CancelMessage.cc @@ -23,13 +23,48 @@ #include "PeerInteraction.h" #include "PeerMessageUtil.h" #include "Util.h" +#include "DlAbortEx.h" -void CancelMessage::receivedAction() { - peerInteraction->deletePieceMessageInQueue(this); +CancelMessage* CancelMessage::create(const char* data, int dataLength) { + if(dataLength != 13) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "cancel", dataLength, 13); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "cancel", ID); + } + CancelMessage* cancelMessage = new CancelMessage(); + cancelMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + cancelMessage->setBegin(PeerMessageUtil::getIntParam(data, 5)); + cancelMessage->setLength(PeerMessageUtil::getIntParam(data, 9)); + return cancelMessage; } -void CancelMessage::send() { - peerInteraction->getPeerConnection()->sendCancel(index, begin, length); +void CancelMessage::receivedAction() { + peerInteraction->rejectPieceMessageInQueue(index, begin, length); +} + +const char* CancelMessage::getMessage() { + if(!inProgress) { + /** + * len --- 13, 4bytes + * id --- 8, 1byte + * index --- index, 4bytes + * begin --- begin, 4bytes + * length -- length, 4bytes + * total: 17bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, ID); + PeerMessageUtil::setIntParam(&msg[5], index); + PeerMessageUtil::setIntParam(&msg[9], begin); + PeerMessageUtil::setIntParam(&msg[13], length); + } + return msg; +} + +int CancelMessage::getMessageLength() { + return sizeof(msg); } void CancelMessage::check() const { diff --git a/src/CancelMessage.h b/src/CancelMessage.h index ddea71ac..a75ae2eb 100644 --- a/src/CancelMessage.h +++ b/src/CancelMessage.h @@ -22,12 +22,10 @@ #ifndef _D_CANCEL_MESSAGE_H_ #define _D_CANCEL_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" #include "TorrentMan.h" -class SendMessageQueue; - -class CancelMessage : public PeerMessage { +class CancelMessage : public SimplePeerMessage { private: int index; int begin; @@ -35,8 +33,10 @@ private: // for check int pieces; int pieceLength; + + char msg[17]; public: - CancelMessage():PeerMessage(), + CancelMessage():SimplePeerMessage(), index(0), begin(0), length(0), pieces(0), pieceLength(0) {} @@ -63,9 +63,12 @@ public: } int getPieceLength() const { return pieceLength;} + static CancelMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual void check() const; virtual string toString() const; }; diff --git a/src/ChokeMessage.cc b/src/ChokeMessage.cc index 30be0245..c2313b4f 100644 --- a/src/ChokeMessage.cc +++ b/src/ChokeMessage.cc @@ -21,16 +21,51 @@ /* copyright --> */ #include "ChokeMessage.h" #include "PeerInteraction.h" +#include "message.h" +#include "PeerMessageUtil.h" +#include "DlAbortEx.h" + +ChokeMessage* ChokeMessage::create(const char* data, int dataLength) { + if(dataLength != 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "choke", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "choke", ID); + } + ChokeMessage* chokeMessage = new ChokeMessage(); + return chokeMessage; +} void ChokeMessage::receivedAction() { peer->peerChoking = true; + peerInteraction->onChoked(); } -void ChokeMessage::send() { - if(!peer->amChoking) { - peerInteraction->getPeerConnection()->sendChoke(); - peer->amChoking = true; +bool ChokeMessage::sendPredicate() const { + return !peer->amChoking; +} + +const char* ChokeMessage::getMessage() { + if(!inProgress) { + /** + * len --- 1, 4bytes + * id --- 0, 1byte + * total: 5bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, ID); } + return msg; +} + +int ChokeMessage::getMessageLength() { + return sizeof(msg); +} + +void ChokeMessage::onSendComplete() { + peer->amChoking = true; + peerInteraction->rejectAllPieceMessageInQueue(); } string ChokeMessage::toString() const { diff --git a/src/ChokeMessage.h b/src/ChokeMessage.h index fc00f218..1fe0dc3e 100644 --- a/src/ChokeMessage.h +++ b/src/ChokeMessage.h @@ -22,11 +22,16 @@ #ifndef _D_CHOKE_MESSAGE_H_ #define _D_CHOKE_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class ChokeMessage : public PeerMessage { +class ChokeMessage : public SimplePeerMessage { +private: + char msg[5]; +protected: + virtual bool sendPredicate() const; + virtual void onSendComplete(); public: - ChokeMessage():PeerMessage() {} + ChokeMessage():SimplePeerMessage() {} virtual ~ChokeMessage() {} enum ID { @@ -35,9 +40,11 @@ public: virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual string toString() const; + static ChokeMessage* create(const char* data, int dataLength); }; #endif // _D_CHOKE_MESSAGE_H_ diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index a8e66304..b2b9a89e 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -35,8 +35,6 @@ DownloadEngine::DownloadEngine():noWait(false), segmentMan(NULL) { } DownloadEngine::~DownloadEngine() { - assert(rsockets.empty()); - assert(wsockets.empty()); if(segmentMan != NULL) { delete segmentMan; } @@ -59,7 +57,7 @@ void DownloadEngine::run() { } } afterEachIteration(); - shortSleep(); + //shortSleep(); if(!noWait && !commands.empty()) { waitData(); } @@ -102,7 +100,7 @@ void DownloadEngine::waitData() { tv.tv_sec = 1; tv.tv_usec = 0; - retval = select(max+1, &rfds, /*&wfds*/NULL, NULL, &tv); + retval = select(max+1, &rfds, &wfds, NULL, &tv); } bool DownloadEngine::addSocket(Sockets& sockets, Socket* socket) { diff --git a/src/HandshakeMessage.cc b/src/HandshakeMessage.cc index 744a60de..5b9771f2 100644 --- a/src/HandshakeMessage.cc +++ b/src/HandshakeMessage.cc @@ -24,16 +24,53 @@ #include "PeerMessageUtil.h" #include "Util.h" -void HandshakeMessage::setPeerInteraction(PeerInteraction* peerInteraction) { - this->peerInteraction = peerInteraction; +HandshakeMessage::HandshakeMessage() { + this->pstrlen = 19; + this->pstr = PSTR; + memset(this->reserved, 0, sizeof(this->reserved)); + // fast extension + this->reserved[7] |= 0x04; +} + +HandshakeMessage* HandshakeMessage::create(const char* data, int dataLength) { + HandshakeMessage* message = new HandshakeMessage(); + message->pstrlen = data[0]; + char pstrTemp[20]; + memcpy(pstrTemp, &data[1], sizeof(pstrTemp)-1); + pstrTemp[sizeof(pstrTemp)-1] = '\0'; + message->pstr = pstrTemp; + memcpy(message->reserved, &data[20], 8); + memcpy(message->infoHash, &data[28], 20); + memcpy(message->peerId, &data[48], 20); + return message; +} + +const char* HandshakeMessage::getMessage() { + if(!inProgress) { + msg[0] = pstrlen; + memcpy(msg+1, pstr.c_str(), pstr.size()); + memcpy(msg+20, reserved, 8); + memcpy(msg+28, infoHash, 20); + memcpy(msg+48, peerId, 20); + } + return msg; +} + +int HandshakeMessage::getMessageLength() { + return sizeof(msg); } string HandshakeMessage::toString() const { return "handshake peerId="+ - Util::urlencode((unsigned char*)peerId, sizeof(peerId)); + Util::urlencode((unsigned char*)peerId, sizeof(peerId))+ + " reserved="+Util::toHex(reserved, sizeof(reserved)); } -void HandshakeMessage::check() { +void HandshakeMessage::check() const { PeerMessageUtil::checkHandshake(this, peerInteraction->getTorrentMan()->getInfoHash()); } + +bool HandshakeMessage::isFastExtensionSupported() const { + return reserved[7]&0x04; +} diff --git a/src/HandshakeMessage.h b/src/HandshakeMessage.h index 4204870a..53a44fdd 100644 --- a/src/HandshakeMessage.h +++ b/src/HandshakeMessage.h @@ -22,29 +22,36 @@ #ifndef _D_HANDSHAKE_MESSAGE_H_ #define _D_HANDSHAKE_MESSAGE_H_ -#include "common.h" - -class PeerInteraction; +#include "SimplePeerMessage.h" +#include "TorrentMan.h" #define PSTR "BitTorrent protocol" #define HANDSHAKE_MESSAGE_LENGTH 68 -class HandshakeMessage { +class HandshakeMessage : public SimplePeerMessage { +private: + char msg[HANDSHAKE_MESSAGE_LENGTH]; public: char pstrlen; string pstr; - unsigned char infoHash[20]; - char peerId[20]; - PeerInteraction* peerInteraction; + unsigned char reserved[8]; + unsigned char infoHash[INFO_HASH_LENGTH]; + char peerId[PEER_ID_LENGTH]; public: - HandshakeMessage() {} - ~HandshakeMessage() {} + HandshakeMessage(); - PeerInteraction* getPeerInteraction() const { return peerInteraction; } - void setPeerInteraction(PeerInteraction* peerInteraction); + static HandshakeMessage* create(const char* data, int dataLength); - string toString() const; - void check(); + virtual ~HandshakeMessage() {} + + virtual int getId() const { return 999; } + virtual void receivedAction() {}; + virtual const char* getMessage(); + virtual int getMessageLength(); + virtual void check() const; + virtual string toString() const; + + bool isFastExtensionSupported() const; }; #endif // _D_HANDSHAKE_MESSAGE_H_ diff --git a/src/HaveAllMessage.cc b/src/HaveAllMessage.cc new file mode 100644 index 00000000..f9fb6ff2 --- /dev/null +++ b/src/HaveAllMessage.cc @@ -0,0 +1,72 @@ +/* */ +#include "HaveAllMessage.h" +#include "DlAbortEx.h" +#include "PeerInteraction.h" +#include "PeerMessageUtil.h" + +HaveAllMessage::HaveAllMessage() {} + +HaveAllMessage::~HaveAllMessage() {} + +HaveAllMessage* HaveAllMessage::create(const char* data, int dataLength) { + if(dataLength != 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have all", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "have all", ID); + } + HaveAllMessage* haveAllMessage = new HaveAllMessage(); + return haveAllMessage; +} + +void HaveAllMessage::receivedAction() { + if(!peer->isFastExtensionEnabled()) { + throw new DlAbortEx("%s received while fast extension is disabled", + toString().c_str()); + } + peer->setAllBitfield(); +} + +const char* HaveAllMessage::getMessage() { + if(!inProgress) { + /** + * len --- 1, 4bytes + * id --- 14, 1byte + * total: 5bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, ID); + } + return msg; +} + +int HaveAllMessage::getMessageLength() { + return sizeof(msg); +} + +void HaveAllMessage::check() const {} + +string HaveAllMessage::toString() const { + return "have all"; +} diff --git a/src/HaveAllMessage.h b/src/HaveAllMessage.h new file mode 100644 index 00000000..c9723f70 --- /dev/null +++ b/src/HaveAllMessage.h @@ -0,0 +1,48 @@ +/* */ +#ifndef _D_HAVE_ALL_MESSAGE_H_ +#define _D_HAVE_ALL_MESSAGE_H_ + +#include "SimplePeerMessage.h" + +class HaveAllMessage : public SimplePeerMessage { +private: + char msg[5]; +public: + HaveAllMessage(); + virtual ~HaveAllMessage(); + + enum ID { + ID = 14 + }; + + static HaveAllMessage* create(const char* data, int dataLength); + + virtual int getId() const { return ID; } + virtual void receivedAction(); + virtual const char* getMessage(); + virtual int getMessageLength(); + virtual void check() const; + virtual string toString() const; +}; + +#endif // _D_HAVE_ALL_MESSAGE_H_ diff --git a/src/HaveMessage.cc b/src/HaveMessage.cc index 98bcd582..c3eeb2eb 100644 --- a/src/HaveMessage.cc +++ b/src/HaveMessage.cc @@ -23,15 +23,46 @@ #include "PeerInteraction.h" #include "PeerMessageUtil.h" #include "Util.h" +#include "DlAbortEx.h" + +HaveMessage* HaveMessage::create(const char* data, int dataLength) { + if(dataLength != 5) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have", dataLength, 5); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "have", ID); + } + HaveMessage* haveMessage = new HaveMessage(); + haveMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + return haveMessage; +} void HaveMessage::receivedAction() { peer->updateBitfield(index, 1); } -void HaveMessage::send() { - if(!peer->hasPiece(index)) { - peerInteraction->getPeerConnection()->sendHave(index); +bool HaveMessage::sendPredicate() const { + return !peer->hasPiece(index); +} + +const char* HaveMessage::getMessage() { + if(!inProgress) { + /** + * len --- 5, 4bytes + * id --- 4, 1byte + * piece index --- index, 4bytes + * total: 9bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, ID); + PeerMessageUtil::setIntParam(&msg[5], index); } + return msg; +} + +int HaveMessage::getMessageLength() { + return sizeof(msg); } void HaveMessage::check() const { diff --git a/src/HaveMessage.h b/src/HaveMessage.h index 6cb9ef84..593e8d7b 100644 --- a/src/HaveMessage.h +++ b/src/HaveMessage.h @@ -22,15 +22,18 @@ #ifndef _D_HAVE_MESSAGE_H_ #define _D_HAVE_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class HaveMessage : public PeerMessage { +class HaveMessage : public SimplePeerMessage { private: int index; // for check int pieces; + char msg[9]; +protected: + virtual bool sendPredicate() const; public: - HaveMessage():PeerMessage(), index(0), pieces(0) {} + HaveMessage():SimplePeerMessage(), index(0), pieces(0) {} virtual ~HaveMessage() {} @@ -48,9 +51,12 @@ public: } int getPieces() const { return pieces;} + static HaveMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual void check() const; virtual string toString() const; }; diff --git a/src/HaveNoneMessage.cc b/src/HaveNoneMessage.cc new file mode 100644 index 00000000..7cb81723 --- /dev/null +++ b/src/HaveNoneMessage.cc @@ -0,0 +1,71 @@ +/* */ +#include "HaveNoneMessage.h" +#include "DlAbortEx.h" +#include "PeerInteraction.h" +#include "PeerMessageUtil.h" + +HaveNoneMessage::HaveNoneMessage() {} + +HaveNoneMessage::~HaveNoneMessage() {} + +HaveNoneMessage* HaveNoneMessage::create(const char* data, int dataLength) { + if(dataLength != 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have none", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "have none", ID); + } + HaveNoneMessage* haveNoneMessage = new HaveNoneMessage(); + return haveNoneMessage; +} + +void HaveNoneMessage::receivedAction() { + if(!peer->isFastExtensionEnabled()) { + throw new DlAbortEx("%s received while fast extension is disabled", + toString().c_str()); + } +} + +const char* HaveNoneMessage::getMessage() { + if(!inProgress) { + /** + * len --- 1, 4bytes + * id --- 15, 1byte + * total: 5bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, ID); + } + return msg; +} + +int HaveNoneMessage::getMessageLength() { + return sizeof(msg); +} + +void HaveNoneMessage::check() const {} + +string HaveNoneMessage::toString() const { + return "have none"; +} diff --git a/src/HaveNoneMessage.h b/src/HaveNoneMessage.h new file mode 100644 index 00000000..2e05ae4e --- /dev/null +++ b/src/HaveNoneMessage.h @@ -0,0 +1,48 @@ +/* */ +#ifndef _D_HAVE_NONE_MESSAGE_H_ +#define _D_HAVE_NONE_MESSAGE_H_ + +#include "SimplePeerMessage.h" + +class HaveNoneMessage : public SimplePeerMessage { +private: + char msg[5]; +public: + HaveNoneMessage(); + virtual ~HaveNoneMessage(); + + enum ID { + ID = 15 + }; + + static HaveNoneMessage* create(const char* data, int dataLength); + + virtual int getId() const { return ID; } + virtual void receivedAction(); + virtual const char* getMessage(); + virtual int getMessageLength(); + virtual void check() const; + virtual string toString() const; +}; + +#endif // _D_HAVE_NONE_MESSAGE_H_ diff --git a/src/InterestedMessage.cc b/src/InterestedMessage.cc index b964bf90..570c42f4 100644 --- a/src/InterestedMessage.cc +++ b/src/InterestedMessage.cc @@ -21,16 +21,48 @@ /* copyright --> */ #include "InterestedMessage.h" #include "PeerInteraction.h" +#include "PeerMessageUtil.h" +#include "DlAbortEx.h" + +InterestedMessage* InterestedMessage::create(const char* data, int dataLength) { + if(dataLength != 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "interested", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "interested", ID); + } + InterestedMessage* interestedMessage = new InterestedMessage(); + return interestedMessage; +} void InterestedMessage::receivedAction() { peer->peerInterested = true; } -void InterestedMessage::send() { - if(!peer->amInterested) { - peerInteraction->getPeerConnection()->sendInterested(); - peer->amInterested = true; +bool InterestedMessage::sendPredicate() const { + return !peer->amInterested; +} + +const char* InterestedMessage::getMessage() { + if(!inProgress) { + /** + * len --- 1, 4bytes + * id --- 2, 1byte + * total: 5bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, ID); } + return msg; +} + +int InterestedMessage::getMessageLength() { + return sizeof(msg); +} + +void InterestedMessage::onSendComplete() { + peer->amInterested = true; } string InterestedMessage::toString() const { diff --git a/src/InterestedMessage.h b/src/InterestedMessage.h index bd2c05f1..ce93bb18 100644 --- a/src/InterestedMessage.h +++ b/src/InterestedMessage.h @@ -22,20 +22,28 @@ #ifndef _D_INTERESTED_MESSAGE_H_ #define _D_INTERESTED_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class InterestedMessage : public PeerMessage { +class InterestedMessage : public SimplePeerMessage { +private: + char msg[5]; +protected: + virtual bool sendPredicate() const; + virtual void onSendComplete(); public: - InterestedMessage():PeerMessage() {} + InterestedMessage():SimplePeerMessage() {} virtual ~InterestedMessage() {} enum ID { ID = 2 }; + static InterestedMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual string toString() const; }; diff --git a/src/KeepAliveMessage.cc b/src/KeepAliveMessage.cc index 266af1b5..f6a5b6b7 100644 --- a/src/KeepAliveMessage.cc +++ b/src/KeepAliveMessage.cc @@ -22,6 +22,17 @@ #include "KeepAliveMessage.h" #include "PeerInteraction.h" -void KeepAliveMessage::send() { - peerInteraction->getPeerConnection()->sendKeepAlive(); +const char* KeepAliveMessage::getMessage() { + if(!inProgress) { + /** + * len --- 0, 4bytes + * total: 4bytes + */ + memset(msg, 0, sizeof(msg)); + } + return msg; +} + +int KeepAliveMessage::getMessageLength() { + return sizeof(msg); } diff --git a/src/KeepAliveMessage.h b/src/KeepAliveMessage.h index f82894ae..77c73233 100644 --- a/src/KeepAliveMessage.h +++ b/src/KeepAliveMessage.h @@ -22,11 +22,13 @@ #ifndef _D_KEEP_ALIVE_MESSAGE_H_ #define _D_KEEP_ALIVE_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class KeepAliveMessage : public PeerMessage { +class KeepAliveMessage : public SimplePeerMessage { +private: + char msg[4]; public: - KeepAliveMessage():PeerMessage() {} + KeepAliveMessage():SimplePeerMessage() {} virtual ~KeepAliveMessage() {} enum ID { @@ -35,7 +37,8 @@ public: virtual int getId() const { return ID; } virtual void receivedAction() {} - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual string toString() const { return "keep alive"; } diff --git a/src/Makefile.am b/src/Makefile.am index 55fe0a59..5ac5d866 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,7 +94,13 @@ SRCS = Socket.cc Socket.h\ PieceMessage.cc PieceMessage.h\ CancelMessage.cc CancelMessage.h\ KeepAliveMessage.cc KeepAliveMessage.h\ - PortMessage.h + PortMessage.cc PortMessage.h\ + HaveAllMessage.cc HaveAllMessage.h\ + HaveNoneMessage.cc HaveNoneMessage.h\ + RejectMessage.cc RejectMessage.h\ + AllowedFastMessage.cc AllowedFastMessage.h\ + SuggestPieceMessage.cc SuggestPieceMessage.h\ + SimplePeerMessage.cc SimplePeerMessage.h noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ diff --git a/src/Makefile.in b/src/Makefile.in index 6cb60fc8..b61a96e9 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -105,7 +105,11 @@ am__objects_1 = Socket.$(OBJEXT) SocketCore.$(OBJEXT) \ InterestedMessage.$(OBJEXT) NotInterestedMessage.$(OBJEXT) \ HaveMessage.$(OBJEXT) BitfieldMessage.$(OBJEXT) \ RequestMessage.$(OBJEXT) PieceMessage.$(OBJEXT) \ - CancelMessage.$(OBJEXT) KeepAliveMessage.$(OBJEXT) + CancelMessage.$(OBJEXT) KeepAliveMessage.$(OBJEXT) \ + PortMessage.$(OBJEXT) HaveAllMessage.$(OBJEXT) \ + HaveNoneMessage.$(OBJEXT) RejectMessage.$(OBJEXT) \ + AllowedFastMessage.$(OBJEXT) SuggestPieceMessage.$(OBJEXT) \ + SimplePeerMessage.$(OBJEXT) am_libaria2c_a_OBJECTS = $(am__objects_1) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" @@ -349,7 +353,13 @@ SRCS = Socket.cc Socket.h\ PieceMessage.cc PieceMessage.h\ CancelMessage.cc CancelMessage.h\ KeepAliveMessage.cc KeepAliveMessage.h\ - PortMessage.h + PortMessage.cc PortMessage.h\ + HaveAllMessage.cc HaveAllMessage.h\ + HaveNoneMessage.cc HaveNoneMessage.h\ + RejectMessage.cc RejectMessage.h\ + AllowedFastMessage.cc AllowedFastMessage.h\ + SuggestPieceMessage.cc SuggestPieceMessage.h\ + SimplePeerMessage.cc SimplePeerMessage.h noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) @@ -437,6 +447,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbstractCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbstractDiskWriter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllowedFastMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMessage.Po@am__quote@ @@ -463,7 +474,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelRequestCommand.Po@am__quote@ @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)/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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpDownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeader.Po@am__quote@ @@ -494,7 +507,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Piece.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceMessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PortMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PreAllocationDiskWriter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RejectMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Request.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestSlot.Po@am__quote@ @@ -502,11 +517,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentSplitter.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)/SimplePeerMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Socket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketCore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitFirstSegmentSplitter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitSlowestSegmentSplitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@ diff --git a/src/NotInterestedMessage.cc b/src/NotInterestedMessage.cc index dafcd095..f42790e0 100644 --- a/src/NotInterestedMessage.cc +++ b/src/NotInterestedMessage.cc @@ -21,16 +21,48 @@ /* copyright --> */ #include "NotInterestedMessage.h" #include "PeerInteraction.h" +#include "PeerMessageUtil.h" +#include "DlAbortEx.h" + +NotInterestedMessage* NotInterestedMessage::create(const char* data, int dataLength) { + if(dataLength != 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "not interested", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "not interested", ID); + } + NotInterestedMessage* notInterestedMessage = new NotInterestedMessage(); + return notInterestedMessage; +} void NotInterestedMessage::receivedAction() { peer->peerInterested = false; } -void NotInterestedMessage::send() { - if(peer->amInterested) { - peerInteraction->getPeerConnection()->sendNotInterested(); - peer->amInterested = false; +bool NotInterestedMessage::sendPredicate() const { + return peer->amInterested; +} + +const char* NotInterestedMessage::getMessage() { + if(!inProgress) { + /** + * len --- 1, 4bytes + * id --- 3, 1byte + * total: 5bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, ID); } + return msg; +} + +int NotInterestedMessage::getMessageLength() { + return sizeof(msg); +} + +void NotInterestedMessage::onSendComplete() { + peer->amInterested = false; } string NotInterestedMessage::toString() const { diff --git a/src/NotInterestedMessage.h b/src/NotInterestedMessage.h index 289bf611..ac4e2d7e 100644 --- a/src/NotInterestedMessage.h +++ b/src/NotInterestedMessage.h @@ -22,20 +22,28 @@ #ifndef _D_NOT_INTERESTED_MESSAGE_H_ #define _D_NOT_INTERESTED_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class NotInterestedMessage : public PeerMessage { +class NotInterestedMessage : public SimplePeerMessage { +private: + char msg[5]; +protected: + virtual bool sendPredicate() const; + virtual void onSendComplete(); public: - NotInterestedMessage():PeerMessage() {} + NotInterestedMessage():SimplePeerMessage() {} virtual ~NotInterestedMessage() {} enum ID { ID = 3 }; + static NotInterestedMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual string toString() const; }; diff --git a/src/Peer.cc b/src/Peer.cc index 01d5c111..9c83321e 100644 --- a/src/Peer.cc +++ b/src/Peer.cc @@ -59,4 +59,20 @@ void Peer::resetStatus() { resetDeltaDownload(); chokingRequired = true; optUnchoking = false; + fastExtensionEnabled = false; + fastSet.clear(); +} + +bool Peer::isInFastSet(int index) const { + return find(fastSet.begin(), fastSet.end(), index) != fastSet.end(); +} + +void Peer::addFastSetIndex(int index) { + if(!isInFastSet(index)) { + fastSet.push_back(index); + } +} + +void Peer::setAllBitfield() { + bitfield->setAllBit(); } diff --git a/src/Peer.h b/src/Peer.h index 3ae58778..6c6ed730 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -48,6 +48,9 @@ public: private: char peerId[PEER_ID_LENGTH]; BitfieldMan* bitfield; + bool fastExtensionEnabled; + // allowed fast indexes that peer has sent by Allowed Fast message + Integers fastSet; long long int peerUpload; long long int peerDownload; int pieceLength; @@ -62,6 +65,7 @@ public: tryCount(0), error(0), cuid(0), chokingRequired(true), optUnchoking(false), bitfield(NULL), + fastExtensionEnabled(false), peerUpload(0), peerDownload(0), pieceLength(pieceLength), totalLength(totalLength), deltaUpload(0), deltaDownload(0) { @@ -98,13 +102,14 @@ public: } const unsigned char* getBitfield() const { return bitfield->getBitfield(); } int getBitfieldLength() const { return bitfield->getBitfieldLength(); } + void setAllBitfield(); /** * operation = 1: set index-th bit 1 * operation = 0: set index-th bit 0 */ void updateBitfield(int index, int operation); - + void addPeerUpload(int size) { peerUpload += size; addDeltaUpload(size); @@ -119,6 +124,16 @@ public: void setPeerDownload(long long int size) { peerDownload = size; } long long int getPeerDownload() const { return peerDownload; } + void setFastExtensionEnabled(bool enabled) { + fastExtensionEnabled = enabled; + } + bool isFastExtensionEnabled() const { return fastExtensionEnabled; } + + void addFastSetIndex(int index); + const Integers getFastSet() const { return fastSet; } + bool isInFastSet(int index) const; + int countFastSet() const { return fastSet.size(); } + bool shouldBeChoking() const; bool hasPiece(int index) const; diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc index 8b7f2ffc..0c6386f0 100644 --- a/src/PeerAbstractCommand.cc +++ b/src/PeerAbstractCommand.cc @@ -28,7 +28,9 @@ #include PeerAbstractCommand::PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, const Socket* s): - Command(cuid), e(e), peer(peer), checkSocketIsReadable(false), checkSocketIsWritable(false) { + Command(cuid), e(e), peer(peer), + checkSocketIsReadable(false), checkSocketIsWritable(false), + uploadLimitCheck(false), uploadLimit(0) { if(s != NULL) { socket = new Socket(*s); @@ -74,8 +76,13 @@ bool PeerAbstractCommand::isTimeoutDetected() { bool PeerAbstractCommand::execute() { try { beforeSocketCheck(); - if(checkSocketIsReadable && !readCheckTarget->isReadable(0) - || checkSocketIsWritable && !writeCheckTarget->isWritable(0)) { + if(uploadLimitCheck && e->getUploadSpeed() <= uploadLimit*1024 || + checkSocketIsReadable && readCheckTarget->isReadable(0) || + checkSocketIsWritable && writeCheckTarget->isWritable(0) || + !checkSocketIsReadable && !checkSocketIsWritable) { + updateCheckPoint(); + return executeInternal(); + } else { if(isTimeoutDetected()) { // TODO checkPoint.tv_sec = 0; @@ -85,10 +92,6 @@ bool PeerAbstractCommand::execute() { e->commands.push_back(this); return false; } - updateCheckPoint(); - bool returnValue = executeInternal(); - //e->torrentMan->updatePeer(peer); - return returnValue; } catch(Exception* err) { logger->error(MSG_DOWNLOAD_ABORTED, err, cuid); onAbort(err); @@ -113,7 +116,7 @@ void PeerAbstractCommand::onAbort(Exception* ex) { peer->error += MAX_PEER_ERROR; } peer->resetStatus(); - logger->debug("CUID#%d - peer %s:%d banned.", cuid, peer->ipaddr.c_str(), peer->port); + logger->debug("CUID#%d - Peer %s:%d banned.", cuid, peer->ipaddr.c_str(), peer->port); } void PeerAbstractCommand::setReadCheckSocket(Socket* socket) { @@ -159,3 +162,11 @@ void PeerAbstractCommand::setWriteCheckSocket(Socket* socket) { } } } + +void PeerAbstractCommand::setUploadLimit(int uploadLimit) { + this->uploadLimit = uploadLimit; +} + +void PeerAbstractCommand::setUploadLimitCheck(bool check) { + this->uploadLimitCheck = check; +} diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h index b5036da0..3bf5bd7b 100644 --- a/src/PeerAbstractCommand.h +++ b/src/PeerAbstractCommand.h @@ -45,11 +45,15 @@ protected: virtual void beforeSocketCheck() {} void setReadCheckSocket(Socket* socket); void setWriteCheckSocket(Socket* socket); + void setUploadLimit(int uploadLimit); + void setUploadLimitCheck(bool check); private: bool checkSocketIsReadable; bool checkSocketIsWritable; Socket* readCheckTarget; Socket* writeCheckTarget; + bool uploadLimitCheck; + int uploadLimit; public: PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, const Socket* s = NULL); virtual ~PeerAbstractCommand(); diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc index aeac89ed..42d64240 100644 --- a/src/PeerConnection.cc +++ b/src/PeerConnection.cc @@ -27,279 +27,30 @@ #include "LogFactory.h" #include -PeerConnection::PeerConnection(int cuid, const Socket* socket, - const Option* op, - Peer* peer, TorrentMan* torrentMan) - :cuid(cuid), socket(socket), option(op), logger(logger), peer(peer), - torrentMan(torrentMan), - resbufLength(0), currentPayloadLength(0), lenbufLength(0) { +PeerConnection::PeerConnection(int cuid, + const Socket* socket, + const Option* op) + :cuid(cuid), + socket(socket), + option(op), + logger(logger), + resbufLength(0), + currentPayloadLength(0), + lenbufLength(0) { logger = LogFactory::getInstance(); } PeerConnection::~PeerConnection() {} -void PeerConnection::sendHandshake() const { - /** - * pstrlen --- '19', 1byte - * pstr --- "BitTorrent protocol", 19bytes - * reserved --- \0 * 8, 8bytes - * info_hash --- info_hash, 20bytes - * peer_id --- peer_id, 20bytes - * total: 68bytes - */ - char msg[HANDSHAKE_MESSAGE_LENGTH]; - memset(msg, 0, sizeof(msg)); - msg[0] = 19; - memcpy(&msg[1], PSTR, strlen(PSTR)); - memcpy(&msg[28], torrentMan->getInfoHash(), 20); - memcpy(&msg[48], torrentMan->peerId.c_str(), 20); - writeOutgoingMessageLog("handshake"); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendKeepAlive() const { - /** - * len --- 0, 4bytes - * total: 4bytes - */ - char msg[4]; - memset(msg, 0, sizeof(msg)); - writeOutgoingMessageLog("keep alive"); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) const { - assert(msgLen >= 5); - memset(msg, 0, msgLen); - setIntParam(msg, payloadLen); - msg[4] = (char)id; -} - -void PeerConnection::setIntParam(char* dest, int param) const { - int nParam = htonl(param); - memcpy(dest, &nParam, 4); -} - -void PeerConnection::writeOutgoingMessageLog(const char* msg) const { - logger->info(MSG_SEND_PEER_MESSAGE, cuid, peer->ipaddr.c_str(), peer->port, msg); -} - -void PeerConnection::writeOutgoingMessageLog(const char* msg, int index) const { - logger->info(MSG_SEND_PEER_MESSAGE_WITH_INDEX, cuid, peer->ipaddr.c_str(), peer->port, msg, index); -} - -void PeerConnection::writeOutgoingMessageLog(const char* msg, const unsigned char* bitfield, int bitfieldLength) const { - logger->info(MSG_SEND_PEER_MESSAGE_WITH_BITFIELD, cuid, peer->ipaddr.c_str(), peer->port, msg, Util::toHex(bitfield, bitfieldLength).c_str()); -} - -void PeerConnection::writeOutgoingMessageLog(const char* msg, int index, int begin, int length) const { - logger->info(MSG_SEND_PEER_MESSAGE_WITH_INDEX_BEGIN_LENGTH, cuid, peer->ipaddr.c_str(), peer->port, msg, index, begin, length); -} - -void PeerConnection::sendChoke() const { - /** - * len --- 1, 4bytes - * id --- 0, 1byte - * total: 5bytes - */ - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 0); - writeOutgoingMessageLog("choke"); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendUnchoke() const { - /** - * len --- 1, 4bytes - * id --- 1, 1byte - * total: 5bytes - */ - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 1); - writeOutgoingMessageLog("unchoke"); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendInterested() const { - /** - * len --- 1, 4bytes - * id --- 2, 1byte - * total: 5bytes - */ - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 2); - writeOutgoingMessageLog("interested"); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendNotInterested() const { - /** - * len --- 1, 4bytes - * id --- 3, 1byte - * total: 5bytes - */ - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 3); - writeOutgoingMessageLog("not interested"); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendHave(int index) const { - /** - * len --- 5, 4bytes - * id --- 4, 1byte - * piece index --- index, 4bytes - * total: 9bytes - */ - char msg[9]; - createNLengthMessage(msg, sizeof(msg), 5, 4); - setIntParam(&msg[5], index); - writeOutgoingMessageLog("have", index); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendBitfield() const { - int len = torrentMan->getBitfieldLength(); - const unsigned char* bitfield = torrentMan->getBitfield(); - /** - * len --- 1+len, 4bytes - * id --- 5, 1byte - * bitfield --- bitfield, len bytes - * total: 5+len bytes - */ - int msgLen = 5+len; - char* msg = new char[msgLen]; - try { - createNLengthMessage(msg, msgLen, 1+len, 5); - writeOutgoingMessageLog("bitfield", bitfield, len); - socket->writeData(msg, msgLen); - delete [] msg; - } catch(Exception* ex) { - delete [] msg; - throw; - } -} - -void PeerConnection::sendRequest(int index, int begin, int length) const { - /** - * len --- 13, 4bytes - * id --- 6, 1byte - * index --- index, 4bytes - * begin --- begin, 4bytes - * length --- length, 4bytes - * total: 17bytes - */ - char msg[17]; - createNLengthMessage(msg, sizeof(msg), 13, 6); - setIntParam(&msg[5], index); - setIntParam(&msg[9], begin); - setIntParam(&msg[13], length); - writeOutgoingMessageLog("request", index, begin, length); - socket->writeData(msg, sizeof(msg)); -} - -void PeerConnection::sendPiece(int index, int begin, int length) const { - /** - * len --- 9+length, 4bytes - * id --- 7, 1byte - * index --- index, 4bytes - * begin --- begin, 4bytes - * sub total: 13bytes - * additionally, - * block --- data, X bytes - */ - char msg[13]; - createNLengthMessage(msg, sizeof(msg), 9+length, 7); - setIntParam(&msg[5], index); - setIntParam(&msg[9], begin); - writeOutgoingMessageLog("piece", index, begin, length); - socket->writeData(msg, sizeof(msg)); - int BUF_SIZE = 4096; - char buf[BUF_SIZE]; - int iteration = length/BUF_SIZE; - long long int pieceOffset = ((long long int)index*torrentMan->pieceLength)+begin; - for(int i = 0; i < iteration; i++) { - if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) { - throw new DlAbortEx("piece reading failed."); - } - socket->writeData(buf, BUF_SIZE); - } - int rem = length%BUF_SIZE; - if(rem > 0) { - if(torrentMan->diskAdaptor->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) { - throw new DlAbortEx("piece reading failed."); - } - socket->writeData(buf, rem); - } -} - -void PeerConnection::sendPieceHeader(int index, int begin, int length) const { - /** - * len --- 9+length, 4bytes - * id --- 7, 1byte - * index --- index, 4bytes - * begin --- begin, 4bytes - * sub total: 13bytes - * additionally, - * block --- data, X bytes - */ - char msg[13]; - createNLengthMessage(msg, sizeof(msg), 9+length, 7); - setIntParam(&msg[5], index); - setIntParam(&msg[9], begin); - writeOutgoingMessageLog("piece", index, begin, length); - socket->writeData(msg, sizeof(msg)); -} - -int PeerConnection::sendPieceData(long long int offset, int length) const { - int BUF_SIZE = 256; - char buf[BUF_SIZE]; - int iteration = length/BUF_SIZE; +int PeerConnection::sendMessage(const char* msg, int length) { int writtenLength = 0; - bool isWritable = true; - for(int i = 0; i < iteration; i++) { - isWritable = socket->isWritable(0); - if(!isWritable) { - return writtenLength; - } - if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) { - throw new DlAbortEx("piece reading failed."); - } - socket->writeData(buf, BUF_SIZE); - writtenLength += BUF_SIZE; - } if(socket->isWritable(0)) { - int rem = length%BUF_SIZE; - if(rem > 0) { - if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) { - throw new DlAbortEx("piece reading failed."); - } - socket->writeData(buf, rem); - writtenLength += rem; - } + socket->writeData(msg, length); + writtenLength += length; } return writtenLength; } - -void PeerConnection::sendCancel(int index, int begin, int length) const { - /** - * len --- 13, 4bytes - * id --- 8, 1byte - * index --- index, 4bytes - * begin --- begin, 4bytes - * length -- length, 4bytes - * total: 17bytes - */ - char msg[17]; - createNLengthMessage(msg, sizeof(msg), 13, 8); - setIntParam(&msg[5], index); - setIntParam(&msg[9], begin); - setIntParam(&msg[13], length); - writeOutgoingMessageLog("cancel", index, begin, length); - socket->writeData(msg, sizeof(msg)); -} - bool PeerConnection::receiveMessage(char* msg, int& length) { if(!socket->isReadable(0)) { return false; diff --git a/src/PeerConnection.h b/src/PeerConnection.h index 28a77058..523865ef 100644 --- a/src/PeerConnection.h +++ b/src/PeerConnection.h @@ -39,8 +39,6 @@ private: const Socket* socket; const Option* option; const Logger* logger; - Peer* peer; - TorrentMan* torrentMan; char resbuf[MAX_PAYLOAD_LEN]; int resbufLength; @@ -48,35 +46,15 @@ private: char lenbuf[4]; int lenbufLength; - void createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) const; - void setIntParam(char* dest, int param) const; - - void writeOutgoingMessageLog(const char* msg) const; - void writeOutgoingMessageLog(const char* msg, int index) const; - void writeOutgoingMessageLog(const char* msg, const unsigned char* bitfield, int bitfieldLength) const; - void writeOutgoingMessageLog(const char* msg, int index, int begin, int length) const; public: - PeerConnection(int cuid, const Socket* socket, const Option* op, - Peer* peer, TorrentMan* torrenMan); + PeerConnection(int cuid, const Socket* socket, const Option* op); ~PeerConnection(); + + // Returns the number of bytes written + int sendMessage(const char* msg, int length); - void sendHandshake() const; - void sendKeepAlive() const; - void sendChoke() const; - void sendUnchoke() const; - void sendInterested() const; - void sendNotInterested() const; - void sendHave(int index) const; - void sendBitfield() const; - void sendRequest(int index, int begin, int length) const; - void sendPiece(int index, int begin, int length) const; - void sendPieceHeader(int index, int begin, int length) const; - int sendPieceData(long long int offset, int length) const; - void sendCancel(int index, int begin, int length) const; bool receiveMessage(char* msg, int& length); bool receiveHandshake(char* msg, int& length); - - Peer* getPeer() const { return peer; } }; #endif // _D_PEER_CONNECTION_H_ diff --git a/src/PeerInteraction.cc b/src/PeerInteraction.cc index 39307fe5..83dfd180 100644 --- a/src/PeerInteraction.cc +++ b/src/PeerInteraction.cc @@ -24,6 +24,7 @@ #include "DlAbortEx.h" #include "KeepAliveMessage.h" #include "PeerMessageUtil.h" +#include "Util.h" #include PeerInteraction::PeerInteraction(int cuid, @@ -36,7 +37,7 @@ PeerInteraction::PeerInteraction(int cuid, torrentMan(torrentMan), peer(peer), piece(Piece::nullPiece) { - peerConnection = new PeerConnection(cuid, socket, op, peer, this->torrentMan); + peerConnection = new PeerConnection(cuid, socket, op); logger = LogFactory::getInstance(); } @@ -45,14 +46,37 @@ PeerInteraction::~PeerInteraction() { for_each(messageQueue.begin(), messageQueue.end(), Deleter()); } -void PeerInteraction::send(int uploadSpeed) { - int size = messageQueue.size(); - for(int i = 0; i < size; i++) { +class MsgPushBack { +private: + MessageQueue* messageQueue; +public: + MsgPushBack(MessageQueue* messageQueue):messageQueue(messageQueue) {} + + void operator()(PeerMessage* msg) { + messageQueue->push_back(msg); + } +}; + +bool PeerInteraction::isSendingMessageInProgress() const { + if(messageQueue.size() > 0) { + PeerMessage* peerMessage = messageQueue.front(); + if(peerMessage->isInProgress()) { + return true; + } + } + return false; +} + +void PeerInteraction::sendMessages(int uploadSpeed) { + MessageQueue tempQueue; + while(messageQueue.size() > 0) { PeerMessage* msg = messageQueue.front(); messageQueue.pop_front(); if(uploadLimit != 0 && uploadLimit*1024 <= uploadSpeed && msg->getId() == PieceMessage::ID && !msg->isInProgress()) { - messageQueue.push_back(msg); + //!((PieceMessage*)msg)->isPendingCountMax()) { + //((PieceMessage*)msg)->incrementPendingCount(); + tempQueue.push_back(msg); } else { try { msg->send(); @@ -68,6 +92,7 @@ void PeerInteraction::send(int uploadSpeed) { } } } + for_each(tempQueue.begin(), tempQueue.end(), MsgPushBack(&messageQueue)); } void PeerInteraction::addMessage(PeerMessage* peerMessage) { @@ -82,22 +107,51 @@ void PeerInteraction::addMessage(PeerMessage* peerMessage) { } } -void PeerInteraction::deletePieceMessageInQueue(const CancelMessage* cancelMessage) { +void PeerInteraction::rejectAllPieceMessageInQueue() { + MessageQueue tempQueue; for(MessageQueue::iterator itr = messageQueue.begin(); itr != messageQueue.end();) { - if((*itr)->getId() == PieceMessage::ID) { + // Don't delete piece message which is in the allowed fast set. + if((*itr)->getId() == PieceMessage::ID && !(*itr)->isInProgress() + && !isInFastSet(((PieceMessage*)*itr)->getIndex())) { PieceMessage* pieceMessage = (PieceMessage*)*itr; - if(pieceMessage->getIndex() == cancelMessage->getIndex() && - pieceMessage->getBegin() == cancelMessage->getBegin() && - pieceMessage->getBlockLength() == cancelMessage->getLength() && - !pieceMessage->isInProgress()) { - logger->debug("CUID#%d - deleting piece message in queue because cancel message received. index=%d, begin=%d, length=%d", - cuid, - cancelMessage->getIndex(), - cancelMessage->getBegin(), - cancelMessage->getLength()); + logger->debug("CUID#%d - Reject piece message in queue because" + " peer has been choked. index=%d, begin=%d, length=%d", + cuid, + pieceMessage->getIndex(), + pieceMessage->getBegin(), + pieceMessage->getBlockLength()); + if(peer->isFastExtensionEnabled()) { + tempQueue.push_back(createRejectMessage(pieceMessage->getIndex(), + pieceMessage->getBegin(), + pieceMessage->getBlockLength())); + } + delete pieceMessage; + itr = messageQueue.erase(itr); + } else { + itr++; + } + } + for_each(tempQueue.begin(), tempQueue.end(), MsgPushBack(&messageQueue)); +} + +void PeerInteraction::rejectPieceMessageInQueue(int index, int begin, int length) { + MessageQueue tempQueue; + for(MessageQueue::iterator itr = messageQueue.begin(); + itr != messageQueue.end();) { + if((*itr)->getId() == PieceMessage::ID && !(*itr)->isInProgress()) { + PieceMessage* pieceMessage = (PieceMessage*)*itr; + if(pieceMessage->getIndex() == index && + pieceMessage->getBegin() == begin && + pieceMessage->getBlockLength() == length) { + logger->debug("CUID#%d - Reject piece message in queue because cancel" + " message received. index=%d, begin=%d, length=%d", + cuid, index, begin, length); delete pieceMessage; itr = messageQueue.erase(itr); + if(peer->isFastExtensionEnabled()) { + tempQueue.push_back(createRejectMessage(index, begin, length)); + } } else { itr++; } @@ -105,52 +159,59 @@ void PeerInteraction::deletePieceMessageInQueue(const CancelMessage* cancelMessa itr++; } } + for_each(tempQueue.begin(), tempQueue.end(), MsgPushBack(&messageQueue)); } -void PeerInteraction::deleteRequestMessageInQueue() { - for(MessageQueue::iterator itr = messageQueue.begin(); - itr != messageQueue.end();) { - if((*itr)->getId() == RequestMessage::ID) { - delete *itr; - itr = messageQueue.erase(itr); - } else { - itr++; - } - } -} - -void PeerInteraction::deleteRequestSlot(const RequestSlot& requestSlot) { - // TODO use STL algorithm - for(RequestSlots::iterator itr = requestSlots.begin(); - itr != requestSlots.end(); itr++) { - if(*itr == requestSlot) { - requestSlots.erase(itr); - break; - } +void PeerInteraction::onChoked() { + if(!Piece::isNull(piece) && !peer->isInFastSet(piece.getIndex())) { + abortPiece(); } } -void PeerInteraction::deleteAllRequestSlot(Piece& piece) { +void PeerInteraction::abortPiece() { if(!Piece::isNull(piece)) { + for(MessageQueue::iterator itr = messageQueue.begin(); + itr != messageQueue.end();) { + if((*itr)->getId() == RequestMessage::ID + && !(*itr)->isInProgress()) { + delete *itr; + itr = messageQueue.erase(itr); + } else { + itr++; + } + } for(RequestSlots::const_iterator itr = requestSlots.begin(); itr != requestSlots.end(); itr++) { - if(itr->getIndex() == piece.getIndex()) { - piece.cancelBlock(itr->getBlockIndex()); - } + logger->debug("CUID#%d - Deleting request slot blockIndex=%d" + " because piece was canceled", + cuid, + itr->getBlockIndex()); + piece.cancelBlock(itr->getBlockIndex()); } - torrentMan->updatePiece(piece); + requestSlots.clear(); + torrentMan->cancelPiece(piece); + piece = Piece::nullPiece; + } +} + + +void PeerInteraction::deleteRequestSlot(const RequestSlot& requestSlot) { + RequestSlots::iterator itr = find(requestSlots.begin(), requestSlots.end(), + requestSlot); + if(itr != requestSlots.end()) { + requestSlots.erase(itr); } - requestSlots.clear(); } void PeerInteraction::deleteTimeoutRequestSlot() { for(RequestSlots::iterator itr = requestSlots.begin(); itr != requestSlots.end();) { if(itr->isTimeout(REQUEST_TIME_OUT)) { - logger->debug("CUID#%d - deleting requestslot blockIndex=%d because of time out", cuid, + logger->debug("CUID#%d - Deleting request slot blockIndex=%d" + " because of time out", + cuid, itr->getBlockIndex()); if(!Piece::isNull(piece)) { - //addMessage(createCancelMessage(itr->getIndex(), itr->getBegin(), itr->getLength())); piece.cancelBlock(itr->getBlockIndex()); } itr = requestSlots.erase(itr); @@ -166,7 +227,8 @@ void PeerInteraction::deleteCompletedRequestSlot() { itr != requestSlots.end();) { if(Piece::isNull(piece) || piece.hasBlock(itr->getBlockIndex()) || torrentMan->hasPiece(piece.getIndex())) { - logger->debug("CUID#%d - deleting requestslot blockIndex=%d because the block is already acquired.", cuid, + logger->debug("CUID#%d - Deleting request slot blockIndex=%d because" + " the block has been acquired.", cuid, itr->getBlockIndex()); addMessage(createCancelMessage(itr->getIndex(), itr->getBegin(), itr->getLength())); itr = requestSlots.erase(itr); @@ -176,28 +238,21 @@ void PeerInteraction::deleteCompletedRequestSlot() { } } -RequestSlot PeerInteraction::getCorrespondingRequestSlot(const PieceMessage* pieceMessage) const { +RequestSlot PeerInteraction::getCorrespondingRequestSlot(int index, + int begin, + int length) const { for(RequestSlots::const_iterator itr = requestSlots.begin(); itr != requestSlots.end(); itr++) { const RequestSlot& slot = *itr; - if(slot.getIndex() == pieceMessage->getIndex() && - slot.getBegin() == pieceMessage->getBegin() && - slot.getLength() == pieceMessage->getBlockLength()) { + if(slot.getIndex() == index && + slot.getBegin() == begin && + slot.getLength() == length) { return slot; } } return RequestSlot::nullSlot; } -void PeerInteraction::cancelAllRequest() { - cancelAllRequest(Piece::nullPiece); -} - -void PeerInteraction::cancelAllRequest(Piece& piece) { - deleteRequestMessageInQueue(); - deleteAllRequestSlot(piece); -} - int PeerInteraction::countMessageInQueue() const { return messageQueue.size(); } @@ -219,12 +274,17 @@ HandshakeMessage* PeerInteraction::receiveHandshake() { delete handshakeMessage; throw; } + if(handshakeMessage->isFastExtensionSupported()) { + peer->setFastExtensionEnabled(true); + logger->info("CUID#%d - Fast extension enabled."); + } return handshakeMessage; } HandshakeMessage* PeerInteraction::createHandshakeMessage(const char* msg, int msgLength) { - HandshakeMessage* message = PeerMessageUtil::createHandshakeMessage(msg, msgLength); - message->setPeerInteraction(this); + HandshakeMessage* message = HandshakeMessage::create(msg, msgLength); + + setPeerMessageCommonProperty(message); return message; } @@ -253,42 +313,61 @@ PeerMessage* PeerInteraction::createPeerMessage(const char* msg, int msgLength) int id = PeerMessageUtil::getId(msg); switch(id) { case ChokeMessage::ID: - peerMessage = PeerMessageUtil::createChokeMessage(msg, msgLength); + peerMessage = ChokeMessage::create(msg, msgLength); break; case UnchokeMessage::ID: - peerMessage = PeerMessageUtil::createUnchokeMessage(msg, msgLength); + peerMessage = UnchokeMessage::create(msg, msgLength); break; case InterestedMessage::ID: - peerMessage = PeerMessageUtil::createInterestedMessage(msg, msgLength); + peerMessage = InterestedMessage::create(msg, msgLength); break; case NotInterestedMessage::ID: - peerMessage = PeerMessageUtil::createNotInterestedMessage(msg, msgLength); + peerMessage = NotInterestedMessage::create(msg, msgLength); break; case HaveMessage::ID: - peerMessage = PeerMessageUtil::createHaveMessage(msg, msgLength); + peerMessage = HaveMessage::create(msg, msgLength); ((HaveMessage*)peerMessage)->setPieces(torrentMan->pieces); break; case BitfieldMessage::ID: - peerMessage = PeerMessageUtil::createBitfieldMessage(msg, msgLength); + peerMessage = BitfieldMessage::create(msg, msgLength); ((BitfieldMessage*)peerMessage)->setPieces(torrentMan->pieces); break; case RequestMessage::ID: - peerMessage = PeerMessageUtil::createRequestMessage(msg, msgLength); + peerMessage = RequestMessage::create(msg, msgLength); ((RequestMessage*)peerMessage)->setPieces(torrentMan->pieces); ((RequestMessage*)peerMessage)->setPieceLength(torrentMan->getPieceLength(((RequestMessage*)peerMessage)->getIndex())); break; case CancelMessage::ID: - peerMessage = PeerMessageUtil::createCancelMessage(msg, msgLength); + peerMessage = CancelMessage::create(msg, msgLength); ((CancelMessage*)peerMessage)->setPieces(torrentMan->pieces); ((CancelMessage*)peerMessage)->setPieceLength(torrentMan->getPieceLength(((CancelMessage*)peerMessage)->getIndex())); break; case PieceMessage::ID: - peerMessage = PeerMessageUtil::createPieceMessage(msg, msgLength); + peerMessage = PieceMessage::create(msg, msgLength); ((PieceMessage*)peerMessage)->setPieces(torrentMan->pieces); ((PieceMessage*)peerMessage)->setPieceLength(torrentMan->getPieceLength(((PieceMessage*)peerMessage)->getIndex())); break; case PortMessage::ID: - peerMessage = PeerMessageUtil::createPortMessage(msg, msgLength); + peerMessage = PortMessage::create(msg, msgLength); + break; + case HaveAllMessage::ID: + peerMessage = HaveAllMessage::create(msg, msgLength); + break; + case HaveNoneMessage::ID: + peerMessage = HaveNoneMessage::create(msg, msgLength); + break; + case RejectMessage::ID: + peerMessage = RejectMessage::create(msg, msgLength); + ((RejectMessage*)peerMessage)->setPieces(torrentMan->pieces); + ((RejectMessage*)peerMessage)->setPieceLength(torrentMan->getPieceLength(((RejectMessage*)peerMessage)->getIndex())); + break; + case SuggestPieceMessage::ID: + peerMessage = SuggestPieceMessage::create(msg, msgLength); + ((SuggestPieceMessage*)peerMessage)->setPieces(torrentMan->pieces); + break; + case AllowedFastMessage::ID: + peerMessage = AllowedFastMessage::create(msg, msgLength); + ((AllowedFastMessage*)peerMessage)->setPieces(torrentMan->pieces); break; default: throw new DlAbortEx("invalid message id. id = %d", id); @@ -306,34 +385,35 @@ void PeerInteraction::syncPiece() { torrentMan->syncPiece(piece); } -Piece PeerInteraction::getNewPieceAndSendInterest() { - cancelAllRequest(); - Piece piece = torrentMan->getMissingPiece(peer); +void PeerInteraction::getNewPieceAndSendInterest() { + piece = torrentMan->getMissingPiece(peer); if(Piece::isNull(piece)) { - logger->debug("CUID#%d - not interested in the peer", cuid); + logger->debug("CUID#%d - Not interested in the peer", cuid); addMessage(createNotInterestedMessage()); } else { - logger->debug("CUID#%d - starting download for piece index=%d (%d/%d completed)", - cuid, piece.getIndex(), piece.countCompleteBlock(), - piece.countBlock()); - logger->debug("CUID#%d - interested in the peer", cuid); + if(peer->peerChoking && !peer->isInFastSet(piece.getIndex())) { + abortPiece(); + } else { + logger->info("CUID#%d - Starting download for piece index=%d (%d/%d completed)", + cuid, piece.getIndex(), piece.countCompleteBlock(), + piece.countBlock()); + } + logger->debug("CUID#%d - Interested in the peer", cuid); addMessage(createInterestedMessage()); } - return piece; } -void PeerInteraction::sendMessages(int currentUploadSpeed) { +void PeerInteraction::addRequests() { if(Piece::isNull(piece)) { // retrive new piece from TorrentMan - piece = getNewPieceAndSendInterest(); - } else if(peer->peerChoking) { - cancelAllRequest(piece); - torrentMan->cancelPiece(piece); - piece = Piece::nullPiece; + getNewPieceAndSendInterest(); + } else if(peer->peerChoking && !peer->isInFastSet(piece.getIndex())) { + onChoked(); } else if(piece.pieceComplete()) { - piece = getNewPieceAndSendInterest(); + abortPiece(); + getNewPieceAndSendInterest(); } - if(!Piece::isNull(piece) && !peer->peerChoking) { + if(!Piece::isNull(piece)) { if(torrentMan->isEndGame()) { BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes(); if(countRequestSlot() == 0) { @@ -355,30 +435,43 @@ void PeerInteraction::sendMessages(int currentUploadSpeed) { } } } - send(currentUploadSpeed); -} - -void PeerInteraction::sendNow(PeerMessage* peerMessage) { - // ignore inProgress state - peerMessage->send(); - delete peerMessage; -} - -void PeerInteraction::trySendNow(PeerMessage* peerMessage) { - if(countMessageInQueue() == 0) { - sendNow(peerMessage); - } else { - addMessage(peerMessage); - } } void PeerInteraction::sendHandshake() { - peerConnection->sendHandshake(); + HandshakeMessage* handshake = new HandshakeMessage(); + memcpy(handshake->infoHash, torrentMan->getInfoHash(), INFO_HASH_LENGTH); + memcpy(handshake->peerId, torrentMan->peerId.c_str(), PEER_ID_LENGTH); + setPeerMessageCommonProperty(handshake); + addMessage(handshake); + sendMessages(0); } -void PeerInteraction::abortPiece() { - cancelAllRequest(piece); - torrentMan->cancelPiece(piece); +void PeerInteraction::sendBitfield() { + if(peer->isFastExtensionEnabled()) { + if(torrentMan->hasAllPieces()) { + addMessage(createHaveAllMessage()); + } else if(torrentMan->getDownloadLength() > 0) { + addMessage(createBitfieldMessage()); + } else { + addMessage(createHaveNoneMessage()); + } + } else { + if(torrentMan->getDownloadLength() > 0) { + addMessage(createBitfieldMessage()); + } + } + sendMessages(0); +} + +void PeerInteraction::sendAllowedFast() { + if(peer->isFastExtensionEnabled()) { + Integers fastSet = Util::computeFastSet(peer->ipaddr, torrentMan->getInfoHash(), + torrentMan->pieces, ALLOWED_FAST_SET_SIZE); + for(Integers::const_iterator itr = fastSet.begin(); + itr != fastSet.end(); itr++) { + addMessage(createAllowedFastMessage(*itr)); + } + } } Piece& PeerInteraction::getDownloadPiece() { @@ -388,6 +481,16 @@ Piece& PeerInteraction::getDownloadPiece() { return piece; } +bool PeerInteraction::isInFastSet(int index) const { + return find(fastSet.begin(), fastSet.end(), index) != fastSet.end(); +} + +void PeerInteraction::addFastSetIndex(int index) { + if(!isInFastSet(index)) { + fastSet.push_back(index); + } +} + void PeerInteraction::setPeerMessageCommonProperty(PeerMessage* peerMessage) { peerMessage->setPeer(peer); peerMessage->setCuid(cuid); @@ -395,68 +498,102 @@ void PeerInteraction::setPeerMessageCommonProperty(PeerMessage* peerMessage) { } RequestMessage* PeerInteraction::createRequestMessage(int blockIndex) { - RequestMessage* msg = - PeerMessageUtil::createRequestMessage(piece.getIndex(), - blockIndex*piece.getBlockLength(), - piece.getBlockLength(blockIndex), - blockIndex); + RequestMessage* msg = new RequestMessage(); + msg->setIndex(piece.getIndex()); + msg->setBegin(blockIndex*piece.getBlockLength()); + msg->setLength(piece.getBlockLength(blockIndex)); + msg->setBlockIndex(blockIndex); setPeerMessageCommonProperty(msg); return msg; } CancelMessage* PeerInteraction::createCancelMessage(int index, int begin, int length) { - CancelMessage* msg = - PeerMessageUtil::createCancelMessage(index, begin, length); + CancelMessage* msg = new CancelMessage(); + msg->setIndex(index); + msg->setBegin(begin); + msg->setLength(length); setPeerMessageCommonProperty(msg); return msg; } PieceMessage* PeerInteraction::createPieceMessage(int index, int begin, int length) { - PieceMessage* msg = - PeerMessageUtil::createPieceMessage(index, begin, length); + PieceMessage* msg = new PieceMessage(); + msg->setIndex(index); + msg->setBegin(begin); + msg->setBlockLength(length); setPeerMessageCommonProperty(msg); return msg; } HaveMessage* PeerInteraction::createHaveMessage(int index) { - HaveMessage* msg = PeerMessageUtil::createHaveMessage(index); + HaveMessage* msg = new HaveMessage(); + msg->setIndex(index); setPeerMessageCommonProperty(msg); return msg; } ChokeMessage* PeerInteraction::createChokeMessage() { - ChokeMessage* msg = PeerMessageUtil::createChokeMessage(); + ChokeMessage* msg = new ChokeMessage(); setPeerMessageCommonProperty(msg); return msg; } UnchokeMessage* PeerInteraction::createUnchokeMessage() { - UnchokeMessage* msg = PeerMessageUtil::createUnchokeMessage(); + UnchokeMessage* msg = new UnchokeMessage(); setPeerMessageCommonProperty(msg); return msg; } InterestedMessage* PeerInteraction::createInterestedMessage() { - InterestedMessage* msg = PeerMessageUtil::createInterestedMessage(); + InterestedMessage* msg = new InterestedMessage(); setPeerMessageCommonProperty(msg); return msg; } NotInterestedMessage* PeerInteraction::createNotInterestedMessage() { - NotInterestedMessage* msg = PeerMessageUtil::createNotInterestedMessage(); + NotInterestedMessage* msg = new NotInterestedMessage(); setPeerMessageCommonProperty(msg); return msg; } BitfieldMessage* PeerInteraction::createBitfieldMessage() { - BitfieldMessage* msg = PeerMessageUtil::createBitfieldMessage(); + BitfieldMessage* msg = new BitfieldMessage(); + msg->setBitfield(getTorrentMan()->getBitfield(), + getTorrentMan()->getBitfieldLength()); setPeerMessageCommonProperty(msg); return msg; } KeepAliveMessage* PeerInteraction::createKeepAliveMessage() { - KeepAliveMessage* msg = PeerMessageUtil::createKeepAliveMessage(); + KeepAliveMessage* msg = new KeepAliveMessage(); setPeerMessageCommonProperty(msg); return msg; } +HaveAllMessage* PeerInteraction::createHaveAllMessage() { + HaveAllMessage* msg = new HaveAllMessage(); + setPeerMessageCommonProperty(msg); + return msg; +} + +HaveNoneMessage* PeerInteraction::createHaveNoneMessage() { + HaveNoneMessage* msg = new HaveNoneMessage(); + setPeerMessageCommonProperty(msg); + return msg; +} + +RejectMessage* PeerInteraction::createRejectMessage(int index, int begin, int length) { + RejectMessage* msg = new RejectMessage(); + msg->setIndex(index); + msg->setBegin(begin); + msg->setLength(length); + setPeerMessageCommonProperty(msg); + return msg; +} + +AllowedFastMessage* PeerInteraction::createAllowedFastMessage(int index) { + AllowedFastMessage* msg = new AllowedFastMessage(); + msg->setIndex(index); + setPeerMessageCommonProperty(msg); + return msg; +} diff --git a/src/PeerInteraction.h b/src/PeerInteraction.h index 289de683..f41c6bce 100644 --- a/src/PeerInteraction.h +++ b/src/PeerInteraction.h @@ -36,9 +36,15 @@ #include "HandshakeMessage.h" #include "KeepAliveMessage.h" #include "PortMessage.h" +#include "HaveAllMessage.h" +#include "HaveNoneMessage.h" +#include "RejectMessage.h" +#include "AllowedFastMessage.h" +#include "SuggestPieceMessage.h" #include "RequestSlot.h" #define REQUEST_TIME_OUT 120 +#define ALLOWED_FAST_SET_SIZE 10 typedef deque RequestSlots; typedef deque MessageQueue; @@ -54,17 +60,14 @@ private: PeerConnection* peerConnection; Peer* peer; Piece piece; + // allowed fast piece indexes that local client has sent + Integers fastSet; const Logger* logger; - - Piece getNewPieceAndSendInterest(); + + void getNewPieceAndSendInterest(); PeerMessage* createPeerMessage(const char* msg, int msgLength); HandshakeMessage* createHandshakeMessage(const char* msg, int msgLength); - void send(int uploadSpeed); void setPeerMessageCommonProperty(PeerMessage* peerMessage); - void deleteAllRequestSlot(Piece& piece); - void deleteRequestMessageInQueue(); - void cancelAllRequest(); - void cancelAllRequest(Piece& piece); int countRequestSlot() const; public: PeerInteraction(int cuid, @@ -75,12 +78,16 @@ public: ~PeerInteraction(); void addMessage(PeerMessage* peerMessage); - void deletePieceMessageInQueue(const CancelMessage* cancelMessage); - + void rejectPieceMessageInQueue(int index, int begin, int length); + void rejectAllPieceMessageInQueue(); + void onChoked(); + void abortPiece(); + + bool isSendingMessageInProgress() const; void deleteRequestSlot(const RequestSlot& requestSlot); void deleteTimeoutRequestSlot(); void deleteCompletedRequestSlot(); - RequestSlot getCorrespondingRequestSlot(const PieceMessage* pieceMessage) const; + RequestSlot getCorrespondingRequestSlot(int index, int begin, int length) const; int countMessageInQueue() const; @@ -100,15 +107,16 @@ public: void setDownloadPiece(const Piece& piece) { this->piece = piece; } + + bool isInFastSet(int index) const; + void addFastSetIndex(int index); void syncPiece(); + void addRequests(); void sendMessages(int currentUploadSpeed); - // after sending message, deletes peerMessage. - // So don't use peerMessage after this function call. - void sendNow(PeerMessage* peerMessage); - void trySendNow(PeerMessage* peerMessage); - void abortPiece(); void sendHandshake(); + void sendBitfield(); + void sendAllowedFast(); PeerMessage* receiveMessage(); HandshakeMessage* receiveHandshake(); @@ -123,6 +131,10 @@ public: NotInterestedMessage* createNotInterestedMessage(); BitfieldMessage* createBitfieldMessage(); KeepAliveMessage* createKeepAliveMessage(); + HaveAllMessage* createHaveAllMessage(); + HaveNoneMessage* createHaveNoneMessage(); + RejectMessage* createRejectMessage(int index, int begin, int length); + AllowedFastMessage* createAllowedFastMessage(int index); }; #endif // _D_PEER_INTERACTION_H_ diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 08afbb1d..16e32515 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -40,6 +40,7 @@ PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer, peerInteraction = new PeerInteraction(cuid, socket, e->option, e->torrentMan, this->peer); peerInteraction->setUploadLimit(e->option->getAsInt(PREF_UPLOAD_LIMIT)); + setUploadLimit(e->option->getAsInt(PREF_UPLOAD_LIMIT)); keepAliveCheckPoint.tv_sec = 0; keepAliveCheckPoint.tv_usec = 0; chokeCheckPoint.tv_sec = 0; @@ -65,6 +66,7 @@ bool PeerInteractionCommand::executeInternal() { setTimeout(e->option->getAsInt(PREF_TIMEOUT)); } setWriteCheckSocket(NULL); + setUploadLimitCheck(false); switch(sequence) { case INITIATOR_SEND_HANDSHAKE: @@ -72,6 +74,12 @@ bool PeerInteractionCommand::executeInternal() { sequence = INITIATOR_WAIT_HANDSHAKE; break; case INITIATOR_WAIT_HANDSHAKE: { + if(peerInteraction->countMessageInQueue() > 0) { + peerInteraction->sendMessages(e->getUploadSpeed()); + if(peerInteraction->countMessageInQueue() > 0) { + break; + } + } HandshakeMessage* handshakeMessage = peerInteraction->receiveHandshake(); if(handshakeMessage == NULL) { break; @@ -81,9 +89,8 @@ bool PeerInteractionCommand::executeInternal() { peer->ipaddr.c_str(), peer->port, handshakeMessage->toString().c_str()); delete handshakeMessage; - if(e->torrentMan->getDownloadLength() > 0) { - peerInteraction->sendNow(peerInteraction->createBitfieldMessage()); - } + peerInteraction->sendBitfield(); + peerInteraction->sendAllowedFast(); sequence = WIRED; break; } @@ -98,9 +105,8 @@ bool PeerInteractionCommand::executeInternal() { handshakeMessage->toString().c_str()); delete handshakeMessage; peerInteraction->sendHandshake(); - if(e->torrentMan->getDownloadLength() > 0) { - peerInteraction->sendNow(peerInteraction->createBitfieldMessage()); - } + peerInteraction->sendBitfield(); + peerInteraction->sendAllowedFast(); sequence = WIRED; break; } @@ -115,11 +121,16 @@ bool PeerInteractionCommand::executeInternal() { } peerInteraction->deleteTimeoutRequestSlot(); peerInteraction->deleteCompletedRequestSlot(); + peerInteraction->addRequests(); peerInteraction->sendMessages(e->getUploadSpeed()); break; } if(peerInteraction->countMessageInQueue() > 0) { - setWriteCheckSocket(socket); + if(peerInteraction->isSendingMessageInProgress()) { + setWriteCheckSocket(socket); + } else { + setUploadLimitCheck(true); + } } e->commands.push_back(this); return false; @@ -246,7 +257,8 @@ void PeerInteractionCommand::keepAlive() { gettimeofday(&now, NULL); if(Util::difftv(now, keepAliveCheckPoint) >= (long long int)120*1000000) { if(peerInteraction->countMessageInQueue() == 0) { - peerInteraction->sendNow(peerInteraction->createKeepAliveMessage()); + peerInteraction->addMessage(peerInteraction->createKeepAliveMessage()); + peerInteraction->sendMessages(e->getUploadSpeed()); } keepAliveCheckPoint = now; } @@ -261,10 +273,18 @@ void PeerInteractionCommand::beforeSocketCheck() { PieceIndexes indexes = e->torrentMan->getAdvertisedPieceIndexes(cuid); if(indexes.size() >= 20) { - peerInteraction->trySendNow(peerInteraction->createBitfieldMessage()); + if(peer->isFastExtensionEnabled()) { + if(e->torrentMan->hasAllPieces()) { + peerInteraction->addMessage(peerInteraction->createHaveAllMessage()); + } else { + peerInteraction->addMessage(peerInteraction->createBitfieldMessage()); + } + } else { + peerInteraction->addMessage(peerInteraction->createBitfieldMessage()); + } } else { for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) { - peerInteraction->trySendNow(peerInteraction->createHaveMessage(*itr)); + peerInteraction->addMessage(peerInteraction->createHaveMessage(*itr)); } } keepAlive(); diff --git a/src/PeerMessageUtil.cc b/src/PeerMessageUtil.cc index 1c93b7f6..54f9dc98 100644 --- a/src/PeerMessageUtil.cc +++ b/src/PeerMessageUtil.cc @@ -40,162 +40,6 @@ int PeerMessageUtil::getShortIntParam(const char* msg, int offset) { return ntohs(nParam); } -ChokeMessage* PeerMessageUtil::createChokeMessage(const char* msg, int len) { - if(len != 1) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "choke", len, 1); - } - ChokeMessage* chokeMessage = new ChokeMessage(); - return chokeMessage; -} - -UnchokeMessage* PeerMessageUtil::createUnchokeMessage(const char* msg, int len) { - if(len != 1) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "unchoke", len, 1); - } - UnchokeMessage* unchokeMessage = new UnchokeMessage(); - return unchokeMessage; -} - -InterestedMessage* PeerMessageUtil::createInterestedMessage(const char* msg, int len) { - if(len != 1) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "interested", len, 1); - } - InterestedMessage* interestedMessage = new InterestedMessage(); - return interestedMessage; -} - -NotInterestedMessage* PeerMessageUtil::createNotInterestedMessage(const char* msg, int len) { - if(len != 1) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "not interested", len, 1); - } - NotInterestedMessage* notInterestedMessage = new NotInterestedMessage(); - return notInterestedMessage; -} - -HaveMessage* PeerMessageUtil::createHaveMessage(const char* msg, int len) { - if(len != 5) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "have", len, 5); - } - HaveMessage* haveMessage = new HaveMessage(); - haveMessage->setIndex(getIntParam(msg, 1)); - return haveMessage; -} - -BitfieldMessage* PeerMessageUtil::createBitfieldMessage(const char* msg, int len) { - if(len <= 1) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be greater than %d", "bitfield", len, 1); - } - BitfieldMessage* bitfieldMessage = new BitfieldMessage(); - bitfieldMessage->setBitfield((unsigned char*)msg+1, len-1); - return bitfieldMessage; -} - -RequestMessage* PeerMessageUtil::createRequestMessage(const char* msg, int len) { - if(len != 13) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "request", len, 13); - } - RequestMessage* requestMessage = new RequestMessage(); - requestMessage->setIndex(getIntParam(msg, 1)); - requestMessage->setBegin(getIntParam(msg, 5)); - requestMessage->setLength(getIntParam(msg, 9)); - return requestMessage; -} - -CancelMessage* PeerMessageUtil::createCancelMessage(const char* msg, int len) { - if(len != 13) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "cancel", len, 13); - } - CancelMessage* cancelMessage = new CancelMessage(); - cancelMessage->setIndex(getIntParam(msg, 1)); - cancelMessage->setBegin(getIntParam(msg, 5)); - cancelMessage->setLength(getIntParam(msg, 9)); - return cancelMessage; -} - -PieceMessage* PeerMessageUtil::createPieceMessage(const char* msg, int len) { - if(len <= 9) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be greater than %d", "piece", len, 9); - } - PieceMessage* pieceMessage = new PieceMessage(); - pieceMessage->setIndex(getIntParam(msg, 1)); - pieceMessage->setBegin(getIntParam(msg, 5)); - pieceMessage->setBlock(msg+9, len-9); - return pieceMessage; -} - -PortMessage* PeerMessageUtil::createPortMessage(const char* msg, int len) { - if(len != 3) { - throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "port", len, 3); - } - PortMessage* portMessage = new PortMessage(); - portMessage->setPort(getShortIntParam(msg, 1)); - return portMessage; -} - -RequestMessage* PeerMessageUtil::createRequestMessage(int index, - int begin, - int length, - int blockIndex) { - RequestMessage* msg = new RequestMessage(); - msg->setIndex(index); - msg->setBegin(begin); - msg->setLength(length); - msg->setBlockIndex(blockIndex); - return msg; -} - -CancelMessage* PeerMessageUtil::createCancelMessage(int index, int begin, int length) { - CancelMessage* msg = new CancelMessage(); - msg->setIndex(index); - msg->setBegin(begin); - msg->setLength(length); - return msg; -} - -PieceMessage* PeerMessageUtil::createPieceMessage(int index, int begin, int length) { - PieceMessage* msg = new PieceMessage(); - msg->setIndex(index); - msg->setBegin(begin); - msg->setBlockLength(length); - return msg; -} - -HaveMessage* PeerMessageUtil::createHaveMessage(int index) { - HaveMessage* msg = new HaveMessage(); - msg->setIndex(index); - return msg; -} - -ChokeMessage* PeerMessageUtil::createChokeMessage() { - ChokeMessage* msg = new ChokeMessage(); - return msg; -} - -UnchokeMessage* PeerMessageUtil::createUnchokeMessage() { - UnchokeMessage* msg = new UnchokeMessage(); - return msg; -} - -InterestedMessage* PeerMessageUtil::createInterestedMessage() { - InterestedMessage* msg = new InterestedMessage(); - return msg; -} - -NotInterestedMessage* PeerMessageUtil::createNotInterestedMessage() { - NotInterestedMessage* msg = new NotInterestedMessage(); - return msg; -} - -BitfieldMessage* PeerMessageUtil::createBitfieldMessage() { - BitfieldMessage* msg = new BitfieldMessage(); - return msg; -} - -KeepAliveMessage* PeerMessageUtil::createKeepAliveMessage() { - KeepAliveMessage* msg = new KeepAliveMessage(); - return msg; -} - void PeerMessageUtil::checkIndex(int index, int pieces) { if(!(0 <= index && index < pieces)) { throw new DlAbortEx("invalid index = %d", index); @@ -244,19 +88,6 @@ void PeerMessageUtil::checkBitfield(const unsigned char* bitfield, int bitfieldL } } -HandshakeMessage* PeerMessageUtil::createHandshakeMessage(const char* msg, int length) { - HandshakeMessage* message = new HandshakeMessage(); - message->pstrlen = msg[0]; - char pstr[20]; - memcpy(pstr, &msg[1], sizeof(pstr)-1); - pstr[sizeof(pstr)-1] = '\0'; - message->pstr = pstr; - memcpy(message->infoHash, &msg[28], 20); - memcpy(message->peerId, &msg[48], 20); - return message; -} - - void PeerMessageUtil::checkHandshake(const HandshakeMessage* message, const unsigned char* infoHash) { if(message->pstrlen != 19) { throw new DlAbortEx("invalid handshake pstrlen = %d", (int)message->pstrlen); @@ -272,3 +103,16 @@ void PeerMessageUtil::checkHandshake(const HandshakeMessage* message, const unsi } } +void PeerMessageUtil::setIntParam(char* dest, int param) { + int nParam = htonl(param); + memcpy(dest, &nParam, 4); +} + +void PeerMessageUtil::createPeerMessageString(char* msg, int msgLength, + int payloadLength, + int messageId) { + assert(msgLength >= 5); + memset(msg, 0, msgLength); + setIntParam(msg, payloadLength); + msg[4] = (char)messageId; +} diff --git a/src/PeerMessageUtil.h b/src/PeerMessageUtil.h index 05a564a1..604ba24c 100644 --- a/src/PeerMessageUtil.h +++ b/src/PeerMessageUtil.h @@ -34,6 +34,8 @@ #include "HandshakeMessage.h" #include "KeepAliveMessage.h" #include "PortMessage.h" +#include "HaveAllMessage.h" +#include "HaveNoneMessage.h" #include "PeerConnection.h" #define MAX_BLOCK_LENGTH (128*1024) @@ -41,36 +43,13 @@ class PeerMessageUtil { private: PeerMessageUtil() {} - +public: static int getIntParam(const char* msg, int offset); static int getShortIntParam(const char* msg, int offset); -public: + static void setIntParam(char* dest, int param); + static int getId(const char* msg); - - static ChokeMessage* createChokeMessage(const char* msg, int len); - static UnchokeMessage* createUnchokeMessage(const char* msg, int len); - static InterestedMessage* createInterestedMessage(const char* msg, int len); - static NotInterestedMessage* createNotInterestedMessage(const char* msg, - int len); - static HaveMessage* createHaveMessage(const char* msg, int len); - static BitfieldMessage* createBitfieldMessage(const char* msg, int len); - static RequestMessage* createRequestMessage(const char* msg, int len); - static CancelMessage* createCancelMessage(const char* msg, int len); - static PieceMessage* createPieceMessage(const char* msg, int len); - static PortMessage* createPortMessage(const char* msg, int len); - - static ChokeMessage* createChokeMessage(); - static UnchokeMessage* createUnchokeMessage(); - static InterestedMessage* createInterestedMessage(); - static NotInterestedMessage* createNotInterestedMessage(); - static HaveMessage* createHaveMessage(int index); - static BitfieldMessage* createBitfieldMessage(); - static RequestMessage* createRequestMessage(int index, int begin, - int length, int blockIndex); - static CancelMessage* createCancelMessage(int index, int begin, int length); - static PieceMessage* createPieceMessage(int index, int begin, int length); - static KeepAliveMessage* createKeepAliveMessage(); - + static void checkIndex(int index, int pieces); static void checkBegin(int begin, int pieceLength); static void checkLength(int length); @@ -79,9 +58,11 @@ public: int bitfieldLength, int pieces); - static HandshakeMessage* createHandshakeMessage(const char* msg, int length); static void checkHandshake(const HandshakeMessage* message, const unsigned char* infoHash); + + static void createPeerMessageString(char* msg, int msgLength, + int payloadLength, int messageId); }; #endif // _D_PEER_MESSAGE_UTIL_H_ diff --git a/src/PieceMessage.cc b/src/PieceMessage.cc index 2c8f7d97..54de5851 100644 --- a/src/PieceMessage.cc +++ b/src/PieceMessage.cc @@ -24,6 +24,7 @@ #include "PeerInteraction.h" #include "Util.h" #include "message.h" +#include "DlAbortEx.h" void PieceMessage::setBlock(const char* block, int blockLength) { if(this->block != NULL) { @@ -34,16 +35,34 @@ void PieceMessage::setBlock(const char* block, int blockLength) { memcpy(this->block, block, this->blockLength); } +PieceMessage* PieceMessage::create(const char* data, int dataLength) { + if(dataLength <= 9) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be greater than %d", "piece", dataLength, 9); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "piece", ID); + } + PieceMessage* pieceMessage = new PieceMessage(); + pieceMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + pieceMessage->setBegin(PeerMessageUtil::getIntParam(data, 5)); + pieceMessage->setBlock(data+9, dataLength-9); + return pieceMessage; +} + void PieceMessage::receivedAction() { TorrentMan* torrentMan = peerInteraction->getTorrentMan(); - RequestSlot slot = peerInteraction->getCorrespondingRequestSlot(this); + RequestSlot slot = peerInteraction->getCorrespondingRequestSlot(index, + begin, + blockLength); peer->addPeerUpload(blockLength); if(peerInteraction->hasDownloadPiece() && !RequestSlot::isNull(slot)) { Piece& piece = peerInteraction->getDownloadPiece(); long long int offset = ((long long int)index)*torrentMan->pieceLength+begin; - logger->debug("CUID#%d - write block length = %d, offset=%lld", + logger->debug("CUID#%d - Writing the block length=%d, offset=%lld", cuid, blockLength, offset); torrentMan->diskAdaptor->writeData(block, blockLength, @@ -51,7 +70,7 @@ void PieceMessage::receivedAction() { piece.completeBlock(slot.getBlockIndex()); peerInteraction->deleteRequestSlot(slot); torrentMan->updatePiece(piece); - logger->debug("CUID#%d - setting piece bit index=%d", + logger->debug("CUID#%d - Setting piece block index=%d", cuid, slot.getBlockIndex()); torrentMan->addDeltaDownloadLength(blockLength); if(piece.pieceComplete()) { @@ -64,25 +83,95 @@ void PieceMessage::receivedAction() { } } +const char* PieceMessage::getMessageHeader() { + if(!inProgress) { + /** + * len --- 9+blockLength, 4bytes + * id --- 7, 1byte + * index --- index, 4bytes + * begin --- begin, 4bytes + * total: 13bytes + */ + PeerMessageUtil::createPeerMessageString(msgHeader, sizeof(msgHeader), + 9+blockLength, ID); + PeerMessageUtil::setIntParam(&msgHeader[5], index); + PeerMessageUtil::setIntParam(&msgHeader[9], begin); + } + return msgHeader; +} + +int PieceMessage::getMessageHeaderLength() { + return sizeof(msgHeader); +} + void PieceMessage::send() { - if((!peer->amChoking && peer->peerInterested) || inProgress) { - PeerConnection* peerConnection = peerInteraction->getPeerConnection(); + TorrentMan* torrentMan = peerInteraction->getTorrentMan(); + PeerConnection* peerConnection = peerInteraction->getPeerConnection(); + if(!headerSent) { if(!inProgress) { - peerConnection->sendPieceHeader(index, begin, blockLength); - peer->addPeerDownload(blockLength); - leftPieceDataLength = blockLength; - } - inProgress = false; - int pieceLength = peerInteraction->getTorrentMan()->pieceLength; - long long int pieceDataOffset = - ((long long int)index)*pieceLength+begin+blockLength-leftPieceDataLength; - int writtenLength = - peerConnection->sendPieceData(pieceDataOffset, leftPieceDataLength); - if(writtenLength != leftPieceDataLength) { + logger->info(MSG_SEND_PEER_MESSAGE, + cuid, peer->ipaddr.c_str(), peer->port, + toString().c_str()); + getMessageHeader(); + leftDataLength = getMessageHeaderLength(); inProgress = true; - leftPieceDataLength -= writtenLength; + } + int writtenLength + = peerConnection->sendMessage(msgHeader+getMessageHeaderLength()-leftDataLength, + leftDataLength); + if(writtenLength == leftDataLength) { + headerSent = true; + leftDataLength = blockLength; + } else { + leftDataLength -= writtenLength; } } + if(headerSent) { + inProgress = false; + int pieceLength = torrentMan->pieceLength; + long long int pieceDataOffset = + ((long long int)index)*pieceLength+begin+blockLength-leftDataLength; + int writtenLength = + sendPieceData(pieceDataOffset, leftDataLength); + peer->addPeerDownload(writtenLength); + torrentMan->addUploadLength(writtenLength); + torrentMan->addDeltaUploadLength(writtenLength); + if(writtenLength != leftDataLength) { + inProgress = true; + } + leftDataLength -= writtenLength; + } +} + +int PieceMessage::sendPieceData(long long int offset, int length) const { + int BUF_SIZE = 256; + char buf[BUF_SIZE]; + int iteration = length/BUF_SIZE; + int writtenLength = 0; + TorrentMan* torrentMan = peerInteraction->getTorrentMan(); + PeerConnection* peerConnection = peerInteraction->getPeerConnection(); + for(int i = 0; i < iteration; i++) { + if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) { + throw new DlAbortEx("Failed to read data from disk."); + } + int ws = peerConnection->sendMessage(buf, BUF_SIZE); + writtenLength += ws; + if(ws != BUF_SIZE) { + //logger->debug("CUID#%d - %d bytes written", cuid, writtenLength); + return writtenLength; + } + } + + int rem = length%BUF_SIZE; + if(rem > 0) { + if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) { + throw new DlAbortEx("Failed to read data from disk."); + } + int ws = peerConnection->sendMessage(buf, rem); + writtenLength += ws; + } + //logger->debug("CUID#%d - %d bytes written", cuid, writtenLength); + return writtenLength; } void PieceMessage::check() const { diff --git a/src/PieceMessage.h b/src/PieceMessage.h index 7ebcba6f..9f7652e6 100644 --- a/src/PieceMessage.h +++ b/src/PieceMessage.h @@ -31,19 +31,25 @@ private: int begin; char* block; int blockLength; - int leftPieceDataLength; + int leftDataLength; + bool headerSent; + int pendingCount; // for check int pieces; int pieceLength; + + char msgHeader[13]; bool checkPieceHash(const Piece& piece); void onGotNewPiece(Piece& piece); void onGotWrongPiece(Piece& piece); void erasePieceOnDisk(const Piece& piece); + int sendPieceData(long long int offset, int length) const; public: PieceMessage():PeerMessage(), index(0), begin(0), block(NULL), blockLength(0), - leftPieceDataLength(0), + leftDataLength(0), headerSent(false), + pendingCount(0), pieces(0), pieceLength(0) {} virtual ~PieceMessage() { @@ -75,8 +81,15 @@ public: } int getPieceLength() const { return pieceLength;} + void incrementPendingCount() { pendingCount++; } + bool isPendingCountMax() const { return pendingCount > 2; } + + static PieceMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); + virtual const char* getMessageHeader(); + virtual int getMessageHeaderLength(); virtual void send(); virtual void check() const; virtual string toString() const; diff --git a/src/PortMessage.cc b/src/PortMessage.cc new file mode 100644 index 00000000..2358a82b --- /dev/null +++ b/src/PortMessage.cc @@ -0,0 +1,38 @@ +/* */ +#include "PortMessage.h" +#include "PeerMessageUtil.h" +#include "DlAbortEx.h" + +PortMessage* PortMessage::create(const char* data, int dataLength) { + if(dataLength != 3) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "port", dataLength, 3); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "piece", ID); + } + PortMessage* portMessage = new PortMessage(); + portMessage->setPort(PeerMessageUtil::getShortIntParam(data, 1)); + return portMessage; +} diff --git a/src/PortMessage.h b/src/PortMessage.h index b0325e3b..e62e187a 100644 --- a/src/PortMessage.h +++ b/src/PortMessage.h @@ -39,14 +39,16 @@ public: void setPort(int port) { this->port = port; } virtual int getId() const { return ID; } + + static PortMessage* create(const char* data, int dataLength); + virtual void receivedAction() { - logger->info("no DHT support right now."); + logger->info("DHT is not supported yet."); } virtual void send() {} virtual string toString() const { return "port"; } - }; #endif // _D_PORT_MESSAGE_H_ diff --git a/src/RejectMessage.cc b/src/RejectMessage.cc new file mode 100644 index 00000000..a6edd978 --- /dev/null +++ b/src/RejectMessage.cc @@ -0,0 +1,93 @@ +/* */ +#include "RejectMessage.h" +#include "PeerInteraction.h" +#include "PeerMessageUtil.h" +#include "Util.h" +#include "DlAbortEx.h" + +RejectMessage* RejectMessage::create(const char* data, int dataLength) { + if(dataLength != 13) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "reject", dataLength, 13); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "reject", ID); + } + RejectMessage* rejectMessage = new RejectMessage(); + rejectMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + rejectMessage->setBegin(PeerMessageUtil::getIntParam(data, 5)); + rejectMessage->setLength(PeerMessageUtil::getIntParam(data, 9)); + return rejectMessage; +} + +void RejectMessage::receivedAction() { + if(!peer->isFastExtensionEnabled()) { + throw new DlAbortEx("%s received while fast extension is disabled", + toString().c_str()); + } + // TODO Current implementation does not close a connection even if + // a request for this reject message is never sent. + RequestSlot slot = + peerInteraction->getCorrespondingRequestSlot(index, begin, length); + if(RequestSlot::isNull(slot)) { + //throw new DlAbortEx("reject recieved, but it is not in the request slots."); + } else { + peerInteraction->deleteRequestSlot(slot); + } + +} + +const char* RejectMessage::getMessage() { + if(!inProgress) { + /** + * len --- 13, 4bytes + * id --- 16, 1byte + * index --- index, 4bytes + * begin --- begin, 4bytes + * length -- length, 4bytes + * total: 17bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, ID); + PeerMessageUtil::setIntParam(&msg[5], index); + PeerMessageUtil::setIntParam(&msg[9], begin); + PeerMessageUtil::setIntParam(&msg[13], length); + } + return msg; +} + +int RejectMessage::getMessageLength() { + return sizeof(msg); +} + +void RejectMessage::check() const { + PeerMessageUtil::checkIndex(index, pieces); + PeerMessageUtil::checkBegin(begin, pieceLength); + PeerMessageUtil::checkLength(length); + PeerMessageUtil::checkRange(begin, length, pieceLength); +} + +string RejectMessage::toString() const { + return "reject index="+Util::itos(index)+", begin="+Util::itos(begin)+ + ", length="+Util::itos(length); +} diff --git a/src/RejectMessage.h b/src/RejectMessage.h new file mode 100644 index 00000000..bbb0355d --- /dev/null +++ b/src/RejectMessage.h @@ -0,0 +1,76 @@ +/* */ +#ifndef _D_REJECT_MESSAGE_H_ +#define _D_REJECT_MESSAGE_H_ + +#include "SimplePeerMessage.h" +#include "TorrentMan.h" + +class RejectMessage : public SimplePeerMessage { +private: + int index; + int begin; + int length; + // for check + int pieces; + int pieceLength; + + char msg[17]; +public: + RejectMessage():SimplePeerMessage(), + index(0), begin(0), length(0), + pieces(0), pieceLength(0) {} + + virtual ~RejectMessage() {} + + enum ID { + ID = 16 + }; + + int getIndex() const { return index; } + void setIndex(int index) { this->index = index; } + int getBegin() const { return begin; } + void setBegin(int begin) { this->begin = begin; } + int getLength() const { return length; } + void setLength(int length) { this->length = length; } + + void setPieces(int pieces) { + this->pieces = pieces; + } + int getPieces() const { return pieces;} + + void setPieceLength(int pieceLength) { + this->pieceLength = pieceLength; + } + int getPieceLength() const { return pieceLength;} + + static RejectMessage* create(const char* data, int dataLength); + + virtual int getId() const { return ID; } + virtual void receivedAction(); + virtual const char* getMessage(); + virtual int getMessageLength(); + virtual void check() const; + virtual string toString() const; +}; + +#endif // _D_REJECT_MESSAGE_H_ diff --git a/src/RequestMessage.cc b/src/RequestMessage.cc index a3acd626..05b8a515 100644 --- a/src/RequestMessage.cc +++ b/src/RequestMessage.cc @@ -23,20 +23,57 @@ #include "PeerInteraction.h" #include "PeerMessageUtil.h" #include "Util.h" +#include "DlAbortEx.h" + +RequestMessage* RequestMessage::create(const char* data, int dataLength) { + if(dataLength != 13) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "request", dataLength, 13); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "request", ID); + } + RequestMessage* requestMessage = new RequestMessage(); + requestMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + requestMessage->setBegin(PeerMessageUtil::getIntParam(data, 5)); + requestMessage->setLength(PeerMessageUtil::getIntParam(data, 9)); + return requestMessage; +} void RequestMessage::receivedAction() { TorrentMan* torrentMan = peerInteraction->getTorrentMan(); - if(torrentMan->hasPiece(index)) { + if(torrentMan->hasPiece(index) && + (!peer->amChoking || + peer->amChoking && peerInteraction->isInFastSet(index))) { peerInteraction->addMessage(peerInteraction->createPieceMessage(index, begin, length)); - torrentMan->addUploadLength(length); - torrentMan->addDeltaUploadLength(length); + } else { + if(peer->isFastExtensionEnabled()) { + peerInteraction->addMessage(peerInteraction->createRejectMessage(index, begin, length)); + } } } -void RequestMessage::send() { - if(!peer->peerChoking) { - peerInteraction->getPeerConnection()->sendRequest(index, begin, length); +const char* RequestMessage::getMessage() { + if(!inProgress) { + /** + * len --- 13, 4bytes + * id --- 6, 1byte + * index --- index, 4bytes + * begin --- begin, 4bytes + * length --- length, 4bytes + * total: 17bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, ID); + PeerMessageUtil::setIntParam(&msg[5], index); + PeerMessageUtil::setIntParam(&msg[9], begin); + PeerMessageUtil::setIntParam(&msg[13], length); } + return msg; +} + +int RequestMessage::getMessageLength() { + return sizeof(msg); } void RequestMessage::check() const { diff --git a/src/RequestMessage.h b/src/RequestMessage.h index ee46025e..b84963cf 100644 --- a/src/RequestMessage.h +++ b/src/RequestMessage.h @@ -22,10 +22,10 @@ #ifndef _D_REQUEST_MESSAGE_H_ #define _D_REQUEST_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" #include "TorrentMan.h" -class RequestMessage : public PeerMessage { +class RequestMessage : public SimplePeerMessage { private: int index; int begin; @@ -34,8 +34,10 @@ private: // for check int pieces; int pieceLength; + + char msg[17]; public: - RequestMessage():PeerMessage(), + RequestMessage():SimplePeerMessage(), index(0), begin(0), length(0), blockIndex(0), pieces(0), pieceLength(0) {} virtual ~RequestMessage() {} @@ -63,9 +65,12 @@ public: } int getPieceLength() const { return pieceLength;} + static RequestMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); + virtual const char* getMessage(); + virtual int getMessageLength(); virtual void check() const; virtual string toString() const; }; diff --git a/src/SuggestPieceMessage.cc b/src/SuggestPieceMessage.cc new file mode 100644 index 00000000..28c687dd --- /dev/null +++ b/src/SuggestPieceMessage.cc @@ -0,0 +1,70 @@ +/* */ +#include "SuggestPieceMessage.h" +#include "PeerInteraction.h" +#include "PeerMessageUtil.h" +#include "Util.h" +#include "DlAbortEx.h" + +SuggestPieceMessage* SuggestPieceMessage::create(const char* data, int dataLength) { + if(dataLength != 5) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "suggest piece", dataLength, 5); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "suggest piece", ID); + } + SuggestPieceMessage* suggestPieceMessage = new SuggestPieceMessage(); + suggestPieceMessage->setIndex(PeerMessageUtil::getIntParam(data, 1)); + return suggestPieceMessage; +} + +void SuggestPieceMessage::receivedAction() { + // TODO Current implementation ignores this message. +} + +const char* SuggestPieceMessage::getMessage() { + if(!inProgress) { + /** + * len --- 5, 4bytes + * id --- 13, 1byte + * piece index --- index, 4bytes + * total: 9bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, ID); + PeerMessageUtil::setIntParam(&msg[5], index); + } + return msg; +} + +int SuggestPieceMessage::getMessageLength() { + return sizeof(msg); +} + +void SuggestPieceMessage::check() const { + PeerMessageUtil::checkIndex(index, pieces); +} + +string SuggestPieceMessage::toString() const { + return "suggest piece index="+Util::itos(index); +} diff --git a/src/SuggestPieceMessage.h b/src/SuggestPieceMessage.h new file mode 100644 index 00000000..fa91f39d --- /dev/null +++ b/src/SuggestPieceMessage.h @@ -0,0 +1,62 @@ +/* */ +#ifndef _D_SUGGEST_PIECE_MESSAGE_H_ +#define _D_SUGGEST_PIECE_MESSAGE_H_ + +#include "SimplePeerMessage.h" + +class SuggestPieceMessage : public SimplePeerMessage { +private: + int index; + // for check + int pieces; + char msg[9]; +public: + SuggestPieceMessage():SimplePeerMessage(), index(0), pieces(0) {} + + virtual ~SuggestPieceMessage() {} + + enum ID { + ID = 13 + }; + + void setIndex(int index) { + this->index = index; + } + int getIndex() const { return index; } + + void setPieces(int pieces) { + this->pieces = pieces; + } + int getPieces() const { return pieces;} + + static SuggestPieceMessage* create(const char* data, int dataLength); + + virtual int getId() const { return ID; } + virtual void receivedAction(); + virtual const char* getMessage(); + virtual int getMessageLength(); + virtual void check() const; + virtual string toString() const; +}; + +#endif // _D_SUGGEST_PIECE_MESSAGE_H_ diff --git a/src/TorrentMan.cc b/src/TorrentMan.cc index f8ab44b6..0cad6e26 100644 --- a/src/TorrentMan.cc +++ b/src/TorrentMan.cc @@ -147,10 +147,30 @@ bool TorrentMan::isEndGame() const { Piece TorrentMan::getMissingPiece(const Peer* peer) { int index = -1; - if(isEndGame()) { - index = bitfield->getMissingIndex(peer->getBitfield(), peer->getBitfieldLength()); - } else { - index = bitfield->getMissingUnusedIndex(peer->getBitfield(), peer->getBitfieldLength()); + if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) { + BitfieldMan tempBitfield(pieceLength, totalLength); + for(Integers::const_iterator itr = peer->getFastSet().begin(); + itr != peer->getFastSet().end(); itr++) { + if(!hasPiece(*itr) && peer->hasPiece(*itr)) { + tempBitfield.setBit(*itr); + } + } + if(isEndGame()) { + index = bitfield->getMissingIndex(tempBitfield.getBitfield(), + tempBitfield.getBitfieldLength()); + } else { + index = bitfield->getMissingUnusedIndex(tempBitfield.getBitfield(), + tempBitfield.getBitfieldLength()); + } + } + if(index == -1) { + if(isEndGame()) { + index = bitfield->getMissingIndex(peer->getBitfield(), + peer->getBitfieldLength()); + } else { + index = bitfield->getMissingUnusedIndex(peer->getBitfield(), + peer->getBitfieldLength()); + } } if(index == -1) { return Piece::nullPiece; @@ -248,6 +268,7 @@ void TorrentMan::cancelPiece(const Piece& piece) { if(Piece::isNull(piece)) { return; } + updatePiece(piece); bitfield->unsetUseBit(piece.getIndex()); if(!isEndGame()) { if(piece.countCompleteBlock() == 0) { @@ -303,6 +324,10 @@ bool TorrentMan::downloadComplete() const { return bitfield->isAllBitSet(); } +bool TorrentMan::hasAllPieces() const { + return bitfield->getTotalLength() == downloadLength; +} + void TorrentMan::readFileEntry(FileEntries& fileEntries, Directory** pTopDir, const Dictionary* infoDic, const string& defaultName) { Data* topName = (Data*)infoDic->get("name"); if(topName != NULL) { diff --git a/src/TorrentMan.h b/src/TorrentMan.h index 1b9363d9..2a84a45c 100644 --- a/src/TorrentMan.h +++ b/src/TorrentMan.h @@ -41,6 +41,7 @@ using namespace std; #define INFO_HASH_LENGTH 20 +#define PEER_ID_LENGTH 20 #define DEFAULT_ANNOUNCE_INTERVAL 300 #define DEFAULT_ANNOUNCE_MIN_INTERVAL 300 #define MAX_PEERS 55 @@ -93,6 +94,7 @@ private: public: int pieceLength; int pieces; + // TODO type char* would be better string peerId; string announce; string trackerId; @@ -133,6 +135,7 @@ public: void initBitfield(); bool isEndGame() const; bool downloadComplete() const; + bool hasAllPieces() const; void setBitfield(unsigned char* bitfield, int len); const unsigned char* getBitfield() const { return bitfield->getBitfield(); diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc index 41e4c435..296f2333 100644 --- a/src/TrackerUpdateCommand.cc +++ b/src/TrackerUpdateCommand.cc @@ -99,17 +99,19 @@ bool TrackerUpdateCommand::execute() { Data* trackerId = (Data*)response->get("tracker id"); if(trackerId != NULL) { e->torrentMan->trackerId = trackerId->toString(); - logger->debug("Tracker ID:%s", e->torrentMan->trackerId.c_str()); + logger->debug("CUID#%d - Tracker ID:%s", + cuid, e->torrentMan->trackerId.c_str()); } Data* interval = (Data*)response->get("interval"); if(interval != NULL) { e->torrentMan->interval = interval->toInt(); - logger->debug("interval:%d", e->torrentMan->interval); + logger->debug("CUID#%d - Interval:%d", cuid, e->torrentMan->interval); } Data* minInterval = (Data*)response->get("min interval"); if(minInterval != NULL) { e->torrentMan->minInterval = minInterval->toInt(); - logger->debug("min interval:%d", e->torrentMan->minInterval); + logger->debug("CUID#%d - Min interval:%d", + cuid, e->torrentMan->minInterval); } if(e->torrentMan->minInterval > e->torrentMan->interval) { e->torrentMan->minInterval = e->torrentMan->interval; @@ -117,12 +119,13 @@ bool TrackerUpdateCommand::execute() { Data* complete = (Data*)response->get("complete"); if(complete != NULL) { e->torrentMan->complete = complete->toInt(); - logger->debug("complete:%d", e->torrentMan->complete); + logger->debug("CUID#%d - Complete:%d", cuid, e->torrentMan->complete); } Data* incomplete = (Data*)response->get("incomplete"); if(incomplete != NULL) { e->torrentMan->incomplete = incomplete->toInt(); - logger->debug("incomplete:%d", e->torrentMan->incomplete); + logger->debug("CUID#%d - Incomplete:%d", + cuid, e->torrentMan->incomplete); } Data* peers = (Data*)response->get("peers"); if(peers != NULL) { @@ -139,13 +142,14 @@ bool TrackerUpdateCommand::execute() { Peer* peer = new Peer(ipaddr, port, e->torrentMan->pieceLength, e->torrentMan->getTotalLength()); if(e->torrentMan->addPeer(peer)) { - logger->debug("adding peer %s:%d", peer->ipaddr.c_str(), peer->port); + logger->debug("CUID#%d - Adding peer %s:%d", + cuid, peer->ipaddr.c_str(), peer->port); } else { delete peer; } } } else { - logger->info("no peer list received."); + logger->info("CUID#%d - No peer list received.", cuid); } while(e->torrentMan->isPeerAvailable() && e->torrentMan->connections < MAX_PEER_UPDATE) { @@ -154,7 +158,7 @@ bool TrackerUpdateCommand::execute() { peer->cuid = newCuid; PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e); e->commands.push_back(command); - logger->debug("adding new command CUID#%d", newCuid); + logger->debug("CUID#%d - Adding new command CUID#%d", cuid, newCuid); } if(e->torrentMan->req->getTrackerEvent() == Request::STARTED) { e->torrentMan->req->setTrackerEvent(Request::AUTO); diff --git a/src/TrackerWatcherCommand.cc b/src/TrackerWatcherCommand.cc index 4bd1d0b5..0677c52e 100644 --- a/src/TrackerWatcherCommand.cc +++ b/src/TrackerWatcherCommand.cc @@ -25,16 +25,27 @@ #include "Util.h" TrackerWatcherCommand::TrackerWatcherCommand(int cuid, - TorrentDownloadEngine* e): - Command(cuid), e(e) { + TorrentDownloadEngine* e, + int interval): + Command(cuid), e(e), interval(interval) { + checkPoint.tv_sec = 0; + checkPoint.tv_usec = 0; } TrackerWatcherCommand::~TrackerWatcherCommand() {} bool TrackerWatcherCommand::execute() { - if(e->torrentMan->trackers == 0 && e->torrentMan->connections < MIN_PEERS) { + struct timeval now; + gettimeofday(&now, NULL); + + if(e->torrentMan->trackers == 0 && + Util::difftvsec(now, checkPoint) >= interval) { + checkPoint = now; e->torrentMan->req->resetTryCount(); - + int numWant = 50; + if(e->torrentMan->connections >= MIN_PEERS) { + numWant = 0; + } if(e->torrentMan->downloadComplete()) { if(e->torrentMan->req->getTrackerEvent() == Request::COMPLETED) { e->torrentMan->req->setTrackerEvent(Request::AFTER_COMPLETED); @@ -67,7 +78,8 @@ 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; + "key="+e->torrentMan->peerId+"&"+ + "numwant="+Util::itos(numWant); if(!event.empty()) { url += string("&")+"event="+event; } @@ -81,8 +93,7 @@ bool TrackerWatcherCommand::execute() { logger->info("CUID#%d - creating new tracker request command #%d", cuid, command->getCuid()); } - SleepCommand* slpCommand = new SleepCommand(cuid, e, this, - e->torrentMan->minInterval); - e->commands.push_back(slpCommand); + interval = e->torrentMan->minInterval; + e->commands.push_back(this); return false; } diff --git a/src/TrackerWatcherCommand.h b/src/TrackerWatcherCommand.h index 14625a9f..0597a0a6 100644 --- a/src/TrackerWatcherCommand.h +++ b/src/TrackerWatcherCommand.h @@ -24,14 +24,17 @@ #include "Command.h" #include "TorrentDownloadEngine.h" +#include #define MIN_PEERS 15 class TrackerWatcherCommand : public Command { private: TorrentDownloadEngine* e; + int interval; + struct timeval checkPoint; public: - TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e); + TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e, int interval); ~TrackerWatcherCommand(); bool execute(); diff --git a/src/UnchokeMessage.cc b/src/UnchokeMessage.cc index 61894998..5bd1bc31 100644 --- a/src/UnchokeMessage.cc +++ b/src/UnchokeMessage.cc @@ -21,16 +21,48 @@ /* copyright --> */ #include "UnchokeMessage.h" #include "PeerInteraction.h" +#include "PeerMessageUtil.h" +#include "DlAbortEx.h" + +UnchokeMessage* UnchokeMessage::create(const char* data, int dataLength) { + if(dataLength != 1) { + throw new DlAbortEx("invalid payload size for %s, size = %d. It should be %d", "unchoke", dataLength, 1); + } + int id = PeerMessageUtil::getId(data); + if(id != ID) { + throw new DlAbortEx("invalid ID=%d for %s. It should be %d.", + id, "unchoke", ID); + } + UnchokeMessage* unchokeMessage = new UnchokeMessage(); + return unchokeMessage; +} void UnchokeMessage::receivedAction() { peer->peerChoking = false; } -void UnchokeMessage::send() { - if(peer->amChoking) { - peerInteraction->getPeerConnection()->sendUnchoke(); - peer->amChoking = false; +bool UnchokeMessage::sendPredicate() const { + return peer->amChoking; +} + +const char* UnchokeMessage::getMessage() { + if(!inProgress) { + /** + * len --- 1, 4bytes + * id --- 1, 1byte + * total: 5bytes + */ + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, ID); } + return msg; +} + +int UnchokeMessage::getMessageLength() { + return sizeof(msg); +} + +void UnchokeMessage::onSendComplete() { + peer->amChoking = false; } string UnchokeMessage::toString() const { diff --git a/src/UnchokeMessage.h b/src/UnchokeMessage.h index d6d01e2f..6c40c577 100644 --- a/src/UnchokeMessage.h +++ b/src/UnchokeMessage.h @@ -22,21 +22,28 @@ #ifndef _D_UNCHOKE_MESSAGE_H_ #define _D_UNCHOKE_MESSAGE_H_ -#include "PeerMessage.h" +#include "SimplePeerMessage.h" -class UnchokeMessage : public PeerMessage { +class UnchokeMessage : public SimplePeerMessage { +private: + char msg[5]; +protected: + virtual bool sendPredicate() const; + virtual void onSendComplete(); public: - UnchokeMessage():PeerMessage() {} + UnchokeMessage():SimplePeerMessage() {} virtual ~UnchokeMessage() {} enum ID { ID = 1 }; + static UnchokeMessage* create(const char* data, int dataLength); + virtual int getId() const { return ID; } virtual void receivedAction(); - virtual void send(); - + virtual const char* getMessage(); + virtual int getMessageLength(); virtual string toString() const; }; diff --git a/src/Util.cc b/src/Util.cc index eeb3d397..d1d7470f 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -23,10 +23,17 @@ #include "DlAbortEx.h" #include "File.h" #include "message.h" +#ifdef ENABLE_SHA1DIGEST +#include "messageDigest.h" +#endif // ENABLE_SHA1DIGEST #include #include #include #include +#include +#include +#include +#include string Util::itos(int value, bool comma) { string str = llitos(value, comma); @@ -355,3 +362,51 @@ string Util::getContentDispositionFilename(const string& header) { } return trim(header.substr(filenamesp, filenameep-filenamesp)); } + +void Util::sha1Sum(unsigned char* digest, const void* data, int dataLength) { +#ifdef ENABLE_SHA1DIGEST + MessageDigestContext ctx; + sha1DigestInit(ctx); + sha1DigestReset(ctx); + sha1DigestUpdate(ctx, data, dataLength); + sha1DigestFinal(ctx, digest); + sha1DigestFree(ctx); +#endif // ENABLE_SHA1DIGEST +} + +Integers Util::computeFastSet(string ipaddr, const unsigned char* infoHash, + int pieces, int fastSetSize) { + Integers fastSet; + struct in_addr saddr; + if(inet_aton(ipaddr.c_str(), &saddr) == 0) { + abort(); + } + unsigned char tx[24]; + memcpy(tx, (void*)&saddr.s_addr, 4); + if((tx[0] & 0x80) == 0 || (tx[0] & 0x40) == 0) { + tx[2] = 0x00; + tx[3] = 0x00; + } else { + tx[3] = 0x00; + } + memcpy(tx+4, infoHash, 20); + unsigned char x[20]; + sha1Sum(x, tx, 24); + while((int)fastSet.size() < fastSetSize) { + for(int i = 0; i < 5 && (int)fastSet.size() < fastSetSize; i++) { + int j = i*4; + unsigned int ny; + memcpy(&ny, x+j, 4); + unsigned int y = ntohl(ny); + int index = y%pieces; + if(find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) { + fastSet.push_back(index); + } + } + unsigned char temp[20]; + sha1Sum(temp, x, 20); + memcpy(x, temp, sizeof(x)); + } + return fastSet; +} + diff --git a/src/Util.h b/src/Util.h index 4bf74896..05e5ca93 100644 --- a/src/Util.h +++ b/src/Util.h @@ -78,6 +78,12 @@ public: // this function temporarily put here static string getContentDispositionFilename(const string& header); + + // digest must be at least 20 bytes long. + static void sha1Sum(unsigned char* digest, const void* data, int dataLength); + + static Integers computeFastSet(string ipaddr, const unsigned char* infoHash, + int pieces, int fastSetSize); }; #endif // _D_UTIL_H_ diff --git a/src/main.cc b/src/main.cc index 30afdb92..918afa54 100644 --- a/src/main.cc +++ b/src/main.cc @@ -704,7 +704,8 @@ int main(int argc, char* argv[]) { te->torrentMan->setPort(port); te->commands.push_back(listenCommand); te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(), - te)); + te, + te->torrentMan->minInterval)); te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(), te)); te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(), diff --git a/test/AllowedFastMessageTest.cc b/test/AllowedFastMessageTest.cc new file mode 100644 index 00000000..95492904 --- /dev/null +++ b/test/AllowedFastMessageTest.cc @@ -0,0 +1,59 @@ +#include "AllowedFastMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class AllowedFastMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(AllowedFastMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(AllowedFastMessageTest); + +void AllowedFastMessageTest::testCreate() { + char msg[9]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, 17); + PeerMessageUtil::setIntParam(&msg[5], 12345); + AllowedFastMessage* pm = AllowedFastMessage::create(&msg[4], 5); + CPPUNIT_ASSERT_EQUAL(17, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + + // case: payload size is wrong + try { + char msg[10]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 6, 17); + AllowedFastMessage::create(&msg[4], 6); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[9]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, 18); + AllowedFastMessage::create(&msg[4], 5); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void AllowedFastMessageTest::testGetMessage() { + AllowedFastMessage msg; + msg.setIndex(12345); + char data[9]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 5, 17); + PeerMessageUtil::setIntParam(&data[5], 12345); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 9) == 0); +} diff --git a/test/BitfieldMessageTest.cc b/test/BitfieldMessageTest.cc new file mode 100644 index 00000000..ab02ab9d --- /dev/null +++ b/test/BitfieldMessageTest.cc @@ -0,0 +1,63 @@ +#include "BitfieldMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class BitfieldMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(BitfieldMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(BitfieldMessageTest); + +void BitfieldMessageTest::testCreate() { + char msg[5+2]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 3, 5); + unsigned char bitfield[2]; + memset(bitfield, 0xff, sizeof(bitfield)); + memcpy(&msg[5], bitfield, sizeof(bitfield)); + BitfieldMessage* pm = BitfieldMessage::create(&msg[4], 3); + CPPUNIT_ASSERT_EQUAL(5, pm->getId()); + CPPUNIT_ASSERT(memcmp(bitfield, pm->getBitfield(), sizeof(bitfield)) == 0); + CPPUNIT_ASSERT_EQUAL(2, pm->getBitfieldLength()); + // case: payload size is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 5); + BitfieldMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5+2]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 3, 6); + BitfieldMessage::create(&msg[4], 3); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void BitfieldMessageTest::testGetMessage() { + BitfieldMessage msg; + unsigned char bitfield[2]; + memset(bitfield, 0xff, sizeof(bitfield)); + msg.setBitfield(bitfield, sizeof(bitfield)); + char data[5+2]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 3, 5); + memcpy(&data[5], bitfield, sizeof(bitfield)); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 7) == 0); +} diff --git a/test/CancelMessageTest.cc b/test/CancelMessageTest.cc new file mode 100644 index 00000000..d091f684 --- /dev/null +++ b/test/CancelMessageTest.cc @@ -0,0 +1,67 @@ +#include "CancelMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class CancelMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(CancelMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(CancelMessageTest); + +void CancelMessageTest::testCreate() { + char msg[17]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, 8); + PeerMessageUtil::setIntParam(&msg[5], 12345); + PeerMessageUtil::setIntParam(&msg[9], 256); + PeerMessageUtil::setIntParam(&msg[13], 1024); + CancelMessage* pm = CancelMessage::create(&msg[4], 13); + CPPUNIT_ASSERT_EQUAL(8, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + CPPUNIT_ASSERT_EQUAL(256, pm->getBegin()); + CPPUNIT_ASSERT_EQUAL(1024, pm->getLength()); + + // case: payload size is wrong + try { + char msg[18]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 14, 8); + CancelMessage::create(&msg[4], 14); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[17]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, 9); + CancelMessage::create(&msg[4], 13); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void CancelMessageTest::testGetMessage() { + CancelMessage msg; + msg.setIndex(12345); + msg.setBegin(256); + msg.setLength(1024); + char data[17]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 13, 8); + PeerMessageUtil::setIntParam(&data[5], 12345); + PeerMessageUtil::setIntParam(&data[9], 256); + PeerMessageUtil::setIntParam(&data[13], 1024); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0); +} diff --git a/test/ChokeMessageTest.cc b/test/ChokeMessageTest.cc new file mode 100644 index 00000000..54ba24f5 --- /dev/null +++ b/test/ChokeMessageTest.cc @@ -0,0 +1,55 @@ +#include "ChokeMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class ChokeMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(ChokeMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(ChokeMessageTest); + +void ChokeMessageTest::testCreate() { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 0); + PeerMessage* pm = ChokeMessage::create(&msg[4], 1); + CPPUNIT_ASSERT_EQUAL(0, pm->getId()); + + // case: payload size is wrong + try { + char msg[6]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 2, 0); + ChokeMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 1); + ChokeMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void ChokeMessageTest::testGetMessage() { + ChokeMessage msg; + char data[5]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 1, 0); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0); +} diff --git a/test/HaveAllMessageTest.cc b/test/HaveAllMessageTest.cc new file mode 100644 index 00000000..f7d6dda4 --- /dev/null +++ b/test/HaveAllMessageTest.cc @@ -0,0 +1,55 @@ +#include "HaveAllMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class HaveAllMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(HaveAllMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(HaveAllMessageTest); + +void HaveAllMessageTest::testCreate() { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 14); + PeerMessage* pm = HaveAllMessage::create(&msg[4], 1); + CPPUNIT_ASSERT_EQUAL(14, pm->getId()); + + // case: payload size is wrong + try { + char msg[6]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 2, 14); + HaveAllMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 15); + HaveAllMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void HaveAllMessageTest::testGetMessage() { + HaveAllMessage msg; + char data[5]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 1, 14); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0); +} diff --git a/test/HaveMessageTest.cc b/test/HaveMessageTest.cc new file mode 100644 index 00000000..e73ecc80 --- /dev/null +++ b/test/HaveMessageTest.cc @@ -0,0 +1,59 @@ +#include "HaveMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class HaveMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(HaveMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(HaveMessageTest); + +void HaveMessageTest::testCreate() { + char msg[9]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, 4); + PeerMessageUtil::setIntParam(&msg[5], 12345); + HaveMessage* pm = HaveMessage::create(&msg[4], 5); + CPPUNIT_ASSERT_EQUAL(4, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + + // case: payload size is wrong + try { + char msg[10]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 6, 4); + HaveMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[9]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, 5); + HaveMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void HaveMessageTest::testGetMessage() { + HaveMessage msg; + msg.setIndex(12345); + char data[9]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 5, 4); + PeerMessageUtil::setIntParam(&data[5], 12345); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 9) == 0); +} diff --git a/test/HaveNoneMessageTest.cc b/test/HaveNoneMessageTest.cc new file mode 100644 index 00000000..41e0b5ed --- /dev/null +++ b/test/HaveNoneMessageTest.cc @@ -0,0 +1,55 @@ +#include "HaveNoneMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class HaveNoneMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(HaveNoneMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(HaveNoneMessageTest); + +void HaveNoneMessageTest::testCreate() { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 15); + PeerMessage* pm = HaveNoneMessage::create(&msg[4], 1); + CPPUNIT_ASSERT_EQUAL(15, pm->getId()); + + // case: payload size is wrong + try { + char msg[6]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 2, 15); + HaveNoneMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 16); + HaveNoneMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void HaveNoneMessageTest::testGetMessage() { + HaveNoneMessage msg; + char data[5]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 1, 15); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0); +} diff --git a/test/InterestedMessageTest.cc b/test/InterestedMessageTest.cc new file mode 100644 index 00000000..e757c402 --- /dev/null +++ b/test/InterestedMessageTest.cc @@ -0,0 +1,55 @@ +#include "InterestedMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class InterestedMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(InterestedMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(InterestedMessageTest); + +void InterestedMessageTest::testCreate() { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 2); + PeerMessage* pm = InterestedMessage::create(&msg[4], 1); + CPPUNIT_ASSERT_EQUAL(2, pm->getId()); + + // case: payload size is wrong + try { + char msg[6]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 2, 2); + InterestedMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 3); + InterestedMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void InterestedMessageTest::testGetMessage() { + InterestedMessage msg; + char data[5]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 1, 2); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0); +} diff --git a/test/Makefile.am b/test/Makefile.am index 035ee7eb..215c8903 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -17,7 +17,21 @@ aria2c_SOURCES = AllTest.cc\ PeerMessageUtilTest.cc\ BitfieldManTest.cc\ DefaultDiskWriterTest.cc\ - MultiDiskWriterTest.cc + MultiDiskWriterTest.cc\ + ChokeMessageTest.cc\ + UnchokeMessageTest.cc\ + HaveAllMessageTest.cc\ + HaveNoneMessageTest.cc\ + InterestedMessageTest.cc\ + NotInterestedMessageTest.cc\ + HaveMessageTest.cc\ + BitfieldMessageTest.cc\ + RequestMessageTest.cc\ + CancelMessageTest.cc\ + PieceMessageTest.cc\ + RejectMessageTest.cc\ + AllowedFastMessageTest.cc\ + SuggestPieceMessageTest.cc #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} diff --git a/test/Makefile.in b/test/Makefile.in index e23d9a12..2490ea5e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -64,7 +64,14 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) RequestTest.$(OBJEXT) \ MetaFileUtilTest.$(OBJEXT) ShaVisitorTest.$(OBJEXT) \ TorrentManTest.$(OBJEXT) PeerMessageUtilTest.$(OBJEXT) \ BitfieldManTest.$(OBJEXT) DefaultDiskWriterTest.$(OBJEXT) \ - MultiDiskWriterTest.$(OBJEXT) + MultiDiskWriterTest.$(OBJEXT) ChokeMessageTest.$(OBJEXT) \ + UnchokeMessageTest.$(OBJEXT) HaveAllMessageTest.$(OBJEXT) \ + HaveNoneMessageTest.$(OBJEXT) InterestedMessageTest.$(OBJEXT) \ + NotInterestedMessageTest.$(OBJEXT) HaveMessageTest.$(OBJEXT) \ + BitfieldMessageTest.$(OBJEXT) RequestMessageTest.$(OBJEXT) \ + CancelMessageTest.$(OBJEXT) PieceMessageTest.$(OBJEXT) \ + RejectMessageTest.$(OBJEXT) AllowedFastMessageTest.$(OBJEXT) \ + SuggestPieceMessageTest.$(OBJEXT) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1) @@ -222,7 +229,21 @@ aria2c_SOURCES = AllTest.cc\ PeerMessageUtilTest.cc\ BitfieldManTest.cc\ DefaultDiskWriterTest.cc\ - MultiDiskWriterTest.cc + MultiDiskWriterTest.cc\ + ChokeMessageTest.cc\ + UnchokeMessageTest.cc\ + HaveAllMessageTest.cc\ + HaveNoneMessageTest.cc\ + InterestedMessageTest.cc\ + NotInterestedMessageTest.cc\ + HaveMessageTest.cc\ + BitfieldMessageTest.cc\ + RequestMessageTest.cc\ + CancelMessageTest.cc\ + PieceMessageTest.cc\ + RejectMessageTest.cc\ + AllowedFastMessageTest.cc\ + SuggestPieceMessageTest.cc #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} @@ -284,22 +305,36 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllowedFastMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64Test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMessageTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CancelMessageTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChokeMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncodingTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxTest.Po@am__quote@ @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)/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@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveNoneMessageTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InterestedMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ListTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskWriterTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NotInterestedMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OptionTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtilTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceMessageTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RejectMessageTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitorTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentManTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnchokeMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@ .cc.o: diff --git a/test/MetaFileUtilTest.cc b/test/MetaFileUtilTest.cc index aa53aa74..e8965a57 100644 --- a/test/MetaFileUtilTest.cc +++ b/test/MetaFileUtilTest.cc @@ -37,41 +37,41 @@ void MetaFileUtilTest::testBdecoding() { try { char* str = "5:abcd"; MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str)); - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } catch(DlAbortEx* ex) { delete ex; } catch(...) { - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } try { char* str = "i1234"; MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str)); - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } catch(DlAbortEx* ex) { delete ex; } catch(...) { - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } try { char* str = "5abcd"; MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str)); - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } catch(DlAbortEx* ex) { delete ex; } catch(...) { - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } try { char* str = "d"; MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str)); - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } catch(DlAbortEx* ex) { delete ex; } catch(...) { - CPPUNIT_FAIL("DlAbortEx exception must be throwed."); + CPPUNIT_FAIL("DlAbortEx exception must be threw."); } } diff --git a/test/NotInterestedMessageTest.cc b/test/NotInterestedMessageTest.cc new file mode 100644 index 00000000..0af52516 --- /dev/null +++ b/test/NotInterestedMessageTest.cc @@ -0,0 +1,55 @@ +#include "NotInterestedMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class NotInterestedMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(NotInterestedMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(NotInterestedMessageTest); + +void NotInterestedMessageTest::testCreate() { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 3); + PeerMessage* pm = NotInterestedMessage::create(&msg[4], 1); + CPPUNIT_ASSERT_EQUAL(3, pm->getId()); + + // case: payload size is wrong + try { + char msg[6]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 2, 3); + NotInterestedMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 4); + NotInterestedMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void NotInterestedMessageTest::testGetMessage() { + NotInterestedMessage msg; + char data[5]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 1, 3); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0); +} diff --git a/test/PeerMessageUtilTest.cc b/test/PeerMessageUtilTest.cc index 9cd0f9bf..d38a7f20 100644 --- a/test/PeerMessageUtilTest.cc +++ b/test/PeerMessageUtilTest.cc @@ -8,16 +8,6 @@ using namespace std; class PeerMessageUtilTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(PeerMessageUtilTest); - CPPUNIT_TEST(testCreatePeerMessageChoke); - CPPUNIT_TEST(testCreatePeerMessageUnchoke); - CPPUNIT_TEST(testCreatePeerMessageInterested); - CPPUNIT_TEST(testCreatePeerMessageNotInterested); - CPPUNIT_TEST(testCreatePeerMessageHave); - CPPUNIT_TEST(testCreatePeerMessageBitfield); - CPPUNIT_TEST(testCreatePeerMessageRequest); - CPPUNIT_TEST(testCreatePeerMessagePiece); - CPPUNIT_TEST(testCreatePeerMessageCancel); - CPPUNIT_TEST(testCreatePortMessage); CPPUNIT_TEST(testCheckIntegrityHave); CPPUNIT_TEST(testCheckIntegrityBitfield); CPPUNIT_TEST(testCheckIntegrityRequest); @@ -28,7 +18,6 @@ public: void setUp() { } - void testCreatePeerMessageChoke(); void testCreatePeerMessageUnchoke(); void testCreatePeerMessageInterested(); void testCreatePeerMessageNotInterested(); @@ -62,191 +51,11 @@ void createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) { msg[4] = (char)id; } -void PeerMessageUtilTest::testCreatePeerMessageChoke() { - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 0); - PeerMessage* pm = PeerMessageUtil::createChokeMessage(&msg[4], 1); - CPPUNIT_ASSERT_EQUAL((int)ChokeMessage::ID, pm->getId()); - - try { - char msg[6]; - createNLengthMessage(msg, sizeof(msg), 2, 0); - PeerMessageUtil::createChokeMessage(&msg[4], 2); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) { - } -} - -void PeerMessageUtilTest::testCreatePeerMessageUnchoke() { - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 1); - PeerMessage* pm = PeerMessageUtil::createUnchokeMessage(&msg[4], 1); - CPPUNIT_ASSERT_EQUAL((int)UnchokeMessage::ID, pm->getId()); - - try { - char msg[6]; - createNLengthMessage(msg, sizeof(msg), 2, 1); - PeerMessageUtil::createUnchokeMessage(&msg[4], 2); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) { - } -} - -void PeerMessageUtilTest::testCreatePeerMessageInterested() { - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 2); - PeerMessage* pm = PeerMessageUtil::createInterestedMessage(&msg[4], 1); - CPPUNIT_ASSERT_EQUAL((int)InterestedMessage::ID, pm->getId()); - - try { - char msg[6]; - createNLengthMessage(msg, sizeof(msg), 2, 2); - PeerMessageUtil::createInterestedMessage(&msg[4], 2); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) { - } -} - -void PeerMessageUtilTest::testCreatePeerMessageNotInterested() { - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 3); - PeerMessage* pm = PeerMessageUtil::createNotInterestedMessage(&msg[4], 1); - CPPUNIT_ASSERT_EQUAL((int)NotInterestedMessage::ID, pm->getId()); - - try { - char msg[6]; - createNLengthMessage(msg, sizeof(msg), 2, 3); - PeerMessageUtil::createNotInterestedMessage(&msg[4], 2); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) { - } -} - -void PeerMessageUtilTest::testCreatePeerMessageHave() { - char msg[9]; - createNLengthMessage(msg, sizeof(msg), 5, 4); - setIntParam(&msg[5], 100); - HaveMessage* pm = PeerMessageUtil::createHaveMessage(&msg[4], 5); - CPPUNIT_ASSERT_EQUAL((int)HaveMessage::ID, pm->getId()); - CPPUNIT_ASSERT_EQUAL(100, pm->getIndex()); - - try { - char msg[8]; - createNLengthMessage(msg, sizeof(msg), 4, 4); - PeerMessageUtil::createHaveMessage(&msg[4], 4); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) {} - - try { - char msg[5]; - createNLengthMessage(msg, sizeof(msg), 1, 4); - PeerMessageUtil::createHaveMessage(&msg[4], 1); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) {} -} - -void PeerMessageUtilTest::testCreatePeerMessageBitfield() { - int msgLen = 5+2; - char* msg = new char[msgLen]; - createNLengthMessage(msg, msgLen, 3, 5); - BitfieldMessage* pm = PeerMessageUtil::createBitfieldMessage(&msg[4], 3); - CPPUNIT_ASSERT_EQUAL((int)BitfieldMessage::ID, pm->getId()); - CPPUNIT_ASSERT_EQUAL((unsigned char)0, pm->getBitfield()[0]); - CPPUNIT_ASSERT_EQUAL((unsigned char)0, pm->getBitfield()[1]); - CPPUNIT_ASSERT_EQUAL(2, pm->getBitfieldLength()); - - try { - int msgLen = 5; - char* msg = new char[msgLen]; - createNLengthMessage(msg, msgLen, 1, 5); - PeerMessageUtil::createBitfieldMessage(&msg[4], 1); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) {} -} - -void PeerMessageUtilTest::testCreatePeerMessageRequest() { - char msg[17]; - createNLengthMessage(msg, sizeof(msg), 13, 6); - setIntParam(&msg[5], 1); - setIntParam(&msg[9], 16*1024); - setIntParam(&msg[13], 16*1024-1); - RequestMessage* pm = PeerMessageUtil::createRequestMessage(&msg[4], 13); - CPPUNIT_ASSERT_EQUAL((int)RequestMessage::ID, pm->getId()); - CPPUNIT_ASSERT_EQUAL(1, pm->getIndex()); - CPPUNIT_ASSERT_EQUAL(16*1024, pm->getBegin()); - CPPUNIT_ASSERT_EQUAL(16*1024-1, pm->getLength()); - - try { - char msg[13]; - createNLengthMessage(msg, sizeof(msg), 9, 6); - setIntParam(&msg[5], 1); - setIntParam(&msg[9], 16*1024); - PeerMessageUtil::createRequestMessage(&msg[4], 9); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) {} -} - -void PeerMessageUtilTest::testCreatePeerMessagePiece() { - char msg[23]; - createNLengthMessage(msg, sizeof(msg), 9+10, 7); - setIntParam(&msg[5], 1); - setIntParam(&msg[9], 16*1024); - PieceMessage* pm = PeerMessageUtil::createPieceMessage(&msg[4], 19); - CPPUNIT_ASSERT_EQUAL((int)PieceMessage::ID, pm->getId()); - CPPUNIT_ASSERT_EQUAL(1, pm->getIndex()); - CPPUNIT_ASSERT_EQUAL(16*1024, pm->getBegin()); - CPPUNIT_ASSERT_EQUAL(10, pm->getBlockLength()); - for(int i = 0; i < 10; i++) { - CPPUNIT_ASSERT_EQUAL((char)0, pm->getBlock()[i]); - } - - try { - char msg[13]; - createNLengthMessage(msg, sizeof(msg), 9, 7); - setIntParam(&msg[5], 1); - setIntParam(&msg[9], 16*1024); - PeerMessageUtil::createPieceMessage(&msg[4], 9); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) {} -} - -void PeerMessageUtilTest::testCreatePeerMessageCancel() { - char msg[17]; - createNLengthMessage(msg, sizeof(msg), 13, 8); - setIntParam(&msg[5], 1); - setIntParam(&msg[9], 16*1024); - setIntParam(&msg[13], 16*1024-1); - CancelMessage* pm = PeerMessageUtil::createCancelMessage(&msg[4], 13); - CPPUNIT_ASSERT_EQUAL((int)CancelMessage::ID, pm->getId()); - CPPUNIT_ASSERT_EQUAL(1, pm->getIndex()); - CPPUNIT_ASSERT_EQUAL(16*1024, pm->getBegin()); - CPPUNIT_ASSERT_EQUAL(16*1024-1, pm->getLength()); - - try { - char msg[13]; - createNLengthMessage(msg, sizeof(msg), 9, 8); - setIntParam(&msg[5], 1); - setIntParam(&msg[9], 16*1024); - PeerMessageUtil::createCancelMessage(&msg[4], 9); - CPPUNIT_FAIL("exception must be throwed."); - } catch(...) {} -} - -void PeerMessageUtilTest::testCreatePortMessage() { - char msg[7]; - createNLengthMessage(msg, sizeof(msg), 3, 9); - setShortIntParam(&msg[5], 65535); - PortMessage* pm = PeerMessageUtil::createPortMessage(&msg[4], 3); - CPPUNIT_ASSERT_EQUAL((int)PortMessage::ID, pm->getId()); - CPPUNIT_ASSERT_EQUAL(65535, pm->getPort()); -} - void PeerMessageUtilTest::testCheckIntegrityHave() { HaveMessage* pm = new HaveMessage(); pm->setIndex(119); pm->setPieces(120); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); } catch(Exception* ex) { cerr << ex->getMsg() << endl; @@ -255,9 +64,8 @@ void PeerMessageUtilTest::testCheckIntegrityHave() { pm->setIndex(120); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(...) {} } @@ -270,7 +78,6 @@ void PeerMessageUtilTest::testCheckIntegrityBitfield() { pm->setBitfield(bitfield, bitfieldLength); pm->setPieces(120); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); } catch(Exception* ex) { cerr << ex->getMsg() << endl; @@ -282,9 +89,8 @@ void PeerMessageUtilTest::testCheckIntegrityBitfield() { memset(bitfield, 0xff, bitfieldLength); pm->setBitfield(bitfield, bitfieldLength); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(Exception* ex) { } delete [] bitfield; @@ -293,9 +99,8 @@ void PeerMessageUtilTest::testCheckIntegrityBitfield() { memset(bitfield, 0xff, bitfieldLength); pm->setBitfield(bitfield, bitfieldLength); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(Exception* ex) { } delete [] bitfield; @@ -306,7 +111,6 @@ void PeerMessageUtilTest::testCheckIntegrityBitfield() { pm->setBitfield(bitfield, bitfieldLength); pm->setPieces(119); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 119, 256*1024*120); pm->check(); } catch(Exception* ex) { cerr << ex->getMsg() << endl; @@ -318,9 +122,8 @@ void PeerMessageUtilTest::testCheckIntegrityBitfield() { memset(bitfield, 0xff, bitfieldLength); pm->setBitfield(bitfield, bitfieldLength); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 119, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(Exception* ex) { } delete [] bitfield; @@ -334,7 +137,6 @@ void PeerMessageUtilTest::testCheckIntegrityRequest() { pm->setPieces(120); pm->setPieceLength(256*1024); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); } catch(Exception* ex) { cerr << ex->getMsg() << endl; @@ -344,24 +146,21 @@ void PeerMessageUtilTest::testCheckIntegrityRequest() { pm->setBegin(256*1024); pm->setLength(16*1024); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(Exception* ex) {} pm->setBegin(0); pm->setLength(256*1024); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(Exception* ex) {} pm->setBegin(0); pm->setLength(5); try { - //PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120); pm->check(); - CPPUNIT_FAIL("exception must be throwed."); + CPPUNIT_FAIL("exception must be threw."); } catch(Exception* ex) {} } diff --git a/test/PieceMessageTest.cc b/test/PieceMessageTest.cc new file mode 100644 index 00000000..7b01cbed --- /dev/null +++ b/test/PieceMessageTest.cc @@ -0,0 +1,69 @@ +#include "PieceMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class PieceMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(PieceMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessageHeader); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessageHeader(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(PieceMessageTest); + +void PieceMessageTest::testCreate() { + char msg[13+2]; + char data[2]; + memset(data, 0xff, sizeof(data)); + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 11, 7); + PeerMessageUtil::setIntParam(&msg[5], 12345); + PeerMessageUtil::setIntParam(&msg[9], 256); + memcpy(&msg[13], data, sizeof(data)); + PieceMessage* pm = PieceMessage::create(&msg[4], 11); + CPPUNIT_ASSERT_EQUAL(7, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + CPPUNIT_ASSERT_EQUAL(256, pm->getBegin()); + CPPUNIT_ASSERT(memcmp(data, pm->getBlock(), sizeof(data)) == 0); + CPPUNIT_ASSERT_EQUAL(2, pm->getBlockLength()); + + // case: payload size is wrong + try { + char msg[13]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 9, 7); + PieceMessage::create(&msg[4], 9); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[13+2]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 11, 8); + PieceMessage::create(&msg[4], 11); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void PieceMessageTest::testGetMessageHeader() { + PieceMessage msg; + msg.setIndex(12345); + msg.setBegin(256); + msg.setBlockLength(1024); + char data[13]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 9+1024, 7); + PeerMessageUtil::setIntParam(&data[5], 12345); + PeerMessageUtil::setIntParam(&data[9], 256); + CPPUNIT_ASSERT(memcmp(msg.getMessageHeader(), data, 13) == 0); +} diff --git a/test/RejectMessageTest.cc b/test/RejectMessageTest.cc new file mode 100644 index 00000000..5ee932c5 --- /dev/null +++ b/test/RejectMessageTest.cc @@ -0,0 +1,67 @@ +#include "RejectMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class RejectMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(RejectMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(RejectMessageTest); + +void RejectMessageTest::testCreate() { + char msg[17]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, 16); + PeerMessageUtil::setIntParam(&msg[5], 12345); + PeerMessageUtil::setIntParam(&msg[9], 256); + PeerMessageUtil::setIntParam(&msg[13], 1024); + RejectMessage* pm = RejectMessage::create(&msg[4], 13); + CPPUNIT_ASSERT_EQUAL(16, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + CPPUNIT_ASSERT_EQUAL(256, pm->getBegin()); + CPPUNIT_ASSERT_EQUAL(1024, pm->getLength()); + + // case: payload size is wrong + try { + char msg[18]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 14, 16); + RejectMessage::create(&msg[4], 14); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[17]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, 17); + RejectMessage::create(&msg[4], 13); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void RejectMessageTest::testGetMessage() { + RejectMessage msg; + msg.setIndex(12345); + msg.setBegin(256); + msg.setLength(1024); + char data[17]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 13, 16); + PeerMessageUtil::setIntParam(&data[5], 12345); + PeerMessageUtil::setIntParam(&data[9], 256); + PeerMessageUtil::setIntParam(&data[13], 1024); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0); +} diff --git a/test/RequestMessageTest.cc b/test/RequestMessageTest.cc new file mode 100644 index 00000000..d4b6ee2d --- /dev/null +++ b/test/RequestMessageTest.cc @@ -0,0 +1,67 @@ +#include "RequestMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class RequestMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(RequestMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(RequestMessageTest); + +void RequestMessageTest::testCreate() { + char msg[17]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, 6); + PeerMessageUtil::setIntParam(&msg[5], 12345); + PeerMessageUtil::setIntParam(&msg[9], 256); + PeerMessageUtil::setIntParam(&msg[13], 1024); + RequestMessage* pm = RequestMessage::create(&msg[4], 13); + CPPUNIT_ASSERT_EQUAL(6, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + CPPUNIT_ASSERT_EQUAL(256, pm->getBegin()); + CPPUNIT_ASSERT_EQUAL(1024, pm->getLength()); + + // case: payload size is wrong + try { + char msg[18]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 14, 6); + RequestMessage::create(&msg[4], 14); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[17]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 13, 7); + RequestMessage::create(&msg[4], 13); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void RequestMessageTest::testGetMessage() { + RequestMessage msg; + msg.setIndex(12345); + msg.setBegin(256); + msg.setLength(1024); + char data[17]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 13, 6); + PeerMessageUtil::setIntParam(&data[5], 12345); + PeerMessageUtil::setIntParam(&data[9], 256); + PeerMessageUtil::setIntParam(&data[13], 1024); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0); +} diff --git a/test/SuggestPieceMessageTest.cc b/test/SuggestPieceMessageTest.cc new file mode 100644 index 00000000..ce7ef9c3 --- /dev/null +++ b/test/SuggestPieceMessageTest.cc @@ -0,0 +1,59 @@ +#include "SuggestPieceMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class SuggestPieceMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(SuggestPieceMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(SuggestPieceMessageTest); + +void SuggestPieceMessageTest::testCreate() { + char msg[9]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, 13); + PeerMessageUtil::setIntParam(&msg[5], 12345); + SuggestPieceMessage* pm = SuggestPieceMessage::create(&msg[4], 5); + CPPUNIT_ASSERT_EQUAL(13, pm->getId()); + CPPUNIT_ASSERT_EQUAL(12345, pm->getIndex()); + + // case: payload size is wrong + try { + char msg[10]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 6, 13); + SuggestPieceMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[9]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 5, 14); + SuggestPieceMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void SuggestPieceMessageTest::testGetMessage() { + SuggestPieceMessage msg; + msg.setIndex(12345); + char data[9]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 5, 13); + PeerMessageUtil::setIntParam(&data[5], 12345); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 9) == 0); +} diff --git a/test/UnchokeMessageTest.cc b/test/UnchokeMessageTest.cc new file mode 100644 index 00000000..30f13e07 --- /dev/null +++ b/test/UnchokeMessageTest.cc @@ -0,0 +1,55 @@ +#include "UnchokeMessage.h" +#include "PeerMessageUtil.h" +#include + +using namespace std; + +class UnchokeMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(UnchokeMessageTest); + CPPUNIT_TEST(testCreate); + CPPUNIT_TEST(testGetMessage); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testCreate(); + void testGetMessage(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(UnchokeMessageTest); + +void UnchokeMessageTest::testCreate() { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 1); + PeerMessage* pm = UnchokeMessage::create(&msg[4], 1); + CPPUNIT_ASSERT_EQUAL(1, pm->getId()); + + // case: payload size is wrong + try { + char msg[6]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 2, 1); + UnchokeMessage::create(&msg[4], 2); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } + // case: id is wrong + try { + char msg[5]; + PeerMessageUtil::createPeerMessageString(msg, sizeof(msg), 1, 2); + UnchokeMessage::create(&msg[4], 1); + CPPUNIT_FAIL("exception must be threw."); + } catch(...) { + } +} + +void UnchokeMessageTest::testGetMessage() { + UnchokeMessage msg; + char data[5]; + PeerMessageUtil::createPeerMessageString(data, sizeof(data), 1, 1); + CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 5) == 0); +} diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 7e8003fc..e7960eaa 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -15,6 +15,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testStartsWith); // may be moved to other helper class in the future. CPPUNIT_TEST(testGetContentDispositionFilename); + CPPUNIT_TEST(testComputeFastSet); CPPUNIT_TEST_SUITE_END(); private: @@ -28,6 +29,7 @@ public: void testEndsWith(); void testReplace(); void testStartsWith(); + void testComputeFastSet(); // may be moved to other helper class in the future. void testGetContentDispositionFilename(); }; @@ -175,3 +177,34 @@ void UtilTest::testGetContentDispositionFilename() { string h4 = "attachment;"; CPPUNIT_ASSERT_EQUAL(string(""), Util::getContentDispositionFilename(h4)); } + +class Printer { +public: + template + void operator()(T t) { + cerr << t << ", "; + } +}; + +void UtilTest::testComputeFastSet() { + string ipaddr = "192.168.0.1"; + unsigned char infoHash[20]; + memset(infoHash, 0, sizeof(infoHash)); + infoHash[0] = 0xff; + + int pieces = 1000; + int fastSetSize = 10; + + Integers fastSet = Util::computeFastSet(ipaddr, infoHash, pieces, fastSetSize); + //for_each(fastSet.begin(), fastSet.end(), Printer()); + //cerr << endl; + int ans1[] = { 686, 459, 278, 200, 404, 834, 64, 203, 760, 950 }; + Integers ansSet1(&ans1[0], &ans1[10]); + CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet1.begin())); + + ipaddr = "10.0.0.1"; + fastSet = Util::computeFastSet(ipaddr, infoHash, pieces, fastSetSize); + int ans2[] = { 568, 188, 466, 452, 550, 662, 109, 226, 398, 11 }; + Integers ansSet2(&ans2[0], &ans2[10]); + CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet2.begin())); +}