| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966 |
- /* <!-- 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(new Context(false, 0, 0, options))
- {}
- Session::~Session()
- {}
- SessionConfig::SessionConfig()
- : keepRunning(false),
- useSignalHandler(true),
- downloadEventCallback(0),
- userData(0)
- {}
- namespace {
- Platform* platform = 0;
- } // 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;
- Session* session;
- try {
- session = new Session(options);
- } catch(RecoverableException& e) {
- return 0;
- }
- if(session->context->reqinfo) {
- if(!config.useSignalHandler) {
- session->context->reqinfo->setUseSignalHandler(false);
- }
- rv = session->context->reqinfo->prepare();
- if(rv != 0) {
- delete session;
- return 0;
- }
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- if(config.keepRunning) {
- e->getRequestGroupMan()->setKeepRunning(true);
- // Add command to make aria2 keep event polling
- e->addCommand(new KeepRunningCommand(e->newCUID(), e.get()));
- }
- if(config.downloadEventCallback) {
- std::shared_ptr<DownloadEventListener> listener
- (new ApiCallbackDownloadEventListener(session,
- config.downloadEventCallback,
- config.userData));
- SingletonHolder<Notifier>::instance()
- ->addDownloadEventListener(listener);
- }
- } else {
- delete session;
- return 0;
- }
- return session;
- }
- int sessionFinal(Session* session)
- {
- error_code::Value rv = session->context->reqinfo->getResult();
- delete session;
- return rv;
- }
- int run(Session* session, RUN_MODE mode)
- {
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- return e->run(mode == RUN_ONCE);
- }
- int shutdown(Session* session, bool force)
- {
- const std::shared_ptr<DownloadEngine>& 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;
- const Pref* 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,
- const std::shared_ptr<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)
- {
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<Option> requestOption(new 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, 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
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<Option> requestOption(new 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
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- std::shared_ptr<Option> requestOption(new 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, 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)
- {
- const std::shared_ptr<DownloadEngine>& 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(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)
- {
- const std::shared_ptr<DownloadEngine>& 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(0);
- return 0;
- }
- }
- return -1;
- }
- int unpauseDownload(Session* session, A2Gid gid)
- {
- const std::shared_ptr<DownloadEngine>& 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)
- {
- const std::shared_ptr<DownloadEngine>& 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)
- {
- const std::shared_ptr<DownloadEngine>& 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)
- {
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- const Pref* pref = option::k2p(name);
- if(OptionParser::getInstance()->find(pref)) {
- return e->getOption()->get(pref);
- } else {
- return A2STR::NIL;
- }
- }
- KeyVals getGlobalOptions(Session* session)
- {
- const std::shared_ptr<DownloadEngine>& 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) {
- const Pref* 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)
- {
- const std::shared_ptr<DownloadEngine>& 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)
- {
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- const std::shared_ptr<RequestGroupMan>& 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)
- {
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- const RequestGroupList& groups = e->getRequestGroupMan()->getRequestGroups();
- std::vector<A2Gid> res;
- for(RequestGroupList::const_iterator i = groups.begin(),
- eoi = groups.end(); i != eoi; ++i) {
- res.push_back((*i)->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) {
- const Pref* 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)
- {
- const Pref* 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() {}
- virtual DownloadStatus getStatus()
- {
- if(group->getState() == RequestGroup::STATE_ACTIVE) {
- return DOWNLOAD_ACTIVE;
- } else {
- if(group->isPauseRequested()) {
- return DOWNLOAD_PAUSED;
- } else {
- return DOWNLOAD_WAITING;
- }
- }
- }
- virtual int64_t getTotalLength()
- {
- return group->getTotalLength();
- }
- virtual int64_t getCompletedLength()
- {
- return group->getCompletedLength();
- }
- virtual int64_t getUploadLength()
- {
- return ts.allTimeUploadLength;
- }
- virtual std::string getBitfield()
- {
- 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()
- {
- return ts.downloadSpeed;
- }
- virtual int getUploadSpeed()
- {
- return ts.uploadSpeed;
- }
- virtual const std::string& getInfoHash()
- {
- #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()
- {
- const std::shared_ptr<DownloadContext>& dctx = group->getDownloadContext();
- return dctx->getPieceLength();
- }
- virtual int getNumPieces()
- {
- return group->getDownloadContext()->getNumPieces();
- }
- virtual int getConnections()
- {
- return group->getNumConnection();
- }
- virtual int getErrorCode()
- {
- return 0;
- }
- virtual const std::vector<A2Gid>& getFollowedBy()
- {
- return group->followedBy();
- }
- virtual A2Gid getBelongsTo()
- {
- return group->belongsTo();
- }
- virtual const std::string& getDir()
- {
- return group->getOption()->get(PREF_DIR);
- }
- virtual std::vector<FileData> getFiles()
- {
- 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()
- {
- const std::shared_ptr<DownloadContext>& dctx = group->getDownloadContext();
- return dctx->getFileEntries().size();
- }
- virtual FileData getFile(int index)
- {
- 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()
- {
- 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)
- {
- return getRequestOption(group->getOption(), name);
- }
- virtual KeyVals getOptions()
- {
- return getRequestOptions(group->getOption());
- }
- std::shared_ptr<RequestGroup> group;
- TransferStat ts;
- };
- } // namespace
- namespace {
- struct DownloadResultDH : public DownloadHandle {
- DownloadResultDH(const std::shared_ptr<DownloadResult>& dr)
- : dr(dr)
- {}
- virtual ~DownloadResultDH() {}
- virtual DownloadStatus getStatus()
- {
- 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()
- {
- return dr->totalLength;
- }
- virtual int64_t getCompletedLength()
- {
- return dr->completedLength;
- }
- virtual int64_t getUploadLength()
- {
- return dr->uploadLength;
- }
- virtual std::string getBitfield()
- {
- return dr->bitfield;
- }
- virtual int getDownloadSpeed()
- {
- return 0;
- }
- virtual int getUploadSpeed()
- {
- return 0;
- }
- virtual const std::string& getInfoHash()
- {
- return dr->infoHash;
- }
- virtual size_t getPieceLength()
- {
- return dr->pieceLength;
- }
- virtual int getNumPieces()
- {
- return dr->numPieces;
- }
- virtual int getConnections()
- {
- return 0;
- }
- virtual int getErrorCode()
- {
- return dr->result;
- }
- virtual const std::vector<A2Gid>& getFollowedBy()
- {
- return dr->followedBy;
- }
- virtual A2Gid getBelongsTo()
- {
- return dr->belongsTo;
- }
- virtual const std::string& getDir()
- {
- return dr->dir;
- }
- virtual std::vector<FileData> getFiles()
- {
- 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()
- {
- return dr->fileEntries.size();
- }
- virtual FileData getFile(int index)
- {
- 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()
- {
- return BtMetaInfoData();
- }
- virtual const std::string& getOption(const std::string& name)
- {
- return getRequestOption(dr->option, name);
- }
- virtual KeyVals getOptions()
- {
- return getRequestOptions(dr->option);
- }
- std::shared_ptr<DownloadResult> dr;
- };
- } // namespace
- DownloadHandle* getDownloadHandle(Session* session, A2Gid gid)
- {
- const std::shared_ptr<DownloadEngine>& e =
- session->context->reqinfo->getDownloadEngine();
- const std::shared_ptr<RequestGroupMan>& 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 0;
- }
- void deleteDownloadHandle(DownloadHandle* dh)
- {
- delete dh;
- }
- } // namespace aria2
|