mirror of https://github.com/aria2/aria2
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.pull/25/merge
parent
7176107414
commit
01e1fdaf49
|
@ -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
|
||||
|
||||
#include "DiskWriterFactory.h"
|
||||
|
||||
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() {}
|
||||
|
||||
MemoryBufferPreDownloadHandler::~MemoryBufferPreDownloadHandler() {}
|
||||
|
||||
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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
#include "AnonDiskWriterFactory.h"
|
||||
#include "BencodeDiskWriter.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
namespace json {
|
||||
namespace bittorrent {
|
||||
|
||||
JsonDiskWriter::JsonDiskWriter()
|
||||
: parser_(&psm_)
|
||||
{}
|
||||
typedef AnonDiskWriterFactory<BencodeDiskWriter> BencodeDiskWriterFactory;
|
||||
|
||||
JsonDiskWriter::~JsonDiskWriter()
|
||||
{}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
SharedHandle<ValueBase> JsonDiskWriter::getResult() const
|
||||
{
|
||||
return psm_.getResult();
|
||||
}
|
||||
|
||||
void JsonDiskWriter::reset()
|
||||
{
|
||||
parser_.reset();
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // namespace bittorrent
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // D_BENCODE_DISK_WRITER_FACTORY_H
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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"));
|
||||
|
|
|
@ -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
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
226
src/bencode2.cc
226
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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
@ -244,6 +244,33 @@ void createRequestGroupForBitTorrent
|
|||
const std::vector<std::string>& uris,
|
||||
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) {
|
||||
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -65,12 +65,12 @@ std::vector<std::vector<std::string> > toVector
|
|||
void AnnounceListTest::testSingleElementList() {
|
||||
std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
|
||||
AnnounceList announceList(toVector(downcast<List>(announcesList)));
|
||||
|
||||
|
||||
CPPUNIT_ASSERT(!announceList.allTiersFailed());
|
||||
std::string url = announceList.getAnnounce();
|
||||
std::string event = announceList.getEventString();
|
||||
|
@ -111,13 +111,12 @@ void AnnounceListTest::testSingleElementList() {
|
|||
|
||||
void AnnounceListTest::testMultiElementList() {
|
||||
std::string peersString = "ll8:tracker18:tracker28:tracker3ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1, tracker2, tracker3 ] ]
|
||||
AnnounceList announceList(toVector(downcast<List>(announcesList)));
|
||||
|
||||
|
||||
CPPUNIT_ASSERT(!announceList.allTiersFailed());
|
||||
std::string url = announceList.getAnnounce();
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("tracker1"), url);
|
||||
|
@ -145,8 +144,7 @@ void AnnounceListTest::testMultiElementList() {
|
|||
|
||||
void AnnounceListTest::testSingleAndMulti() {
|
||||
std::string peersString = "ll8:tracker18:tracker2el8:tracker3ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1, tracker2 ], [ tracker3 ] ]
|
||||
|
@ -172,16 +170,14 @@ void AnnounceListTest::testSingleAndMulti() {
|
|||
|
||||
void AnnounceListTest::testNoGroup() {
|
||||
std::string peersString = "llee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
AnnounceList announceList(toVector(downcast<List>(announcesList)));
|
||||
CPPUNIT_ASSERT(announceList.countTier() == 0);
|
||||
}
|
||||
|
||||
void AnnounceListTest::testNextEventIfAfterStarted() {
|
||||
std::string peersString = "ll8:tracker1ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1 ] ]
|
||||
|
@ -201,8 +197,7 @@ void AnnounceListTest::testNextEventIfAfterStarted() {
|
|||
|
||||
void AnnounceListTest::testEvent() {
|
||||
std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
|
||||
|
@ -226,8 +221,7 @@ void AnnounceListTest::testEvent() {
|
|||
|
||||
void AnnounceListTest::testCountStoppedAllowedTier() {
|
||||
std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
|
||||
|
@ -254,8 +248,7 @@ void AnnounceListTest::testCountStoppedAllowedTier() {
|
|||
|
||||
void AnnounceListTest::testCountCompletedAllowedTier() {
|
||||
std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
|
||||
SharedHandle<ValueBase> announcesList =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
|
||||
|
||||
// ANNOUNCE_LIST
|
||||
// [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
|
||||
|
|
|
@ -9,191 +9,16 @@ namespace aria2 {
|
|||
class Bencode2Test:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(Bencode2Test);
|
||||
CPPUNIT_TEST(testDecode);
|
||||
CPPUNIT_TEST(testDecode_overflow);
|
||||
CPPUNIT_TEST(testEncode);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
public:
|
||||
void testDecode();
|
||||
void testDecode_overflow();
|
||||
void testEncode();
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( Bencode2Test );
|
||||
|
||||
void Bencode2Test::testDecode()
|
||||
{
|
||||
{
|
||||
// string, integer and list in dict
|
||||
std::string src = "d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee";
|
||||
SharedHandle<ValueBase> r = bencode2::decode(src.begin(), src.end());
|
||||
const Dict* dict = downcast<Dict>(r);
|
||||
CPPUNIT_ASSERT(dict);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"),
|
||||
downcast<String>(dict->get("name"))->s());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<Integer::ValueType>(12345678900LL),
|
||||
downcast<Integer>(dict->get("size"))->i());
|
||||
const List* list = downcast<List>(dict->get("files"));
|
||||
CPPUNIT_ASSERT(list);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), list->size());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("bin"),
|
||||
downcast<String>(list->get(0))->s());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("doc"),
|
||||
downcast<String>(list->get(1))->s());
|
||||
}
|
||||
{
|
||||
// dict in list
|
||||
std::string src = "ld1:ki123eee";
|
||||
SharedHandle<ValueBase> r = bencode2::decode(src.begin(), src.end());
|
||||
const List* list = downcast<List>(r);
|
||||
CPPUNIT_ASSERT(list);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), list->size());
|
||||
const Dict* dict = downcast<Dict>(list->get(0));
|
||||
CPPUNIT_ASSERT(dict);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<Integer::ValueType>(123),
|
||||
downcast<Integer>(dict->get("k"))->i());
|
||||
}
|
||||
{
|
||||
// empty key is allowed
|
||||
std::string src = "d0:1:ve";
|
||||
SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end());
|
||||
}
|
||||
{
|
||||
// empty string
|
||||
std::string src = "0:";
|
||||
SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string(""), downcast<String>(s)->s());
|
||||
}
|
||||
{
|
||||
// empty dict
|
||||
std::string src = "de";
|
||||
SharedHandle<ValueBase> d = bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_ASSERT(downcast<Dict>(d)->empty());
|
||||
}
|
||||
{
|
||||
// empty list
|
||||
std::string src = "le";
|
||||
SharedHandle<ValueBase> l = bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_ASSERT(downcast<List>(l)->empty());
|
||||
}
|
||||
{
|
||||
// integer, without ending 'e'
|
||||
std::string src = "i3";
|
||||
try {
|
||||
bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
|
||||
" Integer expected but none found"),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// dict, without ending 'e'
|
||||
std::string src = "d";
|
||||
try {
|
||||
bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
|
||||
" Unexpected EOF in dict context."
|
||||
" 'e' expected."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// list, without ending 'e'
|
||||
try {
|
||||
std::string src = "l";
|
||||
bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
|
||||
" Unexpected EOF in list context."
|
||||
" 'e' expected."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// string, less than the specified length.
|
||||
try {
|
||||
std::string src = "3:ab";
|
||||
bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
|
||||
" Expected 3 bytes of data,"
|
||||
" but only 2 read."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// string, but length is invalid
|
||||
try {
|
||||
std::string src = "x:abc";
|
||||
bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
|
||||
" A positive integer expected"
|
||||
" but none found."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// string with minus length
|
||||
std::string src = "-1:a";
|
||||
try {
|
||||
bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
|
||||
" A positive integer expected"
|
||||
" but none found."),
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
{
|
||||
// empty encoded data
|
||||
std::string src = "";
|
||||
CPPUNIT_ASSERT(!bencode2::decode(src.begin(), src.end()));
|
||||
}
|
||||
{
|
||||
// ignore trailing garbage at the end of the input.
|
||||
std::string src = "5:aria2trail";
|
||||
SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), downcast<String>(s)->s());
|
||||
}
|
||||
{
|
||||
// Get trailing garbage position
|
||||
std::string src = "5:aria2trail";
|
||||
size_t end;
|
||||
SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end(), end);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("aria2"), downcast<String>(s)->s());
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)7, end);
|
||||
}
|
||||
}
|
||||
|
||||
void Bencode2Test::testDecode_overflow()
|
||||
{
|
||||
std::string s;
|
||||
size_t depth = bencode2::MAX_STRUCTURE_DEPTH+1;
|
||||
for(size_t i = 0; i < depth; ++i) {
|
||||
s += "l";
|
||||
}
|
||||
for(size_t i = 0; i < depth; ++i) {
|
||||
s += "e";
|
||||
}
|
||||
try {
|
||||
bencode2::decode(s.begin(), s.end());
|
||||
CPPUNIT_FAIL("exception must be thrown.");
|
||||
} catch(RecoverableException& e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
|
||||
void Bencode2Test::testEncode()
|
||||
{
|
||||
{
|
||||
|
|
|
@ -746,8 +746,7 @@ void BittorrentHelperTest::testMetadata() {
|
|||
SharedHandle<DownloadContext> dctx(new DownloadContext());
|
||||
load(A2_TEST_DIR"/test.torrent", dctx, option_);
|
||||
std::string torrentData = readFile(A2_TEST_DIR"/test.torrent");
|
||||
SharedHandle<ValueBase> tr =
|
||||
bencode2::decode(torrentData.begin(), torrentData.end());
|
||||
SharedHandle<ValueBase> tr = bencode2::decode(torrentData);
|
||||
SharedHandle<ValueBase> infoDic = downcast<Dict>(tr)->get("info");
|
||||
std::string metadata = bencode2::encode(infoDic);
|
||||
SharedHandle<TorrentAttribute> attrs = getTorrentAttrs(dctx);
|
||||
|
@ -831,8 +830,7 @@ void BittorrentHelperTest::testExtractPeerFromString()
|
|||
std::string hextext = "100210354527354678541237324732171ae1";
|
||||
hextext += "20010db8bd0501d2288a1fc0000110ee1ae2";
|
||||
std::string peersstr = "36:"+fromHex(hextext);
|
||||
SharedHandle<ValueBase> str =
|
||||
bencode2::decode(peersstr.begin(), peersstr.end());
|
||||
SharedHandle<ValueBase> str = bencode2::decode(peersstr);
|
||||
std::deque<SharedHandle<Peer> > peers;
|
||||
extractPeer(str, AF_INET6, std::back_inserter(peers));
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
|
||||
|
@ -846,14 +844,14 @@ void BittorrentHelperTest::testExtractPeerFromString()
|
|||
hextext = "c0a800011ae1";
|
||||
hextext += "c0a800021ae2";
|
||||
peersstr = "12:"+fromHex(hextext);
|
||||
str = bencode2::decode(peersstr.begin(), peersstr.end());
|
||||
str = bencode2::decode(peersstr);
|
||||
peers.clear();
|
||||
extractPeer(str, AF_INET, std::back_inserter(peers));
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peers[0]->getIPAddress());
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peers[0]->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peers[1]->getIPAddress());
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6882, peers[1]->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6882, peers[1]->getPort());
|
||||
}
|
||||
|
||||
void BittorrentHelperTest::testExtractPeerFromList()
|
||||
|
@ -862,9 +860,8 @@ void BittorrentHelperTest::testExtractPeerFromList()
|
|||
"d5:peersld2:ip11:192.168.0.17:peer id20:aria2-00000000000000"
|
||||
"4:porti2006eeee";
|
||||
|
||||
SharedHandle<ValueBase> dict =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
|
||||
SharedHandle<ValueBase> dict = bencode2::decode(peersString);
|
||||
|
||||
std::deque<SharedHandle<Peer> > peers;
|
||||
extractPeer(downcast<Dict>(dict)->get("peers"), AF_INET, std::back_inserter(peers));
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size());
|
||||
|
@ -880,8 +877,7 @@ void BittorrentHelperTest::testExtract2PeersFromList()
|
|||
"4:porti65535eed2:ip11:192.168.0.27:peer id20:aria2-00000000000000"
|
||||
"4:porti2007eeee";
|
||||
|
||||
SharedHandle<ValueBase> dict =
|
||||
bencode2::decode(peersString.begin(), peersString.end());
|
||||
SharedHandle<ValueBase> dict = bencode2::decode(peersString);
|
||||
|
||||
std::deque<SharedHandle<Peer> > peers;
|
||||
extractPeer(downcast<Dict>(dict)->get("peers"), AF_INET, std::back_inserter(peers));
|
||||
|
|
Loading…
Reference in New Issue