diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2012-07-26 21:07:10 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2012-07-26 21:07:10 +0900 |
| commit | 01e1fdaf495342ae8735ec74eb57f912fa67d535 (patch) | |
| tree | e5573e8aa7f3786d8364c76cabf5397f7473ed2f /src | |
| parent | 7176107414f73d7fe0cfd7d5ce516aa41a2f0b22 (diff) | |
Parse torrent file on the fly if --follow-torrent=mem is given
In this changes, Bencode parser in bencode2 is removed and the request
is delegated to BencodeParser.
Diffstat (limited to 'src')
27 files changed, 493 insertions, 406 deletions
diff --git a/src/MemoryBufferPreDownloadHandler.cc b/src/AnonDiskWriterFactory.h index bdf60bf8..f92556d1 100644 --- a/src/MemoryBufferPreDownloadHandler.cc +++ b/src/AnonDiskWriterFactory.h @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * Copyright (C) 2012 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 @@ -32,24 +32,27 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#include "MemoryBufferPreDownloadHandler.h" -#include "RequestGroup.h" -#include "ByteArrayDiskWriterFactory.h" -#include "DownloadContext.h" +#ifndef D_ANON_DISK_WRITER_FACTORY_H +#define D_ANON_DISK_WRITER_FACTORY_H -namespace aria2 { +#include "DiskWriterFactory.h" -MemoryBufferPreDownloadHandler::MemoryBufferPreDownloadHandler() {} +namespace aria2 { -MemoryBufferPreDownloadHandler::~MemoryBufferPreDownloadHandler() {} +// DiskwriterFactory class template to create DiskWriter derived +// object, ignoring filename. +template<class DiskWriterType> +class AnonDiskWriterFactory:public DiskWriterFactory { +public: + AnonDiskWriterFactory() {} + virtual ~AnonDiskWriterFactory() {} -void MemoryBufferPreDownloadHandler::execute(RequestGroup* requestGroup) -{ - SharedHandle<DiskWriterFactory> dwf(new ByteArrayDiskWriterFactory()); - requestGroup->setDiskWriterFactory(dwf); - requestGroup->setFileAllocationEnabled(false); - requestGroup->setPreLocalFileCheckEnabled(false); - requestGroup->markInMemoryDownload(); -} + virtual SharedHandle<DiskWriter> newDiskWriter(const std::string& filename) + { + return SharedHandle<DiskWriter>(new DiskWriterType()); + } +}; } // namespace aria2 + +#endif // D_ANON_DISK_WRITER_FACTORY_H diff --git a/src/ByteArrayDiskWriterFactory.cc b/src/BencodeDiskWriter.h index 495488e4..1554c799 100644 --- a/src/ByteArrayDiskWriterFactory.cc +++ b/src/BencodeDiskWriter.h @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * Copyright (C) 2012 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 @@ -32,15 +32,20 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#include "ByteArrayDiskWriterFactory.h" -#include "ByteArrayDiskWriter.h" +#ifndef D_BENCODE_DISK_WRITER_H +#define D_BENCODE_DISK_WRITER_H + +#include "ValueBaseDiskWriter.h" +#include "BencodeParser.h" namespace aria2 { -DiskWriterHandle ByteArrayDiskWriterFactory::newDiskWriter -(const std::string& filename) -{ - return SharedHandle<DiskWriter>(new ByteArrayDiskWriter()); -} +namespace bittorrent { + +typedef ValueBaseDiskWriter<BencodeParser> BencodeDiskWriter; + +} // namespace bittorrent } // namespace aria2 + +#endif // D_BENCODE_DISK_WRITER_H diff --git a/src/JsonDiskWriter.cc b/src/BencodeDiskWriterFactory.h index b616e2bd..a4a6038b 100644 --- a/src/JsonDiskWriter.cc +++ b/src/BencodeDiskWriterFactory.h @@ -32,47 +32,20 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#include "JsonDiskWriter.h" -#include "ValueBase.h" +#ifndef D_BENCODE_DISK_WRITER_FACTORY_H +#define D_BENCODE_DISK_WRITER_FACTORY_H -namespace aria2 { - -namespace json { - -JsonDiskWriter::JsonDiskWriter() - : parser_(&psm_) -{} - -JsonDiskWriter::~JsonDiskWriter() -{} +#include "AnonDiskWriterFactory.h" +#include "BencodeDiskWriter.h" -void JsonDiskWriter::initAndOpenFile(int64_t totalLength) -{ - parser_.reset(); -} - -void JsonDiskWriter::writeData(const unsigned char* data, size_t len, - int64_t offset) -{ - // Return value is ignored here but handled in finalize() - parser_.parseUpdate(reinterpret_cast<const char*>(data), len); -} - -int JsonDiskWriter::finalize() -{ - return parser_.parseFinal(0, 0); -} +namespace aria2 { -SharedHandle<ValueBase> JsonDiskWriter::getResult() const -{ - return psm_.getResult(); -} +namespace bittorrent { -void JsonDiskWriter::reset() -{ - parser_.reset(); -} +typedef AnonDiskWriterFactory<BencodeDiskWriter> BencodeDiskWriterFactory; -} // namespace json +} // namespace bittorrent } // namespace aria2 + +#endif // D_BENCODE_DISK_WRITER_FACTORY_H diff --git a/src/BtPostDownloadHandler.cc b/src/BtPostDownloadHandler.cc index 00ecea28..c3faccfc 100644 --- a/src/BtPostDownloadHandler.cc +++ b/src/BtPostDownloadHandler.cc @@ -48,6 +48,10 @@ #include "DownloadContext.h" #include "download_helper.h" #include "fmt.h" +#include "ValueBaseBencodeParser.h" +#include "DiskWriter.h" +#include "AbstractSingleDiskAdaptor.h" +#include "BencodeDiskWriter.h" namespace aria2 { @@ -70,19 +74,41 @@ void BtPostDownloadHandler::getNextRequestGroups { A2_LOG_INFO(fmt("Generating RequestGroups for Torrent file %s", requestGroup->getFirstFilePath().c_str())); - std::string content; - try { - requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile(); - content = util::toString(requestGroup->getPieceStorage()->getDiskAdaptor()); - requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); - } catch(Exception& e) { - requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); - throw; + SharedHandle<ValueBase> torrent; + if(requestGroup->inMemoryDownload()) { + const SharedHandle<DiskWriter>& dw = + static_pointer_cast<AbstractSingleDiskAdaptor> + (requestGroup->getPieceStorage()->getDiskAdaptor())->getDiskWriter(); + const SharedHandle<bittorrent::BencodeDiskWriter>& bdw = + static_pointer_cast<bittorrent::BencodeDiskWriter>(dw); + int error = bdw->finalize(); + if(error == 0) { + torrent = bdw->getResult(); + } + } else { + std::string content; + try { + requestGroup->getPieceStorage()->getDiskAdaptor()->openExistingFile(); + content = util::toString(requestGroup->getPieceStorage() + ->getDiskAdaptor()); + requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); + } catch(Exception& e) { + requestGroup->getPieceStorage()->getDiskAdaptor()->closeFile(); + throw; + } + ssize_t error; + torrent = bittorrent::ValueBaseBencodeParser().parseFinal + (content.c_str(), content.size(), error); + } + if(!torrent) { + throw DL_ABORT_EX2("Could not parse BitTorrent metainfo", + error_code::BENCODE_PARSE_ERROR); } std::vector<SharedHandle<RequestGroup> > newRgs; createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(), std::vector<std::string>(), - content); + "", + torrent); requestGroup->followedBy(newRgs.begin(), newRgs.end()); SharedHandle<MetadataInfo> mi = createMetadataInfoFromFirstFileEntry(requestGroup->getDownloadContext()); diff --git a/src/ByteArrayDiskWriterFactory.h b/src/ByteArrayDiskWriterFactory.h index c770e7ac..5a839371 100644 --- a/src/ByteArrayDiskWriterFactory.h +++ b/src/ByteArrayDiskWriterFactory.h @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * Copyright (C) 2012 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 @@ -35,17 +35,13 @@ #ifndef D_BYTE_ARRAY_DISK_WRITER_FACTORY_H #define D_BYTE_ARRAY_DISK_WRITER_FACTORY_H -#include "DiskWriterFactory.h" +#include "AnonDiskWriterFactory.h" +#include "ByteArrayDiskWriter.h" namespace aria2 { -class ByteArrayDiskWriter; - -class ByteArrayDiskWriterFactory:public DiskWriterFactory -{ -public: - SharedHandle<DiskWriter> newDiskWriter(const std::string& filename); -}; +typedef AnonDiskWriterFactory<ByteArrayDiskWriter> +ByteArrayDiskWriterFactory; typedef SharedHandle<ByteArrayDiskWriterFactory> ByteArrayDiskWriterFactoryHandle; diff --git a/src/DHTMessageReceiver.cc b/src/DHTMessageReceiver.cc index 8b2b98b1..e5558d9d 100644 --- a/src/DHTMessageReceiver.cc +++ b/src/DHTMessageReceiver.cc @@ -76,7 +76,7 @@ SharedHandle<DHTMessage> DHTMessageReceiver::receiveMessage() return SharedHandle<DHTMessage>(); } bool isReply = false; - SharedHandle<ValueBase> decoded = bencode2::decode(data, data+length); + SharedHandle<ValueBase> decoded = bencode2::decode(data, length); const Dict* dict = downcast<Dict>(decoded); if(dict) { const String* y = downcast<String>(dict->get(DHTMessage::Y)); diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc index 8f60285c..1a76df15 100644 --- a/src/DefaultBtAnnounce.cc +++ b/src/DefaultBtAnnounce.cc @@ -222,7 +222,7 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse, { A2_LOG_DEBUG("Now processing tracker response."); SharedHandle<ValueBase> decodedValue = - bencode2::decode(trackerResponse, trackerResponse+trackerResponseLength); + bencode2::decode(trackerResponse, trackerResponseLength); const Dict* dict = downcast<Dict>(decodedValue); if(!dict) { throw DL_ABORT_EX(MSG_NULL_TRACKER_RESPONSE); diff --git a/src/DefaultExtensionMessageFactory.cc b/src/DefaultExtensionMessageFactory.cc index 47fa26b3..a86765c0 100644 --- a/src/DefaultExtensionMessageFactory.cc +++ b/src/DefaultExtensionMessageFactory.cc @@ -102,7 +102,7 @@ DefaultExtensionMessageFactory::createMessage(const unsigned char* data, size_t } size_t end; SharedHandle<ValueBase> decoded = - bencode2::decode(data+1, data+length, end); + bencode2::decode(data+1, length - 1, end); const Dict* dict = downcast<Dict>(decoded); if(!dict) { throw DL_ABORT_EX("Bad ut_metadata: dictionary not found"); diff --git a/src/DownloadHandlerFactory.cc b/src/DownloadHandlerFactory.cc index 985a90c7..8fdb7a35 100644 --- a/src/DownloadHandlerFactory.cc +++ b/src/DownloadHandlerFactory.cc @@ -54,7 +54,7 @@ DownloadHandlerFactory::metalinkPostDownloadHandler_; #ifdef ENABLE_BITTORRENT -SharedHandle<MemoryBufferPreDownloadHandler> +SharedHandle<bittorrent::MemoryBencodePreDownloadHandler> DownloadHandlerFactory::btPreDownloadHandler_; SharedHandle<BtPostDownloadHandler> @@ -96,11 +96,12 @@ DownloadHandlerFactory::getMetalinkPostDownloadHandler() #ifdef ENABLE_BITTORRENT -SharedHandle<MemoryBufferPreDownloadHandler> +SharedHandle<bittorrent::MemoryBencodePreDownloadHandler> DownloadHandlerFactory::getBtPreDownloadHandler() { if(!btPreDownloadHandler_) { - btPreDownloadHandler_.reset(new MemoryBufferPreDownloadHandler()); + btPreDownloadHandler_.reset + (new bittorrent::MemoryBencodePreDownloadHandler()); RequestGroupCriteriaHandle criteria (new ContentTypeRequestGroupCriteria diff --git a/src/DownloadHandlerFactory.h b/src/DownloadHandlerFactory.h index 94550db5..1ec81fd7 100644 --- a/src/DownloadHandlerFactory.h +++ b/src/DownloadHandlerFactory.h @@ -37,10 +37,13 @@ #include "common.h" #include "SharedHandle.h" +#include "MemoryBufferPreDownloadHandler.h" +#ifdef ENABLE_BITTORRENT +# include "MemoryBencodePreDownloadHandler.h" +#endif // ENABLE_BITTORRENT namespace aria2 { -class MemoryBufferPreDownloadHandler; #ifdef ENABLE_METALINK class MetalinkPostDownloadHandler; #endif // ENABLE_METALINK @@ -61,7 +64,7 @@ private: #endif // ENABLE_METALINK #ifdef ENABLE_BITTORRENT - static SharedHandle<MemoryBufferPreDownloadHandler> + static SharedHandle<bittorrent::MemoryBencodePreDownloadHandler> btPreDownloadHandler_; static SharedHandle<BtPostDownloadHandler> @@ -80,7 +83,7 @@ public: #endif // ENABLE_METALINK #ifdef ENABLE_BITTORRENT - static SharedHandle<MemoryBufferPreDownloadHandler> + static SharedHandle<bittorrent::MemoryBencodePreDownloadHandler> getBtPreDownloadHandler(); static SharedHandle<BtPostDownloadHandler> diff --git a/src/GenericParser.h b/src/GenericParser.h index 77985f69..f988d58b 100644 --- a/src/GenericParser.h +++ b/src/GenericParser.h @@ -37,6 +37,8 @@ #include "common.h" #include "SharedHandle.h" +#include "a2io.h" +#include "util.h" namespace aria2 { @@ -50,6 +52,9 @@ public: ~GenericParser() {} + typedef typename ParserStateMachine::ResultType ResultType; + typedef ParserStateMachine ParserStateMachineType; + // Parses |size| bytes of data |data| and returns the number of // bytes processed. On error, one of the negative error codes is // returned. @@ -63,13 +68,13 @@ public: // number of bytes processed (>= 0). On error, it will be one of the // negative error code. This function also resets underlying parser // facility and make it ready to reuse. - typename ParserStateMachine::ResultType + ResultType parseFinal(const char* data, size_t size, ssize_t& error) { - typename ParserStateMachine::ResultType res; + ResultType res; error = parser_.parseFinal(data, size); if(error < 0) { - res = ParserStateMachine::noResult; + res = ParserStateMachine::noResult(); } else { res = psm_.getResult(); } @@ -81,6 +86,29 @@ private: Parser parser_; }; +template<typename Parser> +typename Parser::ResultType parseFile(Parser& parser, + const std::string& filename) +{ + int fd; + // TODO Overrode a2open(const char*,..) and a2open(const std::wstring&,..) + while((fd = a2open(utf8ToWChar(filename).c_str(), + O_BINARY | O_RDONLY, OPEN_MODE)) == -1 && fd != EINTR); + if(fd == -1) { + return Parser::ParserStateMachineType::noResult(); + } + char buf[4096]; + ssize_t nread; + ssize_t nproc; + while((nread = read(fd, buf, sizeof(buf))) > 0) { + nproc = parser.parseUpdate(buf, nread); + if(nproc < 0) { + break; + } + } + return parser.parseFinal(0, 0, nproc); +} + } // namespace aria2 #endif // D_GENERIC_PARSER_H diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc index cdfc9d1d..4a9c065c 100644 --- a/src/HandshakeExtensionMessage.cc +++ b/src/HandshakeExtensionMessage.cc @@ -168,7 +168,7 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length) HandshakeExtensionMessageHandle msg(new HandshakeExtensionMessage()); A2_LOG_DEBUG(fmt("Creating HandshakeExtensionMessage from %s", util::percentEncode(data, length).c_str())); - SharedHandle<ValueBase> decoded = bencode2::decode(data+1, data+length); + SharedHandle<ValueBase> decoded = bencode2::decode(data+1, length - 1); const Dict* dict = downcast<Dict>(decoded); if(!dict) { throw DL_ABORT_EX diff --git a/src/JsonDiskWriter.h b/src/JsonDiskWriter.h index 72a4a1c1..70ba2660 100644 --- a/src/JsonDiskWriter.h +++ b/src/JsonDiskWriter.h @@ -35,57 +35,14 @@ #ifndef D_JSON_DISK_WRITER_H #define D_JSON_DISK_WRITER_H -#include "DiskWriter.h" -#include "ValueBaseStructParserStateMachine.h" +#include "ValueBaseDiskWriter.h" #include "JsonParser.h" namespace aria2 { namespace json { -// DiskWriter backed with ValueBaseJsonParser. The written bytes are -// consumed by ValueBaseJsonParser. It is only capable of sequential -// write so offset argument in write() will be ignored. It also does -// not offer read(). -class JsonDiskWriter : public DiskWriter { -public: - JsonDiskWriter(); - - virtual ~JsonDiskWriter(); - - virtual void initAndOpenFile(int64_t totalLength = 0); - - virtual void openFile(int64_t totalLength = 0) - { - initAndOpenFile(totalLength); - } - - virtual void closeFile() {} - - virtual void openExistingFile(int64_t totalLength = 0) - { - initAndOpenFile(totalLength); - } - - virtual int64_t size() - { - return 0; - } - - virtual void writeData(const unsigned char* data, size_t len, int64_t offset); - - virtual ssize_t readData(unsigned char* data, size_t len, int64_t offset) - { - return 0; - } - - int finalize(); - SharedHandle<ValueBase> getResult() const; - void reset(); -private: - ValueBaseStructParserStateMachine psm_; - JsonParser parser_; -}; +typedef ValueBaseDiskWriter<JsonParser> JsonDiskWriter; } // namespace json diff --git a/src/Makefile.am b/src/Makefile.am index 25ec3723..8766237b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -116,7 +116,8 @@ SRCS = Socket.h\ DownloadHandler.cc DownloadHandler.h\ DownloadHandlerConstants.cc DownloadHandlerConstants.h\ DownloadHandlerFactory.cc DownloadHandlerFactory.h\ - MemoryBufferPreDownloadHandler.cc MemoryBufferPreDownloadHandler.h\ + MemoryPreDownloadHandler.h\ + MemoryBufferPreDownloadHandler.h\ HaveEraseCommand.cc HaveEraseCommand.h\ Piece.cc Piece.h\ CheckIntegrityMan.h\ @@ -132,7 +133,7 @@ SRCS = Socket.h\ BtRegistry.cc BtRegistry.h\ MultiFileAllocationIterator.cc MultiFileAllocationIterator.h\ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\ - ByteArrayDiskWriterFactory.cc ByteArrayDiskWriterFactory.h\ + ByteArrayDiskWriterFactory.h\ DownloadContext.cc DownloadContext.h\ TimedHaltCommand.cc TimedHaltCommand.h\ CUIDCounter.cc CUIDCounter.h\ @@ -205,7 +206,7 @@ SRCS = Socket.h\ ValueBaseStructParserState.h\ ValueBaseStructParserStateImpl.cc ValueBaseStructParserStateImpl.h\ ValueBaseStructParserStateMachine.cc ValueBaseStructParserStateMachine.h\ - JsonDiskWriter.cc JsonDiskWriter.h\ + JsonDiskWriter.h\ HttpServerBodyCommand.cc HttpServerBodyCommand.h\ RpcRequest.cc RpcRequest.h\ RpcMethod.cc RpcMethod.h\ @@ -234,7 +235,9 @@ SRCS = Socket.h\ rpc_helper.cc rpc_helper.h\ WatchProcessCommand.cc WatchProcessCommand.h\ UnknownOptionException.cc UnknownOptionException.h\ - Notifier.cc Notifier.h + Notifier.cc Notifier.h\ + ValueBaseDiskWriter.h\ + AnonDiskWriterFactory.h if MINGW_BUILD SRCS += WinConsoleFile.cc WinConsoleFile.h @@ -510,7 +513,10 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\ LpdDispatchMessageCommand.cc LpdDispatchMessageCommand.h\ bencode2.cc bencode2.h\ BencodeParser.cc BencodeParser.h\ - ValueBaseBencodeParser.h + ValueBaseBencodeParser.h\ + BencodeDiskWriter.h\ + BencodeDiskWriterFactory.h\ + MemoryBencodePreDownloadHandler.h endif # ENABLE_BITTORRENT if ENABLE_METALINK diff --git a/src/MemoryBencodePreDownloadHandler.h b/src/MemoryBencodePreDownloadHandler.h new file mode 100644 index 00000000..98e6f275 --- /dev/null +++ b/src/MemoryBencodePreDownloadHandler.h @@ -0,0 +1,52 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2012 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_MEMORY_BENCODE_PRE_DOWNLOAD_HANDLER_H +#define D_MEMORY_BENCODE_PRE_DOWNLOAD_HANDLER_H + +#include "MemoryPreDownloadHandler.h" +#include "BencodeDiskWriterFactory.h" + +namespace aria2 { + +namespace bittorrent { + +typedef MemoryPreDownloadHandler<BencodeDiskWriterFactory> +MemoryBencodePreDownloadHandler; + +} // namespace bittorrent + +} // namespace aria2 + +#endif // D_MEMORY_BENCODE_PRE_DOWNLOAD_HANDLER_H diff --git a/src/MemoryBufferPreDownloadHandler.h b/src/MemoryBufferPreDownloadHandler.h index dda90b73..8e736a77 100644 --- a/src/MemoryBufferPreDownloadHandler.h +++ b/src/MemoryBufferPreDownloadHandler.h @@ -35,19 +35,13 @@ #ifndef D_MEMORY_BUFFER_PRE_DOWNLOAD_HANDLER_H #define D_MEMORY_BUFFER_PRE_DOWNLOAD_HANDLER_H -#include "PreDownloadHandler.h" +#include "MemoryPreDownloadHandler.h" +#include "ByteArrayDiskWriterFactory.h" namespace aria2 { -class MemoryBufferPreDownloadHandler:public PreDownloadHandler -{ -public: - MemoryBufferPreDownloadHandler(); - - virtual ~MemoryBufferPreDownloadHandler(); - - virtual void execute(RequestGroup* requestGroup); -}; +typedef MemoryPreDownloadHandler<ByteArrayDiskWriterFactory> +MemoryBufferPreDownloadHandler; } // namespace aria2 diff --git a/src/MemoryPreDownloadHandler.h b/src/MemoryPreDownloadHandler.h new file mode 100644 index 00000000..c3fc8ca3 --- /dev/null +++ b/src/MemoryPreDownloadHandler.h @@ -0,0 +1,64 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2012 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_MEMORY_PRE_DOWNLOAD_HANDLER_H +#define D_MEMORY_PRE_DOWNLOAD_HANDLER_H + +#include "PreDownloadHandler.h" +#include "RequestGroup.h" + +namespace aria2 { + +template<class DiskWriterFactoryType> +class MemoryPreDownloadHandler:public PreDownloadHandler +{ +public: + MemoryPreDownloadHandler() {} + + virtual ~MemoryPreDownloadHandler() {} + + virtual void execute(RequestGroup* requestGroup) + { + SharedHandle<DiskWriterFactory> dwf(new DiskWriterFactoryType()); + requestGroup->setDiskWriterFactory(dwf); + requestGroup->setFileAllocationEnabled(false); + requestGroup->setPreLocalFileCheckEnabled(false); + requestGroup->markInMemoryDownload(); + requestGroup->setNumConcurrentCommand(1); + } +}; + +} // namespace aria2 + +#endif // D_MEMORY_PRE_DOWNLOAD_HANDLER_H diff --git a/src/UTPexExtensionMessage.cc b/src/UTPexExtensionMessage.cc index 0e1446e0..4b64be47 100644 --- a/src/UTPexExtensionMessage.cc +++ b/src/UTPexExtensionMessage.cc @@ -191,7 +191,7 @@ UTPexExtensionMessage::create(const unsigned char* data, size_t len) } UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data)); - SharedHandle<ValueBase> decoded = bencode2::decode(data+1, data+len); + SharedHandle<ValueBase> decoded = bencode2::decode(data+1, len - 1); const Dict* dict = downcast<Dict>(decoded); if(dict) { const String* added = downcast<String>(dict->get("added")); diff --git a/src/ValueBaseDiskWriter.h b/src/ValueBaseDiskWriter.h new file mode 100644 index 00000000..3f326c96 --- /dev/null +++ b/src/ValueBaseDiskWriter.h @@ -0,0 +1,111 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2012 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_VALUE_BASE_DISK_WRITER_H +#define D_VALUE_BASE_DISK_WRITER_H + +#include "DiskWriter.h" +#include "ValueBaseStructParserStateMachine.h" + +namespace aria2 { + +// DiskWriter backed with ValueBaseParser. The written bytes are +// consumed by ValueBaseParser. It is only capable of sequential write +// so offset argument in write() will be ignored. It also does not +// offer read(). +template<class ValueBaseParser> +class ValueBaseDiskWriter : public DiskWriter { +public: + ValueBaseDiskWriter() + : parser_(&psm_) + {} + + virtual ~ValueBaseDiskWriter() + {} + + virtual void initAndOpenFile(int64_t totalLength = 0) + { + parser_.reset(); + } + + virtual void openFile(int64_t totalLength = 0) + { + initAndOpenFile(totalLength); + } + + virtual void closeFile() {} + + virtual void openExistingFile(int64_t totalLength = 0) + { + initAndOpenFile(totalLength); + } + + virtual int64_t size() + { + return 0; + } + + virtual void writeData(const unsigned char* data, size_t len, int64_t offset) + { + // Return value is ignored here but handled in finalize() + parser_.parseUpdate(reinterpret_cast<const char*>(data), len); + } + + virtual ssize_t readData(unsigned char* data, size_t len, int64_t offset) + { + return 0; + } + + int finalize() + { + return parser_.parseFinal(0, 0); + } + + SharedHandle<ValueBase> getResult() const + { + return psm_.getResult(); + } + + void reset() + { + parser_.reset(); + } +private: + ValueBaseStructParserStateMachine psm_; + ValueBaseParser parser_; +}; + +} // namespace aria2 + +#endif // D_VALUE_BASE_DISK_WRITER_H diff --git a/src/ValueBaseStructParserStateMachine.cc b/src/ValueBaseStructParserStateMachine.cc index 4a446a15..04d1033c 100644 --- a/src/ValueBaseStructParserStateMachine.cc +++ b/src/ValueBaseStructParserStateMachine.cc @@ -65,8 +65,11 @@ NullValueBaseStructParserState* nullState = new NullValueBaseStructParserState(); } // namespace -const SharedHandle<ValueBase> -ValueBaseStructParserStateMachine::noResult = ValueBase::none; +const SharedHandle<ValueBase>& +ValueBaseStructParserStateMachine::noResult() +{ + return ValueBase::none; +} ValueBaseStructParserStateMachine::ValueBaseStructParserStateMachine() : ctrl_(new rpc::XmlRpcRequestParserController()) diff --git a/src/ValueBaseStructParserStateMachine.h b/src/ValueBaseStructParserStateMachine.h index 30143181..5b5efa56 100644 --- a/src/ValueBaseStructParserStateMachine.h +++ b/src/ValueBaseStructParserStateMachine.h @@ -57,7 +57,7 @@ class ValueBaseStructParserState; class ValueBaseStructParserStateMachine : public StructParserStateMachine { public: typedef SharedHandle<ValueBase> ResultType; - static const SharedHandle<ValueBase> noResult; + static const SharedHandle<ValueBase>& noResult(); struct NumberData { int64_t number; diff --git a/src/bencode2.cc b/src/bencode2.cc index 78071879..2e5b2e6a 100644 --- a/src/bencode2.cc +++ b/src/bencode2.cc @@ -41,229 +41,39 @@ #include "error_code.h" #include "BufferedFile.h" #include "util.h" +#include "ValueBaseBencodeParser.h" namespace aria2 { namespace bencode2 { -namespace { -template<typename InputIterator> -std::pair<SharedHandle<ValueBase>, InputIterator> -decodeiter -(InputIterator first, - InputIterator last, - size_t depth); -} // namespace - -namespace { -template<typename InputIterator> -std::pair<std::pair<InputIterator, InputIterator>, InputIterator> -decoderawstring(InputIterator first, InputIterator last) -{ - InputIterator i = first; - int32_t len; - for(; i != last && *i != ':'; ++i); - if(i == last || i == first || - !util::parseIntNoThrow(len, std::string(first, i)) || - len < 0) { - throw DL_ABORT_EX2("Bencode decoding failed:" - " A positive integer expected but none found.", - error_code::BENCODE_PARSE_ERROR); - } - ++i; - if(last-i < len) { - throw DL_ABORT_EX2 - (fmt("Bencode decoding failed:" - " Expected %d bytes of data, but only %d read.", - len, static_cast<int>(last-i)), - error_code::BENCODE_PARSE_ERROR); - } - return std::make_pair(std::make_pair(i, i+len), i+len); -} -} // namespace - -namespace { -template<typename InputIterator> -std::pair<SharedHandle<ValueBase>, InputIterator> -decodestring(InputIterator first, InputIterator last) -{ - std::pair<std::pair<InputIterator, InputIterator>, InputIterator> r = - decoderawstring(first, last); - return std::make_pair(String::g(r.first.first, r.first.second), r.second); -} -} // namespace - -namespace { -template<typename InputIterator> -std::pair<SharedHandle<ValueBase>, InputIterator> -decodeinteger(InputIterator first, InputIterator last) -{ - InputIterator i = first; - for(; i != last && *i != 'e'; ++i); - Integer::ValueType iv; - if(i == last || !util::parseLLIntNoThrow(iv, std::string(first, i))) { - throw DL_ABORT_EX2("Bencode decoding failed:" - " Integer expected but none found", - error_code::BENCODE_PARSE_ERROR); - } - return std::make_pair(Integer::g(iv), ++i); -} -} // namespace - -namespace { -template<typename InputIterator> -std::pair<SharedHandle<ValueBase>, InputIterator> -decodedict -(InputIterator first, - InputIterator last, - size_t depth) -{ - SharedHandle<Dict> dict = Dict::g(); - while(first != last) { - if(*first == 'e') { - return std::make_pair(dict, ++first); - } else { - std::pair<std::pair<InputIterator, InputIterator>, InputIterator> keyp = - decoderawstring(first, last); - std::pair<SharedHandle<ValueBase>, InputIterator> r = - decodeiter(keyp.second, last, depth); - dict->put(std::string(keyp.first.first, keyp.first.second), r.first); - first = r.second; - } - } - throw DL_ABORT_EX2("Bencode decoding failed:" - " Unexpected EOF in dict context. 'e' expected.", - error_code::BENCODE_PARSE_ERROR); -} -} // namespace - -namespace { -template<typename InputIterator> -std::pair<SharedHandle<ValueBase>, InputIterator> -decodelist -(InputIterator first, - InputIterator last, - size_t depth) -{ - SharedHandle<List> list = List::g(); - while(first != last) { - if(*first == 'e') { - return std::make_pair(list, ++first); - } else { - std::pair<SharedHandle<ValueBase>, InputIterator> r = - decodeiter(first, last, depth); - list->append(r.first); - first = r.second; - } - } - throw DL_ABORT_EX2("Bencode decoding failed:" - " Unexpected EOF in list context. 'e' expected.", - error_code::BENCODE_PARSE_ERROR); -} -} // namespace - -namespace { -void checkDepth(size_t depth) -{ - if(depth >= MAX_STRUCTURE_DEPTH) { - throw DL_ABORT_EX2("Bencode decoding failed: Structure is too deep.", - error_code::BENCODE_PARSE_ERROR); - } -} -} // namespace - -namespace { -template<typename InputIterator> -std::pair<SharedHandle<ValueBase>, InputIterator> -decodeiter -(InputIterator first, - InputIterator last, - size_t depth) -{ - checkDepth(depth); - if(first == last) { - throw DL_ABORT_EX2("Bencode decoding failed:" - " Unexpected EOF in term context." - " 'd', 'l', 'i' or digit is expected.", - error_code::BENCODE_PARSE_ERROR); - } - if(*first == 'd') { - return decodedict(++first, last, depth+1); - } else if(*first == 'l') { - return decodelist(++first, last, depth+1); - } else if(*first == 'i') { - return decodeinteger(++first, last); - } else { - return decodestring(first, last); - } -} -} // namespace - -namespace { -template<typename InputIterator> -SharedHandle<ValueBase> decodegen -(InputIterator first, - InputIterator last, - size_t& end) -{ - if(first == last) { - return SharedHandle<ValueBase>(); - } - std::pair<SharedHandle<ValueBase>, InputIterator> p = - decodeiter(first, last, 0); - end = p.second-first; - return p.first; -} -} // namespace - -SharedHandle<ValueBase> decode -(std::string::const_iterator first, - std::string::const_iterator last) +SharedHandle<ValueBase> decode(const unsigned char* data, size_t len) { size_t end; - return decodegen(first, last, end); + return decode(data, len, end); } -SharedHandle<ValueBase> decode -(std::string::const_iterator first, - std::string::const_iterator last, - size_t& end) -{ - return decodegen(first, last, end); -} - -SharedHandle<ValueBase> decode -(const unsigned char* first, - const unsigned char* last) +SharedHandle<ValueBase> decode(const std::string& data) { size_t end; - return decodegen(first, last, end); + return decode(reinterpret_cast<const unsigned char*>(data.c_str()), + data.size(), end); } -SharedHandle<ValueBase> decode -(const unsigned char* first, - const unsigned char* last, - size_t& end) +SharedHandle<ValueBase> decode(const unsigned char* data, size_t len, + size_t& end) { - return decodegen(first, last, end); -} - -SharedHandle<ValueBase> decodeFromFile(const std::string& filename) -{ - BufferedFile fp(filename, BufferedFile::READ); - if(fp) { - std::stringstream ss; - fp.transfer(ss); - fp.close(); - const std::string s = ss.str(); - size_t end; - return decodegen(s.begin(), s.end(), end); - } else { - throw DL_ABORT_EX2 - (fmt("Bencode decoding failed: Cannot open file '%s'.", - filename.c_str()), - error_code::BENCODE_PARSE_ERROR); + ssize_t error; + bittorrent::ValueBaseBencodeParser parser; + SharedHandle<ValueBase> res = + parser.parseFinal(reinterpret_cast<const char*>(data), len, error); + if(error < 0) { + throw DL_ABORT_EX2(fmt("Bencode decoding failed: error=%d", + static_cast<int>(error)), + error_code::BENCODE_PARSE_ERROR); } + end = error; + return res; } std::string encode(const ValueBase* vlb) diff --git a/src/bencode2.h b/src/bencode2.h index bfc95de6..7da4c2fd 100644 --- a/src/bencode2.h +++ b/src/bencode2.h @@ -38,7 +38,6 @@ #include "common.h" #include <string> -#include <iosfwd> #include "ValueBase.h" @@ -46,28 +45,15 @@ namespace aria2 { namespace bencode2 { -const size_t MAX_STRUCTURE_DEPTH = 100; +// Decode the data whose length is len. +SharedHandle<ValueBase> decode(const unsigned char* data, size_t len); -// Decode the data in [first, last). -SharedHandle<ValueBase> decode -(std::string::const_iterator first, - std::string::const_iterator last); +SharedHandle<ValueBase> decode(const std::string& data); -// Decode the data in [first, last). After decode is done +// Decode the data whose length is len. After decode is done // successfully, return the bencoded string length in end. -SharedHandle<ValueBase> decode -(std::string::const_iterator first, - std::string::const_iterator last, - size_t& end); - -SharedHandle<ValueBase> decode -(const unsigned char* first, - const unsigned char* last); - -SharedHandle<ValueBase> decode -(const unsigned char* first, - const unsigned char* last, - size_t& end); +SharedHandle<ValueBase> decode(const unsigned char* data, size_t len, + size_t& end); SharedHandle<ValueBase> decodeFromFile(const std::string& filename); diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index b6fc89b7..ea7f1c5b 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -61,6 +61,7 @@ #include "error_code.h" #include "array_fun.h" #include "DownloadFailureException.h" +#include "ValueBaseBencodeParser.h" namespace aria2 { @@ -523,8 +524,9 @@ void load(const std::string& torrentFile, const SharedHandle<Option>& option, const std::string& overrideName) { + ValueBaseBencodeParser parser; processRootDictionary(ctx, - bencode2::decodeFromFile(torrentFile), + parseFile(parser, torrentFile), option, torrentFile, overrideName, @@ -537,8 +539,9 @@ void load(const std::string& torrentFile, const std::vector<std::string>& uris, const std::string& overrideName) { + ValueBaseBencodeParser parser; processRootDictionary(ctx, - bencode2::decodeFromFile(torrentFile), + parseFile(parser, torrentFile), option, torrentFile, overrideName, @@ -553,7 +556,7 @@ void loadFromMemory(const unsigned char* content, const std::string& overrideName) { processRootDictionary(ctx, - bencode2::decode(content, content+length), + bencode2::decode(content, length), option, defaultName, overrideName, @@ -569,7 +572,7 @@ void loadFromMemory(const unsigned char* content, const std::string& overrideName) { processRootDictionary(ctx, - bencode2::decode(content, content+length), + bencode2::decode(content, length), option, defaultName, overrideName, @@ -584,7 +587,7 @@ void loadFromMemory(const std::string& context, { processRootDictionary (ctx, - bencode2::decode(context.begin(), context.end()), + bencode2::decode(context), option, defaultName, overrideName, std::vector<std::string>()); @@ -599,7 +602,22 @@ void loadFromMemory(const std::string& context, { processRootDictionary (ctx, - bencode2::decode(context.begin(), context.end()), + bencode2::decode(context), + option, + defaultName, overrideName, + uris); +} + +void loadFromMemory(const SharedHandle<ValueBase>& torrent, + const SharedHandle<DownloadContext>& ctx, + const SharedHandle<Option>& option, + const std::vector<std::string>& uris, + const std::string& defaultName, + const std::string& overrideName) +{ + processRootDictionary + (ctx, + torrent, option, defaultName, overrideName, uris); diff --git a/src/bittorrent_helper.h b/src/bittorrent_helper.h index b8a5fd41..5f4f17fe 100644 --- a/src/bittorrent_helper.h +++ b/src/bittorrent_helper.h @@ -104,6 +104,13 @@ void loadFromMemory(const std::string& context, const std::string& defaultName, const std::string& overrideName = ""); +void loadFromMemory(const SharedHandle<ValueBase>& torrent, + const SharedHandle<DownloadContext>& ctx, + const SharedHandle<Option>& option, + const std::vector<std::string>& uris, + const std::string& defaultName, + const std::string& overrideName = ""); + // Parses BitTorrent Magnet URI and returns // SharedHandle<TorrentAttribute> which includes infoHash, name and // announceList. If parsing operation failed, an RecoverableException diff --git a/src/download_helper.cc b/src/download_helper.cc index c140fef4..90707cd3 100644 --- a/src/download_helper.cc +++ b/src/download_helper.cc @@ -62,9 +62,10 @@ #include "OptionParser.h" #include "SegList.h" #ifdef ENABLE_BITTORRENT -# include "bittorrent_helper.h" -# include "BtConstants.h" -# include "UTMetadataPostDownloadHandler.h" +# include "bittorrent_helper.h" +# include "BtConstants.h" +# include "UTMetadataPostDownloadHandler.h" +# include "ValueBaseBencodeParser.h" #endif // ENABLE_BITTORRENT namespace aria2 { @@ -160,23 +161,22 @@ SharedHandle<MetadataInfo> createMetadataInfoDataOnly() namespace { SharedHandle<RequestGroup> -createBtRequestGroup(const std::string& torrentFilePath, +createBtRequestGroup(const std::string& metaInfoUri, const SharedHandle<Option>& optionTemplate, const std::vector<std::string>& auxUris, - const std::string& torrentData = "", + const SharedHandle<ValueBase>& torrent, bool adjustAnnounceUri = true) { SharedHandle<Option> option = util::copy(optionTemplate); SharedHandle<RequestGroup> rg(new RequestGroup(option)); SharedHandle<DownloadContext> dctx(new DownloadContext()); - if(torrentData.empty()) { - // may throw exception - bittorrent::load(torrentFilePath, dctx, option, auxUris); - rg->setMetadataInfo(createMetadataInfo(torrentFilePath)); - } else { - // may throw exception - bittorrent::loadFromMemory(torrentData, dctx, option, auxUris, "default"); + // may throw exception + bittorrent::loadFromMemory(torrent, dctx, option, auxUris, + metaInfoUri.empty() ? "default" : metaInfoUri); + if(metaInfoUri.empty()) { rg->setMetadataInfo(createMetadataInfoDataOnly()); + } else { + rg->setMetadataInfo(createMetadataInfo(metaInfoUri)); } if(adjustAnnounceUri) { bittorrent::adjustAnnounceUri(bittorrent::getTorrentAttrs(dctx), option); @@ -245,6 +245,33 @@ void createRequestGroupForBitTorrent const std::string& torrentData, bool adjustAnnounceUri) { + SharedHandle<ValueBase> torrent; + bittorrent::ValueBaseBencodeParser parser; + if(torrentData.empty()) { + torrent = parseFile(parser, option->get(PREF_TORRENT_FILE)); + } else { + ssize_t error; + torrent = parser.parseFinal(torrentData.c_str(), torrentData.size(), + error); + } + if(!torrent) { + throw DL_ABORT_EX2("Bencode decoding failed", + error_code::BENCODE_PARSE_ERROR); + } + createRequestGroupForBitTorrent(result, option, uris, + torrentData.empty() ? + option->get(PREF_TORRENT_FILE) : "", + torrent); +} + +void createRequestGroupForBitTorrent +(std::vector<SharedHandle<RequestGroup> >& result, + const SharedHandle<Option>& option, + const std::vector<std::string>& uris, + const std::string& metaInfoUri, + const SharedHandle<ValueBase>& torrent, + bool adjustAnnounceUri) +{ std::vector<std::string> nargs; if(option->get(PREF_PARAMETERIZED_URI) == A2_V_TRUE) { unfoldURI(nargs, uris); @@ -254,8 +281,8 @@ void createRequestGroupForBitTorrent // we ignore -Z option here size_t numSplit = option->getAsInt(PREF_SPLIT); SharedHandle<RequestGroup> rg = - createBtRequestGroup(option->get(PREF_TORRENT_FILE), option, nargs, - torrentData, adjustAnnounceUri); + createBtRequestGroup(metaInfoUri, option, nargs, + torrent, adjustAnnounceUri); rg->setNumConcurrentCommand(numSplit); result.push_back(rg); } @@ -322,8 +349,15 @@ public: requestGroups_.push_back(group); } else if(!ignoreLocalPath_ && detector_.guessTorrentFile(uri)) { try { + bittorrent::ValueBaseBencodeParser parser; + SharedHandle<ValueBase> torrent = parseFile(parser, uri); + if(!torrent) { + throw DL_ABORT_EX2("Bencode decoding failed", + error_code::BENCODE_PARSE_ERROR); + } requestGroups_.push_back - (createBtRequestGroup(uri, option_, std::vector<std::string>())); + (createBtRequestGroup(uri, option_, std::vector<std::string>(), + torrent)); } catch(RecoverableException& e) { if(throwOnError_) { throw; @@ -333,7 +367,7 @@ public: A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e); } } - } + } #endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK else if(!ignoreLocalPath_ && detector_.guessMetalinkFile(uri)) { diff --git a/src/download_helper.h b/src/download_helper.h index b9f90ab2..46cb7000 100644 --- a/src/download_helper.h +++ b/src/download_helper.h @@ -50,6 +50,7 @@ class Option; class MetadataInfo; class DownloadContext; class UriListParser; +class ValueBase; #ifdef ENABLE_BITTORRENT // Create RequestGroup object using torrent file specified by @@ -64,6 +65,15 @@ void createRequestGroupForBitTorrent const std::vector<std::string>& uris, const std::string& torrentData = "", bool adjustAnnounceUri = true); + +void createRequestGroupForBitTorrent +(std::vector<SharedHandle<RequestGroup> >& result, + const SharedHandle<Option>& option, + const std::vector<std::string>& uris, + const std::string& metaInfoUri, + const SharedHandle<ValueBase>& torrent, + bool adjustAnnounceUri = true); + #endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK |
