| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886 |
- /* <!-- copyright */
- /*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2013 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you
- * do not wish to do so, delete this exception statement from your
- * version. If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
- /* copyright --> */
- #include "aria2api.h"
- #include <functional>
- #include "Platform.h"
- #include "Context.h"
- #include "DownloadEngine.h"
- #include "OptionParser.h"
- #include "Option.h"
- #include "DlAbortEx.h"
- #include "fmt.h"
- #include "OptionHandler.h"
- #include "RequestGroupMan.h"
- #include "RequestGroup.h"
- #include "MultiUrlRequestInfo.h"
- #include "prefs.h"
- #include "download_helper.h"
- #include "LogFactory.h"
- #include "PieceStorage.h"
- #include "DownloadContext.h"
- #include "FileEntry.h"
- #include "BitfieldMan.h"
- #include "DownloadContext.h"
- #include "RpcMethodImpl.h"
- #include "console.h"
- #include "KeepRunningCommand.h"
- #include "A2STR.h"
- #include "SingletonHolder.h"
- #include "Notifier.h"
- #include "ApiCallbackDownloadEventListener.h"
- #ifdef ENABLE_BITTORRENT
- #include "bittorrent_helper.h"
- #endif // ENABLE_BITTORRENT
- namespace aria2 {
- Session::Session(const KeyVals& options)
- : context(std::make_shared<Context>(false, 0, nullptr, options))
- {
- }
- Session::~Session() = default;
- SessionConfig::SessionConfig()
- : keepRunning(false),
- useSignalHandler(true),
- downloadEventCallback(nullptr),
- userData(nullptr)
- {
- }
- namespace {
- Platform* platform = nullptr;
- } // namespace
- int libraryInit()
- {
- global::initConsole(true);
- try {
- platform = new Platform();
- }
- catch (RecoverableException& e) {
- A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e);
- return -1;
- }
- LogFactory::setConsoleOutput(false);
- return 0;
- }
- int libraryDeinit()
- {
- delete platform;
- return 0;
- }
- Session* sessionNew(const KeyVals& options, const SessionConfig& config)
- {
- int rv;
- std::unique_ptr<Session> session;
- try {
- session = make_unique<Session>(options);
- }
- catch (RecoverableException& e) {
- return nullptr;
- }
- if (session->context->reqinfo) {
- if (!config.useSignalHandler) {
- session->context->reqinfo->setUseSignalHandler(false);
- }
- rv = session->context->reqinfo->prepare();
- if (rv != 0) {
- return nullptr;
- }
- auto& e = session->context->reqinfo->getDownloadEngine();
- if (config.keepRunning) {
- e->getRequestGroupMan()->setKeepRunning(true);
- // Add command to make aria2 keep event polling
- e->addCommand(make_unique<KeepRunningCommand>(e->newCUID(), e.get()));
- }
- if (config.downloadEventCallback) {
- session->listener = make_unique<ApiCallbackDownloadEventListener>(
- session.get(), config.downloadEventCallback, config.userData);
- SingletonHolder<Notifier>::instance()->addDownloadEventListener(
- session->listener.get());
- }
- }
- else {
- return nullptr;
- }
- return session.release();
- }
- int sessionFinal(Session* session)
- {
- error_code::Value rv = session->context->reqinfo->getResult();
- delete session;
- return rv;
- }
- int run(Session* session, RUN_MODE mode)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- return e->run(mode == RUN_ONCE);
- }
- int shutdown(Session* session, bool force)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- if (force) {
- e->requestForceHalt();
- }
- else {
- e->requestHalt();
- }
- // Skip next polling timeout. This avoids 1 second delay when there
- // is no Command other than KeepRunningCommand in the queue.
- e->setNoWait(true);
- return 0;
- }
- std::string gidToHex(A2Gid gid) { return GroupId::toHex(gid); }
- A2Gid hexToGid(const std::string& hex)
- {
- A2Gid gid;
- if (GroupId::toNumericId(gid, hex.c_str()) == 0) {
- return gid;
- }
- else {
- return 0;
- }
- }
- bool isNull(A2Gid gid) { return gid == 0; }
- namespace {
- template <typename InputIterator, typename Pred>
- void apiGatherOption(InputIterator first, InputIterator last, Pred pred,
- Option* option,
- const std::shared_ptr<OptionParser>& optionParser)
- {
- for (; first != last; ++first) {
- const std::string& optionName = (*first).first;
- PrefPtr pref = option::k2p(optionName);
- const OptionHandler* handler = optionParser->find(pref);
- if (!handler || !pred(handler)) {
- // Just ignore the unacceptable options in this context.
- continue;
- }
- handler->parse(*option, (*first).second);
- }
- }
- } // namespace
- namespace {
- void apiGatherRequestOption(Option* option, const KeyVals& options,
- const std::shared_ptr<OptionParser>& optionParser)
- {
- apiGatherOption(options.begin(), options.end(),
- std::mem_fn(&OptionHandler::getInitialOption), option,
- optionParser);
- }
- } // namespace
- namespace {
- void apiGatherChangeableOption(
- Option* option, const KeyVals& options,
- const std::shared_ptr<OptionParser>& optionParser)
- {
- apiGatherOption(options.begin(), options.end(),
- std::mem_fn(&OptionHandler::getChangeOption), option,
- optionParser);
- }
- } // namespace
- namespace {
- void apiGatherChangeableOptionForReserved(
- Option* option, const KeyVals& options,
- const std::shared_ptr<OptionParser>& optionParser)
- {
- apiGatherOption(options.begin(), options.end(),
- std::mem_fn(&OptionHandler::getChangeOptionForReserved),
- option, optionParser);
- }
- } // namespace
- namespace {
- void apiGatherChangeableGlobalOption(
- Option* option, const KeyVals& options,
- const std::shared_ptr<OptionParser>& optionParser)
- {
- apiGatherOption(options.begin(), options.end(),
- std::mem_fn(&OptionHandler::getChangeGlobalOption), option,
- optionParser);
- }
- } // namespace
- namespace {
- void addRequestGroup(const std::shared_ptr<RequestGroup>& group,
- DownloadEngine* e, int position)
- {
- if (position >= 0) {
- e->getRequestGroupMan()->insertReservedGroup(position, group);
- }
- else {
- e->getRequestGroupMan()->addReservedGroup(group);
- }
- }
- } // namespace
- int addUri(Session* session, A2Gid* gid, const std::vector<std::string>& uris,
- const KeyVals& options, int position)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- auto requestOption = std::make_shared<Option>(*e->getOption());
- try {
- apiGatherRequestOption(requestOption.get(), options,
- OptionParser::getInstance());
- }
- catch (RecoverableException& e) {
- A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, e);
- return -1;
- }
- std::vector<std::shared_ptr<RequestGroup>> result;
- createRequestGroupForUri(result, requestOption, uris,
- /* ignoreForceSeq = */ true,
- /* ignoreLocalPath = */ true);
- if (!result.empty()) {
- addRequestGroup(result.front(), e.get(), position);
- if (gid) {
- *gid = result.front()->getGID();
- }
- }
- return 0;
- }
- int addMetalink(Session* session, std::vector<A2Gid>* gids,
- const std::string& metalinkFile, const KeyVals& options,
- int position)
- {
- #ifdef ENABLE_METALINK
- auto& e = session->context->reqinfo->getDownloadEngine();
- auto requestOption = std::make_shared<Option>(*e->getOption());
- std::vector<std::shared_ptr<RequestGroup>> result;
- try {
- apiGatherRequestOption(requestOption.get(), options,
- OptionParser::getInstance());
- requestOption->put(PREF_METALINK_FILE, metalinkFile);
- createRequestGroupForMetalink(result, requestOption);
- }
- catch (RecoverableException& e) {
- A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, e);
- return -1;
- }
- if (!result.empty()) {
- if (position >= 0) {
- e->getRequestGroupMan()->insertReservedGroup(position, result);
- }
- else {
- e->getRequestGroupMan()->addReservedGroup(result);
- }
- if (gids) {
- for (std::vector<std::shared_ptr<RequestGroup>>::const_iterator
- i = result.begin(),
- eoi = result.end();
- i != eoi; ++i) {
- (*gids).push_back((*i)->getGID());
- }
- }
- }
- return 0;
- #else // !ENABLE_METALINK
- return -1;
- #endif // !ENABLE_METALINK
- }
- int addTorrent(Session* session, A2Gid* gid, const std::string& torrentFile,
- const std::vector<std::string>& webSeedUris,
- const KeyVals& options, int position)
- {
- #ifdef ENABLE_BITTORRENT
- auto& e = session->context->reqinfo->getDownloadEngine();
- auto requestOption = std::make_shared<Option>(*e->getOption());
- std::vector<std::shared_ptr<RequestGroup>> result;
- try {
- apiGatherRequestOption(requestOption.get(), options,
- OptionParser::getInstance());
- requestOption->put(PREF_TORRENT_FILE, torrentFile);
- createRequestGroupForBitTorrent(result, requestOption, webSeedUris,
- torrentFile);
- }
- catch (RecoverableException& e) {
- A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, e);
- return -1;
- }
- if (!result.empty()) {
- addRequestGroup(result.front(), e.get(), position);
- if (gid) {
- *gid = result.front()->getGID();
- }
- }
- return 0;
- #else // !ENABLE_BITTORRENT
- return -1;
- #endif // !ENABLE_BITTORRENT
- }
- int addTorrent(Session* session, A2Gid* gid, const std::string& torrentFile,
- const KeyVals& options, int position)
- {
- return addTorrent(session, gid, torrentFile, std::vector<std::string>(),
- options, position);
- }
- int removeDownload(Session* session, A2Gid gid, bool force)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<RequestGroup> group = e->getRequestGroupMan()->findGroup(gid);
- if (group) {
- if (group->getState() == RequestGroup::STATE_ACTIVE) {
- if (force) {
- group->setForceHaltRequested(true, RequestGroup::USER_REQUEST);
- }
- else {
- group->setHaltRequested(true, RequestGroup::USER_REQUEST);
- }
- e->setRefreshInterval(std::chrono::milliseconds(0));
- }
- else {
- if (group->isDependencyResolved()) {
- e->getRequestGroupMan()->removeReservedGroup(gid);
- }
- else {
- return -1;
- }
- }
- }
- else {
- return -1;
- }
- return 0;
- }
- int pauseDownload(Session* session, A2Gid gid, bool force)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<RequestGroup> group = e->getRequestGroupMan()->findGroup(gid);
- if (group) {
- bool reserved = group->getState() == RequestGroup::STATE_WAITING;
- if (pauseRequestGroup(group, reserved, force)) {
- e->setRefreshInterval(std::chrono::milliseconds(0));
- return 0;
- }
- }
- return -1;
- }
- int unpauseDownload(Session* session, A2Gid gid)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<RequestGroup> group = e->getRequestGroupMan()->findGroup(gid);
- if (!group || group->getState() != RequestGroup::STATE_WAITING ||
- !group->isPauseRequested()) {
- return -1;
- }
- else {
- group->setPauseRequested(false);
- e->getRequestGroupMan()->requestQueueCheck();
- }
- return 0;
- }
- int changePosition(Session* session, A2Gid gid, int pos, OffsetMode how)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- try {
- return e->getRequestGroupMan()->changeReservedGroupPosition(gid, pos, how);
- }
- catch (RecoverableException& e) {
- A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, e);
- return -1;
- }
- }
- int changeOption(Session* session, A2Gid gid, const KeyVals& options)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<RequestGroup> group = e->getRequestGroupMan()->findGroup(gid);
- if (group) {
- Option option;
- try {
- if (group->getState() == RequestGroup::STATE_ACTIVE) {
- apiGatherChangeableOption(&option, options,
- OptionParser::getInstance());
- }
- else {
- apiGatherChangeableOptionForReserved(&option, options,
- OptionParser::getInstance());
- }
- }
- catch (RecoverableException& err) {
- A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, err);
- return -1;
- }
- changeOption(group, option, e.get());
- return 0;
- }
- else {
- return -1;
- }
- }
- const std::string& getGlobalOption(Session* session, const std::string& name)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- PrefPtr pref = option::k2p(name);
- if (OptionParser::getInstance()->find(pref)) {
- return e->getOption()->get(pref);
- }
- else {
- return A2STR::NIL;
- }
- }
- KeyVals getGlobalOptions(Session* session)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- const std::shared_ptr<OptionParser>& optionParser =
- OptionParser::getInstance();
- const Option* option = e->getOption();
- KeyVals options;
- for (size_t i = 1, len = option::countOption(); i < len; ++i) {
- PrefPtr pref = option::i2p(i);
- if (option->defined(pref) && optionParser->find(pref)) {
- options.push_back(KeyVals::value_type(pref->k, option->get(pref)));
- }
- }
- return options;
- }
- int changeGlobalOption(Session* session, const KeyVals& options)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- Option option;
- try {
- apiGatherChangeableGlobalOption(&option, options,
- OptionParser::getInstance());
- }
- catch (RecoverableException& err) {
- A2_LOG_INFO_EX(EX_EXCEPTION_CAUGHT, err);
- return -1;
- }
- changeGlobalOption(option, e.get());
- return 0;
- }
- GlobalStat getGlobalStat(Session* session)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- auto& rgman = e->getRequestGroupMan();
- TransferStat ts = rgman->calculateStat();
- GlobalStat res;
- res.downloadSpeed = ts.downloadSpeed;
- res.uploadSpeed = ts.uploadSpeed;
- res.numActive = rgman->getRequestGroups().size();
- res.numWaiting = rgman->getReservedGroups().size();
- res.numStopped = rgman->getDownloadResults().size();
- return res;
- }
- std::vector<A2Gid> getActiveDownload(Session* session)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- const RequestGroupList& groups = e->getRequestGroupMan()->getRequestGroups();
- std::vector<A2Gid> res;
- for (const auto& group : groups) {
- res.push_back(group->getGID());
- }
- return res;
- }
- namespace {
- template <typename OutputIterator, typename InputIterator>
- void createUriEntry(OutputIterator out, InputIterator first, InputIterator last,
- UriStatus status)
- {
- for (; first != last; ++first) {
- UriData uriData;
- uriData.uri = *first;
- uriData.status = status;
- out++ = uriData;
- }
- }
- } // namespace
- namespace {
- template <typename OutputIterator>
- void createUriEntry(OutputIterator out, const std::shared_ptr<FileEntry>& file)
- {
- createUriEntry(out, file->getSpentUris().begin(), file->getSpentUris().end(),
- URI_USED);
- createUriEntry(out, file->getRemainingUris().begin(),
- file->getRemainingUris().end(), URI_WAITING);
- }
- } // namespace
- namespace {
- FileData createFileData(const std::shared_ptr<FileEntry>& fe, int index,
- const BitfieldMan* bf)
- {
- FileData file;
- file.index = index;
- file.path = fe->getPath();
- file.length = fe->getLength();
- file.completedLength =
- bf->getOffsetCompletedLength(fe->getOffset(), fe->getLength());
- file.selected = fe->isRequested();
- createUriEntry(std::back_inserter(file.uris), fe);
- return file;
- }
- } // namespace
- namespace {
- template <typename OutputIterator, typename InputIterator>
- void createFileEntry(OutputIterator out, InputIterator first,
- InputIterator last, const BitfieldMan* bf)
- {
- size_t index = 1;
- for (; first != last; ++first) {
- out++ = createFileData(*first, index++, bf);
- }
- }
- } // namespace
- namespace {
- template <typename OutputIterator, typename InputIterator>
- void createFileEntry(OutputIterator out, InputIterator first,
- InputIterator last, int64_t totalLength,
- int32_t pieceLength, const std::string& bitfield)
- {
- BitfieldMan bf(pieceLength, totalLength);
- bf.setBitfield(reinterpret_cast<const unsigned char*>(bitfield.data()),
- bitfield.size());
- createFileEntry(out, first, last, &bf);
- }
- } // namespace
- namespace {
- template <typename OutputIterator, typename InputIterator>
- void createFileEntry(OutputIterator out, InputIterator first,
- InputIterator last, int64_t totalLength,
- int32_t pieceLength,
- const std::shared_ptr<PieceStorage>& ps)
- {
- BitfieldMan bf(pieceLength, totalLength);
- if (ps) {
- bf.setBitfield(ps->getBitfield(), ps->getBitfieldLength());
- }
- createFileEntry(out, first, last, &bf);
- }
- } // namespace
- namespace {
- template <typename OutputIterator>
- void pushRequestOption(OutputIterator out,
- const std::shared_ptr<Option>& option,
- const std::shared_ptr<OptionParser>& oparser)
- {
- for (size_t i = 1, len = option::countOption(); i < len; ++i) {
- PrefPtr pref = option::i2p(i);
- const OptionHandler* h = oparser->find(pref);
- if (h && h->getInitialOption() && option->defined(pref)) {
- out++ = KeyVals::value_type(pref->k, option->get(pref));
- }
- }
- }
- } // namespace
- namespace {
- const std::string& getRequestOption(const std::shared_ptr<Option>& option,
- const std::string& name)
- {
- PrefPtr pref = option::k2p(name);
- if (OptionParser::getInstance()->find(pref)) {
- return option->get(pref);
- }
- else {
- return A2STR::NIL;
- }
- }
- } // namespace
- namespace {
- KeyVals getRequestOptions(const std::shared_ptr<Option>& option)
- {
- KeyVals res;
- pushRequestOption(std::back_inserter(res), option,
- OptionParser::getInstance());
- return res;
- }
- } // namespace
- namespace {
- struct RequestGroupDH : public DownloadHandle {
- RequestGroupDH(const std::shared_ptr<RequestGroup>& group)
- : group(group), ts(group->calculateStat())
- {
- }
- virtual ~RequestGroupDH() = default;
- virtual DownloadStatus getStatus() CXX11_OVERRIDE
- {
- if (group->getState() == RequestGroup::STATE_ACTIVE) {
- return DOWNLOAD_ACTIVE;
- }
- else {
- if (group->isPauseRequested()) {
- return DOWNLOAD_PAUSED;
- }
- else {
- return DOWNLOAD_WAITING;
- }
- }
- }
- virtual int64_t getTotalLength() CXX11_OVERRIDE
- {
- return group->getTotalLength();
- }
- virtual int64_t getCompletedLength() CXX11_OVERRIDE
- {
- return group->getCompletedLength();
- }
- virtual int64_t getUploadLength() CXX11_OVERRIDE
- {
- return ts.allTimeUploadLength;
- }
- virtual std::string getBitfield() CXX11_OVERRIDE
- {
- const std::shared_ptr<PieceStorage>& ps = group->getPieceStorage();
- if (ps) {
- return std::string(reinterpret_cast<const char*>(ps->getBitfield()),
- ps->getBitfieldLength());
- }
- else {
- return "";
- }
- }
- virtual int getDownloadSpeed() CXX11_OVERRIDE { return ts.downloadSpeed; }
- virtual int getUploadSpeed() CXX11_OVERRIDE { return ts.uploadSpeed; }
- virtual const std::string& getInfoHash() CXX11_OVERRIDE
- {
- #ifdef ENABLE_BITTORRENT
- if (group->getDownloadContext()->hasAttribute(CTX_ATTR_BT)) {
- return bittorrent::getTorrentAttrs(group->getDownloadContext())->infoHash;
- }
- #endif // ENABLE_BITTORRENT
- return A2STR::NIL;
- }
- virtual size_t getPieceLength() CXX11_OVERRIDE
- {
- const std::shared_ptr<DownloadContext>& dctx = group->getDownloadContext();
- return dctx->getPieceLength();
- }
- virtual int getNumPieces() CXX11_OVERRIDE
- {
- return group->getDownloadContext()->getNumPieces();
- }
- virtual int getConnections() CXX11_OVERRIDE
- {
- return group->getNumConnection();
- }
- virtual int getErrorCode() CXX11_OVERRIDE { return 0; }
- virtual const std::vector<A2Gid>& getFollowedBy() CXX11_OVERRIDE
- {
- return group->followedBy();
- }
- virtual A2Gid getFollowing() CXX11_OVERRIDE { return group->following(); }
- virtual A2Gid getBelongsTo() CXX11_OVERRIDE { return group->belongsTo(); }
- virtual const std::string& getDir() CXX11_OVERRIDE
- {
- return group->getOption()->get(PREF_DIR);
- }
- virtual std::vector<FileData> getFiles() CXX11_OVERRIDE
- {
- std::vector<FileData> res;
- const std::shared_ptr<DownloadContext>& dctx = group->getDownloadContext();
- createFileEntry(std::back_inserter(res), dctx->getFileEntries().begin(),
- dctx->getFileEntries().end(), dctx->getTotalLength(),
- dctx->getPieceLength(), group->getPieceStorage());
- return res;
- }
- virtual int getNumFiles() CXX11_OVERRIDE
- {
- const std::shared_ptr<DownloadContext>& dctx = group->getDownloadContext();
- return dctx->getFileEntries().size();
- }
- virtual FileData getFile(int index) CXX11_OVERRIDE
- {
- const std::shared_ptr<DownloadContext>& dctx = group->getDownloadContext();
- BitfieldMan bf(dctx->getPieceLength(), dctx->getTotalLength());
- const std::shared_ptr<PieceStorage>& ps = group->getPieceStorage();
- if (ps) {
- bf.setBitfield(ps->getBitfield(), ps->getBitfieldLength());
- }
- return createFileData(dctx->getFileEntries()[index - 1], index, &bf);
- }
- virtual BtMetaInfoData getBtMetaInfo() CXX11_OVERRIDE
- {
- BtMetaInfoData res;
- #ifdef ENABLE_BITTORRENT
- if (group->getDownloadContext()->hasAttribute(CTX_ATTR_BT)) {
- auto torrentAttrs =
- bittorrent::getTorrentAttrs(group->getDownloadContext());
- res.announceList = torrentAttrs->announceList;
- res.comment = torrentAttrs->comment;
- res.creationDate = torrentAttrs->creationDate;
- res.mode = torrentAttrs->mode;
- if (!torrentAttrs->metadata.empty()) {
- res.name = torrentAttrs->name;
- }
- }
- else
- #endif // ENABLE_BITTORRENT
- {
- res.creationDate = 0;
- res.mode = BT_FILE_MODE_NONE;
- }
- return res;
- }
- virtual const std::string& getOption(const std::string& name) CXX11_OVERRIDE
- {
- return getRequestOption(group->getOption(), name);
- }
- virtual KeyVals getOptions() CXX11_OVERRIDE
- {
- return getRequestOptions(group->getOption());
- }
- std::shared_ptr<RequestGroup> group;
- TransferStat ts;
- };
- } // namespace
- namespace {
- struct DownloadResultDH : public DownloadHandle {
- DownloadResultDH(std::shared_ptr<DownloadResult> dr) : dr(std::move(dr)) {}
- virtual ~DownloadResultDH() = default;
- virtual DownloadStatus getStatus() CXX11_OVERRIDE
- {
- switch (dr->result) {
- case error_code::FINISHED:
- return DOWNLOAD_COMPLETE;
- case error_code::REMOVED:
- return DOWNLOAD_REMOVED;
- default:
- return DOWNLOAD_ERROR;
- }
- }
- virtual int64_t getTotalLength() CXX11_OVERRIDE { return dr->totalLength; }
- virtual int64_t getCompletedLength() CXX11_OVERRIDE
- {
- return dr->completedLength;
- }
- virtual int64_t getUploadLength() CXX11_OVERRIDE { return dr->uploadLength; }
- virtual std::string getBitfield() CXX11_OVERRIDE { return dr->bitfield; }
- virtual int getDownloadSpeed() CXX11_OVERRIDE { return 0; }
- virtual int getUploadSpeed() CXX11_OVERRIDE { return 0; }
- virtual const std::string& getInfoHash() CXX11_OVERRIDE
- {
- return dr->infoHash;
- }
- virtual size_t getPieceLength() CXX11_OVERRIDE { return dr->pieceLength; }
- virtual int getNumPieces() CXX11_OVERRIDE { return dr->numPieces; }
- virtual int getConnections() CXX11_OVERRIDE { return 0; }
- virtual int getErrorCode() CXX11_OVERRIDE { return dr->result; }
- virtual const std::vector<A2Gid>& getFollowedBy() CXX11_OVERRIDE
- {
- return dr->followedBy;
- }
- virtual A2Gid getFollowing() CXX11_OVERRIDE { return dr->following; }
- virtual A2Gid getBelongsTo() CXX11_OVERRIDE { return dr->belongsTo; }
- virtual const std::string& getDir() CXX11_OVERRIDE { return dr->dir; }
- virtual std::vector<FileData> getFiles() CXX11_OVERRIDE
- {
- std::vector<FileData> res;
- createFileEntry(std::back_inserter(res), dr->fileEntries.begin(),
- dr->fileEntries.end(), dr->totalLength, dr->pieceLength,
- dr->bitfield);
- return res;
- }
- virtual int getNumFiles() CXX11_OVERRIDE { return dr->fileEntries.size(); }
- virtual FileData getFile(int index) CXX11_OVERRIDE
- {
- BitfieldMan bf(dr->pieceLength, dr->totalLength);
- bf.setBitfield(reinterpret_cast<const unsigned char*>(dr->bitfield.data()),
- dr->bitfield.size());
- return createFileData(dr->fileEntries[index - 1], index, &bf);
- }
- virtual BtMetaInfoData getBtMetaInfo() CXX11_OVERRIDE
- {
- return BtMetaInfoData();
- }
- virtual const std::string& getOption(const std::string& name) CXX11_OVERRIDE
- {
- return getRequestOption(dr->option, name);
- }
- virtual KeyVals getOptions() CXX11_OVERRIDE
- {
- return getRequestOptions(dr->option);
- }
- std::shared_ptr<DownloadResult> dr;
- };
- } // namespace
- DownloadHandle* getDownloadHandle(Session* session, A2Gid gid)
- {
- auto& e = session->context->reqinfo->getDownloadEngine();
- auto& rgman = e->getRequestGroupMan();
- std::shared_ptr<RequestGroup> group = rgman->findGroup(gid);
- if (group) {
- return new RequestGroupDH(group);
- }
- else {
- std::shared_ptr<DownloadResult> ds = rgman->findDownloadResult(gid);
- if (ds) {
- return new DownloadResultDH(ds);
- }
- }
- return nullptr;
- }
- void deleteDownloadHandle(DownloadHandle* dh) { delete dh; }
- } // namespace aria2
|