Skip to content

Commit

Permalink
[transferengine] Use p2p dbus for transfer engine API. Contributes to…
Browse files Browse the repository at this point in the history
… JB#54084 OMP#JOLLA-113

Offer discovery API on session bus (to allow autostart of the
transferengine process when required by clients), but offer the
transfer API via p2p DBus (to ensure data is private).
  • Loading branch information
chriadam committed May 11, 2021
1 parent b79c8c8 commit a027c05
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 29 deletions.
4 changes: 2 additions & 2 deletions dbus/org.nemo.transferengine.service
@@ -1,5 +1,5 @@
[D-BUS Service]
Interface=/org/nemo/transferengine
Name=org.nemo.transferengine
Interface=/
Name=org.nemo.transferengine.discovery
Exec=/usr/bin/invoker --type=qt5 --global-syms /usr/bin/nemo-transfer-engine
SystemdService=transferengine.service
55 changes: 42 additions & 13 deletions declarative/declarativetransfermodel.cpp
Expand Up @@ -173,8 +173,6 @@ void TransferModel::classBegin()

void TransferModel::componentComplete()
{
m_complete = true;

m_roles[TransferDBRecord::TransferID] = "transferId";
m_roles[TransferDBRecord::TransferType] = "transferType";
m_roles[TransferDBRecord::Progress] = "progress";
Expand All @@ -192,19 +190,50 @@ void TransferModel::componentComplete()
m_roles[TransferDBRecord::CancelSupported] = "cancelEnabled";
m_roles[TransferDBRecord::RestartSupported] = "restartEnabled";

QDBusMessage msg = QDBusMessage::createMethodCall(
"org.nemo.transferengine.discovery",
"/",
"org.nemo.transferengine.discovery",
"peerToPeerAddress");
QDBusConnection::sessionBus().callWithCallback(
msg,
this,
SLOT(discoverySucceeded(QString)),
SLOT(discoveryFailed()),
15000); // allow 15 seconds for the transfer engine to start.
}

void TransferModel::discoveryFailed()
{
qWarning() << "Unable to discover transfer-engine IPC socket address";
}

void TransferModel::discoverySucceeded(const QString &p2pAddress)
{
m_complete = true;
refresh();

m_client = new TransferEngineInterface("org.nemo.transferengine",
"/org/nemo/transferengine",
QDBusConnection::sessionBus(),
this);

connect(m_client, SIGNAL(progressChanged(int,double)),
this, SLOT(refresh()));
connect(m_client, SIGNAL(transfersChanged()),
this, SLOT(refresh()));
connect(m_client, SIGNAL(statusChanged(int,int)),
this, SLOT(refresh()));
static int connectionCount = 0;
const QString name = QString::fromLatin1("transfer-engine-connection-dtm-%1").arg(connectionCount++);
QDBusConnection p2pc = QDBusConnection::connectToPeer(p2pAddress, name);
if (!p2pc.isConnected()) {
qWarning() << "Unable to connect to transfer-engine on address:"
<< p2pAddress << ":" << p2pc.lastError()
<< p2pc.lastError().type() << p2pc.lastError().name();
} else {
m_client = new TransferEngineInterface(
"org.nemo.transferengine",
"/org/nemo/transferengine",
p2pc,
this);

connect(m_client, SIGNAL(progressChanged(int,double)),
this, SLOT(refresh()));
connect(m_client, SIGNAL(transfersChanged()),
this, SLOT(refresh()));
connect(m_client, SIGNAL(statusChanged(int,int)),
this, SLOT(refresh()));
}
}

void TransferModel::insertRange(
Expand Down
4 changes: 4 additions & 0 deletions declarative/declarativetransfermodel.h
Expand Up @@ -109,6 +109,10 @@ public slots:
void countChanged();
void transfersInProgressChanged();

private slots:
void discoveryFailed();
void discoverySucceeded(const QString &p2pAddress);

private:
void run();
bool executeQuery(QVector<TransferDBRecord> *rows, int *activeTransfers, QString *errorString);
Expand Down
63 changes: 59 additions & 4 deletions lib/transferengineclient.cpp
Expand Up @@ -25,6 +25,29 @@
#include "transferengineclient.h"
#include "transferengineinterface.h"

#include <QStandardPaths>

namespace {
QString p2pSocketAddress()
{
const QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
if (path.isEmpty()) {
qWarning() << "No writable runtime directory found, cannot create socket file";
return QString();
}

QDir dir(path);
if (!dir.mkpath(dir.absolutePath())) {
qWarning() << "Could not create socket file directory";
return QString();
}

const QString socketFile = QString::fromUtf8("%1/%2").arg(dir.absolutePath(), QLatin1String("transfer-engine.socket"));
const QString address = QString::fromUtf8("unix:path=%1").arg(socketFile);

return address;
}
}

class CallbackInterfacePrivate {
public:
Expand Down Expand Up @@ -183,10 +206,18 @@ TransferEngineClient::TransferEngineClient(QObject *parent) :
d_ptr(new TransferEngineClientPrivate)
{
Q_D(TransferEngineClient);
d->m_client = new TransferEngineInterface("org.nemo.transferengine",
"/org/nemo/transferengine",
QDBusConnection::sessionBus(),
this);

QDBusMessage msg = QDBusMessage::createMethodCall(
"org.nemo.transferengine.discovery",
"/",
"org.nemo.transferengine.discovery",
"peerToPeerAddress");
QDBusConnection::sessionBus().callWithCallback(
msg,
this,
SLOT(discoverySucceeded(QString)),
SLOT(discoveryFailed()),
15000); // allow 15 seconds for the transfer engine to start.
}

TransferEngineClient::~TransferEngineClient()
Expand All @@ -197,6 +228,30 @@ TransferEngineClient::~TransferEngineClient()
d_ptr = 0;
}

void TransferEngineClient::discoveryFailed()
{
qWarning() << "Failed to discover transfer-engine p2p address";
}

void TransferEngineClient::discoverySucceeded(const QString &p2pAddress)
{
Q_D(TransferEngineClient);
static int connectionCount = 0;
const QString name = QString::fromLatin1("transfer-engine-connection-%1").arg(connectionCount++);
QDBusConnection p2pc = QDBusConnection::connectToPeer(p2pAddress, name);
if (!p2pc.isConnected()) {
qWarning() << "Unable to connect to transfer-engine on address:"
<< p2pAddress << ":" << p2pc.lastError()
<< p2pc.lastError().type() << p2pc.lastError().name();
} else {
d->m_client = new TransferEngineInterface(
"org.nemo.transferengine",
"/org/nemo/transferengine",
p2pc,
this);
}
}

/*!
Creates a download event to the TransferEngine. This method requires the following parameters
\a displayName, a human readable name for the entry. \a applicationIcon is the \c QUrl to the icon
Expand Down
4 changes: 4 additions & 0 deletions lib/transferengineclient.h
Expand Up @@ -84,6 +84,10 @@ class TransferEngineClient : public QObject
void enableNotifications(bool enable);
bool notificationsEnabled() const;

private Q_SLOTS:
void discoveryFailed();
void discoverySucceeded(const QString &p2pAddress);

private:
TransferEngineClientPrivate *d_ptr;
Q_DECLARE_PRIVATE(TransferEngineClient)
Expand Down
88 changes: 79 additions & 9 deletions src/transferengine.cpp
Expand Up @@ -37,9 +37,11 @@
#include <QtDebug>
#include <QPluginLoader>
#include <QDBusMessage>
#include <QDBusServer>
#include <QFileSystemWatcher>
#include <QTimer>
#include <QSettings>
#include <QStandardPaths>

#include <notification.h>

Expand All @@ -58,6 +60,28 @@

#define TRANSFER_PROGRESS_HINT "x-nemo-progress"

namespace {
QString p2pSocketAddress()
{
const QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
if (path.isEmpty()) {
qWarning() << "No writable runtime directory found, cannot create socket file";
return QString();
}

QDir dir(path);
if (!dir.mkpath(dir.absolutePath())) {
qWarning() << "Could not create socket file directory";
return QString();
}

const QString socketFile = QString::fromUtf8("%1/%2").arg(dir.absolutePath(), QLatin1String("transfer-engine.socket"));
const QString address = QString::fromUtf8("unix:path=%1").arg(socketFile);

return address;
}
}

TransferEngineSignalHandler * TransferEngineSignalHandler::instance()
{
static TransferEngineSignalHandler instance;
Expand Down Expand Up @@ -858,21 +882,26 @@ TransferEngine::TransferEngine(QObject *parent) :

new TransferEngineAdaptor(this);

QDBusConnection connection = QDBusConnection::sessionBus();
if (!connection.registerObject("/org/nemo/transferengine", this)) {
qFatal("Could not register object \'/org/nemo/transferengine\'");
}

if (!connection.registerService("org.nemo.transferengine")) {
qFatal("DBUS service already taken. Kill the other instance first.");
}
const QString p2pAddress = p2pSocketAddress();
new DiscoveryObject(p2pAddress, this);
QDBusServer *dbusServer = new QDBusServer(p2pAddress, this);
connect(dbusServer, &QDBusServer::newConnection,
this, [this, p2pAddress](const QDBusConnection &clientConnection) {
QDBusConnection connection(clientConnection);
if (!connection.registerObject("/org/nemo/transferengine", this)) {
qWarning() << "Could not register object on p2p connection:" << p2pAddress;
} else {
connection.registerService("org.nemo.transferengine");
qDebug() << "Registered p2p object with the client connection:" << p2pAddress;
}
});

// Let's make sure that db is open by creating
// DbManager singleton instance.
DbManager::instance();
Q_D(TransferEngine);
d->recoveryCheck();
d->enabledPluginsCheck();
d->enabledPluginsCheck();
}

/*!
Expand Down Expand Up @@ -1451,3 +1480,44 @@ bool TransferEngine::notificationsEnabled()
d->exitSafely();
return d->m_notificationsEnabled;
}

DiscoveryObject::DiscoveryObject(
const QString &p2pAddress,
QObject *parent)
: QObject(parent)
, m_p2pAddress(p2pAddress)
{
registerObject();
}

bool DiscoveryObject::registerObject(
const QString &serviceName,
const QString &objectPath)
{
if (m_registered) {
return true;
}

if (!QDBusConnection::sessionBus().registerObject(objectPath, this, QDBusConnection::ExportAllSlots)) {
qWarning() << "Unable to register session bus service:" << serviceName << "at path:" << objectPath;
qFatal("transfer-engine discovery object unable to be registered on session bus!");
}

if (!QDBusConnection::sessionBus().registerService(serviceName)) {
qWarning() << "Unable to register session bus service:" << serviceName;
qFatal("transfer-engine discovery service unable to be registered on session bus!");
}

m_registered = true;
return true;
}

void DiscoveryObject::setPeerToPeerAddress(const QString &p2pAddress)
{
m_p2pAddress = p2pAddress;
}

QString DiscoveryObject::peerToPeerAddress() const
{
return m_p2pAddress;
}
29 changes: 29 additions & 0 deletions src/transferengine.h
Expand Up @@ -114,5 +114,34 @@ public Q_SLOTS:
Q_DECLARE_PRIVATE(TransferEngine)
};

// registered on the session bus
class DiscoveryObject : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.nemo.transferengine.discovery")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name=\"org.nemo.transferengine.discovery\">\n"
" <method name=\"peerToPeerAddress\">\n"
" <arg name=\"address\" type=\"s\" direction=\"out\" />\n"
" </method>\n"
" </interface>\n"
"")

public:
DiscoveryObject(const QString &p2pAddress = QString(),
QObject *parent = nullptr);

bool registerObject(const QString &serviceName = QString::fromLatin1("org.nemo.transferengine.discovery"),
const QString &objectPath = QString::fromLatin1("/"));

void setPeerToPeerAddress(const QString &p2pAddress);

public Q_SLOTS:
QString peerToPeerAddress() const;

private:
QString m_p2pAddress;
bool m_registered = false;
};

#endif // TRANSFERENGINE_H
2 changes: 1 addition & 1 deletion transferengine.service
Expand Up @@ -6,5 +6,5 @@ Requires=dbus.socket booster-qt5.service
[Service]
Type=dbus
ExecStart=/usr/bin/invoker --type=qt5 --global-syms /usr/bin/nemo-transfer-engine
BusName=org.nemo.transferengine
BusName=org.nemo.transferengine.discovery

0 comments on commit a027c05

Please sign in to comment.