summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2012-07-26 21:07:10 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2012-07-26 21:07:10 +0900
commit01e1fdaf495342ae8735ec74eb57f912fa67d535 (patch)
treee5573e8aa7f3786d8364c76cabf5397f7473ed2f /src
parent7176107414f73d7fe0cfd7d5ce516aa41a2f0b22 (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')
-rw-r--r--src/AnonDiskWriterFactory.h (renamed from src/MemoryBufferPreDownloadHandler.cc)35
-rw-r--r--src/BencodeDiskWriter.h (renamed from src/ByteArrayDiskWriterFactory.cc)21
-rw-r--r--src/BencodeDiskWriterFactory.h (renamed from src/JsonDiskWriter.cc)47
-rw-r--r--src/BtPostDownloadHandler.cc44
-rw-r--r--src/ByteArrayDiskWriterFactory.h14
-rw-r--r--src/DHTMessageReceiver.cc2
-rw-r--r--src/DefaultBtAnnounce.cc2
-rw-r--r--src/DefaultExtensionMessageFactory.cc2
-rw-r--r--src/DownloadHandlerFactory.cc7
-rw-r--r--src/DownloadHandlerFactory.h9
-rw-r--r--src/GenericParser.h34
-rw-r--r--src/HandshakeExtensionMessage.cc2
-rw-r--r--src/JsonDiskWriter.h47
-rw-r--r--src/Makefile.am16
-rw-r--r--src/MemoryBencodePreDownloadHandler.h52
-rw-r--r--src/MemoryBufferPreDownloadHandler.h14
-rw-r--r--src/MemoryPreDownloadHandler.h64
-rw-r--r--src/UTPexExtensionMessage.cc2
-rw-r--r--src/ValueBaseDiskWriter.h111
-rw-r--r--src/ValueBaseStructParserStateMachine.cc7
-rw-r--r--src/ValueBaseStructParserStateMachine.h2
-rw-r--r--src/bencode2.cc226
-rw-r--r--src/bencode2.h26
-rw-r--r--src/bittorrent_helper.cc30
-rw-r--r--src/bittorrent_helper.h7
-rw-r--r--src/download_helper.cc66
-rw-r--r--src/download_helper.h10
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