Browse Source

Implement sync/maindata request

adaptive-webui-19844
buinsky 10 years ago
parent
commit
383c0e1418
  1. 171
      src/webui/btjson.cpp
  2. 2
      src/webui/btjson.h
  3. 10
      src/webui/requesthandler.cpp
  4. 1
      src/webui/requesthandler.h
  5. 4
      src/webui/webapplication.h

171
src/webui/btjson.cpp

@ -101,6 +101,7 @@ static const char KEY_TORRENT_ETA[] = "eta";
static const char KEY_TORRENT_STATE[] = "state"; static const char KEY_TORRENT_STATE[] = "state";
static const char KEY_TORRENT_SEQUENTIAL_DOWNLOAD[] = "seq_dl"; static const char KEY_TORRENT_SEQUENTIAL_DOWNLOAD[] = "seq_dl";
static const char KEY_TORRENT_FIRST_LAST_PIECE_PRIO[] = "f_l_piece_prio"; static const char KEY_TORRENT_FIRST_LAST_PIECE_PRIO[] = "f_l_piece_prio";
static const char KEY_TORRENT_LABEL[] = "label";
// Tracker keys // Tracker keys
static const char KEY_TRACKER_URL[] = "url"; static const char KEY_TRACKER_URL[] = "url";
@ -147,6 +148,8 @@ static const char KEY_FULL_UPDATE[] = "full_update";
static const char KEY_RESPONSE_ID[] = "rid"; static const char KEY_RESPONSE_ID[] = "rid";
static const char KEY_SUFFIX_REMOVED[] = "_removed"; static const char KEY_SUFFIX_REMOVED[] = "_removed";
QVariantMap getTranserInfoMap();
QVariantMap toMap(const QTorrentHandle& h);
void processMap(QVariantMap prevData, QVariantMap data, QVariantMap &syncData); void processMap(QVariantMap prevData, QVariantMap data, QVariantMap &syncData);
void processHash(QVariantHash prevData, QVariantHash data, QVariantHash &syncData, QVariantList &removedItems); void processHash(QVariantHash prevData, QVariantHash data, QVariantHash &syncData, QVariantList &removedItems);
void processList(QVariantList prevData, QVariantList data, QVariantList &syncData, QVariantList &removedItems); void processList(QVariantList prevData, QVariantList data, QVariantList &syncData, QVariantList &removedItems);
@ -204,36 +207,6 @@ private:
#endif #endif
}; };
static QVariantMap toMap(const QTorrentHandle& h)
{
libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters);
QVariantMap ret;
ret[KEY_TORRENT_HASH] = h.hash();
ret[KEY_TORRENT_NAME] = h.name();
ret[KEY_TORRENT_SIZE] = static_cast<qlonglong>(status.total_wanted);
ret[KEY_TORRENT_PROGRESS] = h.progress(status);
ret[KEY_TORRENT_DLSPEED] = status.download_payload_rate;
ret[KEY_TORRENT_UPSPEED] = status.upload_payload_rate;
if (QBtSession::instance()->isQueueingEnabled() && h.queue_position(status) >= 0)
ret[KEY_TORRENT_PRIORITY] = h.queue_position(status);
else
ret[KEY_TORRENT_PRIORITY] = -1;
ret[KEY_TORRENT_SEEDS] = status.num_seeds;
ret[KEY_TORRENT_NUM_COMPLETE] = status.num_complete;
ret[KEY_TORRENT_LEECHS] = status.num_peers - status.num_seeds;
ret[KEY_TORRENT_NUM_INCOMPLETE] = status.num_incomplete;
const qreal ratio = QBtSession::instance()->getRealRatio(status);
ret[KEY_TORRENT_RATIO] = (ratio > QBtSession::MAX_RATIO) ? -1 : ratio;
ret[KEY_TORRENT_STATE] = h.torrentState().toString();
ret[KEY_TORRENT_ETA] = h.eta();
ret[KEY_TORRENT_SEQUENTIAL_DOWNLOAD] = status.sequential_download;
if (h.has_metadata())
ret[KEY_TORRENT_FIRST_LAST_PIECE_PRIO] = h.first_last_piece_first();
return ret;
}
/** /**
* Returns all the torrents in JSON format. * Returns all the torrents in JSON format.
* *
@ -266,7 +239,7 @@ QByteArray btjson::getTorrents(QString filter, QString label,
std::vector<torrent_handle>::const_iterator end = torrents.end(); std::vector<torrent_handle>::const_iterator end = torrents.end();
QTorrentFilter torrentFilter(filter, label); QTorrentFilter torrentFilter(filter, label);
for(; it != end; ++it) { for (; it != end; ++it) {
QTorrentHandle torrent = QTorrentHandle(*it); QTorrentHandle torrent = QTorrentHandle(*it);
if (torrentFilter.apply(torrent)) if (torrentFilter.apply(torrent))
@ -290,6 +263,76 @@ QByteArray btjson::getTorrents(QString filter, QString label,
return json::toJson(torrent_list); return json::toJson(torrent_list);
} }
/**
* The function returns the changed data from the server to synchronize with the web client.
* Return value is map in JSON format.
* Map contain the key:
* - "Rid": ID response
* Map can contain the keys:
* - "full_update": full data update flag
* - "torrents": dictionary contains information about torrents.
* - "torrents_removed": a list of hashes of removed torrents
* - "labels": list of labels
* - "labels_removed": list of removed labels
* - "queueing": priority system usage flag
* - "server_state": map contains information about the status of the server
* The keys of the 'torrents' dictionary are hashes of torrents.
* Each value of the 'torrents' dictionary contains map. The map can contain following keys:
* - "name": Torrent name
* - "size": Torrent size
* - "progress: Torrent progress
* - "dlspeed": Torrent download speed
* - "upspeed": Torrent upload speed
* - "priority": Torrent priority (-1 if queuing is disabled)
* - "num_seeds": Torrent seeds connected to
* - "num_complete": Torrent seeds in the swarm
* - "num_leechs": Torrent leechers connected to
* - "num_incomplete": Torrent leechers in the swarm
* - "ratio": Torrent share ratio
* - "eta": Torrent ETA
* - "state": Torrent state
* - "seq_dl": Torrent sequential download state
* - "f_l_piece_prio": Torrent first last piece priority state
* Server state map may contain the following keys:
* - "connection_status": conection status
* - "dht_nodes": DHT nodes count
* - "dl_info_data": bytes downloaded
* - "dl_info_speed": download speed
* - "dl_rate_limit: downlaod rate limit
* - "up_info_data: bytes uploaded
* - "up_info_speed: upload speed
* - "up_rate_limit: upload speed limit
*/
QByteArray btjson::getSyncMainData(int acceptedResponseId, QVariantMap &lastData, QVariantMap &lastAcceptedData)
{
QVariantMap data;
QVariantHash torrents;
std::vector<torrent_handle> torrentsList = QBtSession::instance()->getTorrents();
std::vector<torrent_handle>::const_iterator it = torrentsList.begin();
std::vector<torrent_handle>::const_iterator end = torrentsList.end();
for (; it != end; ++it) {
QTorrentHandle torrent = QTorrentHandle(*it);
QVariantMap map = toMap(torrent);
map.remove(KEY_TORRENT_HASH);
torrents[torrent.hash()] = map;
}
data["torrents"] = torrents;
data["queueing"] = QBtSession::instance()->isQueueingEnabled();
QVariantList labels;
foreach (QString s, Preferences::instance()->getTorrentLabels())
labels << s;
data["labels"] = labels;
data["server_state"] = getTranserInfoMap();
return json::toJson(generateSyncData(acceptedResponseId, data, lastAcceptedData, lastData));
}
/** /**
* Returns the trackers for a torrent in JSON format. * Returns the trackers for a torrent in JSON format.
* *
@ -331,7 +374,7 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
tracker_list.append(tracker_dict); tracker_list.append(tracker_dict);
} }
} }
catch(const std::exception& e) { catch (const std::exception& e) {
qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what()); qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what());
return QByteArray(); return QByteArray();
} }
@ -393,7 +436,7 @@ QByteArray btjson::getPropertiesForTorrent(const QString& hash)
const qreal ratio = QBtSession::instance()->getRealRatio(status); const qreal ratio = QBtSession::instance()->getRealRatio(status);
data[KEY_PROP_RATIO] = ratio > QBtSession::MAX_RATIO ? -1 : ratio; data[KEY_PROP_RATIO] = ratio > QBtSession::MAX_RATIO ? -1 : ratio;
} }
catch(const std::exception& e) { catch (const std::exception& e) {
qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what()); qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what());
return QByteArray(); return QByteArray();
} }
@ -463,23 +506,57 @@ QByteArray btjson::getFilesForTorrent(const QString& hash)
*/ */
QByteArray btjson::getTransferInfo() QByteArray btjson::getTransferInfo()
{ {
QVariantMap info; return json::toJson(getTranserInfoMap());
}
QVariantMap getTranserInfoMap()
{
QVariantMap map;
session_status sessionStatus = QBtSession::instance()->getSessionStatus(); session_status sessionStatus = QBtSession::instance()->getSessionStatus();
session_settings sessionSettings = QBtSession::instance()->getSession()->settings(); session_settings sessionSettings = QBtSession::instance()->getSession()->settings();
info[KEY_TRANSFER_DLSPEED] = sessionStatus.payload_download_rate; map[KEY_TRANSFER_DLSPEED] = sessionStatus.payload_download_rate;
info[KEY_TRANSFER_DLDATA] = static_cast<qlonglong>(sessionStatus.total_payload_download); map[KEY_TRANSFER_DLDATA] = static_cast<qlonglong>(sessionStatus.total_payload_download);
info[KEY_TRANSFER_UPSPEED] = sessionStatus.payload_upload_rate; map[KEY_TRANSFER_UPSPEED] = sessionStatus.payload_upload_rate;
info[KEY_TRANSFER_UPDATA] = static_cast<qlonglong>(sessionStatus.total_payload_upload); map[KEY_TRANSFER_UPDATA] = static_cast<qlonglong>(sessionStatus.total_payload_upload);
if (sessionSettings.download_rate_limit) map[KEY_TRANSFER_DLRATELIMIT] = sessionSettings.download_rate_limit;
info[KEY_TRANSFER_DLRATELIMIT] = sessionSettings.download_rate_limit; map[KEY_TRANSFER_UPRATELIMIT] = sessionSettings.upload_rate_limit;
if (sessionSettings.upload_rate_limit) map[KEY_TRANSFER_DHT_NODES] = sessionStatus.dht_nodes;
info[KEY_TRANSFER_UPRATELIMIT] = sessionSettings.upload_rate_limit;
info[KEY_TRANSFER_DHT_NODES] = sessionStatus.dht_nodes;
if (!QBtSession::instance()->getSession()->is_listening()) if (!QBtSession::instance()->getSession()->is_listening())
info[KEY_TRANSFER_CONNECTION_STATUS] = "disconnected"; map[KEY_TRANSFER_CONNECTION_STATUS] = "disconnected";
else else
info[KEY_TRANSFER_CONNECTION_STATUS] = sessionStatus.has_incoming_connections ? "connected" : "firewalled"; map[KEY_TRANSFER_CONNECTION_STATUS] = sessionStatus.has_incoming_connections ? "connected" : "firewalled";
return json::toJson(info); return map;
}
QVariantMap toMap(const QTorrentHandle& h)
{
libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters);
QVariantMap ret;
ret[KEY_TORRENT_HASH] = h.hash();
ret[KEY_TORRENT_NAME] = h.name();
ret[KEY_TORRENT_SIZE] = static_cast<qlonglong>(status.total_wanted);
ret[KEY_TORRENT_PROGRESS] = h.progress(status);
ret[KEY_TORRENT_DLSPEED] = status.download_payload_rate;
ret[KEY_TORRENT_UPSPEED] = status.upload_payload_rate;
if (QBtSession::instance()->isQueueingEnabled() && h.queue_position(status) >= 0)
ret[KEY_TORRENT_PRIORITY] = h.queue_position(status);
else
ret[KEY_TORRENT_PRIORITY] = -1;
ret[KEY_TORRENT_SEEDS] = status.num_seeds;
ret[KEY_TORRENT_NUM_COMPLETE] = status.num_complete;
ret[KEY_TORRENT_LEECHS] = status.num_peers - status.num_seeds;
ret[KEY_TORRENT_NUM_INCOMPLETE] = status.num_incomplete;
const qreal ratio = QBtSession::instance()->getRealRatio(status);
ret[KEY_TORRENT_RATIO] = (ratio > QBtSession::MAX_RATIO) ? -1 : ratio;
ret[KEY_TORRENT_STATE] = h.torrentState().toString();
ret[KEY_TORRENT_ETA] = h.eta();
ret[KEY_TORRENT_SEQUENTIAL_DOWNLOAD] = status.sequential_download;
if (h.has_metadata())
ret[KEY_TORRENT_FIRST_LAST_PIECE_PRIO] = h.first_last_piece_first();
ret[KEY_TORRENT_LABEL] = TorrentPersistentData::getLabel(h.hash());
return ret;
} }
// Compare two structures (prevData, data) and calculate difference (syncData). // Compare two structures (prevData, data) and calculate difference (syncData).
@ -639,4 +716,4 @@ QVariantMap generateSyncData(int acceptedResponseId, QVariantMap data, QVariantM
syncData[KEY_RESPONSE_ID] = lastResponseId; syncData[KEY_RESPONSE_ID] = lastResponseId;
return syncData; return syncData;
} }

2
src/webui/btjson.h

@ -33,6 +33,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QString> #include <QString>
#include <QVariant>
class QTorrentHandle; class QTorrentHandle;
@ -46,6 +47,7 @@ private:
public: public:
static QByteArray getTorrents(QString filter = "all", QString label = QString(), static QByteArray getTorrents(QString filter = "all", QString label = QString(),
QString sortedColumn = "name", bool reverse = false, int limit = 0, int offset = 0); QString sortedColumn = "name", bool reverse = false, int limit = 0, int offset = 0);
static QByteArray getSyncMainData(int acceptedResponseId, QVariantMap &lastData, QVariantMap &lastAcceptedData);
static QByteArray getTrackersForTorrent(const QString& hash); static QByteArray getTrackersForTorrent(const QString& hash);
static QByteArray getPropertiesForTorrent(const QString& hash); static QByteArray getPropertiesForTorrent(const QString& hash);
static QByteArray getFilesForTorrent(const QString& hash); static QByteArray getFilesForTorrent(const QString& hash);

10
src/webui/requesthandler.cpp

@ -48,6 +48,7 @@
#include "prefjson.h" #include "prefjson.h"
#include "qbtsession.h" #include "qbtsession.h"
#include "requesthandler.h" #include "requesthandler.h"
#include "webapplication.h"
using namespace libtorrent; using namespace libtorrent;
@ -82,6 +83,7 @@ QMap<QString, QMap<QString, RequestHandler::Action> > RequestHandler::initialize
ADD_ACTION(json, propertiesGeneral); ADD_ACTION(json, propertiesGeneral);
ADD_ACTION(json, propertiesTrackers); ADD_ACTION(json, propertiesTrackers);
ADD_ACTION(json, propertiesFiles); ADD_ACTION(json, propertiesFiles);
ADD_ACTION(sync, maindata);
ADD_ACTION(command, shutdown); ADD_ACTION(command, shutdown);
ADD_ACTION(command, download); ADD_ACTION(command, download);
ADD_ACTION(command, upload); ADD_ACTION(command, upload);
@ -261,6 +263,14 @@ void RequestHandler::action_json_propertiesFiles()
print(btjson::getFilesForTorrent(args_.front()), CONTENT_TYPE_JS); print(btjson::getFilesForTorrent(args_.front()), CONTENT_TYPE_JS);
} }
// GET param:
// - rid (int): last response id
void RequestHandler::action_sync_maindata()
{
CHECK_URI(0);
print(btjson::getSyncMainData(request().gets["rid"].toInt(), session()->syncMainDataLastResponse, session()->syncMainDataLastAcceptedResponse));
}
void RequestHandler::action_version_api() void RequestHandler::action_version_api()
{ {
CHECK_URI(0); CHECK_URI(0);

1
src/webui/requesthandler.h

@ -56,6 +56,7 @@ private:
void action_json_propertiesGeneral(); void action_json_propertiesGeneral();
void action_json_propertiesTrackers(); void action_json_propertiesTrackers();
void action_json_propertiesFiles(); void action_json_propertiesFiles();
void action_sync_maindata();
void action_command_shutdown(); void action_command_shutdown();
void action_command_download(); void action_command_download();
void action_command_upload(); void action_command_upload();

4
src/webui/webapplication.h

@ -33,11 +33,13 @@
#include <QMap> #include <QMap>
#include <QHash> #include <QHash>
#include "httptypes.h" #include "httptypes.h"
#include <QVariant>
struct WebSession struct WebSession
{ {
const QString id; const QString id;
QVariantMap syncMainDataLastResponse;
QVariantMap syncMainDataLastAcceptedResponse;
WebSession(const QString& id): id(id) {} WebSession(const QString& id): id(id) {}
}; };

Loading…
Cancel
Save