diff --git a/src/base/bittorrent/torrentinfo.cpp b/src/base/bittorrent/torrentinfo.cpp index 6441c5a0e..6a63eb78a 100644 --- a/src/base/bittorrent/torrentinfo.cpp +++ b/src/base/bittorrent/torrentinfo.cpp @@ -246,6 +246,21 @@ QVector TorrentInfo::fileIndicesForPiece(int pieceIndex) const return res; } +QVector TorrentInfo::pieceHashes() const +{ + if (!isValid()) + return {}; + + const int count = piecesCount(); + QVector hashes; + hashes.reserve(count); + + for (int i = 0; i < count; ++i) + hashes += { m_nativeInfo->hash_for_piece_ptr(i), libtorrent::sha1_hash::size }; + + return hashes; +} + TorrentInfo::PieceRange TorrentInfo::filePieces(const QString& file) const { if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct diff --git a/src/base/bittorrent/torrentinfo.h b/src/base/bittorrent/torrentinfo.h index 8f918087b..87f92266a 100644 --- a/src/base/bittorrent/torrentinfo.h +++ b/src/base/bittorrent/torrentinfo.h @@ -91,6 +91,7 @@ namespace BitTorrent QByteArray metadata() const; QStringList filesForPiece(int pieceIndex) const; QVector fileIndicesForPiece(int pieceIndex) const; + QVector pieceHashes() const; using PieceRange = IndexRange; // returns pair of the first and the last pieces into which diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index 404279e39..869221cf7 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -654,6 +654,59 @@ QByteArray btjson::getFilesForTorrent(const QString& hash) return json::toJson(fileList); } +/** + * Returns an array of hashes (of each pieces respectively) for a torrent in JSON format. + * + * The return value is a JSON-formatted array of strings (hex strings). + */ +QByteArray btjson::getPieceHashesForTorrent(const QString &hash) +{ + CACHED_VARIABLE_FOR_HASH(QVariantList, pieceHashes, CACHE_DURATION_MS, hash); + BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash); + if (!torrent) { + qWarning() << Q_FUNC_INFO << "Invalid torrent " << qPrintable(hash); + return QByteArray(); + } + + const QVector hashes = torrent->info().pieceHashes(); + pieceHashes.reserve(hashes.size()); + foreach (const QByteArray &hash, hashes) + pieceHashes.append(hash.toHex()); + + return json::toJson(pieceHashes); +} + +/** + * Returns an array of states (of each pieces respectively) for a torrent in JSON format. + * + * The return value is a JSON-formatted array of ints. + * 0: piece not downloaded + * 1: piece requested or downloading + * 2: piece already downloaded + */ +QByteArray btjson::getPieceStatesForTorrent(const QString &hash) +{ + CACHED_VARIABLE_FOR_HASH(QVariantList, pieceStates, CACHE_DURATION_MS, hash); + BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash); + if (!torrent) { + qWarning() << Q_FUNC_INFO << "Invalid torrent " << qPrintable(hash); + return QByteArray(); + } + + const QBitArray states = torrent->pieces(); + pieceStates.reserve(states.size()); + for (int i = 0; i < states.size(); ++i) + pieceStates.append(static_cast(states[i]) * 2); + + const QBitArray dlstates = torrent->downloadingPieces(); + for (int i = 0; i < states.size(); ++i) { + if (dlstates[i]) + pieceStates[i] = 1; + } + + return json::toJson(pieceStates); +} + /** * Returns the global transfer information in JSON format. * diff --git a/src/webui/btjson.h b/src/webui/btjson.h index 42c0d379d..914fb1aca 100644 --- a/src/webui/btjson.h +++ b/src/webui/btjson.h @@ -51,6 +51,8 @@ public: static QByteArray getWebSeedsForTorrent(const QString& hash); static QByteArray getPropertiesForTorrent(const QString& hash); static QByteArray getFilesForTorrent(const QString& hash); + static QByteArray getPieceHashesForTorrent(const QString &hash); + static QByteArray getPieceStatesForTorrent(const QString &hash); static QByteArray getTransferInfo(); static QByteArray getTorrentsRatesLimits(QStringList& hashes, bool downloadLimits); static QByteArray getLog(bool normal, bool info, bool warning, bool critical, int lastKnownId); diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index 5d2b28c96..0f8352c5e 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -49,7 +49,7 @@ #include "websessiondata.h" #include "webapplication.h" -static const int API_VERSION = 13; +static const int API_VERSION = 14; static const int API_VERSION_MIN = 13; const QString WWW_FOLDER = ":/www/public/"; @@ -83,6 +83,8 @@ QMap > WebApplication::initialize ADD_ACTION(query, propertiesFiles); ADD_ACTION(query, getLog); ADD_ACTION(query, getPeerLog); + ADD_ACTION(query, getPieceHashes); + ADD_ACTION(query, getPieceStates); ADD_ACTION(sync, maindata); ADD_ACTION(sync, torrent_peers); ADD_ACTION(command, shutdown); @@ -310,6 +312,18 @@ void WebApplication::action_query_getPeerLog() print(btjson::getPeerLog(lastKnownId), Http::CONTENT_TYPE_JSON); } +void WebApplication::action_query_getPieceHashes() +{ + CHECK_URI(1); + print(btjson::getPieceHashesForTorrent(args_.front()), Http::CONTENT_TYPE_JSON); +} + +void WebApplication::action_query_getPieceStates() +{ + CHECK_URI(1); + print(btjson::getPieceStatesForTorrent(args_.front()), Http::CONTENT_TYPE_JSON); +} + // GET param: // - rid (int): last response id void WebApplication::action_sync_maindata() diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index ff482590b..126cfa204 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -56,6 +56,8 @@ private: void action_query_propertiesFiles(); void action_query_getLog(); void action_query_getPeerLog(); + void action_query_getPieceHashes(); + void action_query_getPieceStates(); void action_sync_maindata(); void action_sync_torrent_peers(); void action_command_shutdown();