Files
transmission/qt/AddData.cc
Mike Gelfand 2b917de65b Refactor RPC requests code for proper queueing (patch by intelfx @ GH-10)
This refactoring is driven by the need to be able to do true queued RPC calls
(where each successive call uses the result of the previous).

Currently, such queueing of requests is done by assigning them special "magic"
tag numbers, which are then intercepted in one big switch() statement and acted
upon. This (aside from making code greatly unclear) effectively makes each such
queue a singleton, because state passing is restricted to global variables.

We refactor RpcClient to assign an unique tag to each remote call, and then
abstract all the call<->response matching with Qt's future/promise mechanism.

Finally, we introduce a "RPC request queue" class (RpcQueue) which is built on
top of QFutureWatcher and C++11's <functional> library. This class maintains
a queue of functions, where each function receives an RPC response, does
necessary processing, performs another call and finally returns its future.
2016-04-19 20:41:59 +00:00

134 lines
2.6 KiB
C++

/*
* This file Copyright (C) 2012-2016 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
* $Id$
*/
#include <QFile>
#include <QDir>
#include <libtransmission/transmission.h>
#include <libtransmission/crypto-utils.h> // tr_base64_encode()
#include "AddData.h"
#include "Utils.h"
int
AddData::set (const QString& key)
{
if (Utils::isMagnetLink (key))
{
magnet = key;
type = MAGNET;
}
else if (Utils::isUriWithSupportedScheme (key))
{
url = key;
type = URL;
}
else if (QFile(key).exists ())
{
filename = QDir::fromNativeSeparators (key);
type = FILENAME;
QFile file (key);
file.open (QIODevice::ReadOnly);
metainfo = file.readAll ();
file.close ();
}
else if (Utils::isHexHashcode (key))
{
magnet = QString::fromUtf8("magnet:?xt=urn:btih:") + key;
type = MAGNET;
}
else
{
size_t len;
void * raw = tr_base64_decode (key.toUtf8().constData(), key.toUtf8().size(), &len);
if (raw)
{
metainfo.append (static_cast<const char*> (raw), int(len));
tr_free (raw);
type = METAINFO;
}
else
{
type = NONE;
}
}
return type;
}
QByteArray
AddData::toBase64 () const
{
QByteArray ret;
if (!metainfo.isEmpty ())
{
size_t len;
void * b64 = tr_base64_encode (metainfo.constData(), metainfo.size(), &len);
ret = QByteArray (static_cast<const char*> (b64), int(len));
tr_free (b64);
}
return ret;
}
QString
AddData::readableName () const
{
QString ret;
switch (type)
{
case FILENAME:
ret = filename;
break;
case MAGNET:
ret = magnet;
break;
case URL:
ret = url.toString();
break;
case METAINFO:
{
tr_info inf;
tr_ctor * ctor = tr_ctorNew (NULL);
tr_ctorSetMetainfo (ctor, reinterpret_cast<const quint8*> (metainfo.constData()), metainfo.size());
if (tr_torrentParse (ctor, &inf) == TR_PARSE_OK )
{
ret = QString::fromUtf8 (inf.name); // metainfo is required to be UTF-8
tr_metainfoFree (&inf);
}
tr_ctorFree (ctor);
break;
}
}
return ret;
}
QString
AddData::readableShortName () const
{
switch (type)
{
case FILENAME:
return QFileInfo (filename).fileName ();
case URL:
return url.path ().split (QLatin1Char ('/')).last ();
default:
return readableName ();
}
}