diff --git a/ChangeLog b/ChangeLog index dd1ac996..284531d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2009-11-23 Tatsuhiro Tsujikawa + + Added BitTorrent Magnet Link support. Base32 encoded link is not + supported yet. Fixed typo in method name in RequestGroup. In + metadataGetMode, don't show "Your share ratio was ..." message. + * src/DefaultBtInteractive.cc + * src/DefaultBtInteractive.h + * src/DownloadHandlerFactory.cc + * src/DownloadHandlerFactory.h + * src/HandshakeExtensionMessage.cc + * src/Makefile.am + * src/Metalink2RequestGroup.cc + * src/PeerInteractionCommand.cc + * src/RequestGroup.cc + * src/RequestGroup.h + * src/UTMetadataPostDownloadHandler.cc + * src/UTMetadataPostDownloadHandler.h + * src/download_helper.cc + * test/HandshakeExtensionMessageTest.cc + * test/Makefile.am + * test/UTMetadataPostDownloadHandlerTest.cc + * test/UTMetadataRejectExtensionMessageTest.cc + 2009-11-23 Tatsuhiro Tsujikawa In metadataGetMode, don't show SEEDING. diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc index 3dd62096..df70e063 100644 --- a/src/DefaultBtInteractive.cc +++ b/src/DefaultBtInteractive.cc @@ -69,6 +69,8 @@ #include "RequestGroup.h" #include "RequestGroupMan.h" #include "bittorrent_helper.h" +#include "UTMetadataRequestFactory.h" +#include "UTMetadataRequestTracker.h" namespace aria2 { @@ -78,6 +80,7 @@ DefaultBtInteractive::DefaultBtInteractive : _downloadContext(downloadContext), peer(peer), + _metadataGetMode(false), logger(LogFactory::getInstance()), allowedFastSetSize(10), keepAliveInterval(120), @@ -146,11 +149,15 @@ void DefaultBtInteractive::doPostHandshakeProcessing() { if(peer->isExtendedMessagingEnabled()) { addHandshakeExtendedMessageToQueue(); } - addBitfieldMessageToQueue(); + if(!_metadataGetMode) { + addBitfieldMessageToQueue(); + } if(peer->isDHTEnabled() && _dhtEnabled) { addPortMessageToQueue(); } - addAllowedFastMessageToQueue(); + if(!_metadataGetMode) { + addAllowedFastMessageToQueue(); + } sendPendingMessage(); } @@ -365,6 +372,16 @@ void DefaultBtInteractive::addRequests() { void DefaultBtInteractive::cancelAllPiece() { btRequestFactory->removeAllTargetPiece(); + if(_metadataGetMode && _downloadContext->getTotalLength() > 0) { + std::vector metadataRequests = + _utMetadataRequestTracker->getAllTrackedIndex(); + for(std::vector::const_iterator i = metadataRequests.begin(); + i != metadataRequests.end(); ++i) { + logger->debug("Cancel metadata: piece=%lu", + static_cast(*i)); + _pieceStorage->cancelPiece(_pieceStorage->getPiece(*i)); + } + } } void DefaultBtInteractive::sendPendingMessage() { @@ -439,29 +456,58 @@ void DefaultBtInteractive::addPeerExchangeMessage() } void DefaultBtInteractive::doInteractionProcessing() { - checkActiveInteraction(); + if(_metadataGetMode) { + sendKeepAlive(); + _numReceivedMessage = receiveMessages(); + // PieceStorage is re-initialized with metadata_size in + // HandshakeExtensionMessage::doReceivedAction(). + _pieceStorage = + _downloadContext->getOwnerRequestGroup()->getPieceStorage(); - decideChoking(); + if(peer->getExtensionMessageID("ut_metadata") && + _downloadContext->getTotalLength() > 0) { + size_t num = _utMetadataRequestTracker->avail(); + if(num > 0) { + std::deque > requests; + _utMetadataRequestFactory->create(requests, num, _pieceStorage); + dispatcher->addMessageToQueue(requests); + } + if(_perSecCheckPoint.elapsed(1)) { + _perSecCheckPoint.reset(); + // Drop timeout request after queuing message to give a chance + // to other connection to request piece. + std::vector indexes = + _utMetadataRequestTracker->removeTimeoutEntry(); + for(std::vector::const_iterator i = indexes.begin(); + i != indexes.end(); ++i) { + _pieceStorage->cancelPiece(_pieceStorage->getPiece(*i)); + } + } + } + } else { + checkActiveInteraction(); - detectMessageFlooding(); + decideChoking(); - if(_perSecCheckPoint.elapsed(1)) { - _perSecCheckPoint.reset(); - dispatcher->checkRequestSlotAndDoNecessaryThing(); - } - checkHave(); + detectMessageFlooding(); - sendKeepAlive(); + if(_perSecCheckPoint.elapsed(1)) { + _perSecCheckPoint.reset(); + dispatcher->checkRequestSlotAndDoNecessaryThing(); + } + checkHave(); - _numReceivedMessage = receiveMessages(); + sendKeepAlive(); + + _numReceivedMessage = receiveMessages(); - btRequestFactory->removeCompletedPiece(); + btRequestFactory->removeCompletedPiece(); - decideInterest(); - if(!_pieceStorage->downloadFinished()) { - addRequests(); + decideInterest(); + if(!_pieceStorage->downloadFinished()) { + addRequests(); + } } - if(peer->getExtensionMessageID("ut_pex") && _utPexEnabled) { addPeerExchangeMessage(); } @@ -491,7 +537,11 @@ size_t DefaultBtInteractive::countReceivedMessageInIteration() const size_t DefaultBtInteractive::countOutstandingRequest() { - return dispatcher->countOutstandingRequest(); + if(_metadataGetMode) { + return _utMetadataRequestTracker->count(); + } else { + return dispatcher->countOutstandingRequest(); + } } void DefaultBtInteractive::setBtRuntime diff --git a/src/DefaultBtInteractive.h b/src/DefaultBtInteractive.h index 2f5d1b4b..923e5d07 100644 --- a/src/DefaultBtInteractive.h +++ b/src/DefaultBtInteractive.h @@ -59,6 +59,8 @@ class ExtensionMessageRegistry; class DHTNode; class Logger; class RequestGroupMan; +class UTMetadataRequestFactory; +class UTMetadataRequestTracker; class FloodingStat { private: @@ -114,6 +116,10 @@ private: SharedHandle messageFactory; SharedHandle _extensionMessageFactory; SharedHandle _extensionMessageRegistry; + SharedHandle _utMetadataRequestFactory; + SharedHandle _utMetadataRequestTracker; + + bool _metadataGetMode; WeakHandle _localNode; @@ -230,6 +236,23 @@ public: } void setRequestGroupMan(const WeakHandle& rgman); + + void setUTMetadataRequestTracker + (const SharedHandle& tracker) + { + _utMetadataRequestTracker = tracker; + } + + void setUTMetadataRequestFactory + (const SharedHandle& factory) + { + _utMetadataRequestFactory = factory; + } + + void enableMetadataGetMode() + { + _metadataGetMode = true; + } }; typedef SharedHandle DefaultBtInteractiveHandle; diff --git a/src/DownloadHandlerFactory.cc b/src/DownloadHandlerFactory.cc index 15a8cd98..128372a5 100644 --- a/src/DownloadHandlerFactory.cc +++ b/src/DownloadHandlerFactory.cc @@ -38,6 +38,7 @@ #include "BtPostDownloadHandler.h" #include "DownloadHandlerConstants.h" #include "ContentTypeRequestGroupCriteria.h" +#include "UTMetadataPostDownloadHandler.h" namespace aria2 { @@ -59,6 +60,8 @@ DownloadHandlerFactory::_btPreDownloadHandler; BtPostDownloadHandlerHandle DownloadHandlerFactory::_btPostDownloadHandler; +SharedHandle +DownloadHandlerFactory::_btMetadataPostDownloadHandler; #endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK @@ -118,6 +121,15 @@ BtPostDownloadHandlerHandle DownloadHandlerFactory::getBtPostDownloadHandler() return _btPostDownloadHandler; } +SharedHandle +DownloadHandlerFactory::getUTMetadataPostDownloadHandler() +{ + if(_btMetadataPostDownloadHandler.isNull()) { + _btMetadataPostDownloadHandler.reset(new UTMetadataPostDownloadHandler()); + } + return _btMetadataPostDownloadHandler; +} + #endif // ENABLE_BITTORRENT } // namespace aria2 diff --git a/src/DownloadHandlerFactory.h b/src/DownloadHandlerFactory.h index dd3247c0..0b3b7816 100644 --- a/src/DownloadHandlerFactory.h +++ b/src/DownloadHandlerFactory.h @@ -46,33 +46,48 @@ class MetalinkPostDownloadHandler; #endif // ENABLE_METALINK #ifdef ENABLE_BITTORRENT class BtPostDownloadHandler; +class UTMetadataPostDownloadHandler; #endif // ENABLE_BITTORRENT class DownloadHandlerFactory { private: #ifdef ENABLE_METALINK - static SharedHandle _metalinkPreDownloadHandler; + static SharedHandle + _metalinkPreDownloadHandler; - static SharedHandle _metalinkPostDownloadHandler; + static SharedHandle + _metalinkPostDownloadHandler; #endif // ENABLE_METALINK #ifdef ENABLE_BITTORRENT - static SharedHandle _btPreDownloadHandler; + static SharedHandle + _btPreDownloadHandler; - static SharedHandle _btPostDownloadHandler; + static SharedHandle + _btPostDownloadHandler; + + static SharedHandle + _btMetadataPostDownloadHandler; #endif // ENABLE_BITTORRENT public: #ifdef ENABLE_METALINK - static SharedHandle getMetalinkPreDownloadHandler(); + static SharedHandle + getMetalinkPreDownloadHandler(); - static SharedHandle getMetalinkPostDownloadHandler(); + static SharedHandle + getMetalinkPostDownloadHandler(); #endif // ENABLE_METALINK #ifdef ENABLE_BITTORRENT - static SharedHandle getBtPreDownloadHandler(); + static SharedHandle + getBtPreDownloadHandler(); - static SharedHandle getBtPostDownloadHandler(); + static SharedHandle + getBtPostDownloadHandler(); + + static SharedHandle + getUTMetadataPostDownloadHandler(); #endif // ENABLE_BITTORRENT }; diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc index fd722e78..74c713be 100644 --- a/src/HandshakeExtensionMessage.cc +++ b/src/HandshakeExtensionMessage.cc @@ -110,8 +110,15 @@ void HandshakeExtensionMessage::doReceivedAction() const std::map::value_type& vt = *itr; _peer->setExtension(vt.first, vt.second); } + BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT); + if(!attrs.containsKey(bittorrent::METADATA) && + !_peer->getExtensionMessageID("ut_metadata")) { + // TODO In metadataGetMode, if peer dont' support metadata + // transfer, should we drop connection? There is a possibility + // that peer can still tell us peers using PEX. + throw DL_ABORT_EX("Peer doesn't support ut_metadata extension. Goodbye."); + } if(_metadataSize > 0) { - BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT); if(attrs.containsKey(bittorrent::METADATA_SIZE)) { if(_metadataSize != (size_t)attrs[bittorrent::METADATA_SIZE].i()) { throw DL_ABORT_EX("Wrong metadata_size. Which one is correct!?"); @@ -126,6 +133,9 @@ void HandshakeExtensionMessage::doReceivedAction() _dctx->getOwnerRequestGroup()->getPieceStorage(); pieceStorage->setEndGamePieceNum(0); } + } else { + throw DL_ABORT_EX("Peer didn't provide metadata_size." + " It seems that it doesn't have whole metadata."); } } diff --git a/src/Makefile.am b/src/Makefile.am index 1cfe5221..2f06976e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -351,6 +351,9 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\ UTMetadataRequestExtensionMessage.h\ UTMetadataRejectExtensionMessage.cc UTMetadataRejectExtensionMessage.h\ UTMetadataDataExtensionMessage.cc UTMetadataDataExtensionMessage.h\ + UTMetadataRequestTracker.cc UTMetadataRequestTracker.h\ + UTMetadataRequestFactory.cc UTMetadataRequestFactory.h\ + UTMetadataPostDownloadHandler.cc UTMetadataPostDownloadHandler.h\ DHTNode.cc DHTNode.h\ DHTBucket.cc DHTBucket.h\ DHTRoutingTable.cc DHTRoutingTable.h\ diff --git a/src/Makefile.in b/src/Makefile.in index 1bb60b99..eb3a5bcb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -150,6 +150,9 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.h\ @ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessage.cc UTMetadataRejectExtensionMessage.h\ @ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessage.cc UTMetadataDataExtensionMessage.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestTracker.cc UTMetadataRequestTracker.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestFactory.cc UTMetadataRequestFactory.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataPostDownloadHandler.cc UTMetadataPostDownloadHandler.h\ @ENABLE_BITTORRENT_TRUE@ DHTNode.cc DHTNode.h\ @ENABLE_BITTORRENT_TRUE@ DHTBucket.cc DHTBucket.h\ @ENABLE_BITTORRENT_TRUE@ DHTRoutingTable.cc DHTRoutingTable.h\ @@ -501,7 +504,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ UTMetadataRejectExtensionMessage.cc \ UTMetadataRejectExtensionMessage.h \ UTMetadataDataExtensionMessage.cc \ - UTMetadataDataExtensionMessage.h DHTNode.cc DHTNode.h \ + UTMetadataDataExtensionMessage.h UTMetadataRequestTracker.cc \ + UTMetadataRequestTracker.h UTMetadataRequestFactory.cc \ + UTMetadataRequestFactory.h UTMetadataPostDownloadHandler.cc \ + UTMetadataPostDownloadHandler.h DHTNode.cc DHTNode.h \ DHTBucket.cc DHTBucket.h DHTRoutingTable.cc DHTRoutingTable.h \ DHTMessageEntry.cc DHTMessageEntry.h DHTMessageDispatcher.h \ DHTMessageDispatcherImpl.cc DHTMessageDispatcherImpl.h \ @@ -660,6 +666,9 @@ am__objects_6 = @ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestTracker.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestFactory.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataPostDownloadHandler.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTNode.$(OBJEXT) DHTBucket.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTRoutingTable.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTMessageEntry.$(OBJEXT) \ @@ -1529,8 +1538,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/URIResult.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataDataExtensionMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataExtensionMessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataPostDownloadHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRejectExtensionMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestExtensionMessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestFactory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestTracker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTPexExtensionMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnknownLengthPieceStorage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParser.Po@am__quote@ diff --git a/src/Metalink2RequestGroup.cc b/src/Metalink2RequestGroup.cc index 8e74871c..78718341 100644 --- a/src/Metalink2RequestGroup.cc +++ b/src/Metalink2RequestGroup.cc @@ -179,8 +179,8 @@ Metalink2RequestGroup::createRequestGroup //dctx->setDir(_option->get(PREF_DIR)); dctx->getFirstFileEntry()->setUris(uris); torrentRg->setDownloadContext(dctx); - torrentRg->clearPreDowloadHandler(); - torrentRg->clearPostDowloadHandler(); + torrentRg->clearPreDownloadHandler(); + torrentRg->clearPostDownloadHandler(); // remove "metalink" from Accept Type list to avoid loop in tranparent // metalink torrentRg->removeAcceptType(RequestGroup::ACCEPT_METALINK); diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 7507be30..5cbf025f 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -71,6 +71,8 @@ #include "RequestGroupMan.h" #include "ExtensionMessageRegistry.h" #include "bittorrent_helper.h" +#include "UTMetadataRequestFactory.h" +#include "UTMetadataRequestTracker.h" namespace aria2 { @@ -103,14 +105,27 @@ PeerInteractionCommand::PeerInteractionCommand SharedHandle peerStorage = btRegistry->get(torrentAttrs[bittorrent::INFO_HASH].s())._peerStorage; + bool metadataGetMode = !torrentAttrs.containsKey(bittorrent::METADATA); + SharedHandle exMsgRegistry (new ExtensionMessageRegistry()); + SharedHandle utMetadataRequestFactory; + SharedHandle utMetadataRequestTracker; + if(metadataGetMode) { + utMetadataRequestFactory.reset(new UTMetadataRequestFactory()); + utMetadataRequestTracker.reset(new UTMetadataRequestTracker()); + } + SharedHandle extensionMessageFactory (new DefaultExtensionMessageFactory(peer, exMsgRegistry)); extensionMessageFactory->setPeerStorage(peerStorage); extensionMessageFactory->setDownloadContext (_requestGroup->getDownloadContext()); + extensionMessageFactory->setUTMetadataRequestTracker + (utMetadataRequestTracker); + extensionMessageFactory->setBtRuntime(_btRuntime); + // PieceStorage will be set later. SharedHandle factory(new DefaultBtMessageFactory()); factory->setCuid(cuid); @@ -123,6 +138,9 @@ PeerInteractionCommand::PeerInteractionCommand factory->setRoutingTable(DHTRegistry::_routingTable); factory->setTaskQueue(DHTRegistry::_taskQueue); factory->setTaskFactory(DHTRegistry::_taskFactory); + if(metadataGetMode) { + factory->enableMetadataGetMode(); + } PeerConnectionHandle peerConnection; if(passedPeerConnection.isNull()) { @@ -174,7 +192,7 @@ PeerInteractionCommand::PeerInteractionCommand (getOption()->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL)); btInteractive->setRequestGroupMan(e->_requestGroupMan); btInteractive->setBtMessageFactory(factory); - if(torrentAttrs[bittorrent::PRIVATE].i() == 0) { + if(metadataGetMode || torrentAttrs[bittorrent::PRIVATE].i() == 0) { if(getOption()->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) { btInteractive->setUTPexEnabled(true); } @@ -184,6 +202,12 @@ PeerInteractionCommand::PeerInteractionCommand factory->setDHTEnabled(true); } } + btInteractive->setUTMetadataRequestFactory(utMetadataRequestFactory); + btInteractive->setUTMetadataRequestTracker(utMetadataRequestTracker); + if(metadataGetMode) { + btInteractive->enableMetadataGetMode(); + } + this->btInteractive = btInteractive; // reverse depends @@ -194,6 +218,16 @@ PeerInteractionCommand::PeerInteractionCommand extensionMessageFactory->setBtMessageDispatcher(dispatcher); extensionMessageFactory->setBtMessageFactory(factory); + if(metadataGetMode) { + utMetadataRequestFactory->setDownloadContext + (_requestGroup->getDownloadContext()); + utMetadataRequestFactory->setBtMessageDispatcher(dispatcher); + utMetadataRequestFactory->setBtMessageFactory(factory); + utMetadataRequestFactory->setPeer(peer); + utMetadataRequestFactory->setUTMetadataRequestTracker + (utMetadataRequestTracker); + } + peer->allocateSessionResource (_requestGroup->getDownloadContext()->getPieceLength(), _requestGroup->getDownloadContext()->getTotalLength()); diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index 8317592c..a07bd8ff 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -196,14 +196,15 @@ void RequestGroup::closeFile() } } -void RequestGroup::createInitialCommand(std::deque& commands, - DownloadEngine* e) +void RequestGroup::createInitialCommand +(std::deque& commands, DownloadEngine* e) { #ifdef ENABLE_BITTORRENT { if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) { const BDE& torrentAttrs = _downloadContext->getAttribute(bittorrent::BITTORRENT); + bool metadataGetMode = !torrentAttrs.containsKey(bittorrent::METADATA); if(_option->getAsBool(PREF_DRY_RUN)) { throw DOWNLOAD_FAILURE_EXCEPTION ("Cancel BitTorrent download in dry-run context."); @@ -214,35 +215,45 @@ void RequestGroup::createInitialCommand(std::deque& commands, throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat ("InfoHash %s is already registered.", - util::toHex(torrentAttrs[bittorrent::INFO_HASH].s()).c_str()).str()); + bittorrent::getInfoHashString(_downloadContext).c_str()).str()); } - - if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) { - throw DOWNLOAD_FAILURE_EXCEPTION - (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD, - _downloadContext->getBasePath().c_str()).str()); - } - initPieceStorage(); - if(_downloadContext->getFileEntries().size() > 1) { - _pieceStorage->setupFileFilter(); + if(metadataGetMode) { + // Use UnknownLengthPieceStorage. + initPieceStorage(); + } else { + if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) { + throw DOWNLOAD_FAILURE_EXCEPTION + (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD, + _downloadContext->getBasePath().c_str()).str()); + } + initPieceStorage(); + if(_downloadContext->getFileEntries().size() > 1) { + _pieceStorage->setupFileFilter(); + } } - SharedHandle - progressInfoFile(new DefaultBtProgressInfoFile(_downloadContext, - _pieceStorage, - _option.get())); + SharedHandle progressInfoFile; + if(!metadataGetMode) { + progressInfoFile.reset(new DefaultBtProgressInfoFile(_downloadContext, + _pieceStorage, + _option.get())); + } BtRuntimeHandle btRuntime(new BtRuntime()); btRuntime->setMaxPeers(_option->getAsInt(PREF_BT_MAX_PEERS)); _btRuntime = btRuntime; - progressInfoFile->setBtRuntime(btRuntime); + if(!progressInfoFile.isNull()) { + progressInfoFile->setBtRuntime(btRuntime); + } SharedHandle peerStorage (new DefaultPeerStorage(_option.get())); peerStorage->setBtRuntime(btRuntime); peerStorage->setPieceStorage(_pieceStorage); _peerStorage = peerStorage; - progressInfoFile->setPeerStorage(peerStorage); + if(!progressInfoFile.isNull()) { + progressInfoFile->setPeerStorage(peerStorage); + } SharedHandle btAnnounce (new DefaultBtAnnounce(_downloadContext, _option.get())); @@ -259,7 +270,21 @@ void RequestGroup::createInitialCommand(std::deque& commands, peerStorage, btAnnounce, btRuntime, - progressInfoFile)); + (progressInfoFile.isNull()? + _progressInfoFile: + SharedHandle + (progressInfoFile)))); + if(metadataGetMode) { + std::deque dhtCommands; + DHTSetup().setup(dhtCommands, e, _option.get()); + e->addCommand(dhtCommands); + + SharedHandle entry + (new BtCheckIntegrityEntry(this)); + entry->onDownloadIncomplete(commands, e); + + return; + } // Remove the control file if download file doesn't exist if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) { @@ -875,12 +900,12 @@ void RequestGroup::addPreDownloadHandler(const PreDownloadHandlerHandle& handler _preDownloadHandlers.push_back(handler); } -void RequestGroup::clearPostDowloadHandler() +void RequestGroup::clearPostDownloadHandler() { _postDownloadHandlers.clear(); } -void RequestGroup::clearPreDowloadHandler() +void RequestGroup::clearPreDownloadHandler() { _preDownloadHandlers.clear(); } @@ -934,11 +959,15 @@ void RequestGroup::reportDownloadFinished() #ifdef ENABLE_BITTORRENT if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) { TransferStat stat = calculateStat(); - double shareRatio = ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0; - _logger->notice(MSG_SHARE_RATIO_REPORT, - shareRatio, - util::abbrevSize(stat.getAllTimeUploadLength()).c_str(), - util::abbrevSize(getCompletedLength()).c_str()); + double shareRatio = + ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0; + const BDE& attrs = _downloadContext->getAttribute(bittorrent::BITTORRENT); + if(attrs.containsKey(bittorrent::METADATA)) { + _logger->notice(MSG_SHARE_RATIO_REPORT, + shareRatio, + util::abbrevSize(stat.getAllTimeUploadLength()).c_str(), + util::abbrevSize(getCompletedLength()).c_str()); + } } #endif // ENABLE_BITTORRENT } diff --git a/src/RequestGroup.h b/src/RequestGroup.h index 4f499be1..f390d1ae 100644 --- a/src/RequestGroup.h +++ b/src/RequestGroup.h @@ -169,6 +169,7 @@ private: // returns downloadresultcode::UNKNOWN_ERROR. downloadresultcode::RESULT downloadResult() const; public: + // The copy of option is stored in RequestGroup object. RequestGroup(const SharedHandle