diff --git a/ChangeLog b/ChangeLog index 06dc853e..1ab6f77d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,217 @@ +2007-01-11 Tatsuhiro Tsujikawa + + To add RecoverableException, FatalException: + + * src/AbstractCommand.cc + (onAbort): Exception -> RecoverableException + * src/PeerAbstractCommand.h + (RecoverableException.h): New include. + (onAbort): Exception -> RecoverableException. + * src/PeerInteractionCommand.cc + (onAbort): Exception -> RecoverableException. + * src/PeerAbstractCommand.cc + (execute): Exception -> RecoverableException. + (onAbort): Exception -> RecoverableException. + * src/TorrentRequestInfo.cc + (execute): Exception -> RecoverableException. + * src/MetalinkRequestInfo.cc + (execute): Exception -> RecoverableException. + * src/MetaFileUtil.cc: RecoverableException. + * src/AbstractCommand.h + (onAbort): Exception -> RecoverableException. + * src/DlRetryEx.h: Exception -> RecoverableException. + * src/DlAbortEx.h: Exception -> RecoverableException. + * src/PeerListenCommand.cc: Exception -> RecoverableException. + * src/Util.cc: Exception -> RecoverableException. + * src/DefauldDiskWriter.cc: Exception -> RecoverableException. + * src/TrackerUpdateCommand.cc: Exception -> RecoverableException. + * src/UrlRequestInfo.cc: Exception -> RecoverableException. + + To make ID static const int + + * src/BtInterestedMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtPieceMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtChokeMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtHaveAllMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtKeepAliveMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtHandshakeMessage.h + (ID): New variable. + (getId): Made non-const. + * src/BtSuggestPieceMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtPortMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/AbstractBtMessage.h + (id): Removed. + (AbstractBtMessage): Removed id. + (getId): Removed. + * src/BtHaveMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtAllowedFastMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtCancelMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtNotInterestedMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtChokeMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtRejectMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtBitfieldMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtUnchokeMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtRequestMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + * src/BtHaveMessage.h + (ID_t): Removed. + (ID): New variable. + (getId): Made non-const. + + To add --force-truncate command-line option and a check whether + the file already exists: + + * src/DirectDiskAdaptor.h + (getFilePath): Made virtual public. + * src/MultiDiskAdaptor.h + (File.h): New include. + (DiskWriterEntry::fileEntry): Made private. + (DiskWriterEntry::fileExists): New function. + (DiskWriterEntry::getFileEntry): New function. + (fileExists): New function. + (getFilePath): New function. + * src/TorrentRequestInfo.cc + (FatalException.h): New include. + (message.h): New include. + (RecoverableException.h): New include. + (execute): Added a check whether file is already exists or not. + * src/DiskAdaptor.h + (fileExists): New function. + (getFilePath): New function. + * src/main.cc + (showUsage): Added an explanation of --force-truncate command-line + option. + (main): Added --force-truncate command-line option. + * src/Exception.h + (setMsg): buf[256] -> buf[1024] + * src/CopyDiskWriter.h + (getFilePath): Made public virtual. + * src/MultiDiskAdaptor.cc: fileEntry -> getFileEntry() + (fileExists): New function. + * src/DownloadEngineFactory.cc + (newTorrentConsoleEngine): Don't open file here. + * src/message.h + (EX_FILE_ALREADY_EXISTS): New definition. + * src/prefs.h + (PREF_FOECE_TRUNCATE): New definition. + * src/HttpResponseCommand.cc + (handleDefaultEncoding): Added a check whether the file already exists. + * src/SegmentMan.h + (fileExists): New function. + (shouldCancelDownloadForSafety): New function. + * src/FtpNegotiateCommand.cc + (recvSize): Added a check whether the file already exists. + * src/AbstractSingleDiskAdaptor.cc + (File.h): New include. + (fileExists): New function. + * src/AbstractSingleDiskAdaptor.h + (getFilePath): Removed. + (fileExists): New function. + * src/SegmentMan.cc + (fileExists): New function. + (shouldCancelDownloadForSafety): New function. + + To fix regression bug in torrent downloading: + + * src/DefaultBtRequestFactory.cc + (doChokedAction): New function. + * src/DefaultBtRequestFactory.h + (doChokedAction): New function. + * src/DefaultBtMessageDispatcher.cc + (doChokedAction): Do not delete request if its target is in allowed + fast set. + * src/DefaultBtInteractive.cc + (doPostHandshakeProcessing): Added a call to sendPendingMessage(). + (sendKeepAlive): Send keep alive message even if the outgoing message + queue is not empty. + (decideInterest): Simplified the code. + (fillPiece): Remove a call to dispatcher->doChokedAction() because + it is already called when BtChokeMessage is received from a peer. + * src/BtRequestFactory.h + (doChokedAction): New function. + + To clean up code: + + * src/PeerInteractionCommand.h + (executeInternal): Added virtual keyword explicitly. + (prepareForRetry): Added virtual keyword explicitly. + (prepareForNextPeer): Added virtual keyword explicitly. + (onAbort): Added virtual keyword explicitly. + + * src/RequestSlot.cc + (isTimeout): Use Time::elapsed() instead of differenceInMillis(). + + * src/BtPieceMessage.cc + (doReceivedAction): Added a debug log of piece's bitfield. + * src/Piece.h + (getBitfieldLength): New function. + + * src/ByteArrayDiskWriter.cc + (clear): Added buf = 0 to avoid double free corruption. + + * src/FileAllocator.cc + (allocate): Fixed an assignment of fileAllocationMonitor->currentValue. + Added cp.reset(). + + * src/BitfieldMan.h + (operator=): Rewritten. + * src/BitfieldMan.cc + (BitfieldMan): Initialized bitfield, useBitfield. + + * src/PeerConnection.cc + (receiveMessage): Added a call to socket->readable() after getting + message length to avoid possible EOF. + + * src/Util.cc + (torrentUrlencode): Fixed an encodeing bug. BUG#1629912 + 2007-01-08 Tatsuhiro Tsujikawa To add an ability to pre-allocate file space: diff --git a/TODO b/TODO index 50b02c74..079d77d3 100644 --- a/TODO +++ b/TODO @@ -21,9 +21,7 @@ * Add the message like "you can resume the transfer by invoking aria2 again" when the download stops. * Add --bt-timeout command line option. * Fix DefaultBtProgressInfoFile.cc: save(), load() -* Add a feature that if any existing file is detected, then -do not start downloading and print some useful message to the user. -* Fix Segfaults in BitfieldMan.cc:71 -https://sourceforge.net/tracker/index.php?func=detail&aid=1606060&group_id=159897&atid=813673 -* int32_t * remove blockIndex +* Add piece hash checking +* Stop download after selective download completes +* Add an ability of seeding diff --git a/src/AbstractBtMessage.h b/src/AbstractBtMessage.h index 918cd9de..52cb88f0 100644 --- a/src/AbstractBtMessage.h +++ b/src/AbstractBtMessage.h @@ -50,7 +50,6 @@ protected: bool sendingInProgress; bool invalidate; bool uploading; - int32_t id; int32_t cuid; BtContextHandle btContext; @@ -66,7 +65,6 @@ public: AbstractBtMessage():sendingInProgress(false), invalidate(false), uploading(false), - id(0), cuid(0), btContext(0), pieceStorage(0), @@ -100,10 +98,6 @@ public: this->uploading = uploading; } - virtual uint8_t getId() { - return id; - } - int32_t getCuid() const { return cuid; } diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index fb2cb4c7..45f17bff 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -146,7 +146,7 @@ bool AbstractCommand::prepareForRetry(int wait) { return true; } -void AbstractCommand::onAbort(Exception* ex) { +void AbstractCommand::onAbort(RecoverableException* ex) { logger->debug(MSG_UNREGISTER_CUID, cuid); //e->segmentMan->unregisterId(cuid); e->segmentMan->cancelSegment(cuid); diff --git a/src/AbstractCommand.h b/src/AbstractCommand.h index c4f115cc..4b003e4f 100644 --- a/src/AbstractCommand.h +++ b/src/AbstractCommand.h @@ -40,6 +40,7 @@ #include "DownloadEngine.h" #include "SegmentMan.h" #include "TimeA2.h" +#include "RecoverableException.h" class AbstractCommand : public Command { private: @@ -52,7 +53,7 @@ protected: void tryReserved(); virtual bool prepareForRetry(int wait); - virtual void onAbort(Exception* ex); + virtual void onAbort(RecoverableException* ex); virtual bool executeInternal(Segment& segment) = 0; void setReadCheckSocket(const SocketHandle& socket); diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc index 5691fdf8..41b6c4b4 100644 --- a/src/AbstractSingleDiskAdaptor.cc +++ b/src/AbstractSingleDiskAdaptor.cc @@ -33,6 +33,7 @@ */ /* copyright --> */ #include "AbstractSingleDiskAdaptor.h" +#include "File.h" void AbstractSingleDiskAdaptor::initAndOpenFile() { diskWriter->initAndOpenFile(getFilePath(), totalLength); @@ -61,3 +62,8 @@ int AbstractSingleDiskAdaptor::readData(unsigned char* data, uint32_t len, int64 string AbstractSingleDiskAdaptor::sha1Sum(int64_t offset, uint64_t length) { return diskWriter->sha1Sum(offset, length); } + +bool AbstractSingleDiskAdaptor::fileExists() +{ + return File(getFilePath()).exists(); +} diff --git a/src/AbstractSingleDiskAdaptor.h b/src/AbstractSingleDiskAdaptor.h index 17211c61..db67d2ef 100644 --- a/src/AbstractSingleDiskAdaptor.h +++ b/src/AbstractSingleDiskAdaptor.h @@ -42,8 +42,6 @@ class AbstractSingleDiskAdaptor : public DiskAdaptor { protected: DiskWriterHandle diskWriter; uint64_t totalLength; - - virtual string getFilePath() = 0; public: AbstractSingleDiskAdaptor():diskWriter(0), totalLength(0) {} @@ -63,7 +61,9 @@ public: virtual int readData(unsigned char* data, uint32_t len, int64_t offset); virtual string sha1Sum(int64_t offset, uint64_t length); - + + virtual bool fileExists(); + void setDiskWriter(const DiskWriterHandle diskWriter) { this->diskWriter = diskWriter; } diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index 64e4dc60..c287fdaf 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -37,8 +37,14 @@ #include BitfieldMan::BitfieldMan(uint32_t blockLength, uint64_t totalLength) - :blockLength(blockLength), totalLength(totalLength), filterBitfield(0), - filterEnabled(false), randomizer(0) { + :blockLength(blockLength), + totalLength(totalLength), + bitfield(0), + useBitfield(0), + filterBitfield(0), + filterEnabled(false), + randomizer(0) +{ if(blockLength > 0 && totalLength > 0) { blocks = totalLength/blockLength+(totalLength%blockLength ? 1 : 0); bitfieldLength = blocks/8+(blocks%8 ? 1 : 0); @@ -49,7 +55,13 @@ BitfieldMan::BitfieldMan(uint32_t blockLength, uint64_t totalLength) } } -BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan):randomizer(0) { +BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan) + :bitfield(0), + useBitfield(0), + filterBitfield(0), + filterEnabled(false), + randomizer(0) +{ blockLength = bitfieldMan.blockLength; totalLength = bitfieldMan.totalLength; blocks = bitfieldMan.blocks; @@ -59,7 +71,7 @@ BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan):randomizer(0) { memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength); memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength); filterEnabled = bitfieldMan.filterEnabled; - if(bitfieldMan.filterBitfield) { + if(filterBitfield) { filterBitfield = new unsigned char[bitfieldLength]; memcpy(filterBitfield, bitfieldMan.filterBitfield, bitfieldLength); } else { diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h index 5b24e42e..c78065b4 100644 --- a/src/BitfieldMan.h +++ b/src/BitfieldMan.h @@ -73,26 +73,24 @@ public: if(this != &bitfieldMan) { blockLength = bitfieldMan.blockLength; totalLength = bitfieldMan.totalLength; - if(bitfieldLength != bitfieldMan.bitfieldLength) { - delete [] bitfield; - delete [] useBitfield; - bitfield = new unsigned char[bitfieldMan.bitfieldLength]; - useBitfield = new unsigned char[bitfieldMan.bitfieldLength]; - } blocks = bitfieldMan.blocks; bitfieldLength = bitfieldMan.bitfieldLength; - memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength); - memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength); filterEnabled = bitfieldMan.filterEnabled; - if(bitfieldLength != bitfieldMan.bitfieldLength) { - delete [] filterBitfield; - filterBitfield = 0; - } - if(bitfieldMan.filterBitfield) { - if(!filterBitfield) { - filterBitfield = new unsigned char[bitfieldLength]; - } + + delete [] bitfield; + bitfield = new unsigned char[bitfieldLength]; + memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength); + + delete [] useBitfield; + useBitfield = new unsigned char[bitfieldLength]; + memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength); + + delete [] filterBitfield; + if(filterEnabled) { + filterBitfield = new unsigned char[bitfieldLength]; memcpy(filterBitfield, bitfieldMan.filterBitfield, bitfieldLength); + } else { + filterBitfield = 0; } } return *this; diff --git a/src/BtAllowedFastMessage.h b/src/BtAllowedFastMessage.h index 75b03460..36b7b92e 100644 --- a/src/BtAllowedFastMessage.h +++ b/src/BtAllowedFastMessage.h @@ -57,9 +57,7 @@ public: delete [] msg; } - enum ID_t { - ID = 17 - }; + static const uint8_t ID = 17; void setIndex(int32_t index) { this->index = index; @@ -68,7 +66,7 @@ public: static BtAllowedFastMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtBitfieldMessage.h b/src/BtBitfieldMessage.h index 64bbf209..e047a439 100644 --- a/src/BtBitfieldMessage.h +++ b/src/BtBitfieldMessage.h @@ -72,9 +72,7 @@ public: delete [] msg; } - enum ID_t { - ID = 5 - }; + static const uint8_t ID = 5; void setBitfield(const unsigned char* bitfield, uint32_t bitfieldLength); @@ -84,7 +82,7 @@ public: static BtBitfieldMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtCancelMessage.h b/src/BtCancelMessage.h index 6416408a..670130d8 100644 --- a/src/BtCancelMessage.h +++ b/src/BtCancelMessage.h @@ -61,9 +61,7 @@ public: delete [] msg; } - enum ID_t { - ID = 8 - }; + static const uint8_t ID = 8; int32_t getIndex() const { return index; } @@ -79,7 +77,7 @@ public: static BtCancelMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtChokeMessage.cc b/src/BtChokeMessage.cc index 54e23974..61bd9372 100644 --- a/src/BtChokeMessage.cc +++ b/src/BtChokeMessage.cc @@ -52,6 +52,7 @@ BtChokeMessageHandle BtChokeMessage::create(const unsigned char* data, uint32_t void BtChokeMessage::doReceivedAction() { peer->peerChoking = true; BT_MESSAGE_DISPATCHER(btContext, peer)->doChokedAction(); + BT_REQUEST_FACTORY(btContext, peer)->doChokedAction(); } bool BtChokeMessage::sendPredicate() const { diff --git a/src/BtChokeMessage.h b/src/BtChokeMessage.h index 8b06c2b8..c4628ffd 100644 --- a/src/BtChokeMessage.h +++ b/src/BtChokeMessage.h @@ -53,11 +53,9 @@ public: delete [] msg; } - enum ID_t { - ID = 0 - }; + static const uint8_t ID = 0; - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtHandshakeMessage.h b/src/BtHandshakeMessage.h index 21f05cee..cb40b6d5 100644 --- a/src/BtHandshakeMessage.h +++ b/src/BtHandshakeMessage.h @@ -73,7 +73,9 @@ public: delete [] peerId; } - virtual uint8_t getId() const { return UINT8_MAX; } + static const uint8_t ID = UINT8_MAX; + + virtual uint8_t getId() { return ID; } virtual void doReceivedAction() {}; diff --git a/src/BtHaveAllMessage.h b/src/BtHaveAllMessage.h index 9afe25a3..767b402e 100644 --- a/src/BtHaveAllMessage.h +++ b/src/BtHaveAllMessage.h @@ -53,13 +53,11 @@ public: delete [] msg; } - enum ID_t { - ID = 14 - }; + static const uint8_t ID = 14; static BtHaveAllMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtHaveMessage.h b/src/BtHaveMessage.h index 2209ae0d..bb15f4d9 100644 --- a/src/BtHaveMessage.h +++ b/src/BtHaveMessage.h @@ -53,9 +53,7 @@ public: delete [] msg; } - enum ID_t { - ID = 4 - }; + static const uint8_t ID = 4; void setIndex(int32_t index) { this->index = index; @@ -65,7 +63,7 @@ public: static BtHaveMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtHaveNoneMessage.h b/src/BtHaveNoneMessage.h index 0fbf3be9..94e8eb55 100644 --- a/src/BtHaveNoneMessage.h +++ b/src/BtHaveNoneMessage.h @@ -53,13 +53,11 @@ public: delete [] msg; } - enum ID_t { - ID = 15 - }; - + static const uint8_t ID = 15; + static BtHaveNoneMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtInterestedMessage.h b/src/BtInterestedMessage.h index 30e200d4..7bf84224 100644 --- a/src/BtInterestedMessage.h +++ b/src/BtInterestedMessage.h @@ -53,13 +53,11 @@ public: delete [] msg; } - enum ID_t { - ID = 2 - }; + static const uint8_t ID = 2; static BtInterestedMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtKeepAliveMessage.h b/src/BtKeepAliveMessage.h index f9080741..fea385ee 100644 --- a/src/BtKeepAliveMessage.h +++ b/src/BtKeepAliveMessage.h @@ -53,11 +53,9 @@ public: delete [] msg; } - enum ID_t { - ID = 99 - }; + static const uint8_t ID = 99; - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction() {} diff --git a/src/BtNotInterestedMessage.h b/src/BtNotInterestedMessage.h index 35d6372a..7cd604c7 100644 --- a/src/BtNotInterestedMessage.h +++ b/src/BtNotInterestedMessage.h @@ -53,13 +53,11 @@ public: delete [] msg; } - enum ID_t { - ID = 3 - }; + static const uint8_t ID = 3; static BtNotInterestedMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtPieceMessage.cc b/src/BtPieceMessage.cc index 4f62f663..b6814fa8 100644 --- a/src/BtPieceMessage.cc +++ b/src/BtPieceMessage.cc @@ -81,6 +81,10 @@ void BtPieceMessage::doReceivedAction() { blockLength, offset); piece->completeBlock(slot.getBlockIndex()); + logger->debug("CUID#%d - Piece bitfield %s", + cuid, + Util::toHex(piece->getBitfield(), + piece->getBitfieldLength()).c_str()); BT_MESSAGE_DISPATCHER(btContext, peer)->removeOutstandingRequest(slot); if(piece->pieceComplete()) { if(checkPieceHash(piece)) { diff --git a/src/BtPieceMessage.h b/src/BtPieceMessage.h index c1bdf549..65e6b048 100644 --- a/src/BtPieceMessage.h +++ b/src/BtPieceMessage.h @@ -112,9 +112,7 @@ public: delete [] block; } - enum ID_t { - ID = 7 - }; + static const uint8_t ID = 7; int32_t getIndex() const { return index; } @@ -134,7 +132,7 @@ public: static BtPieceMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtPortMessage.h b/src/BtPortMessage.h index 6a487b82..f711ddfd 100644 --- a/src/BtPortMessage.h +++ b/src/BtPortMessage.h @@ -49,15 +49,13 @@ public: virtual ~BtPortMessage() {} - enum ID_t { - ID = 9 - }; + static const uint8_t ID = 9; uint16_t getPort() const { return port; } void setPort(uint16_t port) { this->port = port; } - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } static BtPortMessageHandle create(const unsigned char* data, uint32_t dataLength); diff --git a/src/BtRejectMessage.h b/src/BtRejectMessage.h index f79ee9dd..a7afbbf1 100644 --- a/src/BtRejectMessage.h +++ b/src/BtRejectMessage.h @@ -59,9 +59,7 @@ public: delete [] msg; } - enum ID_t { - ID = 16 - }; + static const uint8_t ID = 16; int32_t getIndex() const { return index; } void setIndex(int32_t index) { this->index = index; } @@ -74,7 +72,7 @@ public: static BtRejectMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtRequestFactory.h b/src/BtRequestFactory.h index ff7d281f..0f33ece9 100644 --- a/src/BtRequestFactory.h +++ b/src/BtRequestFactory.h @@ -53,6 +53,8 @@ public: virtual void removeCompletedPiece() = 0; + virtual void doChokedAction() = 0; + /** * Creates RequestMessage objects associated to the pieces added by * addTargetPiece() and returns them. diff --git a/src/BtRequestMessage.h b/src/BtRequestMessage.h index 100c8235..dfdbdc28 100644 --- a/src/BtRequestMessage.h +++ b/src/BtRequestMessage.h @@ -84,9 +84,7 @@ public: delete [] msg; } - enum ID_t { - ID = 6 - }; + static const uint8_t ID = 6; int32_t getIndex() const { return index; } void setIndex(int32_t index) { this->index = index; } @@ -102,7 +100,7 @@ public: static BtRequestMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/BtSuggestPieceMessage.h b/src/BtSuggestPieceMessage.h index 00a906af..049f7234 100644 --- a/src/BtSuggestPieceMessage.h +++ b/src/BtSuggestPieceMessage.h @@ -53,9 +53,7 @@ public: delete [] msg; } - enum ID_t { - ID = 13 - }; + static const uint8_t ID = 13; void setIndex(int32_t index) { this->index = index; @@ -65,7 +63,7 @@ public: static BtSuggestPieceMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction() { // TODO Current implementation ignores this message. diff --git a/src/BtUnchokeMessage.h b/src/BtUnchokeMessage.h index 06a4f82f..8ee4675c 100644 --- a/src/BtUnchokeMessage.h +++ b/src/BtUnchokeMessage.h @@ -52,13 +52,11 @@ public: delete [] msg; } - enum ID_t { - ID = 1 - }; + static const uint8_t ID = 1; static BtUnchokeMessageHandle create(const unsigned char* data, uint32_t dataLength); - virtual uint8_t getId() const { return ID; } + virtual uint8_t getId() { return ID; } virtual void doReceivedAction(); diff --git a/src/ByteArrayDiskWriter.cc b/src/ByteArrayDiskWriter.cc index 63236014..4134d2f5 100644 --- a/src/ByteArrayDiskWriter.cc +++ b/src/ByteArrayDiskWriter.cc @@ -44,6 +44,7 @@ ByteArrayDiskWriter::~ByteArrayDiskWriter() { void ByteArrayDiskWriter::clear() { delete [] buf; + buf = 0; } void ByteArrayDiskWriter::init() { diff --git a/src/CompactTrackerResponseProcessor.cc b/src/CompactTrackerResponseProcessor.cc deleted file mode 100644 index 6cfe31f5..00000000 --- a/src/CompactTrackerResponseProcessor.cc +++ /dev/null @@ -1,149 +0,0 @@ -/* */ -#include "CompactTrackerResponseProcessor.h" -#include "LogFactory.h" -#include "TorrentDownloadEngine.h" -#include "MetaFileUtil.h" -#include "DlAbortEx.h" -#include "message.h" -#include "PeerInitiateConnectionCommand.h" -#include - -CompactTrackerResponseProcessor::CompactTrackerResponseProcessor(ByteArrayDiskWriter* diskWriter, TorrentDownloadEngine* e, Request* req): - diskWriter(diskWriter), - e(e), - req(req) { - logger = LogFactory::getInstance(); -} - -CompactTrackerResponseProcessor::~CompactTrackerResponseProcessor() {} - -void CompactTrackerResponseProcessor::resetTrackerResponse() { - if(e->segmentMan->finished()) { - diskWriter->reset(); - e->segmentMan->init(); - } -} - -void CompactTrackerResponseProcessor::execute() { - MetaEntry* entry = NULL; - try { - entry = MetaFileUtil::bdecoding(diskWriter->getByteArray(), - diskWriter->getByteArrayLength()); - Dictionary* response = (Dictionary*)entry; - Data* failureReason = (Data*)response->get("failure reason"); - if(failureReason != NULL) { - throw new DlAbortEx("Tracker returned failure reason: %s", failureReason->toString().c_str()); - } - Data* warningMessage = (Data*)response->get("warning message"); - if(warningMessage != NULL) { - logger->warn(MSG_TRACKER_WARNING_MESSAGE, warningMessage->toString().c_str()); - } - 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()); - } - Data* interval = (Data*)response->get("interval"); - if(interval != NULL) { - e->torrentMan->interval = interval->toInt(); - logger->debug("interval:%d", 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); - } - if(e->torrentMan->minInterval > e->torrentMan->interval) { - e->torrentMan->minInterval = e->torrentMan->interval; - } - Data* complete = (Data*)response->get("complete"); - if(complete != NULL) { - e->torrentMan->complete = complete->toInt(); - logger->debug("complete:%d", e->torrentMan->complete); - } - Data* incomplete = (Data*)response->get("incomplete"); - if(incomplete != NULL) { - e->torrentMan->incomplete = incomplete->toInt(); - logger->debug("incomplete:%d", e->torrentMan->incomplete); - } - Data* peers = (Data*)response->get("peers"); - if(peers != NULL) { - for(int i = 0; i < peers->getLen(); i += 6) { - unsigned int ipaddr1 = (unsigned char)*(peers->getData()+i); - unsigned int ipaddr2 = (unsigned char)*(peers->getData()+i+1); - unsigned int ipaddr3 = (unsigned char)*(peers->getData()+i+2); - unsigned int ipaddr4 = (unsigned char)*(peers->getData()+i+3); - unsigned int port = ntohs(*(unsigned short int*)(peers->getData()+i+4)); - char ipaddr[16]; - - snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", - ipaddr1, ipaddr2, ipaddr3, ipaddr4); - 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); - } else { - delete peer; - } - } - } else { - logger->info("no peer list received."); - } - while(e->torrentMan->isPeerAvailable() && - e->torrentMan->connections < MAX_PEER_UPDATE) { - Peer* peer = e->torrentMan->getPeer(); - int newCuid = e->torrentMan->getNewCuid(); - peer->cuid = newCuid; - PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e); - e->commands.push(command); - logger->debug("adding new command CUID#%d", newCuid); - } - if(req->getTrackerEvent() == Request::STARTED) { - req->setTrackerEvent(Request::AUTO); - } - } catch(Exception* err) { - logger->error("Error occurred while processing tracker response.", err); - delete(err); - } - if(entry != NULL) { - delete entry; - } - e->torrentMan->trackers = 0; -} - -bool CompactTrackerResponseProcessor::isFeeded() const { - return e->segmentMan->finished(); -} diff --git a/src/CopyDiskAdaptor.h b/src/CopyDiskAdaptor.h index 84acd3c2..af6effdf 100644 --- a/src/CopyDiskAdaptor.h +++ b/src/CopyDiskAdaptor.h @@ -43,13 +43,13 @@ private: string topDir; void fixFilename(); -protected: - virtual string getFilePath(); public: CopyDiskAdaptor() {} virtual ~CopyDiskAdaptor() {} + virtual string getFilePath(); + virtual void onDownloadComplete(); // tempFilename is relative to storeDir diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc index f3812b01..03c5e61c 100644 --- a/src/DefaultBtInteractive.cc +++ b/src/DefaultBtInteractive.cc @@ -75,6 +75,7 @@ void DefaultBtInteractive::doPostHandshakeProcessing() { floodingCheckPoint.reset(); addBitfieldMessageToQueue(); addAllowedFastMessageToQueue(); + sendPendingMessage(); } void DefaultBtInteractive::addBitfieldMessageToQueue() { @@ -142,10 +143,8 @@ void DefaultBtInteractive::checkHave() { void DefaultBtInteractive::sendKeepAlive() { if(keepAliveCheckPoint.elapsed(option->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL))) { - if(dispatcher->countMessageInQueue() == 0) { - dispatcher->addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->createKeepAliveMessage()); - dispatcher->sendMessages(); - } + dispatcher->addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)->createKeepAliveMessage()); + dispatcher->sendMessages(); keepAliveCheckPoint.reset(); } } @@ -187,27 +186,26 @@ void DefaultBtInteractive::receiveMessages() { } void DefaultBtInteractive::decideInterest() { - if(!pieceStorage->hasMissingPiece(peer)) { - if(peer->amInterested) { - logger->debug("CUID#%d - Not interested in the peer", cuid); - dispatcher-> - addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)-> - createNotInterestedMessage()); - } - } else { + if(pieceStorage->hasMissingPiece(peer)) { if(!peer->amInterested) { logger->debug("CUID#%d - Interested in the peer", cuid); dispatcher-> addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)-> createInterestedMessage()); } + } else { + if(peer->amInterested) { + logger->debug("CUID#%d - Not interested in the peer", cuid); + dispatcher-> + addMessageToQueue(BT_MESSAGE_FACTORY(btContext, peer)-> + createNotInterestedMessage()); + } } } void DefaultBtInteractive::fillPiece(int maxPieceNum) { if(pieceStorage->hasMissingPiece(peer)) { if(peer->peerChoking) { - dispatcher->doChokedAction(); if(peer->isFastExtensionEnabled()) { while(btRequestFactory->countTargetPiece() < maxPieceNum) { PieceHandle piece = pieceStorage->getMissingFastPiece(peer); diff --git a/src/DefaultBtMessageDispatcher.cc b/src/DefaultBtMessageDispatcher.cc index 2a47f21f..33cfe3f1 100644 --- a/src/DefaultBtMessageDispatcher.cc +++ b/src/DefaultBtMessageDispatcher.cc @@ -129,14 +129,18 @@ void DefaultBtMessageDispatcher::doChokedAction() for(RequestSlots::iterator itr = requestSlots.begin(); itr != requestSlots.end();) { RequestSlot& slot = *itr; - logger->debug("CUID#%d - Deleting request slot index=%d, blockIndex=%d" - " because localhost got choked.", - cuid, - slot.getIndex(), - slot.getBlockIndex()); - PieceHandle piece = pieceStorage->getPiece(slot.getIndex()); - piece->cancelBlock(slot.getBlockIndex()); - itr = requestSlots.erase(itr); + if(peer->isInPeerAllowedIndexSet(slot.getIndex())) { + itr++; + } else { + logger->debug("CUID#%d - Deleting request slot index=%d, blockIndex=%d" + " because localhost got choked.", + cuid, + slot.getIndex(), + slot.getBlockIndex()); + PieceHandle piece = pieceStorage->getPiece(slot.getIndex()); + piece->cancelBlock(slot.getBlockIndex()); + itr = requestSlots.erase(itr); + } } BtChokedEventHandle event = new BtChokedEvent(); diff --git a/src/DefaultBtRequestFactory.cc b/src/DefaultBtRequestFactory.cc index 58effe0c..e52678b2 100644 --- a/src/DefaultBtRequestFactory.cc +++ b/src/DefaultBtRequestFactory.cc @@ -54,6 +54,20 @@ void DefaultBtRequestFactory::removeTargetPiece(const PieceHandle& piece) { pieceStorage->cancelPiece(piece); } +void DefaultBtRequestFactory::doChokedAction() +{ + Pieces temp; + for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) { + PieceHandle& piece = *itr; + if(peer->isInPeerAllowedIndexSet(piece->getIndex())) { + temp.push_back(piece); + } else { + pieceStorage->cancelPiece(*itr); + } + } + pieces = temp; +} + void DefaultBtRequestFactory::removeAllTargetPiece() { for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) { dispatcher->doAbortOutstandingRequestAction(*itr); diff --git a/src/DefaultBtRequestFactory.h b/src/DefaultBtRequestFactory.h index b6c7e8de..62f26a55 100644 --- a/src/DefaultBtRequestFactory.h +++ b/src/DefaultBtRequestFactory.h @@ -82,6 +82,8 @@ public: virtual void removeCompletedPiece(); + virtual void doChokedAction(); + virtual BtMessages createRequestMessages(uint32_t max); virtual BtMessages createRequestMessagesOnEndGame(uint32_t max); diff --git a/src/DefaultDiskWriter.cc b/src/DefaultDiskWriter.cc index 6301e745..d5f4a915 100644 --- a/src/DefaultDiskWriter.cc +++ b/src/DefaultDiskWriter.cc @@ -60,7 +60,7 @@ void DefaultDiskWriter::initAndOpenFile(const string& filename, fileAllocator->allocate(fd, totalLength); } } - } catch(Exception *e) { + } catch(RecoverableException *e) { throw new DlAbortEx(e, EX_FILE_WRITE, filename.c_str(), strerror(errno)); } } diff --git a/src/DirectDiskAdaptor.h b/src/DirectDiskAdaptor.h index ea4ce849..16b01f36 100644 --- a/src/DirectDiskAdaptor.h +++ b/src/DirectDiskAdaptor.h @@ -38,12 +38,12 @@ #include "AbstractSingleDiskAdaptor.h" class DirectDiskAdaptor : public AbstractSingleDiskAdaptor { -protected: - virtual string getFilePath(); public: DirectDiskAdaptor() {}; virtual ~DirectDiskAdaptor() {}; + virtual string getFilePath(); + virtual void onDownloadComplete(); }; diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index 2b9182e7..8ba6e66b 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -64,6 +64,10 @@ public: virtual void onDownloadComplete() = 0; + virtual bool fileExists() = 0; + + virtual string getFilePath() = 0; + void setFileEntries(const FileEntries& fileEntries) { this->fileEntries = fileEntries; } diff --git a/src/DlAbortEx.h b/src/DlAbortEx.h index f818d68a..05f0ec59 100644 --- a/src/DlAbortEx.h +++ b/src/DlAbortEx.h @@ -34,20 +34,20 @@ /* copyright --> */ #ifndef _D_DL_ABORT_EX_H_ #define _D_DL_ABORT_EX_H_ -#include "Exception.h" +#include "RecoverableException.h" -class DlAbortEx:public Exception { +class DlAbortEx : public RecoverableException { public: - DlAbortEx(Exception* cause = 0):Exception(cause) {} + DlAbortEx(Exception* cause = 0):RecoverableException(cause) {} - DlAbortEx(const char* msg, ...):Exception() { + DlAbortEx(const char* msg, ...) { va_list ap; va_start(ap, msg); setMsg(string(msg), ap); va_end(ap); } - DlAbortEx(Exception* cause, const char* msg, ...):Exception(cause) { + DlAbortEx(Exception* cause, const char* msg, ...):RecoverableException(cause) { va_list ap; va_start(ap, msg); setMsg(string(msg), ap); diff --git a/src/DlRetryEx.h b/src/DlRetryEx.h index d3671a02..b4d736bb 100644 --- a/src/DlRetryEx.h +++ b/src/DlRetryEx.h @@ -34,20 +34,20 @@ /* copyright --> */ #ifndef _D_DL_RETRY_EX_H_ #define _D_DL_RETRY_EX_H_ -#include "Exception.h" +#include "RecoverableException.h" -class DlRetryEx:public Exception { +class DlRetryEx : public RecoverableException { public: - DlRetryEx(Exception* cause = 0):Exception(cause) {} + DlRetryEx(Exception* cause = 0):RecoverableException(cause) {} - DlRetryEx(const char* msg, ...):Exception() { + DlRetryEx(const char* msg, ...) { va_list ap; va_start(ap, msg); setMsg(msg, ap); va_end(ap); } - DlRetryEx(Exception* cause, const char* msg, ...):Exception(cause) { + DlRetryEx(Exception* cause, const char* msg, ...):RecoverableException(cause) { va_list ap; va_start(ap, msg); setMsg(msg, ap); diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc index bdc93733..01ac5b91 100644 --- a/src/DownloadEngineFactory.cc +++ b/src/DownloadEngineFactory.cc @@ -130,13 +130,6 @@ DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext, te->setBtContext(btContext); // initialize file storage pieceStorage->initStorage(); - if(btProgressInfoFile->exists()) { - // load .aria2 file if it exists. - btProgressInfoFile->load(); - pieceStorage->getDiskAdaptor()->openExistingFile(); - } else { - pieceStorage->getDiskAdaptor()->initAndOpenFile(); - } Integers selectIndexes; Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes); diff --git a/src/Exception.h b/src/Exception.h index a584fb91..2522051a 100644 --- a/src/Exception.h +++ b/src/Exception.h @@ -49,7 +49,7 @@ protected: Exception* cause; void setMsg(const string& msgsrc, va_list ap) { - char buf[256]; + char buf[1024]; vsnprintf(buf, sizeof(buf), msgsrc.c_str(), ap); msg = buf; } diff --git a/src/FatalException.h b/src/FatalException.h new file mode 100644 index 00000000..9d468adc --- /dev/null +++ b/src/FatalException.h @@ -0,0 +1,58 @@ +/* */ +#ifndef _D_FATAL_EXCEPTION_H_ +#define _D_FATAL_EXCEPTION_H_ +#include "Exception.h" + +class FatalException : public Exception { +public: + FatalException(Exception* cause = 0):Exception(cause) {} + + FatalException(const char* msg, ...):Exception() { + va_list ap; + va_start(ap, msg); + setMsg(string(msg), ap); + va_end(ap); + } + + FatalException(Exception* cause, const char* msg, ...):Exception(cause) { + va_list ap; + va_start(ap, msg); + setMsg(string(msg), ap); + va_end(ap); + } +}; + +#endif // _D_FATAL_EXCEPTION_EX_H_ diff --git a/src/FileAllocator.cc b/src/FileAllocator.cc index b76af6a9..0e52e2ea 100644 --- a/src/FileAllocator.cc +++ b/src/FileAllocator.cc @@ -59,8 +59,9 @@ void FileAllocator::allocate(int fd, uint64_t totalLength) throw new DlAbortEx("Allocation failed: %s", strerror(errno)); } if(cp.elapsedInMillis(500)) { - fileAllocationMonitor->setCurrentValue(x*bufSize); + fileAllocationMonitor->setCurrentValue(i*bufSize); fileAllocationMonitor->showProgress(); + cp.reset(); } } fileAllocationMonitor->setCurrentValue(totalLength); diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 49578887..12e0bbb3 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -39,6 +39,7 @@ #include "message.h" #include "prefs.h" #include "Util.h" +#include "FatalException.h" FtpNegotiationCommand::FtpNegotiationCommand(int cuid, const RequestHandle req, DownloadEngine* e, @@ -188,6 +189,11 @@ bool FtpNegotiationCommand::recvSize() { e->segmentMan->totalSize); e->segmentMan->filename = Util::urldecode(req->getFile()); + if(e->segmentMan->shouldCancelDownloadForSafety()) { + throw new FatalException(EX_FILE_ALREADY_EXISTS, + e->segmentMan->getFilePath().c_str(), + e->segmentMan->getSegmentFilePath().c_str()); + } bool segFileExists = e->segmentMan->segmentFileExists(); if(segFileExists) { e->segmentMan->load(); diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index f7b6aecc..b0970e8e 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -40,6 +40,8 @@ #include "message.h" #include "Util.h" #include "prefs.h" +#include "File.h" +#include "FatalException.h" #include #include @@ -159,6 +161,11 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { // send request again to the server with Range header return prepareForRetry(0); } else { + if(e->segmentMan->shouldCancelDownloadForSafety()) { + throw new FatalException(EX_FILE_ALREADY_EXISTS, + e->segmentMan->getFilePath().c_str(), + e->segmentMan->getSegmentFilePath().c_str()); + } e->segmentMan->totalSize = size; e->segmentMan->initBitfield(e->option->getAsInt(PREF_SEGMENT_SIZE), e->segmentMan->totalSize); diff --git a/src/Makefile.am b/src/Makefile.am index 59226b52..f38be47b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,8 @@ SRCS = Socket.h\ common.h\ message.h\ Exception.h\ + FatalException.h\ + RecoverableException.h\ DlAbortEx.h\ DlRetryEx.h\ Logger.h\ @@ -187,9 +189,9 @@ libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\ @LIBCARES_LIBS@ -#aria2c_LDFLAGS = -pg +aria2c_LDFLAGS = -pg AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ @LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@\ - -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ # -pg \ No newline at end of file + -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg \ No newline at end of file diff --git a/src/Makefile.in b/src/Makefile.in index a30bd9ee..ddb5a07f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -196,18 +196,18 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \ ConsoleDownloadEngine.h Segment.cc Segment.h SegmentMan.cc \ SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \ - message.h Exception.h DlAbortEx.h DlRetryEx.h Logger.h \ - SimpleLogger.cc SimpleLogger.h TransferEncoding.h \ - ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \ - AbstractDiskWriter.cc AbstractDiskWriter.h \ - DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \ - Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \ - messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \ - TimeA2.cc TimeA2.h SharedHandle.h HandleRegistry.h \ - FeatureConfig.cc FeatureConfig.h DownloadEngineFactory.cc \ - DownloadEngineFactory.h RequestInfo.h UrlRequestInfo.cc \ - UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \ - BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \ + message.h Exception.h FatalException.h RecoverableException.h \ + DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \ + SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \ + ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \ + AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \ + File.cc File.h Option.cc Option.h Base64.cc Base64.h \ + CookieBox.cc CookieBox.h messageDigest.h LogFactory.cc \ + LogFactory.h NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ + HandleRegistry.h FeatureConfig.cc FeatureConfig.h \ + DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ + UrlRequestInfo.cc UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h \ + PeerStat.h BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \ BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \ SimpleRandomizer.h FileAllocator.cc FileAllocator.h \ FileAllocationMonitor.cc FileAllocationMonitor.h \ @@ -566,18 +566,18 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ DownloadEngine.cc DownloadEngine.h ConsoleDownloadEngine.cc \ ConsoleDownloadEngine.h Segment.cc Segment.h SegmentMan.cc \ SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \ - message.h Exception.h DlAbortEx.h DlRetryEx.h Logger.h \ - SimpleLogger.cc SimpleLogger.h TransferEncoding.h \ - ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \ - AbstractDiskWriter.cc AbstractDiskWriter.h \ - DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \ - Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \ - messageDigest.h LogFactory.cc LogFactory.h NullLogger.h \ - TimeA2.cc TimeA2.h SharedHandle.h HandleRegistry.h \ - FeatureConfig.cc FeatureConfig.h DownloadEngineFactory.cc \ - DownloadEngineFactory.h RequestInfo.h UrlRequestInfo.cc \ - UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h PeerStat.h \ - BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \ + message.h Exception.h FatalException.h RecoverableException.h \ + DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \ + SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \ + ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \ + AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \ + File.cc File.h Option.cc Option.h Base64.cc Base64.h \ + CookieBox.cc CookieBox.h messageDigest.h LogFactory.cc \ + LogFactory.h NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ + HandleRegistry.h FeatureConfig.cc FeatureConfig.h \ + DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ + UrlRequestInfo.cc UrlRequestInfo.h SpeedCalc.cc SpeedCalc.h \ + PeerStat.h BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \ BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \ SimpleRandomizer.h FileAllocator.cc FileAllocator.h \ FileAllocationMonitor.cc FileAllocationMonitor.h \ @@ -589,12 +589,12 @@ aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\ @LIBCARES_LIBS@ -#aria2c_LDFLAGS = -pg +aria2c_LDFLAGS = -pg AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ @LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@\ - -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ # -pg + -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg all: all-am diff --git a/src/MetaFileUtil.cc b/src/MetaFileUtil.cc index 4c217062..58ab78c3 100644 --- a/src/MetaFileUtil.cc +++ b/src/MetaFileUtil.cc @@ -57,7 +57,7 @@ MetaEntry* MetaFileUtil::parseMetaFile(const string& file) { MetaEntry* entry = bdecoding(buf, len); delete [] buf; return entry; - } catch(Exception* ex) { + } catch(RecoverableException* ex) { delete [] buf; if(fp != NULL) { fclose(fp); @@ -121,7 +121,7 @@ Dictionary* MetaFileUtil::parseDictionaryTree(const char** pp, const char* end) dic->put(name, e); } return dic; - } catch(Exception* ex) { + } catch(RecoverableException* ex) { delete dic; throw; } @@ -142,7 +142,7 @@ List* MetaFileUtil::parseListTree(const char** pp, const char* end) { lis->add(e); } return lis; - } catch(Exception* ex) { + } catch(RecoverableException* ex) { delete lis; throw; } diff --git a/src/MetalinkRequestInfo.cc b/src/MetalinkRequestInfo.cc index ec4e7417..a03d9ff8 100644 --- a/src/MetalinkRequestInfo.cc +++ b/src/MetalinkRequestInfo.cc @@ -125,7 +125,7 @@ RequestInfos MetalinkRequestInfo::execute() { reqInfo->setChecksum(checksum); nextReqInfos.push_front(reqInfo); } - } catch(Exception* ex) { + } catch(RecoverableException* ex) { logger->error("Exception caught", ex); delete ex; fail = true; diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index 8293e9b4..c03416f7 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -117,7 +117,7 @@ void MultiDiskAdaptor::writeData(const unsigned char* data, uint32_t len, writing = true; fileOffset = 0; } else { - fileOffset -= (*itr)->fileEntry->getLength(); + fileOffset -= (*itr)->getFileEntry()->getLength(); } } if(!writing) { @@ -128,8 +128,8 @@ void MultiDiskAdaptor::writeData(const unsigned char* data, uint32_t len, bool MultiDiskAdaptor::isInRange(const DiskWriterEntryHandle entry, int64_t offset) const { - return entry->fileEntry->getOffset() <= offset && - offset < entry->fileEntry->getOffset()+entry->fileEntry->getLength(); + return entry->getFileEntry()->getOffset() <= offset && + offset < entry->getFileEntry()->getOffset()+entry->getFileEntry()->getLength(); } uint32_t MultiDiskAdaptor::calculateLength(const DiskWriterEntryHandle entry, @@ -137,8 +137,8 @@ uint32_t MultiDiskAdaptor::calculateLength(const DiskWriterEntryHandle entry, uint32_t rem) const { uint32_t length; - if(entry->fileEntry->getLength() < fileOffset+rem) { - length = entry->fileEntry->getLength()-fileOffset; + if(entry->getFileEntry()->getLength() < fileOffset+rem) { + length = entry->getFileEntry()->getLength()-fileOffset; } else { length = rem; } @@ -160,7 +160,7 @@ int MultiDiskAdaptor::readData(unsigned char* data, uint32_t len, int64_t offset reading = true; fileOffset = 0; } else { - fileOffset -= (*itr)->fileEntry->getLength(); + fileOffset -= (*itr)->getFileEntry()->getLength(); } } if(!reading) { @@ -205,7 +205,7 @@ string MultiDiskAdaptor::sha1Sum(int64_t offset, uint64_t length) { reading = true; fileOffset = 0; } else { - fileOffset -= (*itr)->fileEntry->getLength(); + fileOffset -= (*itr)->getFileEntry()->getLength(); } } if(!reading) { @@ -215,3 +215,14 @@ string MultiDiskAdaptor::sha1Sum(int64_t offset, uint64_t length) { ctx.digestFinal(hashValue); return Util::toHex(hashValue, 20); } + +bool MultiDiskAdaptor::fileExists() +{ + for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end(); itr++) { + if((*itr)->fileExists(getTopDirPath())) { + return true; + } + } + return false; +} diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index e33a840d..1e58d4b8 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -39,11 +39,11 @@ #include "Option.h" #include "DiskWriter.h" #include "messageDigest.h" +#include "File.h" class DiskWriterEntry { -public: - FileEntryHandle fileEntry; private: + FileEntryHandle fileEntry; DiskWriterHandle diskWriter; public: DiskWriterEntry(const FileEntryHandle& fileEntry): @@ -77,6 +77,15 @@ public: diskWriter->closeFile(); } + bool fileExists(const string& topDir) + { + return File(getFilePath(topDir)).exists(); + } + + FileEntryHandle getFileEntry() const { + return fileEntry; + } + void setDiskWriter(const DiskWriterHandle& diskWriter) { this->diskWriter = diskWriter; } @@ -139,6 +148,12 @@ public: virtual string sha1Sum(int64_t offset, uint64_t length); + virtual bool fileExists(); + + virtual string getFilePath() { + return getTopDirPath(); + } + void setTopDir(const string& topDir) { this->topDir = topDir; } diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc index fec84bf6..11780643 100644 --- a/src/PeerAbstractCommand.cc +++ b/src/PeerAbstractCommand.cc @@ -77,7 +77,7 @@ bool PeerAbstractCommand::execute() { throw new DlRetryEx(EX_TIME_OUT); } return executeInternal(); - } catch(Exception* err) { + } catch(RecoverableException* err) { logger->error(MSG_DOWNLOAD_ABORTED, err, cuid); logger->debug("CUID#%d - Peer %s:%d banned.", cuid, peer->ipaddr.c_str(), peer->port); @@ -96,7 +96,7 @@ bool PeerAbstractCommand::prepareForRetry(int wait) { return true; } -void PeerAbstractCommand::onAbort(Exception* ex) { +void PeerAbstractCommand::onAbort(RecoverableException* ex) { if(peer->isSeeder()) { peer->error++; } else { diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h index 52f25520..61ad3801 100644 --- a/src/PeerAbstractCommand.h +++ b/src/PeerAbstractCommand.h @@ -39,6 +39,7 @@ #include "Request.h" #include "TorrentDownloadEngine.h" #include "TimeA2.h" +#include "RecoverableException.h" class PeerAbstractCommand : public BtContextAwareCommand { private: @@ -52,7 +53,7 @@ protected: void setTimeout(int timeout) { this->timeout = timeout; } virtual bool prepareForNextPeer(int wait); virtual bool prepareForRetry(int wait); - virtual void onAbort(Exception* ex); + virtual void onAbort(RecoverableException* ex); virtual bool executeInternal() = 0; void setReadCheckSocket(const SocketHandle& socket); void setWriteCheckSocket(const SocketHandle& socket); diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc index 6608149a..f9e459d5 100644 --- a/src/PeerConnection.cc +++ b/src/PeerConnection.cc @@ -93,6 +93,9 @@ bool PeerConnection::receiveMessage(unsigned char* data, uint32_t& dataLength) { } currentPayloadLength = payloadLength; } + if(!socket->isReadable(0)) { + return false; + } // we have currentPayloadLen-resbufLen bytes to read uint32_t remaining = currentPayloadLength-resbufLength; if(remaining > 0) { diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 20992357..8371b168 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -204,7 +204,7 @@ bool PeerInteractionCommand::prepareForRetry(int wait) { return false; } -void PeerInteractionCommand::onAbort(Exception* ex) { +void PeerInteractionCommand::onAbort(RecoverableException* ex) { btInteractive->cancelAllPiece(); PeerAbstractCommand::onAbort(ex); } diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h index e4842e7b..fb02b8ea 100644 --- a/src/PeerInteractionCommand.h +++ b/src/PeerInteractionCommand.h @@ -43,10 +43,10 @@ private: int sequence; BtInteractiveHandle btInteractive; protected: - bool executeInternal(); - bool prepareForRetry(int wait); - bool prepareForNextPeer(int wait); - void onAbort(Exception* ex); + virtual bool executeInternal(); + virtual bool prepareForRetry(int wait); + virtual bool prepareForNextPeer(int wait); + virtual void onAbort(RecoverableException* ex); public: PeerInteractionCommand(int cuid, const PeerHandle& peer, diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc index d7808127..9644ce69 100644 --- a/src/PeerListenCommand.cc +++ b/src/PeerListenCommand.cc @@ -53,7 +53,7 @@ int PeerListenCommand::bindPort(int portRangeStart, int portRangeEnd) { logger->info("CUID#%d - using port %d for accepting new connections", cuid, port); return port; - } catch(Exception* ex) { + } catch(RecoverableException* ex) { logger->error("CUID#%d - an error occurred while binding port=%d", ex, cuid, port); socket->closeConnection(); @@ -92,7 +92,7 @@ bool PeerListenCommand::execute() { logger->debug("CUID#%d - incoming connection, adding new command CUID#%d", cuid, newCuid); } } - } catch(Exception* ex) { + } catch(RecoverableException* ex) { logger->error("CUID#%d - error in accepting connection", ex, cuid); delete ex; } diff --git a/src/Piece.h b/src/Piece.h index 79be4b3f..26d83bd3 100644 --- a/src/Piece.h +++ b/src/Piece.h @@ -105,6 +105,10 @@ public: const unsigned char* getBitfield() const { return bitfield->getBitfield(); } void setBitfield(const unsigned char* bitfield, int len); + int getBitfieldLength() const { + return bitfield->getBitfieldLength(); + } + void clearAllBlock(); void setAllBlock(); diff --git a/src/CompactTrackerResponseProcessor.h b/src/RecoverableException.h similarity index 71% rename from src/CompactTrackerResponseProcessor.h rename to src/RecoverableException.h index caa737c6..ed644b85 100644 --- a/src/CompactTrackerResponseProcessor.h +++ b/src/RecoverableException.h @@ -32,31 +32,27 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#ifndef _D_COMPACT_TRACKER_RESPONSE_PROCESSOR_H_ -#define _D_COMPACT_TRACKER_RESPONSE_PROCESSOR_H_ +#ifndef _D_RECOVERABLE_EXCEPTION_H_ +#define _D_RECOVERABLE_EXCEPTION_H_ +#include "Exception.h" -#include "common.h" -#include "ByteArrayDiskWriter.h" -#include "Request.h" - -class TorrentDownloadEngine; -class Logger; - -class CompactTrackerResponseProcessor { -private: - ByteArrayDiskWriter* diskWriter; - TorrentDownloadEngine* e; - Request* req; - const Logger* logger; +class RecoverableException : public Exception { public: - CompactTrackerResponseProcessor(ByteArrayDiskWriter* diskWriter, - TorrentDownloadEngine* e, - Request* req); - ~CompactTrackerResponseProcessor(); + RecoverableException(Exception* cause = 0):Exception(cause) {} - bool isFeeded() const; - void execute(); - void resetTrackerResponse(); + RecoverableException(const char* msg, ...):Exception() { + va_list ap; + va_start(ap, msg); + setMsg(string(msg), ap); + va_end(ap); + } + + RecoverableException(Exception* cause, const char* msg, ...):Exception(cause) { + va_list ap; + va_start(ap, msg); + setMsg(string(msg), ap); + va_end(ap); + } }; -#endif // _D_COMPACT_TRACKER_RESPONSE_PROCESSOR_H_ +#endif // _D_RECOVERABLE_EXCEPTION_EX_H_ diff --git a/src/RequestSlot.cc b/src/RequestSlot.cc index 6d6b4f87..287a5650 100644 --- a/src/RequestSlot.cc +++ b/src/RequestSlot.cc @@ -61,7 +61,7 @@ void RequestSlot::setDispatchedTime(time_t secFromEpoch) { } bool RequestSlot::isTimeout(time_t timeoutSec) const { - return dispatchedTime.differenceInMillis() > timeoutSec*1000; + return dispatchedTime.elapsed(timeoutSec); } int RequestSlot::getLatencyInMillis() const { diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index efd9f2c0..5d5c2356 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -474,3 +474,12 @@ int SegmentMan::calculateDownloadSpeed() const { } return speed; } + +bool SegmentMan::fileExists() { + return File(getFilePath()).exists(); +} + +bool SegmentMan::shouldCancelDownloadForSafety() { + return fileExists() && !segmentFileExists() && + option->get(PREF_FORCE_TRUNCATE) != V_TRUE; +} diff --git a/src/SegmentMan.h b/src/SegmentMan.h index e43df492..ba4cca1e 100644 --- a/src/SegmentMan.h +++ b/src/SegmentMan.h @@ -255,6 +255,11 @@ public: * Returns current download speed in bytes per sec. */ int calculateDownloadSpeed() const; + + bool fileExists(); + + bool shouldCancelDownloadForSafety(); + }; #endif // _D_SEGMENT_MAN_H_ diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc index 84a2af3f..7fcc7bf6 100644 --- a/src/TorrentRequestInfo.cc +++ b/src/TorrentRequestInfo.cc @@ -38,6 +38,9 @@ #include "Util.h" #include "BtRegistry.h" #include "DefaultBtContext.h" +#include "FatalException.h" +#include "message.h" +#include "RecoverableException.h" extern volatile sig_atomic_t btHaltRequested; @@ -60,6 +63,21 @@ RequestInfos TorrentRequestInfo::execute() { op, targetFiles)); + if(BT_PROGRESS_INFO_FILE(btContext)->exists()) { + // load .aria2 file if it exists. + BT_PROGRESS_INFO_FILE(btContext)->load(); + PIECE_STORAGE(btContext)->getDiskAdaptor()->openExistingFile(); + } else { + if(PIECE_STORAGE(btContext)->getDiskAdaptor()->fileExists() && + op->get(PREF_FORCE_TRUNCATE) != V_TRUE) { + throw new FatalException(EX_FILE_ALREADY_EXISTS, + PIECE_STORAGE(btContext)->getDiskAdaptor()->getFilePath().c_str(), + BT_PROGRESS_INFO_FILE(btContext)->getFilename().c_str()); + } else { + PIECE_STORAGE(btContext)->getDiskAdaptor()->initAndOpenFile(); + } + } + Util::setGlobalSignalHandler(SIGINT, torrentHandler, SA_RESETHAND); Util::setGlobalSignalHandler(SIGTERM, torrentHandler, SA_RESETHAND); @@ -68,7 +86,7 @@ RequestInfos TorrentRequestInfo::execute() { if(PIECE_STORAGE(btContext)->downloadFinished()) { printDownloadCompeleteMessage(); } - } catch(Exception* ex) { + } catch(RecoverableException* ex) { logger->error("Exception caught", ex); fail = true; delete ex; diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc index 23a762b7..d619a754 100644 --- a/src/TrackerUpdateCommand.cc +++ b/src/TrackerUpdateCommand.cc @@ -74,7 +74,7 @@ char* TrackerUpdateCommand::getTrackerResponse(size_t& trackerResponseLength) { } trackerResponseLength = bufLength; return buf; - } catch(Exception* e) { + } catch(RecoverableException* e) { delete [] buf; throw; } @@ -113,7 +113,7 @@ bool TrackerUpdateCommand::execute() { btAnnounce->announceSuccess(); btAnnounce->resetAnnounce(); e->segmentMan->init(); - } catch(Exception* err) { + } catch(RecoverableException* err) { logger->error("CUID#%d - Error occurred while processing tracker response.", cuid, err); e->segmentMan->errors++; delete err; diff --git a/src/UrlRequestInfo.cc b/src/UrlRequestInfo.cc index d85476a6..3d849037 100644 --- a/src/UrlRequestInfo.cc +++ b/src/UrlRequestInfo.cc @@ -37,6 +37,7 @@ #include "MetalinkRequestInfo.h" #include "prefs.h" #include "DownloadEngineFactory.h" +#include "RecoverableException.h" extern volatile sig_atomic_t haltRequested; @@ -140,7 +141,7 @@ RequestInfos UrlRequestInfo::execute() { e->segmentMan->diskWriter->closeFile(); printDownloadAbortMessage(); } - } catch(Exception *ex) { + } catch(RecoverableException *ex) { logger->error("Exception caught", ex); delete ex; fail = true; diff --git a/src/Util.cc b/src/Util.cc index 9da2c5fc..fe0fd3b6 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -244,7 +244,9 @@ string Util::urlencode(const unsigned char* target, int len) { string Util::torrentUrlencode(const unsigned char* target, int len) { string dest; for(int i = 0; i < len; i++) { - if(isalpha(target[i]) || isdigit(target[i])) { + if('0' <= target[i] && target[i] <= '9' || + 'A' <= target[i] && target[i] <= 'Z' || + 'a' <= target[i] && target[i] <= 'z') { dest += target[i]; } else { char temp[4]; @@ -339,7 +341,7 @@ void Util::rangedFileCopy(const string& dest, const string& src, long long int s close(destFd); srcFd = -1; destFd = -1; - } catch(Exception* e) { + } catch(RecoverableException* e) { if(srcFd != -1) { close(srcFd); } diff --git a/src/main.cc b/src/main.cc index b41ab8a9..d018671d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -176,6 +176,12 @@ void showUsage() { " This may take some time depending on the size of\n" " file.\n" " Default: 'none'") << endl; + cout << _(" --force-truncate=true|false If this option set to false, aria2 doesn't download\n" + " file which already exists in file system but\n" + " its corresponding .aria2 file doesn't exist.\n" + " Set this option to true if you want to download\n" + " file all over again.\n" + " Default: false") << endl; #ifdef ENABLE_BITTORRENT cout << _(" -T, --torrent-file=TORRENT_FILE The file path to .torrent file.") << endl; cout << _(" --follow-torrent=true|false Setting this option to false prevents aria2 to\n" @@ -337,6 +343,7 @@ int main(int argc, char* argv[]) { op->put(PREF_STARTUP_IDLE_TIME, "10"); op->put(PREF_TRACKER_MAX_TRIES, "10"); op->put(PREF_FILE_ALLOCATION, V_NONE); + op->put(PREF_FORCE_TRUNCATE, V_FALSE); while(1) { int optIndex = 0; int lopt; @@ -366,6 +373,7 @@ int main(int argc, char* argv[]) { { "lowest-speed-limit", required_argument, &lopt, 200 }, { "max-download-limit", required_argument, &lopt, 201 }, { "file-allocation", required_argument, 0, 'a' }, + { "force-truncate", required_argument, &lopt, 202 }, #ifdef ENABLE_BITTORRENT { "torrent-file", required_argument, NULL, 'T' }, { "listen-port", required_argument, &lopt, 15 }, @@ -616,6 +624,17 @@ int main(int argc, char* argv[]) { op->put(PREF_MAX_DOWNLOAD_LIMIT, Util::itos(limit)); break; } + case 202: { + if(string(optarg) == "true") { + op->put(PREF_FORCE_TRUNCATE, V_TRUE); + } else if(string(optarg) == "false") { + op->put(PREF_FORCE_TRUNCATE, V_FALSE); + } else { + cerr << _("force-true must be either 'true' or 'false'.") << endl; + showUsage(); + exit(EXIT_FAILURE); + } + } } break; } diff --git a/src/message.h b/src/message.h index 6cbf5c88..8bf57290 100644 --- a/src/message.h +++ b/src/message.h @@ -111,5 +111,6 @@ #define EX_SOCKET_SEND _("Failed to send data, cause: %s") #define EX_SOCKET_RECV _("Failed to receive data, cause: %s") #define EX_SOCKET_PEEK _("Failed to peek data, cause: %s") +#define EX_FILE_ALREADY_EXISTS _("File %s exists, but %s does not exist. The download was canceled in order to prevent your file from being truncated to 0. If you are sure to download file all over again, then delete it or add --force-truncate=true option and restart aria2.") #endif // _D_MESSAGE_H_ diff --git a/src/prefs.h b/src/prefs.h index 35bdfcad..d6e8dea5 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -84,6 +84,8 @@ // value: prealloc | none #define PREF_FILE_ALLOCATION "file_allocation" # define V_PREALLOC "prealloc" +// value: true | false +#define PREF_FORCE_TRUNCATE "force_truncate" /** * FTP related preferences