diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2009-06-28 10:37:15 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2009-06-28 10:37:15 +0000 |
| commit | 5699b675268658ea958f7c2306e19849dff9bc41 (patch) | |
| tree | c654c18eef6f4361cccf13854895b88967aa33ea /src | |
| parent | 90471d68050ebd05439435330e4d0dbb19c6fd1e (diff) | |
2009-06-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Rewritten DownloadContext and removed SingleFileDownloadContext
and BtContext and its derived classes. BitTorrent specific
attributes are now set by DownloadContext::setAttribute() with key
bittorrent::BITTORRENT.
* src/AbstractBtMessage.cc
* src/AbstractBtMessage.h
* src/AbstractCommand.cc
* src/AbstractCommand.h
* src/AbstractProxyRequestCommand.cc
* src/AbstractProxyResponseCommand.cc
* src/ActivePeerConnectionCommand.cc
* src/ActivePeerConnectionCommand.h
* src/AnnounceList.cc
* src/BtCheckIntegrityEntry.cc
* src/BtConstants.h
* src/BtContext.h: Removed
* src/BtDependency.cc
* src/BtExtendedMessage.cc
* src/BtPieceMessage.cc
* src/BtPieceMessage.h
* src/BtPostDownloadHandler.cc
* src/BtRegistry.cc
* src/BtRegistry.h
* src/BtSetup.cc
* src/CheckIntegrityCommand.cc
* src/CheckIntegrityEntry.cc
* src/ChecksumCheckIntegrityEntry.cc
* src/ConsoleStatCalc.cc
* src/ContentTypeRequestGroupCriteria.cc
* src/DHTGetPeersCommand.cc
* src/DHTGetPeersCommand.h
* src/DHTPeerLookupTask.cc
* src/DHTPeerLookupTask.h
* src/DHTTaskFactory.h
* src/DHTTaskFactoryImpl.cc
* src/DHTTaskFactoryImpl.h
* src/DefaultBtAnnounce.cc
* src/DefaultBtAnnounce.h
* src/DefaultBtContext.cc: Removed
* src/DefaultBtContext.h: Removed
* src/DefaultBtInteractive.cc
* src/DefaultBtInteractive.h
* src/DefaultBtMessageDispatcher.cc
* src/DefaultBtMessageDispatcher.h
* src/DefaultBtMessageFactory.cc
* src/DefaultBtMessageFactory.h
* src/DefaultBtMessageReceiver.cc
* src/DefaultBtMessageReceiver.h
* src/DefaultBtProgressInfoFile.cc
* src/DefaultBtRequestFactory.cc
* src/DefaultBtRequestFactory.h
* src/DefaultExtensionMessageFactory.cc
* src/DefaultExtensionMessageFactory.h
* src/DefaultPeerStorage.cc
* src/DefaultPeerStorage.h
* src/DefaultPieceStorage.cc
* src/DefaultSegmentManFactory.cc
* src/DiskAdaptor.cc
* src/DiskAdaptor.h
* src/DownloadContext.cc
* src/DownloadContext.h
* src/DownloadEngine.cc
* src/DownloadEngineFactory.cc
* src/DownloadHandler.cc
* src/DownloadResult.h
* src/FileAllocationCommand.cc
* src/FileAllocationDispatcherCommand.cc
* src/FileAllocationEntry.cc
* src/FileEntry.h
* src/FillRequestGroupCommand.cc
* src/FtpDownloadCommand.cc
* src/FtpFinishDownloadCommand.cc
* src/FtpInitiateConnectionCommand.cc
* src/FtpNegotiationCommand.cc
* src/FtpTunnelRequestCommand.cc
* src/FtpTunnelResponseCommand.cc
* src/HandshakeExtensionMessage.cc
* src/HandshakeExtensionMessage.h
* src/HaveEraseCommand.cc
* src/HttpDownloadCommand.cc
* src/HttpInitiateConnectionCommand.cc
* src/HttpProxyRequestCommand.cc
* src/HttpProxyResponseCommand.cc
* src/HttpRequest.cc
* src/HttpRequest.h
* src/HttpRequestCommand.cc
* src/HttpResponseCommand.cc
* src/HttpServerBodyCommand.cc
* src/HttpServerCommand.cc
* src/HttpSkipResponseCommand.cc
* src/InitiateConnectionCommandFactory.cc
* src/InitiatorMSEHandshakeCommand.cc
* src/InitiatorMSEHandshakeCommand.h
* src/IteratableChecksumValidator.cc
* src/IteratableChecksumValidator.h
* src/IteratableChunkChecksumValidator.cc
* src/MSEHandshake.cc
* src/MSEHandshake.h
* src/Makefile.am
* src/Makefile.in
* src/Metalink2RequestGroup.cc
* src/MetalinkPostDownloadHandler.cc
* src/MultiDiskAdaptor.cc
* src/MultiDiskAdaptor.h
* src/MultiFileAllocationIterator.cc
* src/MultiUrlRequestInfo.cc
* src/PeerChokeCommand.cc
* src/PeerChokeCommand.h
* src/PeerInitiateConnectionCommand.cc
* src/PeerInitiateConnectionCommand.h
* src/PeerInteractionCommand.cc
* src/PeerInteractionCommand.h
* src/PeerReceiveHandshakeCommand.cc
* src/PieceHashCheckIntegrityEntry.cc
* src/RealtimeCommand.cc
* src/ReceiverMSEHandshakeCommand.cc
* src/RequestGroup.cc
* src/RequestGroup.h
* src/RequestGroupEntry.cc
* src/RequestGroupMan.cc
* src/SeedCheckCommand.cc
* src/SeedCheckCommand.h
* src/SegmentMan.cc
* src/ShareRatioSeedCriteria.h
* src/SingleFileDownloadContext.cc: Removed
* src/SingleFileDownloadContext.h: Removed
* src/SleepCommand.cc
* src/StreamCheckIntegrityEntry.cc
* src/TrackerWatcherCommand.cc
* src/TrackerWatcherCommand.h
* src/UnknownLengthPieceStorage.cc
* src/Util.cc
* src/Util.h
* src/XmlRpcMethodImpl.cc
* src/bittorrent_helper.cc
* src/bittorrent_helper.h
* src/download_helper.cc
* src/main.cc
* src/option_processing.cc
* test/BitfieldManTest.cc
* test/BittorrentHelperTest.cc
* test/BtCancelMessageTest.cc
* test/BtChokeMessageTest.cc
* test/BtDependencyTest.cc
* test/BtPieceMessageTest.cc
* test/BtPostDownloadHandlerTest.cc
* test/BtRegistryTest.cc
* test/BtRejectMessageTest.cc
* test/BtRequestMessageTest.cc
* test/DHTPeerAnnounceStorageTest.cc
* test/DefaultBtAnnounceTest.cc
* test/DefaultBtContextTest.cc: Removed
* test/DefaultBtMessageDispatcherTest.cc
* test/DefaultBtMessageFactoryTest.cc
* test/DefaultBtProgressInfoFileTest.cc
* test/DefaultBtRequestFactoryTest.cc
* test/DefaultExtensionMessageFactoryTest.cc
* test/DefaultPeerStorageTest.cc
* test/DefaultPieceStorageTest.cc
* test/DirectDiskAdaptorTest.cc
* test/DownloadContextTest.cc
* test/DownloadHandlerFactoryTest.cc
* test/DownloadHelperTest.cc
* test/HandshakeExtensionMessageTest.cc
* test/HttpRequestTest.cc
* test/HttpResponseTest.cc
* test/IteratableChecksumValidatorTest.cc
* test/IteratableChunkChecksumValidatorTest.cc
* test/MSEHandshakeTest.cc
* test/Makefile.am
* test/Makefile.in
* test/Metalink2RequestGroupTest.cc
* test/MetalinkPostDownloadHandlerTest.cc
* test/MockBtContext.h: Removed
* test/MockDHTTaskFactory.h
* test/MockDownloadContext.h: Removed
* test/MockPieceStorage.h
* test/MultiDiskAdaptorTest.cc
* test/MultiFileAllocationIteratorTest.cc
* test/RequestGroupManTest.cc
* test/RequestGroupTest.cc
* test/SegmentManTest.cc
* test/ShareRatioSeedCriteriaTest.cc
* test/SingleFileDownloadContextTest.cc: Removed
* test/UtilTest.cc
* test/XmlRpcMethodTest.cc
Diffstat (limited to 'src')
135 files changed, 1582 insertions, 1970 deletions
diff --git a/src/AbstractBtMessage.cc b/src/AbstractBtMessage.cc index f2aa432b..d68d49b1 100644 --- a/src/AbstractBtMessage.cc +++ b/src/AbstractBtMessage.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "AbstractBtMessage.h" #include "Peer.h" -#include "BtContext.h" #include "PieceStorage.h" #include "BtMessageValidator.h" #include "LogFactory.h" @@ -73,11 +72,6 @@ AbstractBtMessage::setBtMessageValidator(const SharedHandle<BtMessageValidator>& this->validator = validator; } -void AbstractBtMessage::setBtContext(const SharedHandle<BtContext>& btContext) -{ - this->btContext = btContext; -} - void AbstractBtMessage::setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage) { this->pieceStorage = pieceStorage; diff --git a/src/AbstractBtMessage.h b/src/AbstractBtMessage.h index 16fa4013..588bc96e 100644 --- a/src/AbstractBtMessage.h +++ b/src/AbstractBtMessage.h @@ -41,7 +41,6 @@ namespace aria2 { -class BtContext; class PieceStorage; class Peer; class BtMessageDispatcher; @@ -60,8 +59,6 @@ protected: std::string _name; - SharedHandle<BtContext> btContext; - SharedHandle<PieceStorage> pieceStorage; SharedHandle<Peer> peer; @@ -137,13 +134,6 @@ public: void setBtMessageValidator(const SharedHandle<BtMessageValidator>& validator); - void setBtContext(const SharedHandle<BtContext>& btContext); - - const SharedHandle<BtContext>& getBtContext() const - { - return btContext; - } - void setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage); void setBtMessageDispatcher(const WeakHandle<BtMessageDispatcher>& dispatcher); diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index b1004a48..57f1a80a 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -36,7 +36,6 @@ #include <algorithm> -#include "RequestGroup.h" #include "Request.h" #include "DownloadEngine.h" #include "Option.h" @@ -231,9 +230,9 @@ bool AbstractCommand::execute() { void AbstractCommand::tryReserved() { _requestGroup->removeServerHost(cuid); - if(_requestGroup->getDownloadContext()->getFileMode() == DownloadContext::SINGLE) { + if(_requestGroup->getDownloadContext()->getFileEntries().size() == 1) { const SharedHandle<FileEntry>& entry = - _requestGroup->getDownloadContext()->getFileEntries().front(); + _requestGroup->getDownloadContext()->getFirstFileEntry(); // Don't create new command if currently file length is unknown // and there are no URI left. Because file length is unknown, we // can assume that there are no in-flight request object. diff --git a/src/AbstractCommand.h b/src/AbstractCommand.h index ba7a7aa4..d7ced6d2 100644 --- a/src/AbstractCommand.h +++ b/src/AbstractCommand.h @@ -39,12 +39,12 @@ #include "SharedHandle.h" #include "TimeA2.h" #include "FileEntry.h" +#include "RequestGroup.h" namespace aria2 { class Request; class DownloadEngine; -class RequestGroup; class Segment; class Exception; class SocketCore; @@ -122,6 +122,11 @@ protected: const std::string& resolveProxyMethod(const std::string& protocol) const; const SharedHandle<Option>& getOption() const; + + const SharedHandle<DownloadContext>& getDownloadContext() const + { + return _requestGroup->getDownloadContext(); + } private: bool checkSocketIsReadable; bool checkSocketIsWritable; diff --git a/src/AbstractProxyRequestCommand.cc b/src/AbstractProxyRequestCommand.cc index 4fc3fadc..698f5bb4 100644 --- a/src/AbstractProxyRequestCommand.cc +++ b/src/AbstractProxyRequestCommand.cc @@ -45,6 +45,7 @@ #include "CookieStorage.h" #include "AuthConfigFactory.h" #include "AuthConfig.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/AbstractProxyResponseCommand.cc b/src/AbstractProxyResponseCommand.cc index 00520cc6..f6b1ac13 100644 --- a/src/AbstractProxyResponseCommand.cc +++ b/src/AbstractProxyResponseCommand.cc @@ -45,6 +45,7 @@ #include "DlRetryEx.h" #include "message.h" #include "HttpHeader.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/ActivePeerConnectionCommand.cc b/src/ActivePeerConnectionCommand.cc index 7c76ab4a..7f5709d8 100644 --- a/src/ActivePeerConnectionCommand.cc +++ b/src/ActivePeerConnectionCommand.cc @@ -36,7 +36,6 @@ #include "PeerInitiateConnectionCommand.h" #include "message.h" #include "DownloadEngine.h" -#include "BtContext.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "BtRuntime.h" @@ -48,6 +47,7 @@ #include "SocketCore.h" #include "BtAnnounce.h" #include "RequestGroup.h" +#include "DownloadContext.h" namespace aria2 { @@ -55,12 +55,10 @@ ActivePeerConnectionCommand::ActivePeerConnectionCommand (int cuid, RequestGroup* requestGroup, DownloadEngine* e, - const BtContextHandle& btContext, time_t interval) : Command(cuid), _requestGroup(requestGroup), - _btContext(btContext), interval(interval), e(e), _numNewConnection(5) @@ -130,7 +128,7 @@ void ActivePeerConnectionCommand::connectToPeer(const PeerHandle& peer) peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e, - _btContext, _btRuntime); + _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); diff --git a/src/ActivePeerConnectionCommand.h b/src/ActivePeerConnectionCommand.h index d8c7c452..3f22b6a6 100644 --- a/src/ActivePeerConnectionCommand.h +++ b/src/ActivePeerConnectionCommand.h @@ -44,7 +44,6 @@ namespace aria2 { class RequestGroup; class DownloadEngine; class Peer; -class BtContext; class BtRuntime; class PieceStorage; class PeerStorage; @@ -53,7 +52,6 @@ class BtAnnounce; class ActivePeerConnectionCommand : public Command { private: RequestGroup* _requestGroup; - SharedHandle<BtContext> _btContext; SharedHandle<BtRuntime> _btRuntime; SharedHandle<PieceStorage> _pieceStorage; SharedHandle<PeerStorage> _peerStorage; @@ -67,7 +65,6 @@ public: ActivePeerConnectionCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, time_t interval); virtual ~ActivePeerConnectionCommand(); diff --git a/src/AnnounceList.cc b/src/AnnounceList.cc index ffe97305..e63d0082 100644 --- a/src/AnnounceList.cc +++ b/src/AnnounceList.cc @@ -39,6 +39,7 @@ #include "A2STR.h" #include "SimpleRandomizer.h" #include "bencode.h" +#include "Util.h" namespace aria2 { @@ -72,7 +73,7 @@ void AnnounceList::reconfigure(const BDE& announceList) elemItr != elemList.listEnd(); ++elemItr) { const BDE& data = *elemItr; if(data.isString()) { - urls.push_back(data.s()); + urls.push_back(Util::trim(data.s())); } } if(!urls.empty()) { diff --git a/src/BtCheckIntegrityEntry.cc b/src/BtCheckIntegrityEntry.cc index 3197e6c2..8aa1277c 100644 --- a/src/BtCheckIntegrityEntry.cc +++ b/src/BtCheckIntegrityEntry.cc @@ -40,6 +40,7 @@ #include "DiskAdaptor.h" #include "prefs.h" #include "Option.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/BtConstants.h b/src/BtConstants.h index 3d1b9cf9..28db953a 100644 --- a/src/BtConstants.h +++ b/src/BtConstants.h @@ -41,6 +41,10 @@ typedef std::map<std::string, uint8_t> Extensions; +#define INFO_HASH_LENGTH 20 + +#define PIECE_HASH_LENGTH 20 + #define PEER_ID_LENGTH 20 #define INFO_HASH_LENGTH 20 diff --git a/src/BtContext.h b/src/BtContext.h deleted file mode 100644 index 858b11cd..00000000 --- a/src/BtContext.h +++ /dev/null @@ -1,97 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#ifndef _D_BT_CONTEXT_H_ -#define _D_BT_CONTEXT_H_ - -#include "DownloadContext.h" - -#include <utility> -#include <deque> - -#include "IntSequence.h" - -namespace aria2 { - -class AnnounceTier; -class RequestGroup; - -class BtContext:public DownloadContext { -protected: - bool _private; -public: - BtContext():_private(false) {} - - virtual ~BtContext() {} - - virtual const unsigned char* getInfoHash() const = 0; - - virtual size_t getInfoHashLength() const = 0; - - virtual const std::string& getInfoHashAsString() const = 0; - - virtual const std::deque<SharedHandle<AnnounceTier> >& - getAnnounceTiers() const = 0; - - virtual void load(const std::string& torrentFile, - const std::string& overrideName = "") = 0; - - /** - * Returns the peer id of localhost, 20 byte length - */ - virtual const unsigned char* getPeerId() = 0; - - bool isPrivate() const - { - return _private; - } - - virtual void computeFastSet - (std::deque<size_t>& fastSet, const std::string& ipaddr, size_t fastSetSize) = 0; - - virtual RequestGroup* getOwnerRequestGroup() = 0; - - virtual std::deque<std::pair<std::string, uint16_t> >& getNodes() = 0; - - virtual const std::string& getName() const = 0; - - virtual void setFileFilter(IntSequence seq) = 0; -}; - -class BtContext; -typedef SharedHandle<BtContext> BtContextHandle; - -} // namespace aria2 - -#endif // _D_BT_CONTEXT_H_ diff --git a/src/BtDependency.cc b/src/BtDependency.cc index 0109f1de..d8f5c0d3 100644 --- a/src/BtDependency.cc +++ b/src/BtDependency.cc @@ -37,7 +37,7 @@ #include "Option.h" #include "LogFactory.h" #include "Logger.h" -#include "DefaultBtContext.h" +#include "DownloadContext.h" #include "RecoverableException.h" #include "message.h" #include "prefs.h" @@ -45,6 +45,8 @@ #include "PieceStorage.h" #include "DiskAdaptor.h" #include "File.h" +#include "bittorrent_helper.h" +#include "DlAbortEx.h" namespace aria2 { @@ -62,39 +64,38 @@ bool BtDependency::resolve() RequestGroupHandle dependee = _dependee; // cut reference here _dependee.reset(); - DefaultBtContextHandle btContext(new DefaultBtContext()); - btContext->setDir(_dependant->getDownloadContext()->getDir()); + SharedHandle<DownloadContext> context(new DownloadContext()); + context->setDir(_dependant->getDownloadContext()->getDir()); try { - DiskAdaptorHandle diskAdaptor = dependee->getPieceStorage()->getDiskAdaptor(); + DiskAdaptorHandle diskAdaptor = + dependee->getPieceStorage()->getDiskAdaptor(); diskAdaptor->openExistingFile(); std::string content = Util::toString(diskAdaptor); - - std::string overrideName; - if(Util::startsWith(_dependant->getDownloadContext()->getActualBasePath(), - _dependant->getDownloadContext()->getDir())) { - overrideName = - _dependant->getDownloadContext()->getActualBasePath().substr - (_dependant->getDownloadContext()->getDir().size()); - if(Util::startsWith(overrideName, "/")) { - overrideName = overrideName.substr(1); - } + bittorrent::loadFromMemory + (content, context, File(dependee->getFirstFilePath()).getBasename()); + if(context->getFileEntries().size() != + _dependant->getDownloadContext()->getFileEntries().size()) { + throw DL_ABORT_EX("The number of file in torrent doesn't match to" + " the dependant."); } - btContext->loadFromMemory(content, - File(dependee->getFilePath()).getBasename(), - overrideName); - if(_dependant->getOption()->defined(PREF_PEER_ID_PREFIX)) { - btContext->setPeerIdPrefix - (_dependant->getOption()->get(PREF_PEER_ID_PREFIX)); + // Copy file path in _dependant's FileEntries to newly created + // context's FileEntries to endorse the path structure of + // _dependant. + for(std::vector<SharedHandle<FileEntry> >::const_iterator s = + _dependant->getDownloadContext()->getFileEntries().begin(), + d = context->getFileEntries().begin(); + d != context->getFileEntries().end(); ++s, ++d) { + (*d)->setPath((*s)->getPath()); } } catch(RecoverableException& e) { _logger->error(EX_EXCEPTION_CAUGHT, e); - _logger->debug("BtDependency for GID#%d failed. Go without Bt.", - _dependant->getGID()); + _logger->info("BtDependency for GID#%d failed. Go without Bt.", + _dependant->getGID()); return true; } _logger->debug("Dependency resolved for GID#%d", _dependant->getGID()); - _dependant->setDownloadContext(btContext); - btContext->setOwnerRequestGroup(_dependant.get()); + _dependant->setDownloadContext(context); + context->setOwnerRequestGroup(_dependant.get()); return true; } else if(_dependee->getNumCommand() == 0) { // _dependee's download failed. diff --git a/src/BtExtendedMessage.cc b/src/BtExtendedMessage.cc index afa19a35..39d61028 100644 --- a/src/BtExtendedMessage.cc +++ b/src/BtExtendedMessage.cc @@ -41,7 +41,6 @@ #include "ExtensionMessageFactory.h" #include "PeerMessageUtil.h" #include "Peer.h" -#include "BtContext.h" #include "DlAbortEx.h" #include "message.h" #include "Util.h" diff --git a/src/BtPieceMessage.cc b/src/BtPieceMessage.cc index 970a35dd..9381d6e4 100644 --- a/src/BtPieceMessage.cc +++ b/src/BtPieceMessage.cc @@ -47,13 +47,13 @@ #include "Logger.h" #include "Peer.h" #include "Piece.h" -#include "BtContext.h" #include "PieceStorage.h" #include "BtMessageDispatcher.h" #include "BtMessageFactory.h" #include "BtRequestFactory.h" #include "PeerConnection.h" #include "StringFormat.h" +#include "DownloadContext.h" namespace aria2 { @@ -85,7 +85,7 @@ void BtPieceMessage::doReceivedAction() { peer->snubbing(false); peer->updateLatency(slot.getLatencyInMillis()); PieceHandle piece = pieceStorage->getPiece(index); - off_t offset = (off_t)index*btContext->getPieceLength()+begin; + off_t offset = (off_t)index*_downloadContext->getPieceLength()+begin; logger->debug(MSG_PIECE_RECEIVED, cuid, index, begin, blockLength, offset, slot.getBlockIndex()); pieceStorage->getDiskAdaptor()->writeData(block, blockLength, offset); @@ -143,7 +143,7 @@ void BtPieceMessage::send() { getMessageHeader(); peerConnection->sendMessage(msgHeader, getMessageHeaderLength()); off_t pieceDataOffset = - (off_t)index*btContext->getPieceLength()+begin; + (off_t)index*_downloadContext->getPieceLength()+begin; size_t writtenLength = sendPieceData(pieceDataOffset, blockLength); logger->debug("msglength = %lu bytes", static_cast<unsigned long>(getMessageHeaderLength()+ @@ -176,12 +176,13 @@ bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) { if(piece->isHashCalculated()) { logger->debug("Hash is available!! index=%lu", static_cast<unsigned long>(piece->getIndex())); - return piece->getHashString() == btContext->getPieceHash(piece->getIndex()); + return + piece->getHashString()==_downloadContext->getPieceHash(piece->getIndex()); } else { - off_t offset = (off_t)piece->getIndex()*btContext->getPieceLength(); + off_t offset = (off_t)piece->getIndex()*_downloadContext->getPieceLength(); return MessageDigestHelper::staticSHA1Digest(pieceStorage->getDiskAdaptor(), offset, piece->getLength()) - == btContext->getPieceHash(piece->getIndex()); + == _downloadContext->getPieceHash(piece->getIndex()); } } @@ -203,7 +204,7 @@ void BtPieceMessage::erasePieceOnDisk(const PieceHandle& piece) { size_t BUFSIZE = 4096; unsigned char buf[BUFSIZE]; memset(buf, 0, BUFSIZE); - off_t offset = (off_t)piece->getIndex()*btContext->getPieceLength(); + off_t offset = (off_t)piece->getIndex()*_downloadContext->getPieceLength(); div_t res = div(piece->getLength(), BUFSIZE); for(int i = 0; i < res.quot; ++i) { pieceStorage->getDiskAdaptor()->writeData(buf, BUFSIZE, offset); @@ -255,4 +256,10 @@ void BtPieceMessage::onCancelSendingPieceEvent } } +void BtPieceMessage::setDownloadContext +(const SharedHandle<DownloadContext>& downloadContext) +{ + _downloadContext = downloadContext; +} + } // namespace aria2 diff --git a/src/BtPieceMessage.h b/src/BtPieceMessage.h index 9b543035..b87cc40b 100644 --- a/src/BtPieceMessage.h +++ b/src/BtPieceMessage.h @@ -41,6 +41,7 @@ namespace aria2 { class Piece; class BtPieceMessage; +class DownloadContext; typedef SharedHandle<BtPieceMessage> BtPieceMessageHandle; @@ -51,6 +52,7 @@ private: uint32_t blockLength; unsigned char* block; unsigned char* msgHeader; + SharedHandle<DownloadContext> _downloadContext; static size_t MESSAGE_HEADER_LENGTH; @@ -100,6 +102,8 @@ public: void setBlockLength(size_t blockLength) { this->blockLength = blockLength; } + void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext); + static BtPieceMessageHandle create(const unsigned char* data, size_t dataLength); virtual void doReceivedAction(); diff --git a/src/BtPostDownloadHandler.cc b/src/BtPostDownloadHandler.cc index 29685e6e..5e733d75 100644 --- a/src/BtPostDownloadHandler.cc +++ b/src/BtPostDownloadHandler.cc @@ -33,7 +33,6 @@ */ /* copyright --> */ #include "BtPostDownloadHandler.h" -#include "DefaultBtContext.h" #include "prefs.h" #include "RequestGroup.h" #include "Option.h" @@ -45,6 +44,8 @@ #include "Util.h" #include "ContentTypeRequestGroupCriteria.h" #include "Exception.h" +#include "DownloadContext.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -64,7 +65,7 @@ void BtPostDownloadHandler::getNextRequestGroups { const SharedHandle<Option>& op = requestGroup->getOption(); _logger->debug("Generating RequestGroups for Torrent file %s", - requestGroup->getFilePath().c_str()); + requestGroup->getFirstFilePath().c_str()); RequestGroupHandle rg(new RequestGroup(op, std::deque<std::string>())); std::string content; @@ -76,14 +77,12 @@ void BtPostDownloadHandler::getNextRequestGroups requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); throw; } - DefaultBtContextHandle btContext(new DefaultBtContext()); - btContext->setDir(requestGroup->getDownloadContext()->getDir()); - btContext->loadFromMemory(content, File(requestGroup->getFilePath()).getBasename()); - if(op->defined(PREF_PEER_ID_PREFIX)) { - btContext->setPeerIdPrefix(op->get(PREF_PEER_ID_PREFIX)); - } - rg->setDownloadContext(btContext); - btContext->setOwnerRequestGroup(rg.get()); + SharedHandle<DownloadContext> context(new DownloadContext()); + context->setDir(requestGroup->getDownloadContext()->getDir()); + bittorrent::loadFromMemory(content, context, + File(requestGroup->getFirstFilePath()).getBasename()); + rg->setDownloadContext(context); + context->setOwnerRequestGroup(rg.get()); groups.push_back(rg); } diff --git a/src/BtRegistry.cc b/src/BtRegistry.cc index 0c90a20c..158da62b 100644 --- a/src/BtRegistry.cc +++ b/src/BtRegistry.cc @@ -34,7 +34,7 @@ /* copyright --> */ #include "BtRegistry.h" #include "DlAbortEx.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "BtAnnounce.h" @@ -43,10 +43,10 @@ namespace aria2 { -SharedHandle<BtContext> -BtRegistry::getBtContext(const std::string& infoHash) const +SharedHandle<DownloadContext> +BtRegistry::getDownloadContext(const std::string& infoHash) const { - return get(infoHash)._btContext; + return get(infoHash)._downloadContext; } void BtRegistry::put(const std::string& infoHash, const BtObject& obj) diff --git a/src/BtRegistry.h b/src/BtRegistry.h index bc124b3f..3b3858f8 100644 --- a/src/BtRegistry.h +++ b/src/BtRegistry.h @@ -49,23 +49,23 @@ class PieceStorage; class BtAnnounce; class BtRuntime; class BtProgressInfoFile; -class BtContext; +class DownloadContext; struct BtObject { - SharedHandle<BtContext> _btContext; + SharedHandle<DownloadContext> _downloadContext; SharedHandle<PieceStorage> _pieceStorage; SharedHandle<PeerStorage> _peerStorage; SharedHandle<BtAnnounce> _btAnnounce; SharedHandle<BtRuntime> _btRuntime; SharedHandle<BtProgressInfoFile> _btProgressInfoFile; - BtObject(const SharedHandle<BtContext>& btContext, + BtObject(const SharedHandle<DownloadContext>& downloadContext, const SharedHandle<PieceStorage>& pieceStorage, const SharedHandle<PeerStorage>& peerStorage, const SharedHandle<BtAnnounce>& btAnnounce, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<BtProgressInfoFile>& btProgressInfoFile): - _btContext(btContext), + _downloadContext(downloadContext), _pieceStorage(pieceStorage), _peerStorage(peerStorage), _btAnnounce(btAnnounce), @@ -76,7 +76,7 @@ struct BtObject { bool isNull() const { - return _btContext.isNull() && + return _downloadContext.isNull() && _pieceStorage.isNull() && _peerStorage.isNull() && _btAnnounce.isNull() && @@ -89,19 +89,21 @@ class BtRegistry { private: std::map<std::string, BtObject> _pool; public: - SharedHandle<BtContext> getBtContext(const std::string& infoHash) const; + SharedHandle<DownloadContext> + getDownloadContext(const std::string& infoHash) const; void put(const std::string& infoHash, const BtObject& obj); BtObject get(const std::string& infoHash) const; template<typename OutputIterator> - void getAllBtContext(OutputIterator dest) + OutputIterator getAllDownloadContext(OutputIterator dest) { for(std::map<std::string, BtObject>::const_iterator i = _pool.begin(); i != _pool.end(); ++i) { - *dest++ = (*i).second._btContext; + *dest++ = (*i).second._downloadContext; } + return dest; } void removeAll(); diff --git a/src/BtSetup.cc b/src/BtSetup.cc index 26472d98..ea339780 100644 --- a/src/BtSetup.cc +++ b/src/BtSetup.cc @@ -58,6 +58,7 @@ #include "BtProgressInfoFile.h" #include "BtAnnounce.h" #include "BtRuntime.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -68,11 +69,13 @@ void BtSetup::setup(std::deque<Command*>& commands, DownloadEngine* e, const Option* option) { - BtContextHandle btContext(dynamic_pointer_cast<BtContext>(requestGroup->getDownloadContext())); - if(btContext.isNull()) { + if(!requestGroup->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) { return; } - BtObject btObject = e->getBtRegistry()->get(btContext->getInfoHashAsString()); + const BDE& torrentAttrs = + requestGroup->getDownloadContext()->getAttribute(bittorrent::BITTORRENT); + BtObject btObject = + e->getBtRegistry()->get(torrentAttrs[bittorrent::INFO_HASH].s()); SharedHandle<PieceStorage> pieceStorage = btObject._pieceStorage; SharedHandle<PeerStorage> peerStorage = btObject._peerStorage; SharedHandle<BtRuntime> btRuntime = btObject._btRuntime; @@ -80,7 +83,7 @@ void BtSetup::setup(std::deque<Command*>& commands, // commands { TrackerWatcherCommand* c = - new TrackerWatcherCommand(e->newCUID(), requestGroup, e, btContext); + new TrackerWatcherCommand(e->newCUID(), requestGroup, e); c->setPeerStorage(peerStorage); c->setPieceStorage(pieceStorage); c->setBtRuntime(btRuntime); @@ -90,7 +93,7 @@ void BtSetup::setup(std::deque<Command*>& commands, } { PeerChokeCommand* c = - new PeerChokeCommand(e->newCUID(), e, btContext); + new PeerChokeCommand(e->newCUID(), e); c->setPeerStorage(peerStorage); c->setBtRuntime(btRuntime); @@ -98,8 +101,7 @@ void BtSetup::setup(std::deque<Command*>& commands, } { ActivePeerConnectionCommand* c = - new ActivePeerConnectionCommand(e->newCUID(), requestGroup, e, btContext, - 10); + new ActivePeerConnectionCommand(e->newCUID(), requestGroup, e, 10); c->setBtRuntime(btRuntime); c->setPieceStorage(pieceStorage); c->setPeerStorage(peerStorage); @@ -108,11 +110,11 @@ void BtSetup::setup(std::deque<Command*>& commands, commands.push_back(c); } - if(!btContext->isPrivate() && DHTSetup::initialized()) { - DHTRegistry::_peerAnnounceStorage->addPeerAnnounce(btContext->getInfoHash(), - peerStorage); + if(torrentAttrs[bittorrent::PRIVATE].i() == 0 && DHTSetup::initialized()) { + DHTRegistry::_peerAnnounceStorage->addPeerAnnounce + (torrentAttrs[bittorrent::INFO_HASH].uc(), peerStorage); DHTGetPeersCommand* command = - new DHTGetPeersCommand(e->newCUID(), requestGroup, e, btContext); + new DHTGetPeersCommand(e->newCUID(), requestGroup, e); command->setTaskQueue(DHTRegistry::_taskQueue); command->setTaskFactory(DHTRegistry::_taskFactory); command->setBtRuntime(btRuntime); @@ -129,7 +131,7 @@ void BtSetup::setup(std::deque<Command*>& commands, if(ratio > 0.0) { SharedHandle<ShareRatioSeedCriteria> cri (new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO), - btContext)); + requestGroup->getDownloadContext())); cri->setPieceStorage(pieceStorage); cri->setPeerStorage(peerStorage); @@ -138,7 +140,7 @@ void BtSetup::setup(std::deque<Command*>& commands, } if(unionCri->getSeedCriterion().size() > 0) { SeedCheckCommand* c = - new SeedCheckCommand(e->newCUID(), requestGroup, e, btContext, unionCri); + new SeedCheckCommand(e->newCUID(), requestGroup, e, unionCri); c->setPieceStorage(pieceStorage); c->setBtRuntime(btRuntime); commands.push_back(c); diff --git a/src/CheckIntegrityCommand.cc b/src/CheckIntegrityCommand.cc index 4c2858e1..d7b92a2e 100644 --- a/src/CheckIntegrityCommand.cc +++ b/src/CheckIntegrityCommand.cc @@ -39,6 +39,7 @@ #include "Logger.h" #include "message.h" #include "prefs.h" +#include "DownloadContext.h" namespace aria2 { @@ -62,13 +63,13 @@ bool CheckIntegrityCommand::executeInternal() if(_requestGroup->downloadFinished()) { logger->notice(MSG_VERIFICATION_SUCCESSFUL, - _requestGroup->getFilePath().c_str()); + _requestGroup->getDownloadContext()->getBasePath().c_str()); std::deque<Command*> commands; _entry->onDownloadFinished(commands, _e); _e->addCommand(commands); } else { logger->error(MSG_VERIFICATION_FAILED, - _requestGroup->getFilePath().c_str()); + _requestGroup->getDownloadContext()->getBasePath().c_str()); std::deque<Command*> commands; _entry->onDownloadIncomplete(commands,_e); _e->addCommand(commands); @@ -86,7 +87,7 @@ bool CheckIntegrityCommand::handleException(Exception& e) _e->_checkIntegrityMan->dropPickedEntry(); logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid); logger->error(MSG_DOWNLOAD_NOT_COMPLETE, - cuid, _requestGroup->getFilePath().c_str()); + cuid, _requestGroup->getDownloadContext()->getBasePath().c_str()); return true; } diff --git a/src/CheckIntegrityEntry.cc b/src/CheckIntegrityEntry.cc index 85b493b9..2d2eb569 100644 --- a/src/CheckIntegrityEntry.cc +++ b/src/CheckIntegrityEntry.cc @@ -41,6 +41,7 @@ #include "FileAllocationEntry.h" #include "DownloadEngine.h" #include "Option.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/ChecksumCheckIntegrityEntry.cc b/src/ChecksumCheckIntegrityEntry.cc index a7e62a1f..7a0897fa 100644 --- a/src/ChecksumCheckIntegrityEntry.cc +++ b/src/ChecksumCheckIntegrityEntry.cc @@ -34,7 +34,7 @@ /* copyright --> */ #include "ChecksumCheckIntegrityEntry.h" #include "RequestGroup.h" -#include "SingleFileDownloadContext.h" +#include "DownloadContext.h" #include "FileEntry.h" #include "IteratableChecksumValidator.h" #include "DownloadEngine.h" @@ -49,18 +49,15 @@ ChecksumCheckIntegrityEntry::~ChecksumCheckIntegrityEntry() {} bool ChecksumCheckIntegrityEntry::isValidationReady() { - SingleFileDownloadContextHandle dctx - (dynamic_pointer_cast<SingleFileDownloadContext>(_requestGroup->getDownloadContext())); - return !dctx.isNull() && dctx->getChecksum().size() > 0 && - dctx->getChecksumHashAlgo().size() > 0; + return !_requestGroup->getDownloadContext()->getChecksum().empty() && + !_requestGroup->getDownloadContext()->getChecksumHashAlgo().empty(); } void ChecksumCheckIntegrityEntry::initValidator() { - SingleFileDownloadContextHandle dctx - (dynamic_pointer_cast<SingleFileDownloadContext>(_requestGroup->getDownloadContext())); - _validator.reset(new IteratableChecksumValidator(dctx, - _requestGroup->getPieceStorage())); + _validator.reset(new IteratableChecksumValidator + (_requestGroup->getDownloadContext(), + _requestGroup->getPieceStorage())); _validator->init(); } diff --git a/src/ConsoleStatCalc.cc b/src/ConsoleStatCalc.cc index c6c94631..8add12b6 100644 --- a/src/ConsoleStatCalc.cc +++ b/src/ConsoleStatCalc.cc @@ -57,8 +57,9 @@ #include "CheckIntegrityMan.h" #include "CheckIntegrityEntry.h" #include "Util.h" +#include "DownloadContext.h" #ifdef ENABLE_BITTORRENT -# include "BtContext.h" +# include "bittorrent_helper.h" # include "Peer.h" # include "PeerStorage.h" # include "BtRegistry.h" @@ -83,10 +84,8 @@ static void printProgress << "#" << rg->getGID() << " "; #ifdef ENABLE_BITTORRENT - SharedHandle<BtContext> btctx = - dynamic_pointer_cast<BtContext>(rg->getDownloadContext()); - - if(!btctx.isNull() && rg->downloadFinished()) { + if(rg->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT) && + rg->downloadFinished()) { o << "SEEDING" << "(" << "ratio:"; if(rg->getCompletedLength() > 0) { o << std::fixed << std::setprecision(1) @@ -114,9 +113,11 @@ static void printProgress << "CN:" << rg->getNumConnection(); #ifdef ENABLE_BITTORRENT - if(!btctx.isNull()) { + if(rg->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) { + const BDE& torrentAttrs = + rg->getDownloadContext()->getAttribute(bittorrent::BITTORRENT); SharedHandle<PeerStorage> ps = - e->getBtRegistry()->get(btctx->getInfoHashAsString())._peerStorage; + e->getBtRegistry()->get(torrentAttrs[bittorrent::INFO_HASH].s())._peerStorage; std::deque<SharedHandle<Peer> > peers; ps->getActivePeers(peers); o << " " << "SEED:" @@ -155,7 +156,7 @@ public: { const char SEP_CHAR = '-'; printProgress(std::cout, rg, _e); - const std::deque<SharedHandle<FileEntry> >& fileEntries = + const std::vector<SharedHandle<FileEntry> >& fileEntries = rg->getDownloadContext()->getFileEntries(); std::cout << "\n" << "FILE: "; diff --git a/src/ContentTypeRequestGroupCriteria.cc b/src/ContentTypeRequestGroupCriteria.cc index cd06ab4b..d479bc88 100644 --- a/src/ContentTypeRequestGroupCriteria.cc +++ b/src/ContentTypeRequestGroupCriteria.cc @@ -34,9 +34,9 @@ /* copyright --> */ #include "ContentTypeRequestGroupCriteria.h" #include "RequestGroup.h" -#include "SingleFileDownloadContext.h" #include "Util.h" #include "FileEntry.h" +#include "DownloadContext.h" namespace aria2 { @@ -49,15 +49,15 @@ ContentTypeRequestGroupCriteria::~ContentTypeRequestGroupCriteria() {} bool ContentTypeRequestGroupCriteria::match(const RequestGroup* requestGroup) const { - if(forwardMatch(requestGroup->getFilePath(), _extensions)) { + if(requestGroup->getDownloadContext()->getFileEntries().size() != 1) { + return false; + } + if(forwardMatch(requestGroup->getFirstFilePath(), _extensions)) { return true; } else { - SingleFileDownloadContextHandle dctx(dynamic_pointer_cast<SingleFileDownloadContext>(requestGroup->getDownloadContext())); - if(dctx.isNull()) { - return false; - } else { - return exactMatch(dctx->getContentType(), _contentTypes); - } + return exactMatch + (requestGroup->getDownloadContext()->getFirstFileEntry()->getContentType(), + _contentTypes); } } diff --git a/src/DHTGetPeersCommand.cc b/src/DHTGetPeersCommand.cc index 594ff8ff..ee65dd84 100644 --- a/src/DHTGetPeersCommand.cc +++ b/src/DHTGetPeersCommand.cc @@ -40,21 +40,20 @@ #include "RequestGroup.h" #include "DHTNode.h" #include "DHTNodeLookupEntry.h" -#include "BtContext.h" #include "BtRuntime.h" #include "PeerStorage.h" #include "Peer.h" #include "Logger.h" +#include "bittorrent_helper.h" +#include "DownloadContext.h" namespace aria2 { DHTGetPeersCommand::DHTGetPeersCommand(int32_t cuid, RequestGroup* requestGroup, - DownloadEngine* e, - const BtContextHandle& ctx): + DownloadEngine* e): Command(cuid), _requestGroup(requestGroup), - _btContext(ctx), _e(e), _numRetry(0), _lastGetPeerTime(0) @@ -76,9 +75,9 @@ bool DHTGetPeersCommand::execute() ((_numRetry > 0 && _lastGetPeerTime.elapsed(RETRY_INTERVAL)) || _lastGetPeerTime.elapsed(GET_PEER_INTERVAL))) { logger->debug("Issuing PeerLookup for infoHash=%s", - _btContext->getInfoHashAsString().c_str()); - _task = _taskFactory->createPeerLookupTask(_btContext, _btRuntime, - _peerStorage); + bittorrent::getInfoHashString(_requestGroup->getDownloadContext()).c_str()); + _task = _taskFactory->createPeerLookupTask + (_requestGroup->getDownloadContext(), _btRuntime, _peerStorage); _taskQueue->addPeriodicTask2(_task); } else if(!_task.isNull() && _task->finished()) { _lastGetPeerTime.reset(); diff --git a/src/DHTGetPeersCommand.h b/src/DHTGetPeersCommand.h index f29bbc8e..dee0e21a 100644 --- a/src/DHTGetPeersCommand.h +++ b/src/DHTGetPeersCommand.h @@ -47,7 +47,6 @@ class DHTTaskFactory; class DHTTask; class DownloadEngine; class RequestGroup; -class BtContext; class BtRuntime; class PeerStorage; @@ -61,8 +60,6 @@ private: RequestGroup* _requestGroup; - SharedHandle<BtContext> _btContext; - SharedHandle<BtRuntime> _btRuntime; SharedHandle<PeerStorage> _peerStorage; @@ -80,8 +77,7 @@ private: Time _lastGetPeerTime; public: DHTGetPeersCommand(int32_t cuid, RequestGroup* requestGroup, - DownloadEngine* e, - const SharedHandle<BtContext>& ctx); + DownloadEngine* e); virtual ~DHTGetPeersCommand(); diff --git a/src/DHTPeerLookupTask.cc b/src/DHTPeerLookupTask.cc index 6869498a..6d4a0a9c 100644 --- a/src/DHTPeerLookupTask.cc +++ b/src/DHTPeerLookupTask.cc @@ -43,15 +43,15 @@ #include "DHTMessageCallback.h" #include "PeerStorage.h" #include "BtRuntime.h" -#include "BtContext.h" #include "Util.h" #include "DHTBucket.h" +#include "bittorrent_helper.h" namespace aria2 { -DHTPeerLookupTask::DHTPeerLookupTask(const SharedHandle<BtContext>& btContext): - DHTAbstractNodeLookupTask(btContext->getInfoHash()), - _ctx(btContext) {} +DHTPeerLookupTask::DHTPeerLookupTask +(const SharedHandle<DownloadContext>& downloadContext): + DHTAbstractNodeLookupTask(bittorrent::getInfoHash(downloadContext)) {} void DHTPeerLookupTask::getNodesFromMessage(std::deque<SharedHandle<DHTNode> >& nodes, @@ -92,11 +92,11 @@ void DHTPeerLookupTask::onFinish() if((*i)->_used) { const SharedHandle<DHTNode>& node = (*i)->_node; SharedHandle<DHTMessage> m = - _factory->createAnnouncePeerMessage(node, - _ctx->getInfoHash(), - _btRuntime->getListenPort(), - _tokenStorage[Util::toHex(node->getID(), - DHT_ID_LENGTH)]); + _factory->createAnnouncePeerMessage + (node, + _targetID, // this is infoHash + _btRuntime->getListenPort(), + _tokenStorage[Util::toHex(node->getID(), DHT_ID_LENGTH)]); _dispatcher->addMessageToQueue(m); } } diff --git a/src/DHTPeerLookupTask.h b/src/DHTPeerLookupTask.h index 261e61c3..d448f74a 100644 --- a/src/DHTPeerLookupTask.h +++ b/src/DHTPeerLookupTask.h @@ -40,7 +40,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class Peer; class PeerStorage; class BtRuntime; @@ -51,13 +51,11 @@ private: std::deque<SharedHandle<Peer> > _peers; - SharedHandle<BtContext> _ctx; - SharedHandle<PeerStorage> _peerStorage; SharedHandle<BtRuntime> _btRuntime; public: - DHTPeerLookupTask(const SharedHandle<BtContext>& btContext); + DHTPeerLookupTask(const SharedHandle<DownloadContext>& downloadContext); virtual void getNodesFromMessage(std::deque<SharedHandle<DHTNode> >& nodes, const SharedHandle<DHTMessage>& message); diff --git a/src/DHTTaskFactory.h b/src/DHTTaskFactory.h index b5c8dcf9..91988e1a 100644 --- a/src/DHTTaskFactory.h +++ b/src/DHTTaskFactory.h @@ -40,7 +40,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class BtRuntime; class PeerStorage; class DHTTask; @@ -61,7 +61,7 @@ public: virtual SharedHandle<DHTTask> createBucketRefreshTask() = 0; virtual SharedHandle<DHTTask> - createPeerLookupTask(const SharedHandle<BtContext>& ctx, + createPeerLookupTask(const SharedHandle<DownloadContext>& ctx, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<PeerStorage>& peerStorage) = 0; diff --git a/src/DHTTaskFactoryImpl.cc b/src/DHTTaskFactoryImpl.cc index d4e93725..6d794b88 100644 --- a/src/DHTTaskFactoryImpl.cc +++ b/src/DHTTaskFactoryImpl.cc @@ -47,7 +47,6 @@ #include "DHTReplaceNodeTask.h" #include "Peer.h" #include "DHTNodeLookupEntry.h" -#include "BtContext.h" #include "PeerStorage.h" #include "BtRuntime.h" #include "DHTMessageCallback.h" @@ -85,7 +84,7 @@ DHTTaskFactoryImpl::createBucketRefreshTask() SharedHandle<DHTTask> DHTTaskFactoryImpl::createPeerLookupTask -(const SharedHandle<BtContext>& ctx, +(const SharedHandle<DownloadContext>& ctx, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<PeerStorage>& peerStorage) { diff --git a/src/DHTTaskFactoryImpl.h b/src/DHTTaskFactoryImpl.h index 9d8c1649..e6f2e5b2 100644 --- a/src/DHTTaskFactoryImpl.h +++ b/src/DHTTaskFactoryImpl.h @@ -77,7 +77,7 @@ public: virtual SharedHandle<DHTTask> createBucketRefreshTask(); virtual SharedHandle<DHTTask> - createPeerLookupTask(const SharedHandle<BtContext>& ctx, + createPeerLookupTask(const SharedHandle<DownloadContext>& ctx, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<PeerStorage>& peerStorage); diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc index 377b0ae3..3cdeb360 100644 --- a/src/DefaultBtAnnounce.cc +++ b/src/DefaultBtAnnounce.cc @@ -41,7 +41,7 @@ #include "DlAbortEx.h" #include "message.h" #include "SimpleRandomizer.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PieceStorage.h" #include "BtRuntime.h" #include "PeerStorage.h" @@ -51,19 +51,21 @@ #include "A2STR.h" #include "Request.h" #include "bencode.h" +#include "bittorrent_helper.h" namespace aria2 { -DefaultBtAnnounce::DefaultBtAnnounce(const BtContextHandle& btContext, - const Option* option): - btContext(btContext), +DefaultBtAnnounce::DefaultBtAnnounce +(const SharedHandle<DownloadContext>& downloadContext, + const Option* option): + _downloadContext(downloadContext), trackers(0), interval(DEFAULT_ANNOUNCE_INTERVAL), minInterval(DEFAULT_ANNOUNCE_INTERVAL), _userDefinedInterval(0), complete(0), incomplete(0), - announceList(btContext->getAnnounceTiers()), + announceList(downloadContext->getAttribute(bittorrent::BITTORRENT)[bittorrent::ANNOUNCE_LIST]), option(option), logger(LogFactory::getInstance()), _randomizer(SimpleRandomizer::getInstance()) @@ -145,10 +147,10 @@ std::string DefaultBtAnnounce::getAnnounceUrl() { std::string url = announceList.getAnnounce(); url += uriHasQuery(url) ? "&" : "?"; url += "info_hash="; - url += Util::torrentUrlencode(btContext->getInfoHash(), - btContext->getInfoHashLength()); + url += Util::torrentUrlencode(bittorrent::getInfoHash(_downloadContext), + INFO_HASH_LENGTH); url += "&peer_id="; - url += Util::torrentUrlencode(btContext->getPeerId(), 20); + url += Util::torrentUrlencode(bittorrent::getStaticPeerId(), PEER_ID_LENGTH); url += "&uploaded="; url += Util::uitos(stat.getSessionUploadLength()); url += "&downloaded="; diff --git a/src/DefaultBtAnnounce.h b/src/DefaultBtAnnounce.h index a561bbec..812cb3e8 100644 --- a/src/DefaultBtAnnounce.h +++ b/src/DefaultBtAnnounce.h @@ -41,7 +41,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class Option; class Logger; class BtRuntime; @@ -51,7 +51,7 @@ class Randomizer; class DefaultBtAnnounce : public BtAnnounce { private: - SharedHandle<BtContext> btContext; + SharedHandle<DownloadContext> _downloadContext; unsigned int trackers; Time prevAnnounceTime; time_t interval; @@ -69,7 +69,7 @@ private: SharedHandle<PieceStorage> pieceStorage; SharedHandle<PeerStorage> peerStorage; public: - DefaultBtAnnounce(const SharedHandle<BtContext>& btContext, + DefaultBtAnnounce(const SharedHandle<DownloadContext>& downloadContext, const Option* option); virtual ~DefaultBtAnnounce(); diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc deleted file mode 100644 index 29aaea47..00000000 --- a/src/DefaultBtContext.cc +++ /dev/null @@ -1,577 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#include "DefaultBtContext.h" - -#include <cstring> -#include <ostream> -#include <functional> -#include <algorithm> -#include <vector> - -#include "DlAbortEx.h" -#include "Util.h" -#include "MessageDigestHelper.h" -#include "a2netcompat.h" -#include "AnnounceTier.h" -#include "SimpleRandomizer.h" -#include "LogFactory.h" -#include "Logger.h" -#include "FileEntry.h" -#include "message.h" -#include "PeerMessageUtil.h" -#include "StringFormat.h" -#include "A2STR.h" -#include "bencode.h" -#include "a2functional.h" - -namespace aria2 { - -const std::string DefaultBtContext::C_NAME("name"); - -const std::string DefaultBtContext::C_NAME_UTF8("name.utf-8"); - -const std::string DefaultBtContext::C_FILES("files"); - -const std::string DefaultBtContext::C_LENGTH("length"); - -const std::string DefaultBtContext::C_PATH("path"); - -const std::string DefaultBtContext::C_PATH_UTF8("path.utf-8"); - -const std::string DefaultBtContext::C_INFO("info"); - -const std::string DefaultBtContext::C_PIECES("pieces"); - -const std::string DefaultBtContext::C_PIECE_LENGTH("piece length"); - -const std::string DefaultBtContext::C_PRIVATE("private"); - -const std::string DefaultBtContext::C_PRIVATE_ON("1"); - -const std::string DefaultBtContext::C_URL_LIST("url-list"); - -const std::string DefaultBtContext::C_ANNOUNCE("announce"); - -const std::string DefaultBtContext::C_ANNOUNCE_LIST("announce-list"); - -const std::string DefaultBtContext::C_NODES("nodes"); - -const std::string DefaultBtContext::DEFAULT_PEER_ID_PREFIX("-aria2-"); - -DefaultBtContext::DefaultBtContext():_peerIdPrefix(DEFAULT_PEER_ID_PREFIX), - _randomizer(SimpleRandomizer::getInstance()), - _ownerRequestGroup(0), - _logger(LogFactory::getInstance()) {} - -DefaultBtContext::~DefaultBtContext() {} - -std::string DefaultBtContext::generatePeerId() const { - std::string peerId = _peerIdPrefix; - peerId += Util::randomAlpha(20-_peerIdPrefix.size(), _randomizer); - if(peerId.size() > 20) { - peerId.erase(20); - } - return peerId; -} - -const unsigned char* DefaultBtContext::getInfoHash() const { - return infoHash; -} - -size_t DefaultBtContext::getInfoHashLength() const { - return INFO_HASH_LENGTH; -} - -const std::string& DefaultBtContext::getInfoHashAsString() const { - return infoHashString; -} - -void DefaultBtContext::clear() { - memset(infoHash, 0, INFO_HASH_LENGTH); - infoHashString = A2STR::NIL; - pieceHashes.clear(); - _fileEntries.clear(); - totalLength = 0; - pieceLength = 0; - fileMode = BtContext::SINGLE; - numPieces = 0; - name = A2STR::NIL; - announceTiers.clear(); - _private = false; -} - -void DefaultBtContext::extractPieceHash(const std::string& hashData, - size_t hashLength) -{ - size_t numPieces = hashData.size()/hashLength; - for(size_t i = 0; i < numPieces; ++i) { - pieceHashes.push_back(Util::toHex(hashData.data()+i*hashLength, - hashLength)); - } -} - -void DefaultBtContext::extractFileEntries(const BDE& infoDict, - const std::string& defaultName, - const std::string& overrideName, - const std::deque<std::string>& urlList) -{ - if(overrideName.empty()) { - std::string nameKey; - if(infoDict.containsKey(C_NAME_UTF8)) { - nameKey = C_NAME_UTF8; - } else { - nameKey = C_NAME; - } - const BDE& nameData = infoDict[nameKey]; - if(nameData.isString()) { - name = nameData.s(); - } else { - name = strconcat(File(defaultName).getBasename(), ".file"); - } - } else { - name = overrideName; - } - const BDE& filesList = infoDict[C_FILES]; - if(filesList.isList()) { - uint64_t length = 0; - off_t offset = 0; - // multi-file mode - fileMode = BtContext::MULTI; - for(BDE::List::const_iterator itr = filesList.listBegin(); - itr != filesList.listEnd(); ++itr) { - const BDE& fileDict = *itr; - if(!fileDict.isDict()) { - continue; - } - - const BDE& fileLengthData = fileDict[C_LENGTH]; - if(!fileLengthData.isInteger()) { - throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, - C_LENGTH.c_str()).str()); - } - length += fileLengthData.i(); - - std::string pathKey; - if(fileDict.containsKey(C_PATH_UTF8)) { - pathKey = C_PATH_UTF8; - } else { - pathKey = C_PATH; - } - const BDE& pathList = fileDict[pathKey]; - if(!pathList.isList() || pathList.empty()) { - throw DL_ABORT_EX("Path is empty."); - } - - std::vector<std::string> pathelem(pathList.size()); - std::transform(pathList.listBegin(), pathList.listEnd(), pathelem.begin(), - std::mem_fun_ref(&BDE::s)); - std::string path = name; - strappend(path, "/", Util::joinPath(pathelem.begin(), pathelem.end())); - // Split path with '/' again because each pathList element can - // contain "/" inside. - std::deque<std::string> elements; - Util::slice(elements, path, '/'); - path = Util::joinPath(elements.begin(), elements.end()); - - std::deque<std::string> uris; - std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris), - std::bind2nd(std::plus<std::string>(), "/"+path)); - FileEntryHandle fileEntry(new FileEntry(strconcat(_dir, "/", path), - fileLengthData.i(), - offset, uris)); - _fileEntries.push_back(fileEntry); - offset += fileEntry->getLength(); - } - totalLength = length; - } else { - // single-file mode; - fileMode = BtContext::SINGLE; - const BDE& lengthData = infoDict[C_LENGTH]; - if(!lengthData.isInteger()) { - throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, - C_LENGTH.c_str()).str()); - } - totalLength = lengthData.i(); - // Slice path by '/' just in case nasty ".." is included in name - std::deque<std::string> pathelems; - Util::slice(pathelems, name, '/'); - - // For each uri in urlList, if it ends with '/', then - // concatenate name to it. Specification just says so. - std::deque<std::string> uris; - for(std::deque<std::string>::const_iterator i = urlList.begin(); - i != urlList.end(); ++i) { - if(Util::endsWith(*i, "/")) { - uris.push_back((*i)+name); - } else { - uris.push_back(*i); - } - } - - SharedHandle<FileEntry> fileEntry - (new FileEntry(strconcat(_dir, "/", - Util::joinPath(pathelems.begin(), - pathelems.end())), - totalLength, 0, uris)); - _fileEntries.push_back(fileEntry); - } -} - -void DefaultBtContext::extractAnnounceURI(const BDE& announceData) -{ - // Assumed announceData is string - std::deque<std::string> urls; - urls.push_back(Util::trim(announceData.s())); - announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls))); -} - -void DefaultBtContext::extractAnnounceList(const BDE& announceList) -{ - // Assumed announceList is string - for(BDE::List::const_iterator itr = announceList.listBegin(); - itr != announceList.listEnd(); ++itr) { - const BDE& elemList = *itr; - if(!elemList.isList()) { - continue; - } - std::deque<std::string> urls; - for(BDE::List::const_iterator elemItr = elemList.listBegin(); - elemItr != elemList.listEnd(); ++elemItr) { - const BDE& url = (*elemItr); - if(url.isString()) { - urls.push_back(Util::trim(url.s())); - } - } - if(!urls.empty()) { - AnnounceTierHandle tier(new AnnounceTier(urls)); - announceTiers.push_back(tier); - } - } -} - -void DefaultBtContext::extractAnnounce(const BDE& rootDict) -{ - const BDE& announceList = rootDict[C_ANNOUNCE_LIST]; - if(announceList.isList()) { - extractAnnounceList(announceList); - } else { - const BDE& announce = rootDict[C_ANNOUNCE]; - if(announce.isString()) { - extractAnnounceURI(announce); - } - } -} - -void DefaultBtContext::extractUrlList(std::deque<std::string>& uris, - const BDE& bde) -{ - if(bde.isList()) { - for(BDE::List::const_iterator itr = bde.listBegin(); - itr != bde.listEnd(); ++itr) { - if((*itr).isString()) { - uris.push_back((*itr).s()); - } - } - } else if(bde.isString()) { - uris.push_back(bde.s()); - } -} - -void DefaultBtContext::extractNodes(const BDE& nodesList) -{ - if(!nodesList.isList()) { - return; - } - for(BDE::List::const_iterator i = nodesList.listBegin(); - i != nodesList.listEnd(); ++i) { - const BDE& addrPairList = (*i); - if(!addrPairList.isList() || addrPairList.size() != 2) { - continue; - } - const BDE& hostname = addrPairList[0]; - if(!hostname.isString()) { - continue; - } - if(Util::trim(hostname.s()).empty()) { - continue; - } - const BDE& port = addrPairList[1]; - if(!port.isInteger() || !(0 < port.i() && port.i() < 65536)) { - continue; - } - _nodes.push_back(std::pair<std::string, uint16_t>(hostname.s(), port.i())); - } -} - -void DefaultBtContext::loadFromMemory(const unsigned char* content, - size_t length, - const std::string& defaultName, - const std::string& overrideName) -{ - processRootDictionary(bencode::decode(content, length), defaultName, - overrideName); -} - -void DefaultBtContext::load(const std::string& torrentFile, - const std::string& overrideName) { - processRootDictionary(bencode::decodeFromFile(torrentFile), torrentFile, - overrideName); -} - -void DefaultBtContext::processRootDictionary(const BDE& rootDict, - const std::string& defaultName, - const std::string& overrideName) -{ - clear(); - if(!rootDict.isDict()) { - throw DL_ABORT_EX("torrent file does not contain a root dictionary."); - } - const BDE& infoDict = rootDict[C_INFO]; - if(!infoDict.isDict()) { - throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, - C_INFO.c_str()).str()); - } - // retrieve infoHash - std::string encodedInfoDict = bencode::encode(infoDict); - MessageDigestHelper::digest(infoHash, INFO_HASH_LENGTH, - MessageDigestContext::SHA1, - encodedInfoDict.data(), - encodedInfoDict.size()); - infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH); - // calculate the number of pieces - const BDE& piecesData = infoDict[C_PIECES]; - if(!piecesData.isString()) { - throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, - C_PIECES.c_str()).str()); - } - if(piecesData.s().empty()) { - throw DL_ABORT_EX("The length of piece hash is 0."); - } - numPieces = piecesData.s().size()/PIECE_HASH_LENGTH; - if(numPieces == 0) { - throw DL_ABORT_EX("The number of pieces is 0."); - } - // retrieve piece length - const BDE& pieceLengthData = infoDict[C_PIECE_LENGTH]; - if(!pieceLengthData.isInteger()) { - throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, - C_PIECE_LENGTH.c_str()).str()); - } - pieceLength = pieceLengthData.i(); - // retrieve piece hashes - extractPieceHash(piecesData.s(), PIECE_HASH_LENGTH); - // private flag - const BDE& privateData = infoDict[C_PRIVATE]; - if(privateData.isInteger()) { - _private = (privateData.i() == 1); - } - // retrieve uri-list. - // This implemantation obeys HTTP-Seeding specification: - // see http://www.getright.com/seedtorrent.html - std::deque<std::string> urlList; - extractUrlList(urlList, rootDict[C_URL_LIST]); - - // retrieve file entries - extractFileEntries(infoDict, defaultName, overrideName, urlList); - if((totalLength+pieceLength-1)/pieceLength != numPieces) { - throw DL_ABORT_EX("Too few/many piece hash."); - } - // retrieve announce - extractAnnounce(rootDict); - // retrieve nodes - extractNodes(rootDict[C_NODES]); -} - -const std::string& DefaultBtContext::getPieceHash(size_t index) const { - if(index < numPieces) { - return pieceHashes[index]; - } else { - return A2STR::NIL; - } -} - -uint64_t DefaultBtContext::getTotalLength() const { - return totalLength; -} - -bool DefaultBtContext::knowsTotalLength() const -{ - return true; -} - -BtContext::FILE_MODE DefaultBtContext::getFileMode() const { - return fileMode; -} - -const std::string& DefaultBtContext::getPieceHashAlgo() const -{ - return MessageDigestContext::SHA1; -} - -const std::deque<SharedHandle<AnnounceTier> >& -DefaultBtContext::getAnnounceTiers() const -{ - return announceTiers; -} - -const std::string& DefaultBtContext::getName() const { - return name; -} - -size_t DefaultBtContext::getPieceLength() const { - return pieceLength; -} - -size_t DefaultBtContext::getNumPieces() const { - return numPieces; -} - -std::string DefaultBtContext::getActualBasePath() const -{ - if(_fileEntries.size() == 1) { - return _fileEntries.front()->getPath(); - } else { - return strconcat(_dir, "/", name); - } -} - -void DefaultBtContext::computeFastSet -(std::deque<size_t>& fastSet, const std::string& ipaddr, size_t fastSetSize) -{ - unsigned char compact[6]; - if(!PeerMessageUtil::createcompact(compact, ipaddr, 0)) { - return; - } - if(numPieces < fastSetSize) { - fastSetSize = numPieces; - } - unsigned char tx[24]; - memcpy(tx, compact, 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]; - MessageDigestHelper::digest(x, sizeof(x), MessageDigestContext::SHA1, tx, 24); - while(fastSet.size() < fastSetSize) { - for(size_t i = 0; i < 5 && fastSet.size() < fastSetSize; ++i) { - size_t j = i*4; - uint32_t ny; - memcpy(&ny, x+j, 4); - uint32_t y = ntohl(ny); - size_t index = y%numPieces; - if(std::find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) { - fastSet.push_back(index); - } - } - unsigned char temp[20]; - MessageDigestHelper::digest(temp, sizeof(temp), MessageDigestContext::SHA1, x, sizeof(x)); - memcpy(x, temp, sizeof(x)); - } -} - -std::ostream& operator<<(std::ostream& o, const DefaultBtContext& ctx) -{ - o << "*** BitTorrent File Information ***" << "\n"; - o << "Mode: " << (ctx.getFileMode() == DownloadContext::SINGLE ? "Single File Torrent":"Multi File Torrent") << "\n"; - o << "Announce:" << "\n"; - AnnounceTiers tiers = ctx.getAnnounceTiers(); - for(AnnounceTiers::const_iterator itr = tiers.begin(); itr != tiers.end(); ++itr) { - const AnnounceTierHandle& tier = *itr; - for(std::deque<std::string>::const_iterator uriItr = tier->urls.begin(); uriItr != tier->urls.end(); ++uriItr) { - o << " " << *uriItr; - } - o << "\n"; - } - o << "Info Hash: " << ctx.getInfoHashAsString() << "\n"; - o << "Piece Length: " << Util::abbrevSize(ctx.getPieceLength()) << "B\n"; - o << "The Number of Pieces: " << ctx.getNumPieces() << "\n"; - o << "Total Length: " << Util::abbrevSize(ctx.getTotalLength()) << "B\n"; - if(ctx.getFileMode() == DownloadContext::MULTI) { - o << "Name: " << ctx.getName() << "\n"; - } - Util::toStream(o, ctx.getFileEntries()); - return o; -} - -void DefaultBtContext::setRandomizer(const RandomizerHandle& randomizer) -{ - _randomizer = randomizer; -} - -std::deque<std::pair<std::string, uint16_t> >& -DefaultBtContext::getNodes() -{ - return _nodes; -} - -void DefaultBtContext::setInfoHash(const unsigned char* infoHash) -{ - memcpy(this->infoHash, infoHash, sizeof(this->infoHash)); -} - -void DefaultBtContext::setFilePathWithIndex -(size_t index, const std::string& path) -{ - if(0 < index && index <= _fileEntries.size()) { - _fileEntries[index-1]->setPath(path); - } else { - throw DL_ABORT_EX(StringFormat("No such file with index=%u", - static_cast<unsigned int>(index)).str()); - } -} - -void DefaultBtContext::setFileFilter(IntSequence seq) -{ - std::deque<int32_t> fileIndexes = seq.flush(); - std::sort(fileIndexes.begin(), fileIndexes.end()); - fileIndexes.erase(std::unique(fileIndexes.begin(), fileIndexes.end()), - fileIndexes.end()); - - bool selectAll = fileIndexes.empty() || _fileEntries.size() == 1; - - int32_t index = 1; - for(std::deque<SharedHandle<FileEntry> >::const_iterator i = - _fileEntries.begin(); i != _fileEntries.end(); ++i, ++index) { - (*i)->setRequested - (selectAll || - std::binary_search(fileIndexes.begin(), fileIndexes.end(), index)); - } -} - -} // namespace aria2 diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h deleted file mode 100644 index a238c7a8..00000000 --- a/src/DefaultBtContext.h +++ /dev/null @@ -1,232 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#ifndef _D_DEFAULT_BT_CONTEXT_H_ -#define _D_DEFAULT_BT_CONTEXT_H_ - -#include "BtContext.h" - -#include <iosfwd> - -#include "IntSequence.h" - -namespace aria2 { - -class Randomizer; -class Logger; -class BDE; - -#define INFO_HASH_LENGTH 20 -#define PIECE_HASH_LENGTH 20 - -class DefaultBtContext : public BtContext { -private: - unsigned char infoHash[INFO_HASH_LENGTH]; - std::string infoHashString; - std::deque<std::string> pieceHashes; - FILE_MODE fileMode; - uint64_t totalLength; - size_t pieceLength; - std::string name; - size_t numPieces; - std::string peerId; - std::string _peerIdPrefix; - std::deque<SharedHandle<AnnounceTier> > announceTiers; - std::deque<std::pair<std::string, uint16_t> > _nodes; - SharedHandle<Randomizer> _randomizer; - - RequestGroup* _ownerRequestGroup; - - Logger* _logger; - - static const std::string C_NAME; - - static const std::string C_NAME_UTF8; - - static const std::string C_FILES; - - static const std::string C_LENGTH; - - static const std::string C_PATH; - - static const std::string C_PATH_UTF8; - - static const std::string C_INFO; - - static const std::string C_PIECES; - - static const std::string C_PIECE_LENGTH; - - static const std::string C_PRIVATE; - - // This is just a string "1". Used as a value of "private" flag. - static const std::string C_PRIVATE_ON; - - static const std::string C_URL_LIST; - - static const std::string C_ANNOUNCE; - - static const std::string C_ANNOUNCE_LIST; - - static const std::string C_NODES; - - void clear(); - void extractPieceHash(const std::string& hashData, size_t hashLength); - void extractFileEntries(const BDE& infoDic, - const std::string& defaultName, - const std::string& overrideName, - const std::deque<std::string>& urlList); - void extractAnnounceURI(const BDE& announceData); - void extractAnnounceList(const BDE& announceListData); - void extractAnnounce(const BDE& rootDict); - - void extractUrlList(std::deque<std::string>& uris, const BDE& obj); - - void extractNodes(const BDE& nodes); - - void processRootDictionary(const BDE& rootDic, - const std::string& defaultName, - const std::string& overrideName); - - public: - DefaultBtContext(); - virtual ~DefaultBtContext(); - - virtual const unsigned char* getInfoHash() const; - - virtual size_t getInfoHashLength() const; - - virtual const std::string& getInfoHashAsString() const; - - virtual const std::string& getPieceHash(size_t index) const; - - virtual const std::deque<std::string>& getPieceHashes() const - { - return pieceHashes; - } - - virtual uint64_t getTotalLength() const; - - virtual bool knowsTotalLength() const; - - virtual FILE_MODE getFileMode() const; - - virtual const std::string& getPieceHashAlgo() const; - - virtual const std::deque<SharedHandle<AnnounceTier> >& - getAnnounceTiers() const; - - // Note: Before calling load* function, call setDir() to specify - // directory. Setting directory after load* function doesn't change - // the output file path. - virtual void load(const std::string& torrentFile, - const std::string& overrideName = ""); - - void loadFromMemory(const unsigned char* content, size_t length, - const std::string& defaultName, - const std::string& overrideName = ""); - - void loadFromMemory(const std::string& context, - const std::string& defaultName, - const std::string& overrideName = "") - { - loadFromMemory(reinterpret_cast<const unsigned char*>(context.c_str()), - context.size(), defaultName, overrideName); - } - - virtual const std::string& getName() const; - - virtual size_t getPieceLength() const; - - virtual size_t getNumPieces() const; - - virtual std::string getActualBasePath() const; - - virtual const unsigned char* getPeerId() { - if(peerId.empty()) { - peerId = generatePeerId(); - } - return reinterpret_cast<const unsigned char*>(peerId.c_str()); - } - - virtual void computeFastSet - (std::deque<size_t>& fastSet, const std::string& ipaddr, size_t fastSetSize); - - virtual RequestGroup* getOwnerRequestGroup() - { - return _ownerRequestGroup; - } - - virtual std::deque<std::pair<std::string, uint16_t> >& getNodes(); - - virtual void setFileFilter(IntSequence seq); - - std::string generatePeerId() const; - - void setPeerIdPrefix(const std::string& peerIdPrefix) - { - _peerIdPrefix = peerIdPrefix; - } - - // for unit test - void setInfoHash(const unsigned char* infoHash); - - void setNumPieces(size_t numPieces) - { - this->numPieces = numPieces; - } - - void setOwnerRequestGroup(RequestGroup* owner) - { - _ownerRequestGroup = owner; - } - - void setRandomizer(const SharedHandle<Randomizer>& randomizer); - - // Sets file path for spcified index. index starts from 1. The index - // is the same used in BtContext::setFileFilter(). Please note that - // path is not the actual file path. The actual file path is - // getDir()+"/"+path. - void setFilePathWithIndex(size_t index, const std::string& path); - - friend std::ostream& operator<<(std::ostream& o, const DefaultBtContext& ctx); - - static const std::string DEFAULT_PEER_ID_PREFIX; -}; - -typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle; - -} // namespace aria2 - -#endif // _D_DEFAULT_BT_CONTEXT_H_ diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc index 5d712744..a69a9cdf 100644 --- a/src/DefaultBtInteractive.cc +++ b/src/DefaultBtInteractive.cc @@ -54,7 +54,7 @@ #include "DHTNode.h" #include "Peer.h" #include "Piece.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PieceStorage.h" #include "PeerStorage.h" #include "BtRuntime.h" @@ -68,13 +68,15 @@ #include "StringFormat.h" #include "RequestGroup.h" #include "RequestGroupMan.h" +#include "bittorrent_helper.h" namespace aria2 { DefaultBtInteractive::DefaultBtInteractive -(const SharedHandle<BtContext>& btContext, const SharedHandle<Peer>& peer) +(const SharedHandle<DownloadContext>& downloadContext, + const SharedHandle<Peer>& peer) : - _btContext(btContext), + _downloadContext(downloadContext), peer(peer), logger(LogFactory::getInstance()), allowedFastSetSize(10), @@ -88,8 +90,8 @@ DefaultBtInteractive::~DefaultBtInteractive() {} void DefaultBtInteractive::initiateHandshake() { SharedHandle<BtMessage> message = - messageFactory->createHandshakeMessage(_btContext->getInfoHash(), - _btContext->getPeerId()); + messageFactory->createHandshakeMessage + (bittorrent::getInfoHash(_downloadContext), bittorrent::getStaticPeerId()); dispatcher->addMessageToQueue(message); dispatcher->sendMessages(); } @@ -100,7 +102,7 @@ BtMessageHandle DefaultBtInteractive::receiveHandshake(bool quickReply) { if(message.isNull()) { return SharedHandle<BtMessage>(); } - if(memcmp(message->getPeerId(), _btContext->getPeerId(), + if(memcmp(message->getPeerId(), bittorrent::getStaticPeerId(), PEER_ID_LENGTH) == 0) { throw DL_ABORT_EX (StringFormat @@ -187,9 +189,12 @@ void DefaultBtInteractive::addBitfieldMessageToQueue() { void DefaultBtInteractive::addAllowedFastMessageToQueue() { if(peer->isFastExtensionEnabled()) { - std::deque<size_t> fastSet; - _btContext->computeFastSet(fastSet, peer->ipaddr, allowedFastSetSize); - for(std::deque<size_t>::const_iterator itr = fastSet.begin(); + std::vector<size_t> fastSet; + bittorrent::computeFastSet(fastSet, peer->ipaddr, + _downloadContext->getNumPieces(), + bittorrent::getInfoHash(_downloadContext), + allowedFastSetSize); + for(std::vector<size_t>::const_iterator itr = fastSet.begin(); itr != fastSet.end(); ++itr) { dispatcher->addMessageToQueue (messageFactory->createAllowedFastMessage(*itr)); @@ -239,7 +244,7 @@ size_t DefaultBtInteractive::receiveMessages() { size_t msgcount = 0; for(int i = 0; i < 50; ++i) { if(_requestGroupMan->doesOverallDownloadSpeedExceed() || - _btContext->getOwnerRequestGroup()->doesDownloadSpeedExceed()) { + _downloadContext->getOwnerRequestGroup()->doesDownloadSpeedExceed()) { break; } BtMessageHandle message = btMessageReceiver->receiveMessage(); diff --git a/src/DefaultBtInteractive.h b/src/DefaultBtInteractive.h index ee522aed..1129dbeb 100644 --- a/src/DefaultBtInteractive.h +++ b/src/DefaultBtInteractive.h @@ -43,7 +43,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class BtRuntime; class PieceStorage; class PeerStorage; @@ -97,7 +97,7 @@ class DefaultBtInteractive : public BtInteractive { private: int32_t cuid; - SharedHandle<BtContext> _btContext; + SharedHandle<DownloadContext> _downloadContext; SharedHandle<BtRuntime> _btRuntime; @@ -151,7 +151,7 @@ private: void addPortMessageToQueue(); public: - DefaultBtInteractive(const SharedHandle<BtContext>& btContext, + DefaultBtInteractive(const SharedHandle<DownloadContext>& downloadContext, const SharedHandle<Peer>& peer); virtual ~DefaultBtInteractive(); diff --git a/src/DefaultBtMessageDispatcher.cc b/src/DefaultBtMessageDispatcher.cc index 1adc3565..fa201198 100644 --- a/src/DefaultBtMessageDispatcher.cc +++ b/src/DefaultBtMessageDispatcher.cc @@ -42,7 +42,7 @@ #include "BtChokingEvent.h" #include "BtMessageFactory.h" #include "message.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "BtMessage.h" @@ -87,7 +87,7 @@ void DefaultBtMessageDispatcher::sendMessages() { messageQueue.pop_front(); if(msg->isUploading() && !msg->isSendingInProgress()) { if(_requestGroupMan->doesOverallUploadSpeedExceed() || - btContext->getOwnerRequestGroup()->doesUploadSpeedExceed()) { + _downloadContext->getOwnerRequestGroup()->doesUploadSpeedExceed()) { tempQueue.push_back(msg); continue; } @@ -412,9 +412,10 @@ void DefaultBtMessageDispatcher::setPeer(const SharedHandle<Peer>& peer) this->peer = peer; } -void DefaultBtMessageDispatcher::setBtContext(const BtContextHandle& btContext) +void DefaultBtMessageDispatcher::setDownloadContext +(const SharedHandle<DownloadContext>& downloadContext) { - this->btContext = btContext; + _downloadContext = downloadContext; } void DefaultBtMessageDispatcher::setPieceStorage diff --git a/src/DefaultBtMessageDispatcher.h b/src/DefaultBtMessageDispatcher.h index 2b3cc2a3..0b5caae6 100644 --- a/src/DefaultBtMessageDispatcher.h +++ b/src/DefaultBtMessageDispatcher.h @@ -40,7 +40,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class PeerStorage; class PieceStorage; class BtMessage; @@ -55,7 +55,7 @@ private: int32_t cuid; std::deque<SharedHandle<BtMessage> > messageQueue; std::deque<RequestSlot> requestSlots; - SharedHandle<BtContext> btContext; + SharedHandle<DownloadContext> _downloadContext; SharedHandle<PeerStorage> _peerStorage; SharedHandle<PieceStorage> _pieceStorage; WeakHandle<BtMessageFactory> messageFactory; @@ -116,7 +116,7 @@ public: void setPeer(const SharedHandle<Peer>& peer); - void setBtContext(const SharedHandle<BtContext>& btContext); + void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext); void setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage); diff --git a/src/DefaultBtMessageFactory.cc b/src/DefaultBtMessageFactory.cc index 0c6306a7..17bc280c 100644 --- a/src/DefaultBtMessageFactory.cc +++ b/src/DefaultBtMessageFactory.cc @@ -61,11 +61,12 @@ #include "ExtensionMessage.h" #include "Peer.h" #include "Piece.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PieceStorage.h" #include "PeerStorage.h" #include "StringFormat.h" #include "ExtensionMessageFactory.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -112,7 +113,7 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL { SharedHandle<BtMessageValidator> v (new IndexBtMessageValidator((BtHaveMessage*)msg.get(), - btContext->getNumPieces())); + _downloadContext->getNumPieces())); msg->setBtMessageValidator(v); } break; @@ -121,7 +122,7 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL { SharedHandle<BtMessageValidator> v (new BtBitfieldMessageValidator((BtBitfieldMessage*)msg.get(), - btContext->getNumPieces())); + _downloadContext->getNumPieces())); msg->setBtMessageValidator(v); } break; @@ -130,7 +131,7 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL SharedHandle<BtMessageValidator> validator (new RangeBtMessageValidator (temp.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(temp->getIndex()))); temp->setBtMessageValidator(validator); msg = temp; @@ -141,7 +142,7 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL SharedHandle<BtMessageValidator> validator (new RangeBtMessageValidator (temp.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(temp->getIndex()))); temp->setBtMessageValidator(validator); msg = temp; @@ -151,9 +152,10 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL BtPieceMessageHandle temp = BtPieceMessage::create(data, dataLength); BtMessageValidatorHandle validator (new BtPieceMessageValidator(temp.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(temp->getIndex()))); temp->setBtMessageValidator(validator); + temp->setDownloadContext(_downloadContext); msg = temp; break; } @@ -168,7 +170,7 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL SharedHandle<BtMessageValidator> validator (new RangeBtMessageValidator (temp.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(temp->getIndex()))); temp->setBtMessageValidator(validator); msg = temp; @@ -177,7 +179,8 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL case BtSuggestPieceMessage::ID: { BtSuggestPieceMessageHandle temp = BtSuggestPieceMessage::create(data, dataLength); SharedHandle<BtMessageValidator> validator - (new IndexBtMessageValidator(temp.get(), btContext->getNumPieces())); + (new IndexBtMessageValidator(temp.get(), + _downloadContext->getNumPieces())); temp->setBtMessageValidator(validator); msg = temp; break; @@ -185,7 +188,8 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL case BtAllowedFastMessage::ID: { BtAllowedFastMessageHandle temp = BtAllowedFastMessage::create(data, dataLength); SharedHandle<BtMessageValidator> validator - (new IndexBtMessageValidator(temp.get(), btContext->getNumPieces())); + (new IndexBtMessageValidator(temp.get(), + _downloadContext->getNumPieces())); temp->setBtMessageValidator(validator); msg = temp; break; @@ -219,7 +223,6 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, size_t dataL void DefaultBtMessageFactory::setCommonProperty(const AbstractBtMessageHandle& msg) { msg->setCuid(cuid); msg->setPeer(peer); - msg->setBtContext(btContext); msg->setPieceStorage(_pieceStorage); msg->setBtMessageDispatcher(dispatcher); msg->setBtRequestFactory(requestFactory); @@ -232,8 +235,8 @@ DefaultBtMessageFactory::createHandshakeMessage(const unsigned char* data, size_ { SharedHandle<BtHandshakeMessage> msg = BtHandshakeMessage::create(data, dataLength); BtMessageValidatorHandle validator - (new BtHandshakeMessageValidator(msg.get(), - btContext->getInfoHash())); + (new BtHandshakeMessageValidator + (msg.get(), bittorrent::getInfoHash(_downloadContext))); msg->setBtMessageValidator(validator); setCommonProperty(msg); return msg; @@ -245,8 +248,8 @@ DefaultBtMessageFactory::createHandshakeMessage(const unsigned char* infoHash, { SharedHandle<BtHandshakeMessage> msg(new BtHandshakeMessage(infoHash, peerId)); BtMessageValidatorHandle validator - (new BtHandshakeMessageValidator(msg.get(), - btContext->getInfoHash())); + (new BtHandshakeMessageValidator + (msg.get(), bittorrent::getInfoHash(_downloadContext))); msg->setBtMessageValidator(validator); msg->setDHTEnabled(_dhtEnabled); setCommonProperty(msg); @@ -264,7 +267,7 @@ DefaultBtMessageFactory::createRequestMessage(const PieceHandle& piece, size_t b SharedHandle<BtMessageValidator> validator (new RangeBtMessageValidator (msg.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(msg->getIndex()))); msg->setBtMessageValidator(validator); setCommonProperty(msg); @@ -278,7 +281,7 @@ DefaultBtMessageFactory::createCancelMessage(size_t index, uint32_t begin, size_ SharedHandle<BtMessageValidator> validator (new RangeBtMessageValidator (msg.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(index))); msg->setBtMessageValidator(validator); setCommonProperty(msg); @@ -291,9 +294,10 @@ DefaultBtMessageFactory::createPieceMessage(size_t index, uint32_t begin, size_t BtPieceMessageHandle msg(new BtPieceMessage(index, begin, length)); BtMessageValidatorHandle validator (new BtPieceMessageValidator(msg.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(index))); msg->setBtMessageValidator(validator); + msg->setDownloadContext(_downloadContext); setCommonProperty(msg); return msg; } @@ -303,7 +307,7 @@ DefaultBtMessageFactory::createHaveMessage(size_t index) { BtHaveMessageHandle msg(new BtHaveMessage(index)); SharedHandle<BtMessageValidator> v - (new IndexBtMessageValidator(msg.get(), btContext->getNumPieces())); + (new IndexBtMessageValidator(msg.get(), _downloadContext->getNumPieces())); msg->setBtMessageValidator(v); setCommonProperty(msg); return msg; @@ -349,7 +353,7 @@ DefaultBtMessageFactory::createBitfieldMessage() _pieceStorage->getBitfieldLength())); SharedHandle<BtMessageValidator> v (new BtBitfieldMessageValidator(msg.get(), - btContext->getNumPieces())); + _downloadContext->getNumPieces())); msg->setBtMessageValidator(v); setCommonProperty(msg); return msg; @@ -386,7 +390,7 @@ DefaultBtMessageFactory::createRejectMessage(size_t index, uint32_t begin, size_ SharedHandle<BtMessageValidator> validator (new RangeBtMessageValidator (msg.get(), - btContext->getNumPieces(), + _downloadContext->getNumPieces(), _pieceStorage->getPieceLength(index))); msg->setBtMessageValidator(validator); setCommonProperty(msg); @@ -398,7 +402,7 @@ DefaultBtMessageFactory::createAllowedFastMessage(size_t index) { BtAllowedFastMessageHandle msg(new BtAllowedFastMessage(index)); SharedHandle<BtMessageValidator> validator - (new IndexBtMessageValidator(msg.get(), btContext->getNumPieces())); + (new IndexBtMessageValidator(msg.get(), _downloadContext->getNumPieces())); msg->setBtMessageValidator(validator); setCommonProperty(msg); return msg; @@ -435,9 +439,10 @@ void DefaultBtMessageFactory::setPeer(const SharedHandle<Peer>& peer) this->peer = peer; } -void DefaultBtMessageFactory::setBtContext(const SharedHandle<BtContext>& btContext) +void DefaultBtMessageFactory::setDownloadContext +(const SharedHandle<DownloadContext>& downloadContext) { - this->btContext = btContext; + _downloadContext = downloadContext; } void DefaultBtMessageFactory::setPieceStorage diff --git a/src/DefaultBtMessageFactory.h b/src/DefaultBtMessageFactory.h index c2ef06fc..7b289946 100644 --- a/src/DefaultBtMessageFactory.h +++ b/src/DefaultBtMessageFactory.h @@ -39,7 +39,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class PieceStorage; class PeerStorage; class Peer; @@ -56,7 +56,7 @@ class DHTTaskFactory; class DefaultBtMessageFactory : public BtMessageFactory { private: int32_t cuid; - SharedHandle<BtContext> btContext; + SharedHandle<DownloadContext> _downloadContext; SharedHandle<PieceStorage> _pieceStorage; SharedHandle<PeerStorage> _peerStorage; SharedHandle<Peer> peer; @@ -134,7 +134,7 @@ public: void setPeer(const SharedHandle<Peer>& peer); - void setBtContext(const SharedHandle<BtContext>& btContext); + void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext); void setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage); diff --git a/src/DefaultBtMessageReceiver.cc b/src/DefaultBtMessageReceiver.cc index d6afbb70..9e5ee0f4 100644 --- a/src/DefaultBtMessageReceiver.cc +++ b/src/DefaultBtMessageReceiver.cc @@ -38,13 +38,14 @@ #include "BtHandshakeMessage.h" #include "message.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "Peer.h" #include "PeerConnection.h" #include "BtMessageDispatcher.h" #include "BtMessageFactory.h" #include "Logger.h" #include "LogFactory.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -71,7 +72,8 @@ DefaultBtMessageReceiver::receiveHandshake(bool quickReply) if(!handshakeSent && quickReply && dataLength >= 48) { handshakeSent = true; // check info_hash - if(memcmp(btContext->getInfoHash(), &data[28], INFO_HASH_LENGTH) == 0) { + if(memcmp(bittorrent::getInfoHash(_downloadContext), &data[28], + INFO_HASH_LENGTH) == 0) { sendHandshake(); } } @@ -92,8 +94,8 @@ DefaultBtMessageReceiver::receiveAndSendHandshake() void DefaultBtMessageReceiver::sendHandshake() { SharedHandle<BtMessage> msg = - messageFactory->createHandshakeMessage(btContext->getInfoHash(), - btContext->getPeerId()); + messageFactory->createHandshakeMessage + (bittorrent::getInfoHash(_downloadContext), bittorrent::getStaticPeerId()); dispatcher->addMessageToQueue(msg); dispatcher->sendMessages(); } @@ -114,9 +116,10 @@ BtMessageHandle DefaultBtMessageReceiver::receiveMessage() { } } -void DefaultBtMessageReceiver::setBtContext(const SharedHandle<BtContext>& btContext) +void DefaultBtMessageReceiver::setDownloadContext +(const SharedHandle<DownloadContext>& downloadContext) { - this->btContext = btContext; + _downloadContext = downloadContext; } void DefaultBtMessageReceiver::setPeer(const SharedHandle<Peer>& peer) diff --git a/src/DefaultBtMessageReceiver.h b/src/DefaultBtMessageReceiver.h index 8344eb10..a5bbbf27 100644 --- a/src/DefaultBtMessageReceiver.h +++ b/src/DefaultBtMessageReceiver.h @@ -39,7 +39,7 @@ namespace aria2 { -class BtContext; +class DownloadContext; class Peer; class PeerConnection; class BtMessageDispatcher; @@ -50,7 +50,7 @@ class DefaultBtMessageReceiver : public BtMessageReceiver { private: int32_t cuid; bool handshakeSent; - SharedHandle<BtContext> btContext; + SharedHandle<DownloadContext> _downloadContext; SharedHandle<Peer> peer; WeakHandle<PeerConnection> peerConnection; WeakHandle<BtMessageDispatcher> dispatcher; @@ -77,7 +77,7 @@ public: return cuid; } - void setBtContext(const SharedHandle<BtContext>& btContext); + void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext); void setPeer(const SharedHandle<Peer>& peer); diff --git a/src/DefaultBtProgressInfoFile.cc b/src/DefaultBtProgressInfoFile.cc index ef2d7474..9b573f95 100644 --- a/src/DefaultBtProgressInfoFile.cc +++ b/src/DefaultBtProgressInfoFile.cc @@ -38,13 +38,8 @@ #include <cstring> #include <fstream> -#include "BtContext.h" #include "PieceStorage.h" #include "Piece.h" -#ifdef ENABLE_BITTORRENT -#include "PeerStorage.h" -#include "BtRuntime.h" -#endif // ENABLE_BITTORRENT #include "BitfieldMan.h" #include "Option.h" #include "TransferStat.h" @@ -59,6 +54,12 @@ #include "DownloadFailureException.h" #include "StringFormat.h" #include "array_fun.h" +#include "DownloadContext.h" +#ifdef ENABLE_BITTORRENT +# include "PeerStorage.h" +# include "BtRuntime.h" +# include "bittorrent_helper.h" +#endif // ENABLE_BITTORRENT namespace aria2 { @@ -67,13 +68,13 @@ const std::string DefaultBtProgressInfoFile::V0001("0001"); static std::string createFilename(const SharedHandle<DownloadContext>& dctx) { - std::string t = dctx->getActualBasePath(); + std::string t = dctx->getBasePath(); t += ".aria2"; return t; } DefaultBtProgressInfoFile::DefaultBtProgressInfoFile -(const DownloadContextHandle& dctx, +(const SharedHandle<DownloadContext>& dctx, const PieceStorageHandle& pieceStorage, const Option* option): _dctx(dctx), @@ -123,13 +124,12 @@ void DefaultBtProgressInfoFile::save() { if(torrentDownload) { // infoHashLength: // length: 32 bits - BtContextHandle btContext(dynamic_pointer_cast<BtContext>(_dctx)); - uint32_t infoHashLengthNL = htonl(btContext->getInfoHashLength()); + const unsigned char* infoHash = bittorrent::getInfoHash(_dctx); + uint32_t infoHashLengthNL = htonl(INFO_HASH_LENGTH); o.write(reinterpret_cast<const char*>(&infoHashLengthNL), sizeof(infoHashLengthNL)); // infoHash: - o.write(reinterpret_cast<const char*>(btContext->getInfoHash()), - btContext->getInfoHashLength()); + o.write(reinterpret_cast<const char*>(infoHash), INFO_HASH_LENGTH); } else { // infoHashLength: // length: 32 bits @@ -240,15 +240,16 @@ void DefaultBtProgressInfoFile::load() array_ptr<unsigned char> savedInfoHash(new unsigned char[infoHashLength]); in.read(reinterpret_cast<char*> (static_cast<unsigned char*>(savedInfoHash)), infoHashLength); - BtContextHandle btContext(dynamic_pointer_cast<BtContext>(_dctx)); - if(infoHashCheckEnabled && - Util::toHex(savedInfoHash, infoHashLength) != - btContext->getInfoHashAsString()) { - throw DL_ABORT_EX - (StringFormat("info hash mismatch. expected: %s, actual: %s", - btContext->getInfoHashAsString().c_str(), - Util::toHex(savedInfoHash, - infoHashLength).c_str()).str()); + if(infoHashCheckEnabled) { + const unsigned char* infoHash = bittorrent::getInfoHash(_dctx); + if(infoHashLength != INFO_HASH_LENGTH || + memcmp(savedInfoHash, infoHash, INFO_HASH_LENGTH) != 0) { + throw DL_ABORT_EX + (StringFormat("info hash mismatch. expected: %s, actual: %s", + Util::toHex(infoHash, INFO_HASH_LENGTH).c_str(), + Util::toHex(savedInfoHash, infoHashLength).c_str() + ).str()); + } } } diff --git a/src/DefaultBtRequestFactory.cc b/src/DefaultBtRequestFactory.cc index f14462f1..059c411c 100644 --- a/src/DefaultBtRequestFactory.cc +++ b/src/DefaultBtRequestFactory.cc @@ -40,7 +40,6 @@ #include "Logger.h" #include "Piece.h" #include "Peer.h" -#include "BtContext.h" #include "PieceStorage.h" #include "BtMessageDispatcher.h" #include "BtMessageFactory.h" @@ -235,11 +234,6 @@ void DefaultBtRequestFactory::getTargetPieceIndexes mem_fun_sh(&Piece::getIndex)); } -void DefaultBtRequestFactory::setBtContext(const SharedHandle<BtContext>& btContext) -{ - this->btContext = btContext; -} - void DefaultBtRequestFactory::setPieceStorage (const SharedHandle<PieceStorage>& pieceStorage) { diff --git a/src/DefaultBtRequestFactory.h b/src/DefaultBtRequestFactory.h index a4000368..bcf8c8cf 100644 --- a/src/DefaultBtRequestFactory.h +++ b/src/DefaultBtRequestFactory.h @@ -39,7 +39,6 @@ namespace aria2 { -class BtContext; class PieceStorage; class Peer; class BtMessageDispatcher; @@ -50,7 +49,6 @@ class Logger; class DefaultBtRequestFactory : public BtRequestFactory { private: int32_t cuid; - SharedHandle<BtContext> btContext; SharedHandle<PieceStorage> _pieceStorage; SharedHandle<Peer> peer; WeakHandle<BtMessageDispatcher> dispatcher; @@ -96,8 +94,6 @@ public: this->cuid = cuid; } - void setBtContext(const SharedHandle<BtContext>& btContext); - void setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage); void setPeer(const SharedHandle<Peer>& peer); diff --git a/src/DefaultExtensionMessageFactory.cc b/src/DefaultExtensionMessageFactory.cc index 6210d108..f28680a4 100644 --- a/src/DefaultExtensionMessageFactory.cc +++ b/src/DefaultExtensionMessageFactory.cc @@ -33,7 +33,6 @@ */ /* copyright --> */ #include "DefaultExtensionMessageFactory.h" -#include "BtContext.h" #include "Peer.h" #include "DlAbortEx.h" #include "HandshakeExtensionMessage.h" @@ -50,10 +49,8 @@ DefaultExtensionMessageFactory::DefaultExtensionMessageFactory(): _logger(LogFactory::getInstance()) {} DefaultExtensionMessageFactory::DefaultExtensionMessageFactory -(const BtContextHandle& btContext, - const PeerHandle& peer, +(const PeerHandle& peer, const SharedHandle<ExtensionMessageRegistry>& registry): - _btContext(btContext), _peer(peer), _registry(registry), _logger(LogFactory::getInstance()) {} @@ -67,7 +64,6 @@ DefaultExtensionMessageFactory::createMessage(const unsigned char* data, size_t if(extensionMessageID == 0) { // handshake HandshakeExtensionMessageHandle m = HandshakeExtensionMessage::create(data, length); - m->setBtContext(_btContext); m->setPeer(_peer); return m; } else { @@ -91,11 +87,6 @@ DefaultExtensionMessageFactory::createMessage(const unsigned char* data, size_t } } -void DefaultExtensionMessageFactory::setBtContext(const BtContextHandle& btContext) -{ - _btContext = btContext; -} - void DefaultExtensionMessageFactory::setPeerStorage (const SharedHandle<PeerStorage>& peerStorage) { diff --git a/src/DefaultExtensionMessageFactory.h b/src/DefaultExtensionMessageFactory.h index a3ffd309..dfc1c0ec 100644 --- a/src/DefaultExtensionMessageFactory.h +++ b/src/DefaultExtensionMessageFactory.h @@ -39,7 +39,6 @@ namespace aria2 { -class BtContext; class PeerStorage; class Peer; class Logger; @@ -47,8 +46,6 @@ class ExtensionMessageRegistry; class DefaultExtensionMessageFactory:public ExtensionMessageFactory { private: - SharedHandle<BtContext> _btContext; - SharedHandle<PeerStorage> _peerStorage; SharedHandle<Peer> _peer; @@ -61,8 +58,7 @@ public: DefaultExtensionMessageFactory(); DefaultExtensionMessageFactory - (const SharedHandle<BtContext>& btContext, - const SharedHandle<Peer>& peer, + (const SharedHandle<Peer>& peer, const SharedHandle<ExtensionMessageRegistry>& registry); virtual ~DefaultExtensionMessageFactory(); @@ -70,8 +66,6 @@ public: virtual SharedHandle<ExtensionMessage> createMessage(const unsigned char* data, size_t length); - void setBtContext(const SharedHandle<BtContext>& btContext); - void setPeerStorage(const SharedHandle<PeerStorage>& peerStorage); void setPeer(const SharedHandle<Peer>& peer); diff --git a/src/DefaultPeerStorage.cc b/src/DefaultPeerStorage.cc index 18e36ceb..78116204 100644 --- a/src/DefaultPeerStorage.cc +++ b/src/DefaultPeerStorage.cc @@ -41,7 +41,6 @@ #include "message.h" #include "a2time.h" #include "Peer.h" -#include "BtContext.h" #include "BtRuntime.h" #include "BtSeederStateChoke.h" #include "BtLeecherStateChoke.h" @@ -51,9 +50,7 @@ namespace aria2 { static const int MAX_PEER_LIST_SIZE = 1024; -DefaultPeerStorage::DefaultPeerStorage(const BtContextHandle& btContext, - const Option* option): - btContext(btContext), +DefaultPeerStorage::DefaultPeerStorage(const Option* option): option(option), logger(LogFactory::getInstance()), removedPeerSessionDownloadLength(0), diff --git a/src/DefaultPeerStorage.h b/src/DefaultPeerStorage.h index 21f4b7ef..c52f0094 100644 --- a/src/DefaultPeerStorage.h +++ b/src/DefaultPeerStorage.h @@ -43,7 +43,6 @@ namespace aria2 { -class BtContext; class Option; class Logger; class BtRuntime; @@ -53,7 +52,6 @@ class PieceStorage; class DefaultPeerStorage : public PeerStorage { private: - SharedHandle<BtContext> btContext; SharedHandle<BtRuntime> _btRuntime; SharedHandle<PieceStorage> _pieceStorage; const Option* option; @@ -73,8 +71,7 @@ private: bool isPeerAlreadyAdded(const SharedHandle<Peer>& peer); public: - DefaultPeerStorage(const SharedHandle<BtContext>& btContext, - const Option* option); + DefaultPeerStorage(const Option* option); virtual ~DefaultPeerStorage(); diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc index 3a707558..02547bf0 100644 --- a/src/DefaultPieceStorage.cc +++ b/src/DefaultPieceStorage.cc @@ -63,7 +63,7 @@ namespace aria2 { DefaultPieceStorage::DefaultPieceStorage -(const DownloadContextHandle& downloadContext, const Option* option): +(const SharedHandle<DownloadContext>& downloadContext, const Option* option): downloadContext(downloadContext), bitfieldMan(BitfieldManFactory::getFactoryInstance()-> createBitfieldMan(downloadContext->getPieceLength(), @@ -421,10 +421,10 @@ size_t DefaultPieceStorage::getInFlightPieceCompletedLength() const // not unittested void DefaultPieceStorage::setupFileFilter() { - const std::deque<SharedHandle<FileEntry> >& fileEntries = + const std::vector<SharedHandle<FileEntry> >& fileEntries = downloadContext->getFileEntries(); bool allSelected = true; - for(std::deque<SharedHandle<FileEntry> >::const_iterator i = + for(std::vector<SharedHandle<FileEntry> >::const_iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { if(!(*i)->isRequested()) { allSelected = false; @@ -434,7 +434,7 @@ void DefaultPieceStorage::setupFileFilter() if(allSelected) { return; } - for(std::deque<SharedHandle<FileEntry> >::const_iterator i = + for(std::vector<SharedHandle<FileEntry> >::const_iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { if((*i)->isRequested()) { bitfieldMan->addFilter((*i)->getOffset(), (*i)->getLength()); @@ -465,11 +465,12 @@ bool DefaultPieceStorage::allDownloadFinished() // not unittested void DefaultPieceStorage::initStorage() { - if(downloadContext->getFileMode() == DownloadContext::SINGLE) { + if(downloadContext->getFileEntries().size() == 1) { logger->debug("Instantiating DirectDiskAdaptor"); DirectDiskAdaptorHandle directDiskAdaptor(new DirectDiskAdaptor()); directDiskAdaptor->setTotalLength(downloadContext->getTotalLength()); - directDiskAdaptor->setFileEntries(downloadContext->getFileEntries()); + directDiskAdaptor->setFileEntries(downloadContext->getFileEntries().begin(), + downloadContext->getFileEntries().end()); DiskWriterHandle writer = _diskWriterFactory->newDiskWriter(directDiskAdaptor->getFilePath()); @@ -480,10 +481,10 @@ void DefaultPieceStorage::initStorage() directDiskAdaptor->setDiskWriter(writer); this->diskAdaptor = directDiskAdaptor; } else { - // file mode == DownloadContext::MULTI logger->debug("Instantiating MultiDiskAdaptor"); MultiDiskAdaptorHandle multiDiskAdaptor(new MultiDiskAdaptor()); - multiDiskAdaptor->setFileEntries(downloadContext->getFileEntries()); + multiDiskAdaptor->setFileEntries(downloadContext->getFileEntries().begin(), + downloadContext->getFileEntries().end()); if(option->getAsBool(PREF_ENABLE_DIRECT_IO)) { multiDiskAdaptor->allowDirectIO(); } diff --git a/src/DefaultSegmentManFactory.cc b/src/DefaultSegmentManFactory.cc index 5ed7edef..8f020f98 100644 --- a/src/DefaultSegmentManFactory.cc +++ b/src/DefaultSegmentManFactory.cc @@ -42,8 +42,9 @@ namespace aria2 { SegmentManHandle -DefaultSegmentManFactory::createNewInstance(const DownloadContextHandle& dctx, - const PieceStorageHandle& ps) +DefaultSegmentManFactory::createNewInstance +(const SharedHandle<DownloadContext>& dctx, + const PieceStorageHandle& ps) { SegmentManHandle segmentMan(new SegmentMan(_option, dctx, ps)); return segmentMan; diff --git a/src/DiskAdaptor.cc b/src/DiskAdaptor.cc index 38e0b3ea..5e17eb2b 100644 --- a/src/DiskAdaptor.cc +++ b/src/DiskAdaptor.cc @@ -47,8 +47,4 @@ DiskAdaptor::DiskAdaptor(): DiskAdaptor::~DiskAdaptor() {} -void DiskAdaptor::setFileEntries(const FileEntries& fileEntries) { - this->fileEntries = fileEntries; -} - } // namespace aria2 diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index 6e59826a..cb794391 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -38,7 +38,7 @@ #include "BinaryStream.h" #include <string> -#include <deque> +#include <vector> #include "TimeA2.h" @@ -50,7 +50,7 @@ class FileAllocationIterator; class DiskAdaptor:public BinaryStream { protected: - std::deque<SharedHandle<FileEntry> > fileEntries; + std::vector<SharedHandle<FileEntry> > fileEntries; #ifdef HAVE_POSIX_FALLOCATE bool _fallocate; #endif // HAVE_POSIX_FALLOCATE @@ -73,9 +73,13 @@ public: virtual uint64_t size() = 0; - void setFileEntries(const std::deque<SharedHandle<FileEntry> >& fileEntries); + template<typename InputIterator> + void setFileEntries(InputIterator first, InputIterator last) + { + fileEntries.assign(first, last); + } - const std::deque<SharedHandle<FileEntry> >& getFileEntries() const + const std::vector<SharedHandle<FileEntry> >& getFileEntries() const { return fileEntries; } diff --git a/src/DownloadContext.cc b/src/DownloadContext.cc index a5dda4d2..f002eb3d 100644 --- a/src/DownloadContext.cc +++ b/src/DownloadContext.cc @@ -37,29 +37,30 @@ #include <algorithm> #include "FileEntry.h" +#include "StringFormat.h" namespace aria2 { DownloadContext::DownloadContext(): _dir("."), + _pieceLength(0), + _knowsTotalLength(true), + _ownerRequestGroup(0), _downloadStartTime(0), _downloadStopTime(_downloadStartTime) {} -DownloadContext::~DownloadContext() {} - -void DownloadContext::setDir(const std::string& dir) -{ - _dir = dir; -} - -SharedHandle<Signature> DownloadContext::getSignature() const -{ - return _signature; -} - -void DownloadContext::setSignature(const SharedHandle<Signature>& signature) +DownloadContext::DownloadContext(size_t pieceLength, + uint64_t totalLength, + const std::string& path): + _dir("."), + _pieceLength(pieceLength), + _knowsTotalLength(true), + _ownerRequestGroup(0), + _downloadStartTime(0), + _downloadStopTime(_downloadStartTime) { - _signature = signature; + SharedHandle<FileEntry> fileEntry(new FileEntry(path, totalLength, 0)); + _fileEntries.push_back(fileEntry); } void DownloadContext::resetDownloadStartTime() @@ -94,7 +95,7 @@ DownloadContext::findFileEntryByOffset(off_t offset) const SharedHandle<FileEntry> obj(new FileEntry()); obj->setOffset(offset); - std::deque<SharedHandle<FileEntry> >::const_iterator i = + std::vector<SharedHandle<FileEntry> >::const_iterator i = std::upper_bound(_fileEntries.begin(), _fileEntries.end(), obj); if(i != _fileEntries.end() && (*i)->getOffset() == offset) { return *i; @@ -103,4 +104,65 @@ DownloadContext::findFileEntryByOffset(off_t offset) const } } +void DownloadContext::setFilePathWithIndex +(size_t index, const std::string& path) +{ + if(0 < index && index <= _fileEntries.size()) { + _fileEntries[index-1]->setPath(path); + } else { + throw DL_ABORT_EX(StringFormat("No such file with index=%u", + static_cast<unsigned int>(index)).str()); + } +} + +void DownloadContext::setFileFilter(IntSequence seq) +{ + std::deque<int32_t> fileIndexes = seq.flush(); + std::sort(fileIndexes.begin(), fileIndexes.end()); + fileIndexes.erase(std::unique(fileIndexes.begin(), fileIndexes.end()), + fileIndexes.end()); + + bool selectAll = fileIndexes.empty() || _fileEntries.size() == 1; + + int32_t index = 1; + for(std::vector<SharedHandle<FileEntry> >::const_iterator i = + _fileEntries.begin(); i != _fileEntries.end(); ++i, ++index) { + (*i)->setRequested + (selectAll || + std::binary_search(fileIndexes.begin(), fileIndexes.end(), index)); + } +} + +void DownloadContext::ensureAttrs() +{ + if(_attrs.isNone()) { + _attrs = BDE::dict(); + } +} + +void DownloadContext::setAttribute(const std::string& key, const BDE& value) +{ + ensureAttrs(); + _attrs[key] = value; +} + +BDE& DownloadContext::getAttribute(const std::string& key) +{ + ensureAttrs(); + if(_attrs.containsKey(key)) { + return _attrs[key]; + } else { + throw DL_ABORT_EX(StringFormat("No attribute named %s", key.c_str()).str()); + } +} + +bool DownloadContext::hasAttribute(const std::string& key) const +{ + if(_attrs.isNone()) { + return false; + } else { + return _attrs.containsKey(key); + } +} + } // namespace aria2 diff --git a/src/DownloadContext.h b/src/DownloadContext.h index f1aed08e..ef55b035 100644 --- a/src/DownloadContext.h +++ b/src/DownloadContext.h @@ -37,80 +37,194 @@ #include "common.h" +#include <cassert> #include <string> -#include <deque> +#include <vector> #include "SharedHandle.h" #include "Signature.h" #include "TimeA2.h" +#include "A2STR.h" +#include "BDE.h" +#include "IntSequence.h" namespace aria2 { class FileEntry; +class RequestGroup; class DownloadContext { -protected: - std::deque<SharedHandle<FileEntry> > _fileEntries; +private: + std::vector<SharedHandle<FileEntry> > _fileEntries; std::string _dir; -private: + + std::vector<std::string> _pieceHashes; + + size_t _pieceLength; + + std::string _pieceHashAlgo; + + std::string _checksum; + + std::string _checksumHashAlgo; + + std::string _basePath; + + bool _knowsTotalLength; + + RequestGroup* _ownerRequestGroup; + + BDE _attrs; + Time _downloadStartTime; Time _downloadStopTime; SharedHandle<Signature> _signature; + + void ensureAttrs(); public: DownloadContext(); - virtual ~DownloadContext(); - - enum FILE_MODE { - SINGLE, - MULTI - }; + // Convenient constructor that creates single file download. + DownloadContext(size_t pieceLength, + uint64_t totalLength, + const std::string& path = A2STR::NIL); - virtual const std::string& getPieceHash(size_t index) const = 0; + const std::string& getPieceHash(size_t index) const + { + if(index < _pieceHashes.size()) { + return _pieceHashes[index]; + } else { + return A2STR::NIL; + } + } - virtual const std::deque<std::string>& getPieceHashes() const = 0; + const std::vector<std::string>& getPieceHashes() const + { + return _pieceHashes; + } + + template<typename InputIterator> + void setPieceHashes(InputIterator first, InputIterator last) + { + _pieceHashes.assign(first, last); + } - virtual uint64_t getTotalLength() const = 0; + uint64_t getTotalLength() const + { + if(_fileEntries.empty()) { + return 0; + } else { + return _fileEntries.back()->getLastOffset(); + } + } - virtual bool knowsTotalLength() const = 0; + bool knowsTotalLength() const { return _knowsTotalLength; } - virtual FILE_MODE getFileMode() const = 0; + void markTotalLengthIsUnknown() { _knowsTotalLength = false; } - const std::deque<SharedHandle<FileEntry> >& getFileEntries() const + const std::vector<SharedHandle<FileEntry> >& getFileEntries() const { return _fileEntries; } - virtual size_t getPieceLength() const = 0; + const SharedHandle<FileEntry>& getFirstFileEntry() const + { + assert(!_fileEntries.empty()); + return _fileEntries[0]; + } + + template<typename InputIterator> + void setFileEntries(InputIterator first, InputIterator last) + { + _fileEntries.assign(first, last); + } + + size_t getPieceLength() const { return _pieceLength; } + + void setPieceLength(size_t length) { _pieceLength = length; } + + size_t getNumPieces() const + { + if(_pieceLength == 0) { + return 0; + } else { + assert(!_fileEntries.empty()); + return (_fileEntries.back()->getLastOffset()+_pieceLength-1)/_pieceLength; + } + } + + const std::string& getPieceHashAlgo() const { return _pieceHashAlgo; } + + void setPieceHashAlgo(const std::string& algo) + { + _pieceHashAlgo = algo; + } + + const std::string& getChecksum() const { return _checksum; } + + void setChecksum(const std::string& checksum) + { + _checksum = checksum; + } + + const std::string& getChecksumHashAlgo() const { return _checksumHashAlgo; } - virtual size_t getNumPieces() const = 0; + void setChecksumHashAlgo(const std::string& algo) + { + _checksumHashAlgo = algo; + } + + // The representative path name for this context. It is used as a + // part of .aria2 control file. If _basePath is set, returns + // _basePath. Otherwise, the first FileEntry's getFilePath() is + // returned. + const std::string& getBasePath() const + { + if(_basePath.empty()) { + assert(!_fileEntries.empty()); + return getFirstFileEntry()->getPath(); + } else { + return _basePath; + } + } + + void setBasePath(const std::string& basePath) { _basePath = basePath; } + + const std::string& getDir() const { return _dir; } - virtual const std::string& getPieceHashAlgo() const = 0; + void setDir(const std::string& dir) { _dir = dir; } - /** - * Returns an actual file path. - * If this contains a single file entry, then returns its file path, - * for example, "/tmp/downloads/aria2.txt" - * If this contains multiple file entries(i,e /tmp/downloads/aria2.txt, - * /tmp/downloads/aria2.bin), then returns its base dir path, - * for example, "/tmp/downloads" - */ - virtual std::string getActualBasePath() const = 0; + SharedHandle<Signature> getSignature() const { return _signature; } - const std::string& getDir() const + void setSignature(const SharedHandle<Signature>& signature) { - return _dir; + _signature = signature; } - void setDir(const std::string& dir); + RequestGroup* getOwnerRequestGroup() { return _ownerRequestGroup; } - SharedHandle<Signature> getSignature() const; + void setOwnerRequestGroup(RequestGroup* owner) + { + _ownerRequestGroup = owner; + } + + void setFileFilter(IntSequence seq); + + // Sets file path for spcified index. index starts from 1. The index + // is the same used in setFileFilter(). Please note that path is + // not the actual file path. The actual file path is + // getDir()+"/"+path. + void setFilePathWithIndex(size_t index, const std::string& path); - void setSignature(const SharedHandle<Signature>& signature); + void setAttribute(const std::string& key, const BDE& value); + + BDE& getAttribute(const std::string& key); + + bool hasAttribute(const std::string& key) const; void resetDownloadStartTime(); @@ -123,8 +237,6 @@ public: SharedHandle<FileEntry> findFileEntryByOffset(off_t offset) const; }; -typedef SharedHandle<DownloadContext> DownloadContextHandle; - } // namespace aria2 #endif // _D_DOWNLOAD_CONTEXT_H_ diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 5808e426..75c507f2 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -65,14 +65,15 @@ #include "Command.h" #include "FileAllocationEntry.h" #include "CheckIntegrityEntry.h" - -#include "BtRegistry.h" -#include "BtContext.h" -#include "PeerStorage.h" -#include "PieceStorage.h" -#include "BtAnnounce.h" -#include "BtRuntime.h" #include "BtProgressInfoFile.h" +#include "DownloadContext.h" +#ifdef ENABLE_BITTORRENT +# include "BtRegistry.h" +# include "PeerStorage.h" +# include "PieceStorage.h" +# include "BtAnnounce.h" +# include "BtRuntime.h" +#endif // ENABLE_BITTORRENT namespace aria2 { diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc index b55b158a..0f83a674 100644 --- a/src/DownloadEngineFactory.cc +++ b/src/DownloadEngineFactory.cc @@ -57,6 +57,7 @@ #include "DownloadResult.h" #include "ServerStatMan.h" #include "a2io.h" +#include "DownloadContext.h" #ifdef HAVE_EPOLL # include "EpollEventPoll.h" #endif // HAVE_EPOLL diff --git a/src/DownloadHandler.cc b/src/DownloadHandler.cc index 93b901d4..8840a630 100644 --- a/src/DownloadHandler.cc +++ b/src/DownloadHandler.cc @@ -37,6 +37,7 @@ #include "Logger.h" #include "RequestGroup.h" #include "RequestGroupCriteria.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/DownloadResult.h b/src/DownloadResult.h index 973095ee..d52c79dc 100644 --- a/src/DownloadResult.h +++ b/src/DownloadResult.h @@ -40,7 +40,7 @@ #include <stdint.h> #include <string> -#include <deque> +#include <vector> #include "SharedHandle.h" #include "FileEntry.h" @@ -64,7 +64,7 @@ public: int32_t gid; - std::deque<SharedHandle<FileEntry> > fileEntries; + std::vector<SharedHandle<FileEntry> > fileEntries; bool inMemoryDownload; @@ -82,7 +82,7 @@ public: RESULT result; DownloadResult(int32_t gid, - const std::deque<SharedHandle<FileEntry> >& fileEntries, + const std::vector<SharedHandle<FileEntry> >& fileEntries, bool inMemoryDownload, uint64_t totalLength, const std::string& uri, diff --git a/src/FileAllocationCommand.cc b/src/FileAllocationCommand.cc index db4967a2..1f0eda1a 100644 --- a/src/FileAllocationCommand.cc +++ b/src/FileAllocationCommand.cc @@ -42,6 +42,7 @@ #include "prefs.h" #include "Util.h" #include "DownloadEngine.h" +#include "DownloadContext.h" namespace aria2 { @@ -78,7 +79,8 @@ bool FileAllocationCommand::handleException(Exception& e) { _e->_fileAllocationMan->dropPickedEntry(); logger->error(MSG_FILE_ALLOCATION_FAILURE, e, cuid); - logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str()); + logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, + _requestGroup->getDownloadContext()->getBasePath().c_str()); return true; } diff --git a/src/FileAllocationDispatcherCommand.cc b/src/FileAllocationDispatcherCommand.cc index ba33aa0b..c86f26cb 100644 --- a/src/FileAllocationDispatcherCommand.cc +++ b/src/FileAllocationDispatcherCommand.cc @@ -37,6 +37,7 @@ #include "FileAllocationCommand.h" #include "message.h" #include "Logger.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FileAllocationEntry.cc b/src/FileAllocationEntry.cc index 6a6cd732..aba0b0c5 100644 --- a/src/FileAllocationEntry.cc +++ b/src/FileAllocationEntry.cc @@ -38,6 +38,7 @@ #include "RequestGroup.h" #include "PieceStorage.h" #include "DiskAdaptor.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FileEntry.h b/src/FileEntry.h index 05ba6067..a40be12e 100644 --- a/src/FileEntry.h +++ b/src/FileEntry.h @@ -60,6 +60,7 @@ private: bool requested; std::deque<SharedHandle<Request> > _requestPool; std::deque<SharedHandle<Request> > _inFlightRequests; + std::string _contentType; public: FileEntry():length(0), offset(0), extracted(false), requested(false) {} @@ -128,6 +129,13 @@ public: // Inserts _uris and _spentUris into uris. void getUris(std::deque<std::string>& uris) const; + void setContentType(const std::string& contentType) + { + _contentType = contentType; + } + + const std::string& getContentType() const { return _contentType; } + std::string selectUri(const SharedHandle<URISelector>& uriSelector); // If pooled Request object is available, one of them is removed diff --git a/src/FillRequestGroupCommand.cc b/src/FillRequestGroupCommand.cc index 869496b5..1a544b72 100644 --- a/src/FillRequestGroupCommand.cc +++ b/src/FillRequestGroupCommand.cc @@ -39,6 +39,7 @@ #include "RecoverableException.h" #include "message.h" #include "Logger.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FtpDownloadCommand.cc b/src/FtpDownloadCommand.cc index 49a62b5c..d66c0f20 100644 --- a/src/FtpDownloadCommand.cc +++ b/src/FtpDownloadCommand.cc @@ -43,6 +43,7 @@ #include "FtpFinishDownloadCommand.h" #include "FtpConnection.h" #include "Logger.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FtpFinishDownloadCommand.cc b/src/FtpFinishDownloadCommand.cc index bf8af2a2..dbf56edc 100644 --- a/src/FtpFinishDownloadCommand.cc +++ b/src/FtpFinishDownloadCommand.cc @@ -47,6 +47,7 @@ #include "SocketCore.h" #include "RequestGroup.h" #include "Logger.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc index 7453337a..dcfcde6b 100644 --- a/src/FtpInitiateConnectionCommand.cc +++ b/src/FtpInitiateConnectionCommand.cc @@ -50,6 +50,7 @@ #include "prefs.h" #include "HttpConnection.h" #include "Socket.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index cbdea101..555ea605 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -53,7 +53,7 @@ #include "Option.h" #include "Logger.h" #include "Segment.h" -#include "SingleFileDownloadContext.h" +#include "DownloadContext.h" #include "DefaultBtProgressInfoFile.h" #include "RequestGroupMan.h" #include "DownloadFailureException.h" @@ -328,17 +328,17 @@ bool FtpNegotiationCommand::sendSize() { bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength) { - SingleFileDownloadContextHandle dctx = - dynamic_pointer_cast<SingleFileDownloadContext>(_requestGroup->getDownloadContext()); - dctx->setTotalLength(totalLength); _fileEntry->setLength(totalLength); - dctx->setFilename - (strconcat(dctx->getDir(), "/", Util::urldecode(req->getFile()))); + if(getOption()->get(PREF_OUT).empty()) { + _fileEntry->setPath + (strconcat(getDownloadContext()->getDir(), + "/", Util::urldecode(req->getFile()))); + } _requestGroup->preDownloadProcessing(); if(e->_requestGroupMan->isSameFileBeingDownloaded(_requestGroup)) { throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD, - _requestGroup->getFilePath().c_str()).str()); + _requestGroup->getFirstFilePath().c_str()).str()); } if(totalLength == 0) { @@ -361,7 +361,7 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength) logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _requestGroup->getGID(), - _requestGroup->getFilePath().c_str()); + _requestGroup->getFirstFilePath().c_str()); poolConnection(); @@ -372,7 +372,7 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength) _requestGroup->initPieceStorage(); _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile(); - if(dctx->knowsTotalLength()) { + if(getDownloadContext()->knowsTotalLength()) { sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED; poolConnection(); return false; @@ -400,7 +400,7 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength) logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _requestGroup->getGID(), - _requestGroup->getFilePath().c_str()); + _requestGroup->getFirstFilePath().c_str()); poolConnection(); @@ -444,10 +444,7 @@ bool FtpNegotiationCommand::recvSize() { // command, resuming and segmented downloading are disabled when the first // contacted FTP server doesn't support it. if(_requestGroup->getPieceStorage().isNull()) { - SingleFileDownloadContextHandle dctx = - dynamic_pointer_cast<SingleFileDownloadContext> - (_requestGroup->getDownloadContext()); - dctx->markTotalLengthIsUnknown(); + getDownloadContext()->markTotalLengthIsUnknown(); return onFileSizeDetermined(0); } diff --git a/src/FtpTunnelRequestCommand.cc b/src/FtpTunnelRequestCommand.cc index 09a162c5..73e5ed9c 100644 --- a/src/FtpTunnelRequestCommand.cc +++ b/src/FtpTunnelRequestCommand.cc @@ -36,6 +36,7 @@ #include "FtpTunnelResponseCommand.h" #include "Request.h" #include "Socket.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/FtpTunnelResponseCommand.cc b/src/FtpTunnelResponseCommand.cc index 293b88c8..0ecb3bd0 100644 --- a/src/FtpTunnelResponseCommand.cc +++ b/src/FtpTunnelResponseCommand.cc @@ -39,6 +39,7 @@ #include "HttpRequest.h" #include "Segment.h" #include "Socket.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc index d276b8d9..370746f4 100644 --- a/src/HandshakeExtensionMessage.cc +++ b/src/HandshakeExtensionMessage.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "HandshakeExtensionMessage.h" #include "Peer.h" -#include "BtContext.h" #include "Util.h" #include "DlAbortEx.h" #include "LogFactory.h" @@ -107,11 +106,6 @@ void HandshakeExtensionMessage::setPeer(const PeerHandle& peer) _peer = peer; } -void HandshakeExtensionMessage::setBtContext(const BtContextHandle& btContext) -{ - _btContext = btContext; -} - uint8_t HandshakeExtensionMessage::getExtensionMessageID(const std::string& name) const { std::map<std::string, uint8_t>::const_iterator i = _extensions.find(name); diff --git a/src/HandshakeExtensionMessage.h b/src/HandshakeExtensionMessage.h index dc054f52..3c9c7dd9 100644 --- a/src/HandshakeExtensionMessage.h +++ b/src/HandshakeExtensionMessage.h @@ -43,7 +43,6 @@ namespace aria2 { -class BtContext; class Peer; class Logger; class HandshakeExtensionMessage; @@ -57,8 +56,6 @@ private: std::map<std::string, uint8_t> _extensions; - SharedHandle<BtContext> _btContext; - SharedHandle<Peer> _peer; Logger* _logger; @@ -120,8 +117,6 @@ public: void setPeer(const SharedHandle<Peer>& peer); - void setBtContext(const SharedHandle<BtContext>& btContext); - static HandshakeExtensionMessageHandle create(const unsigned char* data, size_t dataLength); }; diff --git a/src/HaveEraseCommand.cc b/src/HaveEraseCommand.cc index 4ad39505..910ee761 100644 --- a/src/HaveEraseCommand.cc +++ b/src/HaveEraseCommand.cc @@ -37,6 +37,7 @@ #include "RequestGroupMan.h" #include "PieceStorage.h" #include "RequestGroup.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpDownloadCommand.cc b/src/HttpDownloadCommand.cc index 9819efea..98ada9eb 100644 --- a/src/HttpDownloadCommand.cc +++ b/src/HttpDownloadCommand.cc @@ -46,6 +46,7 @@ #include "HttpResponse.h" #include "HttpHeader.h" #include "Range.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpInitiateConnectionCommand.cc b/src/HttpInitiateConnectionCommand.cc index b9552db5..4245403a 100644 --- a/src/HttpInitiateConnectionCommand.cc +++ b/src/HttpInitiateConnectionCommand.cc @@ -47,6 +47,7 @@ #include "message.h" #include "prefs.h" #include "A2STR.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpProxyRequestCommand.cc b/src/HttpProxyRequestCommand.cc index 9d0a434b..04e534ee 100644 --- a/src/HttpProxyRequestCommand.cc +++ b/src/HttpProxyRequestCommand.cc @@ -36,6 +36,7 @@ #include "HttpProxyResponseCommand.h" #include "Request.h" #include "Socket.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpProxyResponseCommand.cc b/src/HttpProxyResponseCommand.cc index 0054d6d9..be6a58ff 100644 --- a/src/HttpProxyResponseCommand.cc +++ b/src/HttpProxyResponseCommand.cc @@ -39,6 +39,7 @@ #include "HttpRequest.h" #include "Segment.h" #include "Socket.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index d46f68ac..bac87114 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -53,8 +53,7 @@ namespace aria2 { const std::string HttpRequest::USER_AGENT("aria2"); -HttpRequest::HttpRequest():entityLength(0), - _contentEncodingEnabled(true), +HttpRequest::HttpRequest():_contentEncodingEnabled(true), userAgent(USER_AGENT) {} @@ -83,7 +82,8 @@ off_t HttpRequest::getEndByte() const return 0; } else { if(request->isPipeliningEnabled()) { - return _fileEntry->gtoloff(segment->getPosition()+segment->getLength()-1); + off_t endByte = _fileEntry->gtoloff(segment->getPosition()+segment->getLength()-1); + return std::min(endByte, _fileEntry->getLastOffset()-1); } else { return 0; } @@ -96,7 +96,8 @@ RangeHandle HttpRequest::getRange() const if(segment.isNull()) { return SharedHandle<Range>(new Range()); } else { - return SharedHandle<Range>(new Range(getStartByte(), getEndByte(), entityLength)); + return SharedHandle<Range>(new Range(getStartByte(), getEndByte(), + _fileEntry->getLength())); } } @@ -107,9 +108,9 @@ bool HttpRequest::isRangeSatisfied(const RangeHandle& range) const } if((getStartByte() == range->getStartByte()) && ((getEndByte() == 0) || - ((getEndByte() > 0) && (getEndByte() == range->getEndByte()))) && - ((entityLength == 0) || - ((entityLength > 0) && (entityLength == range->getEntityLength())))) { + (getEndByte() == range->getEndByte())) && + ((_fileEntry->getLength() == 0) || + (_fileEntry->getLength() == range->getEntityLength()))) { return true; } else { return false; diff --git a/src/HttpRequest.h b/src/HttpRequest.h index 9ec32171..def1ddd6 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -37,6 +37,7 @@ #include "common.h" +#include <cassert> #include <string> #include <deque> @@ -64,8 +65,6 @@ private: SharedHandle<Segment> segment; - uint64_t entityLength; - bool _contentEncodingEnabled; std::string userAgent; @@ -97,17 +96,10 @@ public: void setRequest(const SharedHandle<Request>& request); - /** - * entityLength is used in isRangeSatisfied() method. - */ - void setEntityLength(uint64_t entityLength) - { - this->entityLength = entityLength; - } - uint64_t getEntityLength() const { - return entityLength; + assert(!_fileEntry.isNull()); + return _fileEntry->getLength(); } const std::string& getHost() const diff --git a/src/HttpRequestCommand.cc b/src/HttpRequestCommand.cc index d95e616b..961e8155 100644 --- a/src/HttpRequestCommand.cc +++ b/src/HttpRequestCommand.cc @@ -52,6 +52,7 @@ #include "CookieStorage.h" #include "AuthConfigFactory.h" #include "AuthConfig.h" +#include "DownloadContext.h" namespace aria2 { @@ -89,7 +90,6 @@ createHttpRequest(const SharedHandle<Request>& req, httpRequest->setRequest(req); httpRequest->setFileEntry(fileEntry); httpRequest->setSegment(segment); - httpRequest->setEntityLength(fileEntry->getLength()); httpRequest->addHeader(option->get(PREF_HEADER)); httpRequest->setCookieStorage(cookieStorage); httpRequest->setAuthConfigFactory(authConfigFactory); diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 30de2641..ece2606a 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -34,7 +34,7 @@ /* copyright --> */ #include "HttpResponseCommand.h" #include "DownloadEngine.h" -#include "SingleFileDownloadContext.h" +#include "DownloadContext.h" #include "FileEntry.h" #include "RequestGroup.h" #include "ServerHost.h" @@ -136,18 +136,20 @@ bool HttpResponseCommand::executeInternal() } if(_requestGroup->getPieceStorage().isNull()) { uint64_t totalLength = httpResponse->getEntityLength(); - SingleFileDownloadContextHandle dctx = - dynamic_pointer_cast<SingleFileDownloadContext>(_requestGroup->getDownloadContext()); - dctx->setTotalLength(totalLength); _fileEntry->setLength(totalLength); - dctx->setFilename - (strconcat(dctx->getDir(), "/", httpResponse->determinFilename())); - dctx->setContentType(httpResponse->getContentType()); + // We assume that in this context + // DownloadContext::getFileEntries().size() == 1 + if(getOption()->get(PREF_OUT).empty()) { + _fileEntry->setPath + (strconcat(getDownloadContext()->getDir(), + "/", httpResponse->determinFilename())); + } + _fileEntry->setContentType(httpResponse->getContentType()); _requestGroup->preDownloadProcessing(); if(e->_requestGroupMan->isSameFileBeingDownloaded(_requestGroup)) { throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD, - _requestGroup->getFilePath().c_str()).str()); + _requestGroup->getFirstFilePath().c_str()).str()); } // update last modified time updateLastModifiedTime(httpResponse->getLastModifiedTime()); @@ -156,13 +158,13 @@ bool HttpResponseCommand::executeInternal() // assume we can do segmented downloading if(totalLength == 0 || shouldInflateContentEncoding(httpResponse)) { // we ignore content-length when inflate is required - dctx->setTotalLength(0); + _fileEntry->setLength(0); if(req->getMethod() == Request::METHOD_GET && (totalLength != 0 || !httpResponse->getHttpHeader()->defined(HttpHeader::CONTENT_LENGTH))){ - // dctx->knowsTotalLength() == true only when server says the - // size of file is 0 explicitly. - dctx->markTotalLengthIsUnknown(); + // DownloadContext::knowsTotalLength() == true only when + // server says the size of file is 0 explicitly. + getDownloadContext()->markTotalLengthIsUnknown(); } return handleOtherEncoding(httpResponse); } else { @@ -241,7 +243,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _requestGroup->getGID(), - _requestGroup->getFilePath().c_str()); + _requestGroup->getFirstFilePath().c_str()); return true; } @@ -249,7 +251,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe DownloadCommand* command = 0; try { _requestGroup->loadAndOpenFile(infoFile); - File file(_requestGroup->getFilePath()); + File file(_requestGroup->getFirstFilePath()); SegmentHandle segment = _requestGroup->getSegmentMan()->getSegment(cuid, 0); // pipelining requires implicit range specified. But the request for @@ -335,7 +337,7 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _requestGroup->getGID(), - _requestGroup->getFilePath().c_str()); + _requestGroup->getFirstFilePath().c_str()); poolConnection(); return true; diff --git a/src/HttpServerBodyCommand.cc b/src/HttpServerBodyCommand.cc index afbf601d..c40efde1 100644 --- a/src/HttpServerBodyCommand.cc +++ b/src/HttpServerBodyCommand.cc @@ -49,6 +49,7 @@ #include "XmlRpcMethod.h" #include "XmlRpcMethodFactory.h" #include "XmlRpcResponse.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpServerCommand.cc b/src/HttpServerCommand.cc index 55f32427..38b9bdee 100644 --- a/src/HttpServerCommand.cc +++ b/src/HttpServerCommand.cc @@ -46,6 +46,7 @@ #include "prefs.h" #include "Option.h" #include "Util.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/HttpSkipResponseCommand.cc b/src/HttpSkipResponseCommand.cc index b9edb717..ff1bf174 100644 --- a/src/HttpSkipResponseCommand.cc +++ b/src/HttpSkipResponseCommand.cc @@ -53,6 +53,7 @@ #include "CookieStorage.h" #include "AuthConfigFactory.h" #include "AuthConfig.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/InitiateConnectionCommandFactory.cc b/src/InitiateConnectionCommandFactory.cc index 2ad3dbda..450f6d46 100644 --- a/src/InitiateConnectionCommandFactory.cc +++ b/src/InitiateConnectionCommandFactory.cc @@ -43,6 +43,7 @@ #include "Option.h" #include "prefs.h" #include "SocketCore.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/InitiatorMSEHandshakeCommand.cc b/src/InitiatorMSEHandshakeCommand.cc index b29fe38c..7afeab6e 100644 --- a/src/InitiatorMSEHandshakeCommand.cc +++ b/src/InitiatorMSEHandshakeCommand.cc @@ -43,7 +43,6 @@ #include "Logger.h" #include "Peer.h" #include "PeerConnection.h" -#include "BtContext.h" #include "BtRuntime.h" #include "PeerStorage.h" #include "PieceStorage.h" @@ -52,6 +51,8 @@ #include "ARC4Encryptor.h" #include "ARC4Decryptor.h" #include "RequestGroup.h" +#include "DownloadContext.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -60,13 +61,11 @@ InitiatorMSEHandshakeCommand::InitiatorMSEHandshakeCommand RequestGroup* requestGroup, const SharedHandle<Peer>& p, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<SocketCore>& s): PeerAbstractCommand(cuid, p, e, s), _requestGroup(requestGroup), - _btContext(btContext), _btRuntime(btRuntime), _sequence(INITIATOR_SEND_KEY), _mseHandshake(new MSEHandshake(cuid, socket, getOption().get())) @@ -114,7 +113,8 @@ bool InitiatorMSEHandshakeCommand::executeInternal() { break; case INITIATOR_WAIT_KEY: { if(_mseHandshake->receivePublicKey()) { - _mseHandshake->initCipher(_btContext->getInfoHash()); + _mseHandshake->initCipher + (bittorrent::getInfoHash(_requestGroup->getDownloadContext()));; if(_mseHandshake->sendInitiatorStep2()) { _sequence = INITIATOR_FIND_VC_MARKER; } else { @@ -151,11 +151,11 @@ bool InitiatorMSEHandshakeCommand::executeInternal() { _mseHandshake->getDecryptor()); } PeerInteractionCommand* c = - new PeerInteractionCommand(cuid, _requestGroup, peer, e, _btContext, - _btRuntime, _pieceStorage, - socket, - PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE, - peerConnection); + new PeerInteractionCommand + (cuid, _requestGroup, peer, e, _btRuntime, _pieceStorage, + socket, + PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE, + peerConnection); c->setPeerStorage(_peerStorage); e->commands.push_back(c); return true; @@ -176,7 +176,7 @@ bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait) peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, - e, _btContext, _btRuntime); + e, _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); @@ -187,7 +187,7 @@ bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait) logger->info("CUID#%d - Retry using legacy BitTorrent handshake.", cuid); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(cuid, _requestGroup, peer, e, - _btContext, _btRuntime, false); + _btRuntime, false); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); diff --git a/src/InitiatorMSEHandshakeCommand.h b/src/InitiatorMSEHandshakeCommand.h index 46cbedf0..996a72e9 100644 --- a/src/InitiatorMSEHandshakeCommand.h +++ b/src/InitiatorMSEHandshakeCommand.h @@ -40,7 +40,6 @@ namespace aria2 { class RequestGroup; -class BtContext; class PeerStorage; class PieceStorage; class BtRuntime; @@ -61,8 +60,6 @@ public: private: RequestGroup* _requestGroup; - SharedHandle<BtContext> _btContext; - SharedHandle<PeerStorage> _peerStorage; SharedHandle<PieceStorage> _pieceStorage; @@ -79,13 +76,13 @@ protected: virtual void onAbort(); virtual bool exitBeforeExecute(); public: - InitiatorMSEHandshakeCommand(int32_t cuid, - RequestGroup* requestGroup, - const SharedHandle<Peer>& peer, - DownloadEngine* e, - const SharedHandle<BtContext>& btContext, - const SharedHandle<BtRuntime>& btRuntime, - const SharedHandle<SocketCore>& s); + InitiatorMSEHandshakeCommand + (int32_t cuid, + RequestGroup* requestGroup, + const SharedHandle<Peer>& peer, + DownloadEngine* e, + const SharedHandle<BtRuntime>& btRuntime, + const SharedHandle<SocketCore>& s); virtual ~InitiatorMSEHandshakeCommand(); diff --git a/src/IteratableChecksumValidator.cc b/src/IteratableChecksumValidator.cc index b250af4d..a3be0a21 100644 --- a/src/IteratableChecksumValidator.cc +++ b/src/IteratableChecksumValidator.cc @@ -38,7 +38,6 @@ #include "Util.h" #include "message.h" -#include "SingleFileDownloadContext.h" #include "PieceStorage.h" #include "messageDigest.h" #include "LogFactory.h" @@ -46,14 +45,16 @@ #include "DiskAdaptor.h" #include "FileEntry.h" #include "BitfieldMan.h" +#include "DownloadContext.h" namespace aria2 { #define BUFSIZE (256*1024) #define ALIGNMENT 512 -IteratableChecksumValidator::IteratableChecksumValidator(const SingleFileDownloadContextHandle& dctx, - const PieceStorageHandle& pieceStorage): +IteratableChecksumValidator::IteratableChecksumValidator +(const SharedHandle<DownloadContext>& dctx, + const PieceStorageHandle& pieceStorage): _dctx(dctx), _pieceStorage(pieceStorage), _currentOffset(0), diff --git a/src/IteratableChecksumValidator.h b/src/IteratableChecksumValidator.h index 2a8997a8..62112e95 100644 --- a/src/IteratableChecksumValidator.h +++ b/src/IteratableChecksumValidator.h @@ -39,7 +39,7 @@ namespace aria2 { -class SingleFileDownloadContext; +class DownloadContext; class PieceStorage; class Logger; class MessageDigestContext; @@ -47,7 +47,7 @@ class MessageDigestContext; class IteratableChecksumValidator:public IteratableValidator { private: - SharedHandle<SingleFileDownloadContext> _dctx; + SharedHandle<DownloadContext> _dctx; SharedHandle<PieceStorage> _pieceStorage; @@ -60,7 +60,7 @@ private: unsigned char* _buffer; public: - IteratableChecksumValidator(const SharedHandle<SingleFileDownloadContext>& dctx, + IteratableChecksumValidator(const SharedHandle<DownloadContext>& dctx, const SharedHandle<PieceStorage>& pieceStorage); virtual ~IteratableChecksumValidator(); diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc index bb3f2fcb..b58ab90d 100644 --- a/src/IteratableChunkChecksumValidator.cc +++ b/src/IteratableChunkChecksumValidator.cc @@ -58,7 +58,7 @@ namespace aria2 { #define ALIGNMENT 512 IteratableChunkChecksumValidator:: -IteratableChunkChecksumValidator(const DownloadContextHandle& dctx, +IteratableChunkChecksumValidator(const SharedHandle<DownloadContext>& dctx, const PieceStorageHandle& pieceStorage): _dctx(dctx), _pieceStorage(pieceStorage), @@ -153,7 +153,7 @@ std::string IteratableChunkChecksumValidator::digest(off_t offset, size_t length curoffset); if(r == 0 || r < static_cast<size_t>(woffset)) { throw DL_ABORT_EX - (StringFormat(EX_FILE_READ, _dctx->getActualBasePath().c_str(), + (StringFormat(EX_FILE_READ, _dctx->getBasePath().c_str(), strerror(errno)).str()); } size_t wlength; diff --git a/src/MSEHandshake.cc b/src/MSEHandshake.cc index 70ce2ef7..760002bc 100644 --- a/src/MSEHandshake.cc +++ b/src/MSEHandshake.cc @@ -50,10 +50,11 @@ #include "MessageDigestHelper.h" #include "SimpleRandomizer.h" #include "Util.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "prefs.h" #include "Option.h" #include "StringFormat.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -435,7 +436,7 @@ bool MSEHandshake::findReceiverHashMarker() } bool MSEHandshake::receiveReceiverHashAndPadCLength -(const std::deque<SharedHandle<BtContext> >& btContexts) +(const std::deque<SharedHandle<DownloadContext> >& downloadContexts) { size_t r = 20+VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2/*PadC length*/-_rbufLength; if(r > receiveNBytes(r)) { @@ -444,22 +445,23 @@ bool MSEHandshake::receiveReceiverHashAndPadCLength // resolve info hash // pointing to the position of HASH('req2', SKEY) xor HASH('req3', S) unsigned char* rbufptr = _rbuf; - SharedHandle<BtContext> btContext; - for(std::deque<SharedHandle<BtContext> >::const_iterator i = btContexts.begin(); - i != btContexts.end(); ++i) { + SharedHandle<DownloadContext> downloadContext; + for(std::deque<SharedHandle<DownloadContext> >::const_iterator i = + downloadContexts.begin(); i != downloadContexts.end(); ++i) { unsigned char md[20]; - createReq23Hash(md, (*i)->getInfoHash()); + const BDE& torrentAttrs = (*i)->getAttribute(bittorrent::BITTORRENT); + createReq23Hash(md, torrentAttrs[bittorrent::INFO_HASH].uc()); if(memcmp(md, rbufptr, sizeof(md)) == 0) { - _logger->debug("CUID#%d - info hash found: %s", _cuid, (*i)->getInfoHashAsString().c_str()); - btContext = *i; + _logger->debug("CUID#%d - info hash found: %s", _cuid, + Util::toHex(torrentAttrs[bittorrent::INFO_HASH].s()).c_str()); + downloadContext = *i; break; } } - if(btContext.isNull()) { + if(downloadContext.isNull()) { throw DL_ABORT_EX("Unknown info hash."); } - initCipher(btContext->getInfoHash()); - + initCipher(bittorrent::getInfoHash(downloadContext)); // decrypt VC rbufptr += 20; verifyVC(rbufptr); diff --git a/src/MSEHandshake.h b/src/MSEHandshake.h index f2ceb3a7..14ef0ad3 100644 --- a/src/MSEHandshake.h +++ b/src/MSEHandshake.h @@ -51,7 +51,7 @@ class SocketCore; class DHKeyExchange; class ARC4Encryptor; class ARC4Decryptor; -class BtContext; +class DownloadContext; class MSEHandshake { public: @@ -158,7 +158,7 @@ public: bool findReceiverHashMarker(); bool receiveReceiverHashAndPadCLength - (const std::deque<SharedHandle<BtContext> >& btContexts); + (const std::deque<SharedHandle<DownloadContext> >& downloadContexts); bool receiveReceiverIALength(); diff --git a/src/Makefile.am b/src/Makefile.am index 5951269f..235befee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -152,7 +152,6 @@ SRCS = Socket.h\ ByteArrayDiskWriterFactory.cc ByteArrayDiskWriterFactory.h\ ServerHost.cc ServerHost.h\ DownloadContext.cc DownloadContext.h\ - SingleFileDownloadContext.cc SingleFileDownloadContext.h\ TimedHaltCommand.cc TimedHaltCommand.h\ CUIDCounter.h\ DNSCache.h\ @@ -294,8 +293,6 @@ SRCS += PeerMessageUtil.cc PeerMessageUtil.h\ PeerListProcessor.h\ AnnounceTier.h\ AnnounceList.h AnnounceList.cc\ - BtContext.h\ - DefaultBtContext.cc DefaultBtContext.h\ PeerStorage.h\ DefaultPeerStorage.cc DefaultPeerStorage.h\ BtAnnounce.cc BtAnnounce.h\ @@ -436,7 +433,8 @@ SRCS += PeerMessageUtil.cc PeerMessageUtil.h\ RangeBtMessageValidator.h\ IndexBtMessageValidator.h\ ExtensionMessageRegistry.h\ - bencode.cc bencode.h + bencode.cc bencode.h\ + bittorrent_helper.cc bittorrent_helper.h endif # ENABLE_BITTORRENT if ENABLE_METALINK diff --git a/src/Makefile.in b/src/Makefile.in index f46e2465..09e34803 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -89,8 +89,6 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ PeerListProcessor.h\ @ENABLE_BITTORRENT_TRUE@ AnnounceTier.h\ @ENABLE_BITTORRENT_TRUE@ AnnounceList.h AnnounceList.cc\ -@ENABLE_BITTORRENT_TRUE@ BtContext.h\ -@ENABLE_BITTORRENT_TRUE@ DefaultBtContext.cc DefaultBtContext.h\ @ENABLE_BITTORRENT_TRUE@ PeerStorage.h\ @ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.cc DefaultPeerStorage.h\ @ENABLE_BITTORRENT_TRUE@ BtAnnounce.cc BtAnnounce.h\ @@ -231,7 +229,8 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ RangeBtMessageValidator.h\ @ENABLE_BITTORRENT_TRUE@ IndexBtMessageValidator.h\ @ENABLE_BITTORRENT_TRUE@ ExtensionMessageRegistry.h\ -@ENABLE_BITTORRENT_TRUE@ bencode.cc bencode.h +@ENABLE_BITTORRENT_TRUE@ bencode.cc bencode.h\ +@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.cc bittorrent_helper.h @ENABLE_METALINK_TRUE@am__append_14 = Metalinker.cc Metalinker.h\ @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @@ -400,11 +399,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ PeerConnection.cc PeerConnection.h ByteArrayDiskWriter.cc \ ByteArrayDiskWriter.h ByteArrayDiskWriterFactory.cc \ ByteArrayDiskWriterFactory.h ServerHost.cc ServerHost.h \ - DownloadContext.cc DownloadContext.h \ - SingleFileDownloadContext.cc SingleFileDownloadContext.h \ - TimedHaltCommand.cc TimedHaltCommand.h CUIDCounter.h \ - DNSCache.h DownloadResult.h Sequence.h IntSequence.h \ - PostDownloadHandler.h PreDownloadHandler.h SingletonHolder.h \ + DownloadContext.cc DownloadContext.h TimedHaltCommand.cc \ + TimedHaltCommand.h CUIDCounter.h DNSCache.h DownloadResult.h \ + Sequence.h IntSequence.h PostDownloadHandler.h \ + PreDownloadHandler.h SingletonHolder.h \ TrueRequestGroupCriteria.h a2algo.h a2functional.h a2io.h \ a2netcompat.h a2time.h array_fun.h help_tags.h prefs.cc \ prefs.h usage_text.h ProtocolDetector.cc ProtocolDetector.h \ @@ -466,8 +464,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ TimeSeedCriteria.h ShareRatioSeedCriteria.h \ UnionSeedCriteria.h SeedCheckCommand.cc SeedCheckCommand.h \ PeerListProcessor.h AnnounceTier.h AnnounceList.h \ - AnnounceList.cc BtContext.h DefaultBtContext.cc \ - DefaultBtContext.h PeerStorage.h DefaultPeerStorage.cc \ + AnnounceList.cc PeerStorage.h DefaultPeerStorage.cc \ DefaultPeerStorage.h BtAnnounce.cc BtAnnounce.h \ DefaultBtAnnounce.cc DefaultBtAnnounce.h BtRuntime.h \ BtMessage.h AbstractBtMessage.cc AbstractBtMessage.h \ @@ -564,9 +561,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ IndexBtMessage.cc IndexBtMessage.h ZeroBtMessage.cc \ ZeroBtMessage.h RangeBtMessageValidator.h \ IndexBtMessageValidator.h ExtensionMessageRegistry.h \ - bencode.cc bencode.h Metalinker.cc Metalinker.h \ - MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \ - MetalinkResource.h MetalinkProcessor.h \ + bencode.cc bencode.h bittorrent_helper.cc bittorrent_helper.h \ + Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \ + MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \ MetalinkParserController.cc MetalinkParserController.h \ MetalinkParserStateMachine.cc MetalinkParserStateMachine.h \ MetalinkParserState.h InitialMetalinkParserState.cc \ @@ -638,7 +635,6 @@ am__objects_6 = @ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ SeedCheckCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ AnnounceList.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ DefaultBtContext.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtAnnounce.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.$(OBJEXT) \ @@ -734,7 +730,8 @@ am__objects_6 = @ENABLE_BITTORRENT_TRUE@ RangeBtMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ IndexBtMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ ZeroBtMessage.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ bencode.$(OBJEXT) +@ENABLE_BITTORRENT_TRUE@ bencode.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.$(OBJEXT) @ENABLE_METALINK_TRUE@am__objects_14 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ @@ -833,10 +830,9 @@ am__objects_26 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ MultiFileAllocationIterator.$(OBJEXT) PeerConnection.$(OBJEXT) \ ByteArrayDiskWriter.$(OBJEXT) \ ByteArrayDiskWriterFactory.$(OBJEXT) ServerHost.$(OBJEXT) \ - DownloadContext.$(OBJEXT) SingleFileDownloadContext.$(OBJEXT) \ - TimedHaltCommand.$(OBJEXT) prefs.$(OBJEXT) \ - ProtocolDetector.$(OBJEXT) StringFormat.$(OBJEXT) \ - HttpSkipResponseCommand.$(OBJEXT) \ + DownloadContext.$(OBJEXT) TimedHaltCommand.$(OBJEXT) \ + prefs.$(OBJEXT) ProtocolDetector.$(OBJEXT) \ + StringFormat.$(OBJEXT) HttpSkipResponseCommand.$(OBJEXT) \ InitiateConnectionCommand.$(OBJEXT) \ FtpFinishDownloadCommand.$(OBJEXT) A2STR.$(OBJEXT) \ RarestPieceSelector.$(OBJEXT) ChunkedDecoder.$(OBJEXT) \ @@ -1157,11 +1153,10 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ PeerConnection.cc PeerConnection.h ByteArrayDiskWriter.cc \ ByteArrayDiskWriter.h ByteArrayDiskWriterFactory.cc \ ByteArrayDiskWriterFactory.h ServerHost.cc ServerHost.h \ - DownloadContext.cc DownloadContext.h \ - SingleFileDownloadContext.cc SingleFileDownloadContext.h \ - TimedHaltCommand.cc TimedHaltCommand.h CUIDCounter.h \ - DNSCache.h DownloadResult.h Sequence.h IntSequence.h \ - PostDownloadHandler.h PreDownloadHandler.h SingletonHolder.h \ + DownloadContext.cc DownloadContext.h TimedHaltCommand.cc \ + TimedHaltCommand.h CUIDCounter.h DNSCache.h DownloadResult.h \ + Sequence.h IntSequence.h PostDownloadHandler.h \ + PreDownloadHandler.h SingletonHolder.h \ TrueRequestGroupCriteria.h a2algo.h a2functional.h a2io.h \ a2netcompat.h a2time.h array_fun.h help_tags.h prefs.cc \ prefs.h usage_text.h ProtocolDetector.cc ProtocolDetector.h \ @@ -1393,7 +1388,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHTUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultAuthResolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounce.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtContext.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtInteractive.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageDispatcher.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageFactory.Po@am__quote@ @@ -1541,7 +1535,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleRandomizer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SingleFileAllocationIterator.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SingleFileDownloadContext.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SizeMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SkipTagMetalinkParserState.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SleepCommand.Po@am__quote@ @@ -1578,6 +1571,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ZeroBtMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asctime_r.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bencode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bittorrent_helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download_helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gai_strerror.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getaddrinfo.Po@am__quote@ diff --git a/src/Metalink2RequestGroup.cc b/src/Metalink2RequestGroup.cc index e8874c8f..1b9a36a4 100644 --- a/src/Metalink2RequestGroup.cc +++ b/src/Metalink2RequestGroup.cc @@ -43,7 +43,7 @@ #include "prefs.h" #include "Util.h" #include "message.h" -#include "SingleFileDownloadContext.h" +#include "DownloadContext.h" #include "MetalinkHelper.h" #include "BinaryStream.h" #include "MemoryBufferPreDownloadHandler.h" @@ -170,10 +170,11 @@ Metalink2RequestGroup::createRequestGroup std::deque<std::string> uris; uris.push_back((*itr)->url); torrentRg.reset(new RequestGroup(option, uris)); - SharedHandle<SingleFileDownloadContext> dctx - (new SingleFileDownloadContext(option->getAsInt(PREF_SEGMENT_SIZE), - 0, - A2STR::NIL)); + SharedHandle<DownloadContext> dctx + (new DownloadContext(option->getAsInt(PREF_SEGMENT_SIZE), + 0, + A2STR::NIL)); + // Since torrent is downloaded in memory, setting dir has no effect. //dctx->setDir(_option->get(PREF_DIR)); torrentRg->setDownloadContext(dctx); torrentRg->clearPreDowloadHandler(); @@ -208,11 +209,10 @@ Metalink2RequestGroup::createRequestGroup #else pieceLength = option->getAsInt(PREF_SEGMENT_SIZE); #endif // ENABLE_MESSAGE_DIGEST - SharedHandle<SingleFileDownloadContext> dctx - (new SingleFileDownloadContext + SharedHandle<DownloadContext> dctx + (new DownloadContext (pieceLength, entry->getLength(), - A2STR::NIL, strconcat(option->get(PREF_DIR), "/", entry->file->getPath()))); dctx->setDir(option->get(PREF_DIR)); #ifdef ENABLE_MESSAGE_DIGEST @@ -222,7 +222,8 @@ Metalink2RequestGroup::createRequestGroup dctx->setChecksumHashAlgo(entry->checksum->getAlgo()); } } else { - dctx->setPieceHashes(entry->chunkChecksum->getChecksums()); + dctx->setPieceHashes(entry->chunkChecksum->getChecksums().begin(), + entry->chunkChecksum->getChecksums().end()); dctx->setPieceHashAlgo(entry->chunkChecksum->getAlgo()); } #endif // ENABLE_MESSAGE_DIGEST diff --git a/src/MetalinkPostDownloadHandler.cc b/src/MetalinkPostDownloadHandler.cc index 7623f1e8..038a3687 100644 --- a/src/MetalinkPostDownloadHandler.cc +++ b/src/MetalinkPostDownloadHandler.cc @@ -62,7 +62,7 @@ void MetalinkPostDownloadHandler::getNextRequestGroups RequestGroup* requestGroup) { _logger->debug("Generating RequestGroups for Metalink file %s", - requestGroup->getFilePath().c_str()); + requestGroup->getFirstFilePath().c_str()); SharedHandle<DiskAdaptor> diskAdaptor = requestGroup->getPieceStorage()->getDiskAdaptor(); try { diskAdaptor->openExistingFile(); diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index 7083de7f..729eb676 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -166,7 +166,7 @@ void MultiDiskAdaptor::resetDiskWriterEntries() return; } - for(std::deque<SharedHandle<FileEntry> >::const_iterator i = + for(std::vector<SharedHandle<FileEntry> >::const_iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { diskWriterEntries.push_back (createDiskWriterEntry(*i, (*i)->isRequested())); @@ -176,9 +176,9 @@ void MultiDiskAdaptor::resetDiskWriterEntries() // TODO Currently, pieceLength == 0 is used for unit testing only. if(pieceLength > 0) { - std::deque<SharedHandle<DiskWriterEntry> >::iterator done = + std::vector<SharedHandle<DiskWriterEntry> >::iterator done = diskWriterEntries.begin(); - for(std::deque<SharedHandle<DiskWriterEntry> >::iterator itr = + for(std::vector<SharedHandle<DiskWriterEntry> >::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end();) { const SharedHandle<FileEntry>& fileEntry = (*itr)->getFileEntry(); @@ -189,7 +189,7 @@ void MultiDiskAdaptor::resetDiskWriterEntries() off_t pieceStartOffset = (fileEntry->getOffset()/pieceLength)*pieceLength; if(itr != diskWriterEntries.begin()) { - for(std::deque<SharedHandle<DiskWriterEntry> >::iterator i = + for(std::vector<SharedHandle<DiskWriterEntry> >::iterator i = itr-1; true; --i) { const SharedHandle<FileEntry>& fileEntry = (*i)->getFileEntry(); if(pieceStartOffset <= fileEntry->getOffset() || @@ -240,7 +240,7 @@ void MultiDiskAdaptor::resetDiskWriterEntries() } } DefaultDiskWriterFactory dwFactory; - for(std::deque<SharedHandle<DiskWriterEntry> >::iterator i = + for(std::vector<SharedHandle<DiskWriterEntry> >::iterator i = diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { if((*i)->needsFileAllocation() || dwreq.find((*i)->getFileEntry()->getPath()) != dwreq.end() || @@ -260,7 +260,7 @@ void MultiDiskAdaptor::resetDiskWriterEntries() void MultiDiskAdaptor::mkdir() const { - for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i = + for(std::vector<SharedHandle<DiskWriterEntry> >::const_iterator i = diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { (*i)->getFileEntry()->setupDir(); } @@ -279,7 +279,7 @@ void MultiDiskAdaptor::openIfNot // Cache is full. // Choose one DiskWriterEntry randomly and close it. size_t index = SimpleRandomizer::getInstance()->getRandomNumber(numOpened); - std::deque<SharedHandle<DiskWriterEntry> >::iterator i = + std::vector<SharedHandle<DiskWriterEntry> >::iterator i = _openedDiskWriterEntries.begin(); std::advance(i, index); (*i)->closeFile(); @@ -443,7 +443,7 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len, off_t offset bool MultiDiskAdaptor::fileExists() { - for(std::deque<SharedHandle<FileEntry> >::iterator i = + for(std::vector<SharedHandle<FileEntry> >::iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { if((*i)->exists()) { return true; @@ -455,10 +455,9 @@ bool MultiDiskAdaptor::fileExists() uint64_t MultiDiskAdaptor::size() { uint64_t size = 0; - for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin(); - itr != diskWriterEntries.end(); ++itr) { - openIfNot(*itr, &DiskWriterEntry::openFile); - size += (*itr)->size(); + for(std::vector<SharedHandle<FileEntry> >::iterator i = + fileEntries.begin(); i != fileEntries.end(); ++i) { + size += File((*i)->getPath()).size(); } return size; } @@ -496,7 +495,7 @@ void MultiDiskAdaptor::disableReadOnly() void MultiDiskAdaptor::cutTrailingGarbage() { - for(std::deque<SharedHandle<DiskWriterEntry> >::const_iterator i = + for(std::vector<SharedHandle<DiskWriterEntry> >::const_iterator i = diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) { uint64_t length = (*i)->getFileEntry()->getLength(); if(File((*i)->getFilePath()).size() > length) { @@ -515,7 +514,7 @@ void MultiDiskAdaptor::setMaxOpenFiles(size_t maxOpenFiles) size_t MultiDiskAdaptor::utime(const Time& actime, const Time& modtime) { size_t numOK = 0; - for(std::deque<SharedHandle<FileEntry> >::const_iterator i = + for(std::vector<SharedHandle<FileEntry> >::const_iterator i = fileEntries.begin(); i != fileEntries.end(); ++i) { if((*i)->isRequested()) { File f((*i)->getPath()); diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index 21018259..74713fee 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -37,6 +37,8 @@ #include "DiskAdaptor.h" +#include <deque> + namespace aria2 { class MultiFileAllocationIterator; @@ -112,7 +114,7 @@ public: typedef SharedHandle<DiskWriterEntry> DiskWriterEntryHandle; -typedef std::deque<DiskWriterEntryHandle> DiskWriterEntries; +typedef std::vector<DiskWriterEntryHandle> DiskWriterEntries; class MultiDiskAdaptor : public DiskAdaptor { friend class MultiFileAllocationIterator; @@ -120,7 +122,7 @@ private: size_t pieceLength; DiskWriterEntries diskWriterEntries; - std::deque<SharedHandle<DiskWriterEntry> > _openedDiskWriterEntries; + std::vector<SharedHandle<DiskWriterEntry> > _openedDiskWriterEntries; size_t _maxOpenFiles; @@ -192,7 +194,7 @@ public: virtual size_t utime(const Time& actime, const Time& modtime); - const std::deque<SharedHandle<DiskWriterEntry> >& + const std::vector<SharedHandle<DiskWriterEntry> >& getDiskWriterEntries() const { return diskWriterEntries; diff --git a/src/MultiFileAllocationIterator.cc b/src/MultiFileAllocationIterator.cc index ff131573..a1f772af 100644 --- a/src/MultiFileAllocationIterator.cc +++ b/src/MultiFileAllocationIterator.cc @@ -45,7 +45,8 @@ namespace aria2 { MultiFileAllocationIterator::MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor): _diskAdaptor(diskAdaptor), - _entries(_diskAdaptor->diskWriterEntries), + _entries(_diskAdaptor->diskWriterEntries.begin(), + _diskAdaptor->diskWriterEntries.end()), _offset(0) {} @@ -111,7 +112,8 @@ uint64_t MultiFileAllocationIterator::getTotalLength() } } -const DiskWriterEntries& MultiFileAllocationIterator::getDiskWriterEntries() const +const std::deque<SharedHandle<DiskWriterEntry> >& +MultiFileAllocationIterator::getDiskWriterEntries() const { return _entries; } diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc index c0fbb878..11351ad3 100644 --- a/src/MultiUrlRequestInfo.cc +++ b/src/MultiUrlRequestInfo.cc @@ -54,6 +54,7 @@ #include "File.h" #include "Netrc.h" #include "AuthConfigFactory.h" +#include "DownloadContext.h" #ifdef ENABLE_SSL # include "SocketCore.h" # include "TLSContext.h" diff --git a/src/PeerChokeCommand.cc b/src/PeerChokeCommand.cc index 8799605f..ca1bb1f0 100644 --- a/src/PeerChokeCommand.cc +++ b/src/PeerChokeCommand.cc @@ -34,18 +34,15 @@ /* copyright --> */ #include "PeerChokeCommand.h" #include "DownloadEngine.h" -#include "BtContext.h" #include "BtRuntime.h" #include "PeerStorage.h" namespace aria2 { PeerChokeCommand::PeerChokeCommand(int32_t cuid, - DownloadEngine* e, - const SharedHandle<BtContext>& btContext): + DownloadEngine* e): Command(cuid), - e(e), - _btContext(btContext) {} + e(e) {} PeerChokeCommand::~PeerChokeCommand() {} diff --git a/src/PeerChokeCommand.h b/src/PeerChokeCommand.h index b81781f3..7f8baf75 100644 --- a/src/PeerChokeCommand.h +++ b/src/PeerChokeCommand.h @@ -41,7 +41,6 @@ namespace aria2 { class DownloadEngine; -class BtContext; class BtRuntime; class PeerStorage; @@ -49,15 +48,12 @@ class PeerChokeCommand : public Command { private: DownloadEngine* e; - SharedHandle<BtContext> _btContext; - SharedHandle<PeerStorage> _peerStorage; SharedHandle<BtRuntime> _btRuntime; public: PeerChokeCommand(int32_t cuid, - DownloadEngine* e, - const SharedHandle<BtContext>& btContext); + DownloadEngine* e); virtual ~PeerChokeCommand(); diff --git a/src/PeerInitiateConnectionCommand.cc b/src/PeerInitiateConnectionCommand.cc index a815bced..bd16a354 100644 --- a/src/PeerInitiateConnectionCommand.cc +++ b/src/PeerInitiateConnectionCommand.cc @@ -42,12 +42,12 @@ #include "Socket.h" #include "Logger.h" #include "Peer.h" -#include "BtContext.h" #include "BtRuntime.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "PeerConnection.h" #include "RequestGroup.h" +#include "DownloadContext.h" namespace aria2 { @@ -56,13 +56,11 @@ PeerInitiateConnectionCommand::PeerInitiateConnectionCommand RequestGroup* requestGroup, const PeerHandle& peer, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SharedHandle<BtRuntime>& btRuntime, bool mseHandshakeEnabled) : PeerAbstractCommand(cuid, peer, e), _requestGroup(requestGroup), - _btContext(btContext), _btRuntime(btRuntime), _mseHandshakeEnabled(mseHandshakeEnabled) { @@ -83,7 +81,7 @@ bool PeerInitiateConnectionCommand::executeInternal() { socket->establishConnection(peer->ipaddr, peer->port); if(_mseHandshakeEnabled) { InitiatorMSEHandshakeCommand* c = - new InitiatorMSEHandshakeCommand(cuid, _requestGroup, peer, e, _btContext, + new InitiatorMSEHandshakeCommand(cuid, _requestGroup, peer, e, _btRuntime, socket); c->setPeerStorage(_peerStorage); c->setPieceStorage(_pieceStorage); @@ -91,7 +89,7 @@ bool PeerInitiateConnectionCommand::executeInternal() { } else { PeerInteractionCommand* command = new PeerInteractionCommand - (cuid, _requestGroup, peer, e, _btContext, _btRuntime, _pieceStorage, + (cuid, _requestGroup, peer, e, _btRuntime, _pieceStorage, socket, PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE); command->setPeerStorage(_peerStorage); e->commands.push_back(command); @@ -106,7 +104,7 @@ bool PeerInitiateConnectionCommand::prepareForNextPeer(time_t wait) { peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e, - _btContext, _btRuntime); + _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); diff --git a/src/PeerInitiateConnectionCommand.h b/src/PeerInitiateConnectionCommand.h index 9ffd5afa..0723eade 100644 --- a/src/PeerInitiateConnectionCommand.h +++ b/src/PeerInitiateConnectionCommand.h @@ -40,7 +40,6 @@ namespace aria2 { class RequestGroup; -class BtContext; class BtRuntime; class PeerStorage; class PieceStorage; @@ -49,8 +48,6 @@ class PeerInitiateConnectionCommand : public PeerAbstractCommand { private: RequestGroup* _requestGroup; - SharedHandle<BtContext> _btContext; - SharedHandle<BtRuntime> _btRuntime; SharedHandle<PeerStorage> _peerStorage; @@ -69,7 +66,6 @@ public: RequestGroup* requestGroup, const SharedHandle<Peer>& peer, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SharedHandle<BtRuntime>& btRuntime, bool mseHandshakeEnabled = true); diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index c3bbc1b9..38644aaf 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -44,7 +44,7 @@ #include "prefs.h" #include "Socket.h" #include "Option.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "BtRegistry.h" #include "Peer.h" #include "BtMessage.h" @@ -70,6 +70,7 @@ #include "DefaultExtensionMessageFactory.h" #include "RequestGroupMan.h" #include "ExtensionMessageRegistry.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -78,7 +79,6 @@ PeerInteractionCommand::PeerInteractionCommand RequestGroup* requestGroup, const PeerHandle& p, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<PieceStorage>& pieceStorage, const SocketHandle& s, @@ -86,7 +86,6 @@ PeerInteractionCommand::PeerInteractionCommand const PeerConnectionHandle& passedPeerConnection) :PeerAbstractCommand(cuid, p, e, s), _requestGroup(requestGroup), - _btContext(btContext), _btRuntime(btRuntime), _pieceStorage(pieceStorage), sequence(sequence) @@ -98,20 +97,22 @@ PeerInteractionCommand::PeerInteractionCommand setTimeout(getOption()->getAsInt(PREF_PEER_CONNECTION_TIMEOUT)); } + const BDE& torrentAttrs = + _requestGroup->getDownloadContext()->getAttribute(bittorrent::BITTORRENT); SharedHandle<BtRegistry> btRegistry = e->getBtRegistry(); SharedHandle<PeerStorage> peerStorage = - btRegistry->get(_btContext->getInfoHashAsString())._peerStorage; + btRegistry->get(torrentAttrs[bittorrent::INFO_HASH].s())._peerStorage; SharedHandle<ExtensionMessageRegistry> exMsgRegistry (new ExtensionMessageRegistry()); SharedHandle<DefaultExtensionMessageFactory> extensionMessageFactory - (new DefaultExtensionMessageFactory(_btContext, peer, exMsgRegistry)); + (new DefaultExtensionMessageFactory(peer, exMsgRegistry)); extensionMessageFactory->setPeerStorage(peerStorage); SharedHandle<DefaultBtMessageFactory> factory(new DefaultBtMessageFactory()); factory->setCuid(cuid); - factory->setBtContext(_btContext); + factory->setDownloadContext(_requestGroup->getDownloadContext()); factory->setPieceStorage(pieceStorage); factory->setPeerStorage(peerStorage); factory->setExtensionMessageFactory(extensionMessageFactory); @@ -132,7 +133,7 @@ PeerInteractionCommand::PeerInteractionCommand (new DefaultBtMessageDispatcher()); dispatcher->setCuid(cuid); dispatcher->setPeer(peer); - dispatcher->setBtContext(_btContext); + dispatcher->setDownloadContext(_requestGroup->getDownloadContext()); dispatcher->setPieceStorage(pieceStorage); dispatcher->setPeerStorage(peerStorage); dispatcher->setRequestTimeout(getOption()->getAsInt(PREF_BT_REQUEST_TIMEOUT)); @@ -142,7 +143,7 @@ PeerInteractionCommand::PeerInteractionCommand DefaultBtMessageReceiverHandle receiver(new DefaultBtMessageReceiver()); receiver->setCuid(cuid); receiver->setPeer(peer); - receiver->setBtContext(_btContext); + receiver->setDownloadContext(_requestGroup->getDownloadContext()); receiver->setPeerConnection(peerConnection); receiver->setDispatcher(dispatcher); receiver->setBtMessageFactory(factory); @@ -151,13 +152,12 @@ PeerInteractionCommand::PeerInteractionCommand (new DefaultBtRequestFactory()); reqFactory->setCuid(cuid); reqFactory->setPeer(peer); - reqFactory->setBtContext(_btContext); reqFactory->setPieceStorage(pieceStorage); reqFactory->setBtMessageDispatcher(dispatcher); reqFactory->setBtMessageFactory(factory); DefaultBtInteractiveHandle btInteractive - (new DefaultBtInteractive(_btContext, peer)); + (new DefaultBtInteractive(_requestGroup->getDownloadContext(), peer)); btInteractive->setBtRuntime(_btRuntime); btInteractive->setPieceStorage(_pieceStorage); btInteractive->setPeerStorage(peerStorage); // Note: Not a member variable. @@ -172,7 +172,7 @@ PeerInteractionCommand::PeerInteractionCommand (getOption()->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL)); btInteractive->setRequestGroupMan(e->_requestGroupMan); btInteractive->setBtMessageFactory(factory); - if(!_btContext->isPrivate()) { + if(torrentAttrs[bittorrent::PRIVATE].i() == 0) { if(getOption()->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) { btInteractive->setUTPexEnabled(true); } @@ -189,8 +189,9 @@ PeerInteractionCommand::PeerInteractionCommand factory->setBtRequestFactory(reqFactory); factory->setPeerConnection(peerConnection); - peer->allocateSessionResource(_btContext->getPieceLength(), - _btContext->getTotalLength()); + peer->allocateSessionResource + (_requestGroup->getDownloadContext()->getPieceLength(), + _requestGroup->getDownloadContext()->getTotalLength()); peer->setBtMessageDispatcher(dispatcher); _btRuntime->increaseConnections(); @@ -290,12 +291,8 @@ bool PeerInteractionCommand::prepareForNextPeer(time_t wait) { PeerHandle peer = _peerStorage->getUnusedPeer(); peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = - new PeerInitiateConnectionCommand(peer->usedBy(), - _requestGroup, - peer, - e, - _btContext, - _btRuntime); + new PeerInitiateConnectionCommand + (peer->usedBy(), _requestGroup, peer, e, _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h index a8ed8514..894cda7d 100644 --- a/src/PeerInteractionCommand.h +++ b/src/PeerInteractionCommand.h @@ -40,7 +40,6 @@ namespace aria2 { class RequestGroup; -class BtContext; class BtInteractive; class PeerConnection; class BtRuntime; @@ -58,8 +57,6 @@ public: private: RequestGroup* _requestGroup; - SharedHandle<BtContext> _btContext; - SharedHandle<BtRuntime> _btRuntime; SharedHandle<PieceStorage> _pieceStorage; @@ -81,7 +78,6 @@ public: RequestGroup* requestGroup, const SharedHandle<Peer>& peer, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SharedHandle<BtRuntime>& btRuntime, const SharedHandle<PieceStorage>& pieceStorage, const SharedHandle<SocketCore>& s, diff --git a/src/PeerReceiveHandshakeCommand.cc b/src/PeerReceiveHandshakeCommand.cc index 20df4391..043ec7c2 100644 --- a/src/PeerReceiveHandshakeCommand.cc +++ b/src/PeerReceiveHandshakeCommand.cc @@ -37,7 +37,7 @@ #include "DownloadEngine.h" #include "BtHandshakeMessage.h" #include "Util.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "DlAbortEx.h" #include "PeerInteractionCommand.h" #include "Peer.h" @@ -91,23 +91,25 @@ bool PeerReceiveHandshakeCommand::executeInternal() // To handle tracker's NAT-checking feature if(dataLength >= 48) { // check info_hash - std::string infoHash = Util::toHex(&data[28], INFO_HASH_LENGTH); + std::string infoHash = std::string(&data[28], &data[28+INFO_HASH_LENGTH]); BtObject btObject = e->getBtRegistry()->get(infoHash); - SharedHandle<BtContext> btContext = btObject._btContext; + SharedHandle<DownloadContext> downloadContext = btObject._downloadContext; SharedHandle<BtRuntime> btRuntime = btObject._btRuntime; SharedHandle<PieceStorage> pieceStorage = btObject._pieceStorage; SharedHandle<PeerStorage> peerStorage = btObject._peerStorage; - if(btContext.isNull() || !btRuntime->ready()) { + if(downloadContext.isNull() || !btRuntime->ready()) { throw DL_ABORT_EX - (StringFormat("Unknown info hash %s", infoHash.c_str()).str()); + (StringFormat("Unknown info hash %s", + Util::toHex(infoHash).c_str()).str()); } - TransferStat tstat = btContext->getOwnerRequestGroup()->calculateStat(); + TransferStat tstat = + downloadContext->getOwnerRequestGroup()->calculateStat(); const unsigned int maxDownloadLimit = - btContext->getOwnerRequestGroup()->getMaxDownloadSpeedLimit(); + downloadContext->getOwnerRequestGroup()->getMaxDownloadSpeedLimit(); unsigned int thresholdSpeed = - btContext->getOwnerRequestGroup()-> + downloadContext->getOwnerRequestGroup()-> getOption()->getAsInt(PREF_BT_REQUEST_PEER_SPEED_LIMIT); if(maxDownloadLimit > 0) { thresholdSpeed = std::min(maxDownloadLimit, thresholdSpeed); @@ -123,10 +125,9 @@ bool PeerReceiveHandshakeCommand::executeInternal() PeerInteractionCommand* command = new PeerInteractionCommand (cuid, - btContext->getOwnerRequestGroup(), + downloadContext->getOwnerRequestGroup(), peer, e, - btContext, btRuntime, pieceStorage, socket, diff --git a/src/PieceHashCheckIntegrityEntry.cc b/src/PieceHashCheckIntegrityEntry.cc index 188e8670..972a40e8 100644 --- a/src/PieceHashCheckIntegrityEntry.cc +++ b/src/PieceHashCheckIntegrityEntry.cc @@ -48,8 +48,10 @@ PieceHashCheckIntegrityEntry::~PieceHashCheckIntegrityEntry() {} bool PieceHashCheckIntegrityEntry::isValidationReady() { - DownloadContextHandle dctx = _requestGroup->getDownloadContext(); - return dctx->getPieceHashes().size() > 0 && + const SharedHandle<DownloadContext>& dctx = + _requestGroup->getDownloadContext(); + return !dctx->getPieceHashAlgo().empty() && + dctx->getPieceHashes().size() > 0 && dctx->getPieceHashes().size() == dctx->getNumPieces(); } diff --git a/src/RealtimeCommand.cc b/src/RealtimeCommand.cc index 0f444ee4..160f1f00 100644 --- a/src/RealtimeCommand.cc +++ b/src/RealtimeCommand.cc @@ -36,6 +36,7 @@ #include "DownloadEngine.h" #include "Exception.h" #include "RequestGroup.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/ReceiverMSEHandshakeCommand.cc b/src/ReceiverMSEHandshakeCommand.cc index defe2a22..fa609b60 100644 --- a/src/ReceiverMSEHandshakeCommand.cc +++ b/src/ReceiverMSEHandshakeCommand.cc @@ -49,7 +49,7 @@ #include "ARC4Decryptor.h" #include "RequestGroupMan.h" #include "BtRegistry.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "BtAnnounce.h" @@ -135,9 +135,10 @@ bool ReceiverMSEHandshakeCommand::executeInternal() break; } case RECEIVER_RECEIVE_PAD_C_LENGTH: { - std::deque<SharedHandle<BtContext> > btContexts; - e->getBtRegistry()->getAllBtContext(std::back_inserter(btContexts)); - if(_mseHandshake->receiveReceiverHashAndPadCLength(btContexts)) { + std::deque<SharedHandle<DownloadContext> > downloadContexts; + e->getBtRegistry()->getAllDownloadContext + (std::back_inserter(downloadContexts)); + if(_mseHandshake->receiveReceiverHashAndPadCLength(downloadContexts)) { _sequence = RECEIVER_RECEIVE_PAD_C; } break; diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index 0da471b9..2e7d9096 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -48,7 +48,6 @@ #include "File.h" #include "message.h" #include "Util.h" -#include "BtRegistry.h" #include "LogFactory.h" #include "Logger.h" #include "DiskAdaptor.h" @@ -57,8 +56,7 @@ #include "StreamCheckIntegrityEntry.h" #include "CheckIntegrityCommand.h" #include "UnknownLengthPieceStorage.h" -#include "BtContext.h" -#include "SingleFileDownloadContext.h" +#include "DownloadContext.h" #include "DlAbortEx.h" #include "DownloadFailureException.h" #include "RequestGroupMan.h" @@ -83,6 +81,8 @@ # include "CheckIntegrityCommand.h" #endif // ENABLE_MESSAGE_DIGEST #ifdef ENABLE_BITTORRENT +# include "bittorrent_helper.h" +# include "BtRegistry.h" # include "BtCheckIntegrityEntry.h" # include "DefaultPeerStorage.h" # include "DefaultBtAnnounce.h" @@ -205,39 +205,30 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, { #ifdef ENABLE_BITTORRENT { - BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext); - if(!btContext.isNull()) { + if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) { + const BDE& torrentAttrs = + _downloadContext->getAttribute(bittorrent::BITTORRENT); if(_option->getAsBool(PREF_DRY_RUN)) { throw DOWNLOAD_FAILURE_EXCEPTION ("Cancel BitTorrent download in dry-run context."); } SharedHandle<BtRegistry> btRegistry = e->getBtRegistry(); - if(!btRegistry->getBtContext(btContext->getInfoHashAsString()).isNull()) { + if(!btRegistry->getDownloadContext + (torrentAttrs[bittorrent::INFO_HASH].s()).isNull()) { throw DOWNLOAD_FAILURE_EXCEPTION - (StringFormat("InfoHash %s is already registered.", - btContext->getInfoHashAsString().c_str()).str()); + (StringFormat + ("InfoHash %s is already registered.", + Util::toHex(torrentAttrs[bittorrent::INFO_HASH].s()).c_str()).str()); } if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) { throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD, - getFilePath().c_str()).str()); + _downloadContext->getBasePath().c_str()).str()); } initPieceStorage(); - if(btContext->getFileEntries().size() > 1) { - // this is really multi file torrent. - // clear http/ftp uris because the current implementation does not - // allow integrating multi-file torrent and http/ftp. - _logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp."); - _uris.clear(); - + if(_downloadContext->getFileEntries().size() > 1) { _pieceStorage->setupFileFilter(); - } else if(btContext->getFileEntries().size() == 1) { - // web-seeding is only enabled for single file torrent - SharedHandle<FileEntry> fileEntry = btContext->getFileEntries().front(); - _uris.insert(_uris.end(), - fileEntry->getAssociatedUris().begin(), - fileEntry->getAssociatedUris().end()); } SharedHandle<DefaultBtProgressInfoFile> @@ -252,14 +243,14 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, progressInfoFile->setBtRuntime(btRuntime); SharedHandle<DefaultPeerStorage> peerStorage - (new DefaultPeerStorage(btContext, _option.get())); + (new DefaultPeerStorage(_option.get())); peerStorage->setBtRuntime(btRuntime); peerStorage->setPieceStorage(_pieceStorage); _peerStorage = peerStorage; progressInfoFile->setPeerStorage(peerStorage); SharedHandle<DefaultBtAnnounce> btAnnounce - (new DefaultBtAnnounce(btContext, _option.get())); + (new DefaultBtAnnounce(_downloadContext, _option.get())); btAnnounce->setBtRuntime(btRuntime); btAnnounce->setPieceStorage(_pieceStorage); btAnnounce->setPeerStorage(peerStorage); @@ -267,8 +258,8 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, (_option->getAsInt(PREF_BT_TRACKER_INTERVAL)); btAnnounce->shuffleAnnounce(); - btRegistry->put(btContext->getInfoHashAsString(), - BtObject(btContext, + btRegistry->put(torrentAttrs[bittorrent::INFO_HASH].s(), + BtObject(_downloadContext, _pieceStorage, peerStorage, btAnnounce, @@ -280,20 +271,20 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, progressInfoFile->removeFile(); _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE, progressInfoFile->getFilename().c_str(), - getFilePath().c_str()); + _downloadContext->getBasePath().c_str()); } { uint64_t actualFileSize = _pieceStorage->getDiskAdaptor()->size(); - if(actualFileSize == btContext->getTotalLength()) { + if(actualFileSize == _downloadContext->getTotalLength()) { // First, make DiskAdaptor read-only mode to allow the // program to seed file in read-only media. _pieceStorage->getDiskAdaptor()->enableReadOnly(); } else { // Open file in writable mode to allow the program - // truncate the file to btContext->getTotalLength() + // truncate the file to _downloadContext->getTotalLength() _logger->debug("File size not match. File is opened in writable mode." " Expected:%s Actual:%s", - Util::uitos(btContext->getTotalLength()).c_str(), + Util::uitos(_downloadContext->getTotalLength()).c_str(), Util::uitos(actualFileSize).c_str()); } } @@ -311,7 +302,7 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat (MSG_FILE_ALREADY_EXISTS, - getFilePath().c_str()).str()); + _downloadContext->getBasePath().c_str()).str()); } else { _pieceStorage->getDiskAdaptor()->openFile(); } @@ -324,14 +315,22 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, } _progressInfoFile = progressInfoFile; - if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) { + if(torrentAttrs[bittorrent::PRIVATE].i() == 0 && + _option->getAsBool(PREF_ENABLE_DHT)) { std::deque<Command*> commands; DHTSetup().setup(commands, e, _option.get()); e->addCommand(commands); - if(!btContext->getNodes().empty() && DHTSetup::initialized()) { + if(!torrentAttrs[bittorrent::NODES].empty() && DHTSetup::initialized()) { + std::deque<std::pair<std::string, uint16_t> > entryPoints; + const BDE& nodes = torrentAttrs[bittorrent::NODES]; + for(BDE::List::const_iterator i = nodes.listBegin(); + i != nodes.listEnd(); ++i) { + std::pair<std::string, uint16_t> addr + ((*i)[bittorrent::HOSTNAME].s(), (*i)[bittorrent::PORT].i()); + entryPoints.push_back(addr); + } DHTEntryPointNameResolveCommand* command = - new DHTEntryPointNameResolveCommand(e->newCUID(), e, - btContext->getNodes()); + new DHTEntryPointNameResolveCommand(e->newCUID(), e, entryPoints); command->setTaskQueue(DHTRegistry::_taskQueue); command->setTaskFactory(DHTRegistry::_taskFactory); command->setRoutingTable(DHTRegistry::_routingTable); @@ -361,8 +360,10 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) { throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD, - getFilePath().c_str()).str()); + _downloadContext->getBasePath().c_str()).str()); } + // TODO1.5 Renaming filename doesn't take into account of + // multi-file download. adjustFilename (SharedHandle<BtProgressInfoFile>(new DefaultBtProgressInfoFile (_downloadContext, @@ -375,7 +376,7 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands, if(!infoFile->exists() && downloadFinishedByFileLength()) { _pieceStorage->markAllPiecesDone(); _logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, - _gid, getFilePath().c_str()); + _gid, _downloadContext->getBasePath().c_str()); } else { loadAndOpenFile(infoFile); SharedHandle<CheckIntegrityEntry> checkIntegrityEntry @@ -412,7 +413,7 @@ void RequestGroup::initPieceStorage() // downloads. Currently multi-file integrated download is not supported. if(!_uris.empty() && _downloadContext->getFileEntries().size() == 1 && - !dynamic_pointer_cast<BtContext>(_downloadContext).isNull()) { + _downloadContext->hasAttribute(bittorrent::BITTORRENT)) { _logger->debug("Using LongestSequencePieceSelector"); ps->setPieceSelector (SharedHandle<PieceSelector>(new LongestSequencePieceSelector())); @@ -449,8 +450,7 @@ bool RequestGroup::downloadFinishedByFileLength() if(!_downloadContext->knowsTotalLength()) { return false; } - // TODO consider the case when the getFilePath() returns dir path. - File outfile(getFilePath()); + File outfile(getFirstFilePath()); if(outfile.exists() && _downloadContext->getTotalLength() == outfile.size()) { return true; } else { @@ -468,7 +468,7 @@ void RequestGroup::adjustFilename } else if(downloadFinishedByFileLength()) { // File was downloaded already, no need to change file name. } else { - File outfile(getFilePath()); + File outfile(getFirstFilePath()); if(outfile.exists() && _option->getAsBool(PREF_CONTINUE) && outfile.size() <= _downloadContext->getTotalLength()) { // File exists but user decided to resume it. @@ -498,14 +498,14 @@ void RequestGroup::loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoF progressInfoFile->removeFile(); _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE, progressInfoFile->getFilename().c_str(), - getFilePath().c_str()); + _downloadContext->getBasePath().c_str()); } if(progressInfoFile->exists()) { progressInfoFile->load(); _pieceStorage->getDiskAdaptor()->openExistingFile(); } else { - File outfile(getFilePath()); + File outfile(getFirstFilePath()); if(outfile.exists() && _option->getAsBool(PREF_CONTINUE) && outfile.size() <= getTotalLength()) { _pieceStorage->getDiskAdaptor()->openExistingFile(); @@ -535,43 +535,36 @@ void RequestGroup::shouldCancelDownloadForSafety() if(_option->getAsBool(PREF_ALLOW_OVERWRITE)) { return; } - File outfile(getFilePath()); + File outfile(getFirstFilePath()); if(outfile.exists()) { if(_option->getAsBool(PREF_AUTO_FILE_RENAMING)) { if(tryAutoFileRenaming()) { - _logger->notice(MSG_FILE_RENAMED, getFilePath().c_str()); + _logger->notice(MSG_FILE_RENAMED, getFirstFilePath().c_str()); } else { throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat("File renaming failed: %s", - getFilePath().c_str()).str()); + getFirstFilePath().c_str()).str()); } } else { throw DOWNLOAD_FAILURE_EXCEPTION (StringFormat(MSG_FILE_ALREADY_EXISTS, - getFilePath().c_str()).str()); + getFirstFilePath().c_str()).str()); } } } bool RequestGroup::tryAutoFileRenaming() { - std::string filepath = getFilePath(); + std::string filepath = getFirstFilePath(); if(filepath.empty()) { return false; } - SingleFileDownloadContextHandle ctx = - dynamic_pointer_cast<SingleFileDownloadContext>(_downloadContext); - // Make a copy of ctx. - SingleFileDownloadContextHandle tempCtx(new SingleFileDownloadContext(*ctx.get())); - - DefaultBtProgressInfoFile tempInfoFile(tempCtx, SharedHandle<PieceStorage>(), 0); - for(unsigned int i = 1; i < 10000; ++i) { File newfile(strconcat(filepath, ".", Util::uitos(i))); - tempCtx->setUFilename(newfile.getPath()); - tempInfoFile.updateFilename(); - if(!newfile.exists() || (newfile.exists() && tempInfoFile.exists())) { - ctx->setUFilename(newfile.getPath()); + // TODO1.5 hard coded ".aria2" extension. + File ctrlfile(newfile.getPath()+".aria2"); + if(!newfile.exists() || (newfile.exists() && ctrlfile.exists())) { + _downloadContext->getFirstFileEntry()->setPath(newfile.getPath()); return true; } } @@ -639,8 +632,8 @@ void RequestGroup::createNextCommand(std::deque<Command*>& commands, static_cast<unsigned int>(_uris.size())); } } - std::deque<std::string> pendingURIs; + for(; numCommand--; ) { Command* command = new CreateRequestCommand(e->newCUID(), this, e); _logger->debug("filePath=%s", _downloadContext->getFileEntries().front()->getPath().c_str()); @@ -685,14 +678,14 @@ void RequestGroup::createNextCommand(std::deque<Command*>& commands, } } -std::string RequestGroup::getFilePath() const +std::string RequestGroup::getFirstFilePath() const { assert(!_downloadContext.isNull()); if(inMemoryDownload()) { static const std::string DIR_MEMORY("[MEMORY]"); - return DIR_MEMORY+File(_downloadContext->getActualBasePath()).getBasename(); + return DIR_MEMORY+File(_downloadContext->getFirstFileEntry()->getPath()).getBasename(); } else { - return _downloadContext->getActualBasePath(); + return _downloadContext->getFirstFileEntry()->getPath(); } } @@ -827,24 +820,25 @@ void RequestGroup::setForceHaltRequested(bool f, HaltReason haltReason) void RequestGroup::releaseRuntimeResource(DownloadEngine* e) { #ifdef ENABLE_BITTORRENT - BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext); - if(!btContext.isNull()) { + if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) { SharedHandle<BtRegistry> btRegistry = e->getBtRegistry(); - BtContextHandle btContextInReg = - btRegistry->getBtContext(btContext->getInfoHashAsString()); - // Make sure that the registered BtContext's GID is equal to - // this->getGID(). Even if createInitialCommand() throws - // exception without registering this BtContext, after that, this - // method is called. In this case, just finding BtContext using - // infoHash may detect another download's BtContext and deleting - // it from BtRegistry causes Segmentation Fault. - if(!btContextInReg.isNull() && - btContextInReg->getOwnerRequestGroup()->getGID() == - btContext->getOwnerRequestGroup()->getGID()) { - btRegistry->remove(btContext->getInfoHashAsString()); + const BDE& torrentAttrs = + _downloadContext->getAttribute(bittorrent::BITTORRENT); + const std::string& infoHash = torrentAttrs[bittorrent::INFO_HASH].s(); + SharedHandle<DownloadContext> contextInReg = + btRegistry->getDownloadContext(infoHash); + // Make sure that the registered DownloadContext's GID is equal to + // _gid. Even if createInitialCommand() throws exception without + // registering this DownloadContext, after that, this method is + // called. In this case, just finding DownloadContext using + // infoHash may detect another download's DownloadContext and + // deleting it from BtRegistry causes Segmentation Fault. + if(!contextInReg.isNull() && + contextInReg->getOwnerRequestGroup()->getGID() == _gid) { + btRegistry->remove(infoHash); if(!DHTRegistry::_peerAnnounceStorage.isNull()) { - DHTRegistry::_peerAnnounceStorage-> - removeLocalPeerAnnounce(btContext->getInfoHash()); + DHTRegistry::_peerAnnounceStorage->removeLocalPeerAnnounce + (torrentAttrs[bittorrent::INFO_HASH].uc()); } } } @@ -856,7 +850,8 @@ void RequestGroup::releaseRuntimeResource(DownloadEngine* e) void RequestGroup::preDownloadProcessing() { - _logger->debug("Finding PreDownloadHandler for path %s.", getFilePath().c_str()); + _logger->debug("Finding PreDownloadHandler for path %s.", + getFirstFilePath().c_str()); try { for(PreDownloadHandlers::const_iterator itr = _preDownloadHandlers.begin(); itr != _preDownloadHandlers.end(); ++itr) { @@ -876,7 +871,8 @@ void RequestGroup::preDownloadProcessing() void RequestGroup::postDownloadProcessing (std::deque<SharedHandle<RequestGroup> >& groups) { - _logger->debug("Finding PostDownloadHandler for path %s.", getFilePath().c_str()); + _logger->debug("Finding PostDownloadHandler for path %s.", + getFirstFilePath().c_str()); try { for(PostDownloadHandlers::const_iterator itr = _postDownloadHandlers.begin(); itr != _postDownloadHandlers.end(); ++itr) { @@ -970,11 +966,6 @@ void RequestGroup::clearPreDowloadHandler() _preDownloadHandlers.clear(); } -void RequestGroup::setDownloadContext(const DownloadContextHandle& downloadContext) -{ - _downloadContext = downloadContext; -} - void RequestGroup::setPieceStorage(const PieceStorageHandle& pieceStorage) { _pieceStorage = pieceStorage; @@ -1104,11 +1095,10 @@ void RequestGroup::removeIdenticalURI(const std::string& uri) void RequestGroup::reportDownloadFinished() { _logger->notice(MSG_FILE_DOWNLOAD_COMPLETED, - getFilePath().c_str()); + _downloadContext->getBasePath().c_str()); _uriSelector->resetCounters(); #ifdef ENABLE_BITTORRENT - SharedHandle<BtContext> ctx = dynamic_pointer_cast<BtContext>(_downloadContext); - if(!ctx.isNull()) { + if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) { TransferStat stat = calculateStat(); double shareRatio = ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0; _logger->notice(MSG_SHARE_RATIO_REPORT, diff --git a/src/RequestGroup.h b/src/RequestGroup.h index a8c4c388..3d579929 100644 --- a/src/RequestGroup.h +++ b/src/RequestGroup.h @@ -221,7 +221,7 @@ public: void closeFile(); - std::string getFilePath() const; + std::string getFirstFilePath() const; uint64_t getTotalLength() const; @@ -275,7 +275,10 @@ public: return _downloadContext; } - void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext); + void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext) + { + _downloadContext = downloadContext; + } const SharedHandle<PieceStorage>& getPieceStorage() const { diff --git a/src/RequestGroupEntry.cc b/src/RequestGroupEntry.cc index 01dd9b15..bba57f8b 100644 --- a/src/RequestGroupEntry.cc +++ b/src/RequestGroupEntry.cc @@ -35,6 +35,7 @@ #include "RequestGroupEntry.h" #include "RequestGroup.h" #include "Command.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc index 41a0f515..9069a4dd 100644 --- a/src/RequestGroupMan.cc +++ b/src/RequestGroupMan.cc @@ -274,7 +274,7 @@ private: if(!sig.isNull() && !sig->getBody().empty()) { // filename of signature file is the path to download file followed by // ".sig". - std::string signatureFile = group->getFilePath()+".sig"; + std::string signatureFile = group->getFirstFilePath()+".sig"; if(sig->save(signatureFile)) { _logger->notice(MSG_SIGNATURE_SAVED, signatureFile.c_str()); } else { @@ -637,7 +637,7 @@ std::string RequestGroupMan::formatDownloadResult(const std::string& status, con o << "n/a"; } o << "|"; - const std::deque<SharedHandle<FileEntry> >& fileEntries = + const std::vector<SharedHandle<FileEntry> >& fileEntries = downloadResult->fileEntries; if(downloadResult->result == DownloadResult::FINISHED || downloadResult->numUri == 0) { @@ -677,7 +677,7 @@ bool RequestGroupMan::isSameFileBeingDownloaded(RequestGroup* requestGroup) cons for(RequestGroups::const_iterator itr = _requestGroups.begin(); itr != _requestGroups.end(); ++itr) { if((*itr).get() != requestGroup) { - const std::deque<SharedHandle<FileEntry> >& entries = + const std::vector<SharedHandle<FileEntry> >& entries = (*itr)->getDownloadContext()->getFileEntries(); std::transform(entries.begin(), entries.end(), std::back_inserter(files), @@ -685,7 +685,7 @@ bool RequestGroupMan::isSameFileBeingDownloaded(RequestGroup* requestGroup) cons } } std::sort(files.begin(), files.end()); - const std::deque<SharedHandle<FileEntry> >& entries = + const std::vector<SharedHandle<FileEntry> >& entries = requestGroup->getDownloadContext()->getFileEntries(); return sameFilePathExists(files.begin(), files.end(), entries.begin(), entries.end()); diff --git a/src/SeedCheckCommand.cc b/src/SeedCheckCommand.cc index d005f68e..680f1fdb 100644 --- a/src/SeedCheckCommand.cc +++ b/src/SeedCheckCommand.cc @@ -36,23 +36,21 @@ #include "DownloadEngine.h" #include "BtRuntime.h" #include "PieceStorage.h" -#include "BtContext.h" #include "Logger.h" #include "SeedCriteria.h" #include "message.h" #include "RequestGroup.h" +#include "DownloadContext.h" namespace aria2 { SeedCheckCommand::SeedCheckCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SeedCriteriaHandle& seedCriteria) :Command(cuid), _requestGroup(requestGroup), e(e), - _btContext(btContext), seedCriteria(seedCriteria), checkStarted(false) { diff --git a/src/SeedCheckCommand.h b/src/SeedCheckCommand.h index 19f6cf5d..7795e68f 100644 --- a/src/SeedCheckCommand.h +++ b/src/SeedCheckCommand.h @@ -43,7 +43,6 @@ namespace aria2 { class RequestGroup; class DownloadEngine; class SeedCriteria; -class BtContext; class BtRuntime; class PieceStorage; @@ -52,7 +51,6 @@ class SeedCheckCommand : public Command private: RequestGroup* _requestGroup; DownloadEngine* e; - SharedHandle<BtContext> _btContext; SharedHandle<PieceStorage> _pieceStorage; SharedHandle<BtRuntime> _btRuntime; SharedHandle<SeedCriteria> seedCriteria; @@ -61,7 +59,6 @@ public: SeedCheckCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e, - const SharedHandle<BtContext>& btContext, const SharedHandle<SeedCriteria>& seedCriteria); virtual ~SeedCheckCommand(); diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index 4598e3d3..a3c72a46 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -60,7 +60,7 @@ SegmentEntry::SegmentEntry(cuid_t cuid, const SegmentHandle& segment): SegmentEntry::~SegmentEntry() {} SegmentMan::SegmentMan(const Option* option, - const DownloadContextHandle& downloadContext, + const SharedHandle<DownloadContext>& downloadContext, const PieceStorageHandle& pieceStorage): _option(option), logger(LogFactory::getInstance()), @@ -104,7 +104,8 @@ void SegmentMan::setPieceStorage(const PieceStorageHandle& pieceStorage) _pieceStorage = pieceStorage; } -void SegmentMan::setDownloadContext(const DownloadContextHandle& downloadContext) +void SegmentMan::setDownloadContext +(const SharedHandle<DownloadContext>& downloadContext) { _downloadContext = downloadContext; } diff --git a/src/ShareRatioSeedCriteria.h b/src/ShareRatioSeedCriteria.h index d09d5219..e4eec635 100644 --- a/src/ShareRatioSeedCriteria.h +++ b/src/ShareRatioSeedCriteria.h @@ -36,7 +36,7 @@ #define _D_SHARE_RATIO_SEED_CRITERIA_H_ #include "SeedCriteria.h" -#include "BtContext.h" +#include "DownloadContext.h" #include "PeerStorage.h" #include "PieceStorage.h" @@ -45,20 +45,21 @@ namespace aria2 { class ShareRatioSeedCriteria : public SeedCriteria { private: double ratio; - SharedHandle<BtContext> btContext; + SharedHandle<DownloadContext> _downloadContext; SharedHandle<PeerStorage> _peerStorage; SharedHandle<PieceStorage> _pieceStorage; public: - ShareRatioSeedCriteria(double ratio, const SharedHandle<BtContext>& btContext) + ShareRatioSeedCriteria + (double ratio, const SharedHandle<DownloadContext>& downloadContext) :ratio(ratio), - btContext(btContext) {} + _downloadContext(downloadContext) {} virtual ~ShareRatioSeedCriteria() {} virtual void reset() {} virtual bool evaluate() { - if(btContext->getTotalLength() == 0) { + if(_downloadContext->getTotalLength() == 0) { return false; } TransferStat stat = _peerStorage->calculateStat(); diff --git a/src/SingleFileDownloadContext.cc b/src/SingleFileDownloadContext.cc deleted file mode 100644 index 1acbb2b1..00000000 --- a/src/SingleFileDownloadContext.cc +++ /dev/null @@ -1,108 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#include "SingleFileDownloadContext.h" -#include "FileEntry.h" - -namespace aria2 { - -const std::string SingleFileDownloadContext::DEFAULT_FILENAME("index.html"); - -SingleFileDownloadContext::SingleFileDownloadContext(size_t pieceLength, - uint64_t totalLength, - const std::string& filename, - const std::string& ufilename): - _pieceLength(pieceLength), - _filename(filename), - _ufilename(ufilename), - _knowsTotalLength(true) -{ - _fileEntries.push_back - (SharedHandle<FileEntry>(new FileEntry(filename, totalLength, 0))); - updateFileEntry(); -} - -void SingleFileDownloadContext::updateFileEntry() -{ - const SharedHandle<FileEntry>& fileEntry = _fileEntries.front(); - if(!_ufilename.empty()) { - fileEntry->setPath(_ufilename); - } else if(!_filename.empty()) { - fileEntry->setPath(_filename); - } else { - fileEntry->setPath(""); - } -} - -const std::deque<std::string>& -SingleFileDownloadContext::getPieceHashes() const -{ - return _pieceHashes; -} - -uint64_t SingleFileDownloadContext::getTotalLength() const -{ - return _fileEntries.front()->getLength(); -} - -bool SingleFileDownloadContext::knowsTotalLength() const -{ - return _knowsTotalLength; -} - -size_t SingleFileDownloadContext::getNumPieces() const -{ - if(_pieceLength == 0) { - return 0; - } else { - return (_fileEntries.front()->getLength()+_pieceLength-1)/_pieceLength; - } -} - -std::string SingleFileDownloadContext::getActualBasePath() const -{ - return _fileEntries.front()->getPath(); -} - -void SingleFileDownloadContext::setTotalLength(uint64_t totalLength) -{ - _fileEntries.front()->setLength(totalLength); -} - -void SingleFileDownloadContext::markTotalLengthIsUnknown() -{ - _knowsTotalLength = false; -} - -} // namespace aria2 diff --git a/src/SingleFileDownloadContext.h b/src/SingleFileDownloadContext.h deleted file mode 100644 index 7f07d9a9..00000000 --- a/src/SingleFileDownloadContext.h +++ /dev/null @@ -1,180 +0,0 @@ -/* <!-- copyright */ -/* - * aria2 - The high speed download utility - * - * Copyright (C) 2006 Tatsuhiro Tsujikawa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations - * including the two. - * You must obey the GNU General Public License in all respects - * for all of the code used other than OpenSSL. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you - * do not wish to do so, delete this exception statement from your - * version. If you delete this exception statement from all source - * files in the program, then also delete it here. - */ -/* copyright --> */ -#ifndef _D_SINGLE_FILE_DOWNLOAD_CONTEXT_H_ -#define _D_SINGLE_FILE_DOWNLOAD_CONTEXT_H_ - -#include "DownloadContext.h" - -#include <string> -#include <deque> - -#include "A2STR.h" - -namespace aria2 { - -class SingleFileDownloadContext:public DownloadContext -{ -private: - size_t _pieceLength; - /** - * _filename and _ufilename may contains directory path name. So - * /usr/local/aria2c is acceptable here. These should be complete - * file path. - */ - std::string _filename; - std::string _ufilename; - - std::string _contentType; - - std::deque<std::string> _pieceHashes; - std::string _pieceHashAlgo; - - std::string _checksum; - std::string _checksumHashAlgo; - - bool _knowsTotalLength; - - void updateFileEntry(); -public: - SingleFileDownloadContext(size_t pieceLength, - uint64_t totalLength, - const std::string& filename, - const std::string& ufilename = A2STR::NIL); - - virtual ~SingleFileDownloadContext() {} - - virtual const std::string& getPieceHash(size_t index) const - { - if(index < _pieceHashes.size()) { - return _pieceHashes[index]; - } else { - return A2STR::NIL; - } - } - - virtual const std::deque<std::string>& getPieceHashes() const; - - virtual uint64_t getTotalLength() const; - - virtual bool knowsTotalLength() const; - - - virtual FILE_MODE getFileMode() const - { - if(_fileEntries.size() == 1) { - return SINGLE; - } else { - return MULTI; - } - } - - virtual size_t getPieceLength() const - { - return _pieceLength; - } - - virtual size_t getNumPieces() const; - - virtual std::string getActualBasePath() const; - - virtual const std::string& getPieceHashAlgo() const - { - return _pieceHashAlgo; - } - - const std::string& getChecksumHashAlgo() const - { - return _checksumHashAlgo; - } - - const std::string& getChecksum() const - { - return _checksum; - } - - void setPieceHashes(const std::deque<std::string>& pieceHashes) - { - _pieceHashes = pieceHashes; - } - - void setChecksumHashAlgo(const std::string& algo) - { - _checksumHashAlgo = algo; - } - - void setChecksum(const std::string& checksum) - { - _checksum = checksum; - } - - void setFilename(const std::string& filename) - { - _filename = filename; - updateFileEntry(); - } - - void setUFilename(const std::string& ufilename) - { - _ufilename = ufilename; - updateFileEntry(); - } - - void setTotalLength(uint64_t totalLength); - - void markTotalLengthIsUnknown(); - - void setPieceHashAlgo(const std::string& algo) - { - _pieceHashAlgo = algo; - } - - void setContentType(const std::string& contentType) - { - _contentType = contentType; - } - - const std::string& getContentType() - { - return _contentType; - } - - static const std::string DEFAULT_FILENAME; -}; - -typedef SharedHandle<SingleFileDownloadContext> SingleFileDownloadContextHandle; - -} // namespace aria2 - -#endif // _D_SINGLE_FILE_DOWNLOAD_CONTEXT_H_ diff --git a/src/SleepCommand.cc b/src/SleepCommand.cc index 17912215..5fd18604 100644 --- a/src/SleepCommand.cc +++ b/src/SleepCommand.cc @@ -35,6 +35,7 @@ #include "SleepCommand.h" #include "RequestGroup.h" #include "DownloadEngine.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/StreamCheckIntegrityEntry.cc b/src/StreamCheckIntegrityEntry.cc index 5a4014c3..39e25393 100644 --- a/src/StreamCheckIntegrityEntry.cc +++ b/src/StreamCheckIntegrityEntry.cc @@ -37,6 +37,7 @@ #include "DownloadEngine.h" #include "StreamFileAllocationEntry.h" #include "Request.h" +#include "DownloadContext.h" namespace aria2 { diff --git a/src/TrackerWatcherCommand.cc b/src/TrackerWatcherCommand.cc index 87a51c58..dddf163e 100644 --- a/src/TrackerWatcherCommand.cc +++ b/src/TrackerWatcherCommand.cc @@ -37,7 +37,6 @@ #include <sstream> #include "DownloadEngine.h" -#include "BtContext.h" #include "BtAnnounce.h" #include "BtRuntime.h" #include "PieceStorage.h" @@ -45,7 +44,6 @@ #include "Peer.h" #include "prefs.h" #include "message.h" -#include "SingleFileDownloadContext.h" #include "ByteArrayDiskWriterFactory.h" #include "RecoverableException.h" #include "PeerInitiateConnectionCommand.h" @@ -59,17 +57,16 @@ #include "SocketCore.h" #include "Request.h" #include "AnnounceTier.h" +#include "DownloadContext.h" +#include "bittorrent_helper.h" namespace aria2 { -TrackerWatcherCommand::TrackerWatcherCommand(int32_t cuid, - RequestGroup* requestGroup, - DownloadEngine* e, - const BtContextHandle& btContext): +TrackerWatcherCommand::TrackerWatcherCommand +(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e): Command(cuid), _requestGroup(requestGroup), - e(e), - _btContext(btContext) + e(e) { _requestGroup->increaseNumCommand(); } @@ -162,12 +159,8 @@ void TrackerWatcherCommand::processTrackerResponse } peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = - new PeerInitiateConnectionCommand(peer->usedBy(), - _requestGroup, - peer, - e, - _btContext, - _btRuntime); + new PeerInitiateConnectionCommand + (peer->usedBy(), _requestGroup, peer, e, _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); @@ -185,15 +178,17 @@ RequestGroupHandle TrackerWatcherCommand::createAnnounce() { } static bool backupTrackerIsAvailable -(const std::deque<SharedHandle<AnnounceTier> >& announceTiers) +(const SharedHandle<DownloadContext>& context) { - if(announceTiers.size() >= 2) { + const BDE& announceList = + context->getAttribute(bittorrent::BITTORRENT)[bittorrent::ANNOUNCE_LIST]; + if(announceList.size() >= 2) { return true; } - if(announceTiers.empty()) { + if(announceList.empty()) { return false; } - if(announceTiers[0]->urls.size() >= 2) { + if(announceList[0].size() >= 2) { return true; } else { return false; @@ -208,7 +203,7 @@ TrackerWatcherCommand::createRequestGroup(const std::string& uri) RequestGroupHandle rg(new RequestGroup(getOption(), uris)); // If backup tracker is available, only try 2 times for each tracker // and if they all fails, then try next one. - if(backupTrackerIsAvailable(_btContext->getAnnounceTiers())) { + if(backupTrackerIsAvailable(_requestGroup->getDownloadContext())) { logger->debug("This is multi-tracker announce."); rg->getOption()->put(PREF_MAX_TRIES, "2"); } else { @@ -217,11 +212,10 @@ TrackerWatcherCommand::createRequestGroup(const std::string& uri) } static const std::string TRACKER_ANNOUNCE_FILE("[tracker.announce]"); - SingleFileDownloadContextHandle dctx - (new SingleFileDownloadContext(getOption()->getAsInt(PREF_SEGMENT_SIZE), - 0, - A2STR::NIL, - TRACKER_ANNOUNCE_FILE)); + SharedHandle<DownloadContext> dctx + (new DownloadContext(getOption()->getAsInt(PREF_SEGMENT_SIZE), + 0, + TRACKER_ANNOUNCE_FILE)); dctx->setDir(A2STR::NIL); dctx->getFileEntries().front()->setUris(uris); rg->setDownloadContext(dctx); diff --git a/src/TrackerWatcherCommand.h b/src/TrackerWatcherCommand.h index 9c7c2417..7ec0c03f 100644 --- a/src/TrackerWatcherCommand.h +++ b/src/TrackerWatcherCommand.h @@ -42,7 +42,6 @@ namespace aria2 { class DownloadEngine; class RequestGroup; -class BtContext; class PeerStorage; class PieceStorage; class BtRuntime; @@ -56,8 +55,6 @@ private: DownloadEngine* e; - SharedHandle<BtContext> _btContext; - SharedHandle<PeerStorage> _peerStorage; SharedHandle<PieceStorage> _pieceStorage; @@ -81,8 +78,7 @@ private: public: TrackerWatcherCommand(int32_t cuid, RequestGroup* requestGroup, - DownloadEngine* e, - const SharedHandle<BtContext>& btContext); + DownloadEngine* e); virtual ~TrackerWatcherCommand(); diff --git a/src/UnknownLengthPieceStorage.cc b/src/UnknownLengthPieceStorage.cc index 369767c7..878fff93 100644 --- a/src/UnknownLengthPieceStorage.cc +++ b/src/UnknownLengthPieceStorage.cc @@ -46,8 +46,9 @@ namespace aria2 { -UnknownLengthPieceStorage::UnknownLengthPieceStorage(const DownloadContextHandle& downloadContext, - const Option* option): +UnknownLengthPieceStorage::UnknownLengthPieceStorage +(const SharedHandle<DownloadContext>& downloadContext, + const Option* option): _downloadContext(downloadContext), _option(option), _diskWriterFactory(new DefaultDiskWriterFactory()), @@ -60,7 +61,8 @@ void UnknownLengthPieceStorage::initStorage() { DirectDiskAdaptorHandle directDiskAdaptor(new DirectDiskAdaptor()); directDiskAdaptor->setTotalLength(_downloadContext->getTotalLength()); - directDiskAdaptor->setFileEntries(_downloadContext->getFileEntries()); + directDiskAdaptor->setFileEntries(_downloadContext->getFileEntries().begin(), + _downloadContext->getFileEntries().end()); DiskWriterHandle writer = _diskWriterFactory->newDiskWriter(directDiskAdaptor->getFilePath()); diff --git a/src/Util.cc b/src/Util.cc index c2cabda1..0ade0084 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -43,7 +43,6 @@ #include <cstring> #include <cstdio> #include <cstdlib> -#include <iomanip> #include <sstream> #include <ostream> #include <algorithm> @@ -709,20 +708,6 @@ time_t Util::httpGMT(const std::string& httpStdTime) return thetime; } -void Util::toStream(std::ostream& os, const FileEntries& fileEntries) -{ - os << _("Files:") << "\n"; - os << "idx|path/length" << "\n"; - os << "===+===========================================================================" << "\n"; - int32_t count = 1; - for(FileEntries::const_iterator itr = fileEntries.begin(); - itr != fileEntries.end(); ++count, ++itr) { - os << std::setw(3) << count << "|" << (*itr)->getPath() << "\n"; - os << " |" << Util::abbrevSize((*itr)->getLength()) << "B" << "\n"; - os << "---+---------------------------------------------------------------------------" << "\n"; - } -} - void Util::sleep(long seconds) { #ifdef HAVE_SLEEP ::sleep(seconds); @@ -43,8 +43,10 @@ #include <utility> #include <deque> #include <iosfwd> +#include <ostream> #include <numeric> #include <map> +#include <iomanip> #include "SharedHandle.h" #include "IntSequence.h" @@ -243,8 +245,20 @@ public: */ static time_t httpGMT(const std::string& httpTimeFormat); - static void toStream(std::ostream& os, - const std::deque<SharedHandle<FileEntry> >& entries); + template<typename InputIterator> + static void toStream + (InputIterator first, InputIterator last, std::ostream& os) + { + os << _("Files:") << "\n"; + os << "idx|path/length" << "\n"; + os << "===+===========================================================================" << "\n"; + int32_t count = 1; + for(; first != last; ++first, ++count) { + os << std::setw(3) << count << "|" << (*first)->getPath() << "\n"; + os << " |" << Util::abbrevSize((*first)->getLength()) << "B" << "\n"; + os << "---+---------------------------------------------------------------------------" << "\n"; + } + } static void sleep(long seconds); diff --git a/src/XmlRpcMethodImpl.cc b/src/XmlRpcMethodImpl.cc index 8bc629a2..954369c2 100644 --- a/src/XmlRpcMethodImpl.cc +++ b/src/XmlRpcMethodImpl.cc @@ -51,17 +51,20 @@ #include "StringFormat.h" #include "XmlRpcRequest.h" #include "PieceStorage.h" -#include "PeerStorage.h" -#include "BtContext.h" -#include "BtRegistry.h" -#include "Peer.h" +#include "DownloadContext.h" #include "DiskAdaptor.h" #include "FileEntry.h" #include "BtProgressInfoFile.h" -#include "BtRuntime.h" -#include "BtAnnounce.h" #include "prefs.h" #include "message.h" +#ifdef ENABLE_BITTORRENT +# include "bittorrent_helper.h" +# include "BtRegistry.h" +# include "PeerStorage.h" +# include "Peer.h" +# include "BtRuntime.h" +# include "BtAnnounce.h" +#endif // ENABLE_BITTORRENT namespace aria2 { @@ -286,13 +289,12 @@ static void gatherProgressCommon #ifdef ENABLE_BITTORRENT static void gatherProgressBitTorrent -(BDE& entryDict, const SharedHandle<BtContext>& btctx, - const SharedHandle<BtRegistry>& btreg) +(BDE& entryDict, const BDE& torrentAttrs, const SharedHandle<BtRegistry>& btreg) { - entryDict["infoHash"] = btctx->getInfoHashAsString(); + const std::string& infoHash = torrentAttrs[bittorrent::INFO_HASH].s(); + entryDict["infoHash"] = Util::toHex(infoHash); - SharedHandle<PeerStorage> peerStorage = - btreg->get(btctx->getInfoHashAsString())._peerStorage; + SharedHandle<PeerStorage> peerStorage = btreg->get(infoHash)._peerStorage; assert(!peerStorage.isNull()); std::deque<SharedHandle<Peer> > peers; @@ -329,11 +331,11 @@ static void gatherProgress { gatherProgressCommon(entryDict, group); #ifdef ENABLE_BITTORRENT - SharedHandle<BtContext> btctx = - dynamic_pointer_cast<BtContext>(group->getDownloadContext()); - if(!btctx.isNull()) { + if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) { + const BDE& torrentAttrs = + group->getDownloadContext()->getAttribute(bittorrent::BITTORRENT); SharedHandle<BtRegistry> btreg = e->getBtRegistry(); - gatherProgressBitTorrent(entryDict, btctx, btreg); + gatherProgressBitTorrent(entryDict, torrentAttrs, btreg); } #endif // ENABLE_BITTORRENT } @@ -400,9 +402,9 @@ BDE GetFilesXmlRpcMethod::process createFileEntry(files, dr->fileEntries.begin(), dr->fileEntries.end()); } } else { - const std::deque<SharedHandle<FileEntry> >& fileEntries = - group->getDownloadContext()->getFileEntries(); - createFileEntry(files, fileEntries.begin(), fileEntries.end()); + createFileEntry(files, + group->getDownloadContext()->getFileEntries().begin(), + group->getDownloadContext()->getFileEntries().end()); } return files; } @@ -455,12 +457,12 @@ BDE GetPeersXmlRpcMethod::process (StringFormat("No peer data is available for GID#%d", gid).str()); } BDE peers = BDE::list(); - SharedHandle<BtContext> btctx = - dynamic_pointer_cast<BtContext>(group->getDownloadContext()); - if(!btctx.isNull()) { + if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) { SharedHandle<BtRegistry> btreg = e->getBtRegistry(); + const BDE& torrentAttrs = + group->getDownloadContext()->getAttribute(bittorrent::BITTORRENT); SharedHandle<PeerStorage> peerStorage = - btreg->get(btctx->getInfoHashAsString())._peerStorage; + btreg->get(torrentAttrs[bittorrent::INFO_HASH].s())._peerStorage; assert(!peerStorage.isNull()); BDE entry = BDE::dict(); gatherPeer(peers, peerStorage); diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc new file mode 100644 index 00000000..cb3be528 --- /dev/null +++ b/src/bittorrent_helper.cc @@ -0,0 +1,529 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2009 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "bittorrent_helper.h" + +#include <algorithm> +#include <deque> + +#include "DownloadContext.h" +#include "Randomizer.h" +#include "bencode.h" +#include "Util.h" +#include "DlAbortEx.h" +#include "message.h" +#include "StringFormat.h" +#include "BtConstants.h" +#include "messageDigest.h" +#include "MessageDigestHelper.h" +#include "PeerMessageUtil.h" +#include "SimpleRandomizer.h" + +namespace aria2 { + +namespace bittorrent { + +static const std::string C_NAME("name"); + +static const std::string C_NAME_UTF8("name.utf-8"); + +static const std::string C_FILES("files"); + +static const std::string C_LENGTH("length"); + +static const std::string C_PATH("path"); + +static const std::string C_PATH_UTF8("path.utf-8"); + +static const std::string C_INFO("info"); + +static const std::string C_PIECES("pieces"); + +static const std::string C_PIECE_LENGTH("piece length"); + +static const std::string C_PRIVATE("private"); + +static const std::string C_URL_LIST("url-list"); + +static const std::string C_ANNOUNCE("announce"); + +static const std::string C_ANNOUNCE_LIST("announce-list"); + +static const std::string C_NODES("nodes"); + +static const std::string DEFAULT_PEER_ID_PREFIX("-aria2-"); + +const std::string INFO_HASH("infoHash"); + +const std::string MODE("mode"); + +const std::string PRIVATE("private"); + +const std::string ANNOUNCE_LIST("announceList"); + +const std::string NODES("nodes"); + +const std::string HOSTNAME("hostname"); + +const std::string PORT("port"); + +const std::string NAME("name"); + +const std::string BITTORRENT("bittorrent"); + +const std::string MULTI("multi"); + +const std::string SINGLE("single"); + +static void extractPieceHash(const SharedHandle<DownloadContext>& ctx, + const std::string& hashData, + size_t hashLength, + size_t numPieces) +{ + std::vector<std::string> pieceHashes; + for(size_t i = 0; i < numPieces; ++i) { + pieceHashes.push_back(Util::toHex(hashData.data()+i*hashLength, + hashLength)); + } + ctx->setPieceHashes(pieceHashes.begin(), pieceHashes.end()); + ctx->setPieceHashAlgo(MessageDigestContext::SHA1); +} + +static void extractUrlList(std::vector<std::string>& uris, const BDE& bde) +{ + if(bde.isList()) { + for(BDE::List::const_iterator itr = bde.listBegin(); + itr != bde.listEnd(); ++itr) { + if((*itr).isString()) { + uris.push_back((*itr).s()); + } + } + } else if(bde.isString()) { + uris.push_back(bde.s()); + } +} + +static void extractFileEntries +(const SharedHandle<DownloadContext>& ctx, + BDE& torrent, + const BDE& infoDict, + const std::string& defaultName, + const std::string& overrideName, + const std::vector<std::string>& urlList) +{ + std::string name; + if(overrideName.empty()) { + std::string nameKey; + if(infoDict.containsKey(C_NAME_UTF8)) { + nameKey = C_NAME_UTF8; + } else { + nameKey = C_NAME; + } + const BDE& nameData = infoDict[nameKey]; + if(nameData.isString()) { + // Slice path by '/' just in case nasty ".." is included in name + std::deque<std::string> pathelems; + Util::slice(pathelems, nameData.s(), '/'); + name = Util::joinPath(pathelems.begin(), pathelems.end()); + torrent[NAME] = nameData.s(); + } else { + name = strconcat(File(defaultName).getBasename(), ".file"); + torrent[NAME] = name; + } + } else { + name = overrideName; + torrent[NAME] = name; + } + + const BDE& filesList = infoDict[C_FILES]; + std::vector<SharedHandle<FileEntry> > fileEntries; + if(filesList.isList()) { + uint64_t length = 0; + off_t offset = 0; + // multi-file mode + torrent[MODE] = MULTI; + for(BDE::List::const_iterator itr = filesList.listBegin(); + itr != filesList.listEnd(); ++itr) { + const BDE& fileDict = *itr; + if(!fileDict.isDict()) { + continue; + } + const BDE& fileLengthData = fileDict[C_LENGTH]; + if(!fileLengthData.isInteger()) { + throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, + C_LENGTH.c_str()).str()); + } + length += fileLengthData.i(); + + std::string pathKey; + if(fileDict.containsKey(C_PATH_UTF8)) { + pathKey = C_PATH_UTF8; + } else { + pathKey = C_PATH; + } + const BDE& pathList = fileDict[pathKey]; + if(!pathList.isList() || pathList.empty()) { + throw DL_ABORT_EX("Path is empty."); + } + + std::vector<std::string> pathelem(pathList.size()); + std::transform(pathList.listBegin(), pathList.listEnd(), pathelem.begin(), + std::mem_fun_ref(&BDE::s)); + std::string path = name; + strappend(path, "/", Util::joinPath(pathelem.begin(), pathelem.end())); + // Split path with '/' again because each pathList element can + // contain "/" inside. + std::deque<std::string> elements; + Util::slice(elements, path, '/'); + path = Util::joinPath(elements.begin(), elements.end()); + + std::deque<std::string> uris; + std::transform(urlList.begin(), urlList.end(), std::back_inserter(uris), + std::bind2nd(std::plus<std::string>(), "/"+path)); + SharedHandle<FileEntry> fileEntry + (new FileEntry(strconcat(ctx->getDir(), "/", path), + fileLengthData.i(), + offset, uris)); + fileEntries.push_back(fileEntry); + offset += fileEntry->getLength(); + } + } else { + // single-file mode; + torrent[MODE] = SINGLE; + const BDE& lengthData = infoDict[C_LENGTH]; + if(!lengthData.isInteger()) { + throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, + C_LENGTH.c_str()).str()); + } + uint64_t totalLength = lengthData.i(); + + // For each uri in urlList, if it ends with '/', then + // concatenate name to it. Specification just says so. + std::deque<std::string> uris; + for(std::vector<std::string>::const_iterator i = urlList.begin(); + i != urlList.end(); ++i) { + if(Util::endsWith(*i, "/")) { + uris.push_back((*i)+name); + } else { + uris.push_back(*i); + } + } + + SharedHandle<FileEntry> fileEntry + (new FileEntry(strconcat(ctx->getDir(), "/", name),totalLength, 0, + uris)); + fileEntries.push_back(fileEntry); + } + ctx->setFileEntries(fileEntries.begin(), fileEntries.end()); + if(torrent[MODE].s() == MULTI) { + ctx->setBasePath(strconcat(ctx->getDir(), "/", name)); + } +} + +static void extractAnnounce(BDE& torrent, const BDE& rootDict) +{ + const BDE& announceList = rootDict[C_ANNOUNCE_LIST]; + if(announceList.isList()) { + torrent[ANNOUNCE_LIST] = announceList; + } else { + const BDE& announce = rootDict[C_ANNOUNCE]; + BDE announceList = BDE::list(); + if(announce.isString()) { + announceList << BDE::list(); + announceList[0] << announce; + } + torrent[ANNOUNCE_LIST] = announceList; + } +} + +static void extractNodes(BDE& torrent, const BDE& nodesList) +{ + BDE nodes = BDE::list(); + if(nodesList.isList()) { + for(BDE::List::const_iterator i = nodesList.listBegin(); + i != nodesList.listEnd(); ++i) { + const BDE& addrPairList = (*i); + if(!addrPairList.isList() || addrPairList.size() != 2) { + continue; + } + const BDE& hostname = addrPairList[0]; + if(!hostname.isString()) { + continue; + } + if(Util::trim(hostname.s()).empty()) { + continue; + } + const BDE& port = addrPairList[1]; + if(!port.isInteger() || !(0 < port.i() && port.i() < 65536)) { + continue; + } + BDE node = BDE::dict(); + node[HOSTNAME] = hostname; + node[PORT] = port; + nodes << node; + } + } + torrent[NODES] = nodes; +} + +static void processRootDictionary +(const SharedHandle<DownloadContext>& ctx, + const BDE& rootDict, + const std::string& defaultName, + const std::string& overrideName) +{ + if(!rootDict.isDict()) { + throw DL_ABORT_EX("torrent file does not contain a root dictionary."); + } + const BDE& infoDict = rootDict[C_INFO]; + if(!infoDict.isDict()) { + throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, + C_INFO.c_str()).str()); + } + BDE torrent = BDE::dict(); + + // retrieve infoHash + std::string encodedInfoDict = bencode::encode(infoDict); + unsigned char infoHash[INFO_HASH_LENGTH]; + MessageDigestHelper::digest(infoHash, INFO_HASH_LENGTH, + MessageDigestContext::SHA1, + encodedInfoDict.data(), + encodedInfoDict.size()); + torrent[INFO_HASH] = std::string(&infoHash[0], &infoHash[INFO_HASH_LENGTH]); + + // calculate the number of pieces + const BDE& piecesData = infoDict[C_PIECES]; + if(!piecesData.isString()) { + throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, + C_PIECES.c_str()).str()); + } + if(piecesData.s().empty()) { + throw DL_ABORT_EX("The length of piece hash is 0."); + } + size_t numPieces = piecesData.s().size()/PIECE_HASH_LENGTH; + if(numPieces == 0) { + throw DL_ABORT_EX("The number of pieces is 0."); + } + // retrieve piece length + const BDE& pieceLengthData = infoDict[C_PIECE_LENGTH]; + if(!pieceLengthData.isInteger()) { + throw DL_ABORT_EX(StringFormat(MSG_MISSING_BT_INFO, + C_PIECE_LENGTH.c_str()).str()); + } + size_t pieceLength = pieceLengthData.i(); + ctx->setPieceLength(pieceLength); + // retrieve piece hashes + extractPieceHash(ctx, piecesData.s(), PIECE_HASH_LENGTH, numPieces); + // private flag + const BDE& privateData = infoDict[C_PRIVATE]; + int privatefg = 0; + if(privateData.isInteger()) { + if(privateData.i() == 1) { + privatefg = 1; + } + } + torrent[PRIVATE] = BDE((int64_t)privatefg); + // retrieve uri-list. + // This implemantation obeys HTTP-Seeding specification: + // see http://www.getright.com/seedtorrent.html + std::vector<std::string> urlList; + extractUrlList(urlList, rootDict[C_URL_LIST]); + + // retrieve file entries + extractFileEntries(ctx, torrent, infoDict, defaultName, overrideName, urlList); + if((ctx->getTotalLength()+pieceLength-1)/pieceLength != numPieces) { + throw DL_ABORT_EX("Too few/many piece hash."); + } + // retrieve announce + extractAnnounce(torrent, rootDict); + // retrieve nodes + extractNodes(torrent, rootDict[C_NODES]); + + ctx->setAttribute(BITTORRENT, torrent); +} + +void load(const std::string& torrentFile, + const SharedHandle<DownloadContext>& ctx, + const std::string& overrideName) +{ + processRootDictionary(ctx, + bencode::decodeFromFile(torrentFile), + torrentFile, + overrideName); + +} + +void loadFromMemory(const unsigned char* content, + size_t length, + const SharedHandle<DownloadContext>& ctx, + const std::string& defaultName, + const std::string& overrideName) +{ + processRootDictionary(ctx, + bencode::decode(content, length), + defaultName, + overrideName); +} + +void loadFromMemory(const std::string& context, + const SharedHandle<DownloadContext>& ctx, + const std::string& defaultName, + const std::string& overrideName) +{ + processRootDictionary + (ctx, + bencode::decode(reinterpret_cast<const unsigned char*>(context.c_str()), + context.size()), + defaultName, overrideName); +} + +const unsigned char* +getInfoHash(const SharedHandle<DownloadContext>& downloadContext) +{ + return downloadContext->getAttribute(BITTORRENT)[INFO_HASH].uc(); +} + +std::string +getInfoHashString(const SharedHandle<DownloadContext>& downloadContext) +{ + return Util::toHex(downloadContext->getAttribute(BITTORRENT)[INFO_HASH].s()); +} + +void print(std::ostream& o, const SharedHandle<DownloadContext>& dctx) +{ + const BDE& torrentAttrs = dctx->getAttribute(BITTORRENT); + o << "*** BitTorrent File Information ***" << "\n"; + o << "Mode: " << torrentAttrs[MODE].s() << "\n"; + o << "Announce:" << "\n"; + const BDE& announceList = torrentAttrs[ANNOUNCE_LIST]; + for(BDE::List::const_iterator tieritr = announceList.listBegin(); + tieritr != announceList.listEnd(); ++tieritr) { + if(!(*tieritr).isList()) { + continue; + } + for(BDE::List::const_iterator i = (*tieritr).listBegin(); + i != (*tieritr).listEnd(); ++i) { + o << " " << (*i).s(); + } + o << "\n"; + } + o << "Info Hash: " << Util::toHex(torrentAttrs[INFO_HASH].s()) << "\n"; + o << "Piece Length: " << Util::abbrevSize(dctx->getPieceLength()) << "B\n"; + o << "The Number of Pieces: " << dctx->getNumPieces() << "\n"; + o << "Total Length: " << Util::abbrevSize(dctx->getTotalLength()) << "B\n"; + o << "Name: " << torrentAttrs[NAME].s() << "\n"; + Util::toStream(dctx->getFileEntries().begin(), dctx->getFileEntries().end(), o); +} + +void computeFastSet +(std::vector<size_t>& fastSet, const std::string& ipaddr, + size_t numPieces, const unsigned char* infoHash, size_t fastSetSize) +{ + unsigned char compact[6]; + if(!PeerMessageUtil::createcompact(compact, ipaddr, 0)) { + return; + } + if(numPieces < fastSetSize) { + fastSetSize = numPieces; + } + unsigned char tx[24]; + memcpy(tx, compact, 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]; + MessageDigestHelper::digest(x, sizeof(x), MessageDigestContext::SHA1, tx, 24); + while(fastSet.size() < fastSetSize) { + for(size_t i = 0; i < 5 && fastSet.size() < fastSetSize; ++i) { + size_t j = i*4; + uint32_t ny; + memcpy(&ny, x+j, 4); + uint32_t y = ntohl(ny); + size_t index = y%numPieces; + if(std::find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) { + fastSet.push_back(index); + } + } + unsigned char temp[20]; + MessageDigestHelper::digest(temp, sizeof(temp), MessageDigestContext::SHA1, x, sizeof(x)); + memcpy(x, temp, sizeof(x)); + } +} + +std::string generatePeerId +(const std::string& peerIdPrefix, const SharedHandle<Randomizer>& randomizer) +{ + std::string peerId = peerIdPrefix; + peerId += Util::randomAlpha(20-peerIdPrefix.size(), randomizer); + if(peerId.size() > 20) { + peerId.erase(20); + } + return peerId; +} + +static std::string peerId; + +const std::string& generateStaticPeerId +(const std::string& peerIdPrefix, const SharedHandle<Randomizer>& randomizer) +{ + if(peerId.empty()) { + peerId = generatePeerId(peerIdPrefix, randomizer); + } + return peerId; +} + +void setStaticPeerId(const std::string& newPeerId) +{ + peerId = newPeerId; +} + +// If PeerID is not generated, it is created with default peerIdPrefix +// (-aria2-) and SimpleRandomizer. +const unsigned char* getStaticPeerId() +{ + if(peerId.empty()) { + return + reinterpret_cast<const unsigned char*>(generateStaticPeerId(DEFAULT_PEER_ID_PREFIX, SimpleRandomizer::getInstance()).data()); + } else { + return reinterpret_cast<const unsigned char*>(peerId.data()); + } +} + +} // namespace bittorrent + +} // namespace aria2 diff --git a/src/bittorrent_helper.h b/src/bittorrent_helper.h new file mode 100644 index 00000000..99db7d9a --- /dev/null +++ b/src/bittorrent_helper.h @@ -0,0 +1,132 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2009 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_BITTORRENT_HELPER_H_ +#define _D_BITTORRENT_HELPER_H_ + +#include "common.h" + +#include <string> +#include <vector> + +#include "SharedHandle.h" +#include "AnnounceTier.h" +#include "BDE.h" +#include "Util.h" + +namespace aria2 { + +class DownloadContext; +class Randomizer; + +namespace bittorrent { + +extern const std::string INFO_HASH; + +extern const std::string MODE; + +extern const std::string PRIVATE; + +extern const std::string ANNOUNCE_LIST; + +extern const std::string NODES; + +extern const std::string HOSTNAME; + +extern const std::string PORT; + +extern const std::string NAME; + +extern const std::string SINGLE; + +extern const std::string MULTI; + +extern const std::string BITTORRENT; + +void load(const std::string& torrentFile, + const SharedHandle<DownloadContext>& ctx, + const std::string& overrideName = ""); + +void loadFromMemory(const unsigned char* content, size_t length, + const SharedHandle<DownloadContext>& ctx, + const std::string& defaultName, + const std::string& overrideName = ""); + +void loadFromMemory(const std::string& context, + const SharedHandle<DownloadContext>& ctx, + const std::string& defaultName, + const std::string& overrideName = ""); + +// Generates Peer ID. BitTorrent specification says Peer ID is 20-byte +// length. This function uses peerIdPrefix as a Peer ID and it is +// less than 20bytes, random bytes are generated and appened to it. If +// peerIdPrefix is larger than 20bytes, first 20bytes are used. +std::string generatePeerId +(const std::string& peerIdPrefix, const SharedHandle<Randomizer>& randomizer); + +// Generates Peer ID and stores it in static variable. This function +// uses generatePeerId(peerIdPrefix, randomizer) to produce Peer ID. +const std::string& generateStaticPeerId +(const std::string& peerIdPrefix, const SharedHandle<Randomizer>& randomizer); + +// Returns Peer ID statically stored by generateStaticPeerId(). If +// Peer ID is not stored yet, this function calls +// generateStaticPeerId("-aria2-", randomizer) +const unsigned char* getStaticPeerId(); + +// Set newPeerId as a static Peer ID. newPeerId must be 20-byte +// length. +void setStaticPeerId(const std::string& newPeerId); + +// Computes fast set index and stores them in fastset. +void computeFastSet +(std::vector<size_t>& fastSet, const std::string& ipaddr, + size_t numPieces, const unsigned char* infoHash, size_t fastSetSize); + +// Writes the detailed information about torrent loaded in dctx. +void print(std::ostream& o, const SharedHandle<DownloadContext>& dctx); + +// Returns the value associated with INFO_HASH key in BITTORRENT +// attribute. +const unsigned char* +getInfoHash(const SharedHandle<DownloadContext>& downloadContext); + +std::string +getInfoHashString(const SharedHandle<DownloadContext>& downloadContext); + +} // namespace bittorrent + +} // namespace aria2 + +#endif // _D_BITTORRENT_HELPER_H_ diff --git a/src/download_helper.cc b/src/download_helper.cc index b232f33d..baabf94e 100644 --- a/src/download_helper.cc +++ b/src/download_helper.cc @@ -48,12 +48,11 @@ #include "ParameterizedStringParser.h" #include "PStringBuildVisitor.h" #include "UriListParser.h" -#include "SingleFileDownloadContext.h" +#include "DownloadContext.h" #include "RecoverableException.h" #include "DlAbortEx.h" #include "message.h" #include "StringFormat.h" -#include "DefaultBtContext.h" #include "FileEntry.h" #include "LogFactory.h" #include "File.h" @@ -62,6 +61,9 @@ #include "OptionHandler.h" #include "ByteArrayDiskWriter.h" #include "a2functional.h" +#ifdef ENABLE_BITTORRENT +# include "bittorrent_helper.h" +#endif // ENABLE_BITTORRENT namespace aria2 { @@ -178,16 +180,14 @@ static SharedHandle<RequestGroup> createRequestGroup bool useOutOption = false) { SharedHandle<RequestGroup> rg(new RequestGroup(option, uris)); - SharedHandle<SingleFileDownloadContext> dctx - (new SingleFileDownloadContext + SharedHandle<DownloadContext> dctx + (new DownloadContext (option->getAsInt(PREF_SEGMENT_SIZE), 0, - A2STR::NIL, useOutOption&&!option->blank(PREF_OUT)? strconcat(option->get(PREF_DIR), "/", option->get(PREF_OUT)):A2STR::NIL)); - dctx->setDir(option->get(PREF_DIR)); - dctx->getFileEntries().front()->setUris(uris); + dctx->getFirstFileEntry()->setUris(uris); rg->setDownloadContext(dctx); return rg; } @@ -202,28 +202,26 @@ createBtRequestGroup(const std::string& torrentFilePath, const std::string& torrentData = "") { SharedHandle<RequestGroup> rg(new RequestGroup(option, auxUris)); - SharedHandle<DefaultBtContext> btContext(new DefaultBtContext()); - btContext->setDir(option->get(PREF_DIR)); + SharedHandle<DownloadContext> dctx(new DownloadContext()); + dctx->setDir(option->get(PREF_DIR)); if(torrentData.empty()) { - btContext->load(torrentFilePath);// may throw exception + bittorrent::load(torrentFilePath, dctx);// may throw exception } else { - btContext->loadFromMemory(torrentData, "default"); // may throw exception - } - if(option->defined(PREF_PEER_ID_PREFIX)) { - btContext->setPeerIdPrefix(option->get(PREF_PEER_ID_PREFIX)); + bittorrent::loadFromMemory(torrentData, dctx, "default"); // may + // throw + // exception } - btContext->setFileFilter - (Util::parseIntRange(option->get(PREF_SELECT_FILE))); + dctx->setFileFilter(Util::parseIntRange(option->get(PREF_SELECT_FILE))); std::istringstream indexOutIn(option->get(PREF_INDEX_OUT)); std::map<size_t, std::string> indexPathMap = Util::createIndexPathMap(indexOutIn); for(std::map<size_t, std::string>::const_iterator i = indexPathMap.begin(); i != indexPathMap.end(); ++i) { - btContext->setFilePathWithIndex - ((*i).first, strconcat(btContext->getDir(), "/", (*i).second)); + dctx->setFilePathWithIndex + ((*i).first, strconcat(dctx->getDir(), "/", (*i).second)); } - rg->setDownloadContext(btContext); - btContext->setOwnerRequestGroup(rg.get()); + rg->setDownloadContext(dctx); + dctx->setOwnerRequestGroup(rg.get()); return rg; } diff --git a/src/main.cc b/src/main.cc index 1c4210bd..a3a13ffb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -59,7 +59,6 @@ #include "a2io.h" #include "a2time.h" #include "Platform.h" -#include "DefaultBtContext.h" #include "FileEntry.h" #include "RequestGroup.h" #include "ConsoleStatCalc.h" @@ -69,6 +68,10 @@ #include "ProtocolDetector.h" #include "RecoverableException.h" #include "SocketCore.h" +#include "DownloadContext.h" +#ifdef ENABLE_BITTORRENT +# include "bittorrent_helper.h" +#endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK # include "MetalinkHelper.h" # include "MetalinkEntry.h" @@ -108,9 +111,9 @@ std::ostream& getSummaryOut(const SharedHandle<Option>& op) #ifdef ENABLE_BITTORRENT static void showTorrentFile(const std::string& uri) { - SharedHandle<DefaultBtContext> btContext(new DefaultBtContext()); - btContext->load(uri); - std::cout << btContext << std::endl; + SharedHandle<DownloadContext> dctx(new DownloadContext()); + bittorrent::load(uri, dctx); + bittorrent::print(std::cout, dctx); } #endif // ENABLE_BITTORRENT @@ -122,7 +125,7 @@ static void showMetalinkFile MetalinkHelper::parseAndQuery(metalinkEntries, uri, op.get()); std::deque<SharedHandle<FileEntry> > fileEntries; MetalinkEntry::toFileEntry(fileEntries, metalinkEntries); - Util::toStream(std::cout, fileEntries); + Util::toStream(fileEntries.begin(), fileEntries.end(), std::cout); std::cout << std::endl; } #endif // ENABLE_METALINK diff --git a/src/option_processing.cc b/src/option_processing.cc index 8b27f197..240f2bac 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -54,6 +54,8 @@ #include "StringFormat.h" #include "OptionHandlerException.h" #include "DownloadResult.h" +#include "SimpleRandomizer.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -202,6 +204,10 @@ void option_processing(Option& op, std::deque<std::string>& uris, } } #endif // HAVE_DAEMON +#ifdef ENABLE_BITTORRENT + bittorrent::generateStaticPeerId(op.get(PREF_PEER_ID_PREFIX), + SimpleRandomizer::getInstance()); +#endif // ENABLE_BITTORRENT } } // namespace aria2 |
