Commit 368f9840 authored by flypig's avatar flypig

[libconnman-qt] Convert VPN routes to/from dbus. Contributes to JB#46120

The userRoutes and serverRoutes VPN properties are passed to connman via
dbus in the following form.

Variant array [struct {array [
    dict entry(
        string "ProtocolFamily"
        variant int32 4
    )
    dict entry(
        string "Network"
        variant string "172.18.13.1"
    )
    dict entry(
        string "Netmask"
        variant string "255.255.255.255"
    )
    dict entry(
        string "Gateway"
        variant string "172.18.13.5"
    )
]}]

These need to be converted to and from the appropriate datatypes used in
QML and javascript. This change adds the conversion functions needed for
this.
parent d2e425bd
......@@ -31,10 +31,99 @@
*/
#include <QDebug>
#include <QDBusMetaType>
#include "vpnconnection.h"
#include "marshalutils.h"
// Empty namespace for local static functions
namespace {
// Marshall the RouteStructure data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const RouteStructure &routestruct)
{
QVariantMap dict;
dict.insert("ProtocolFamily", routestruct.protocolFamily);
dict.insert("Network", routestruct.network);
dict.insert("Netmask", routestruct.netmask);
dict.insert("Gateway", routestruct.gateway);
argument.beginStructure();
argument << dict;
argument.endStructure();
return argument;
}
// Retrieve the RouteStructure data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, RouteStructure &routestruct)
{
QVariantMap dict;
argument.beginStructure();
argument >> dict;
argument.endStructure();
routestruct.protocolFamily = dict.value("ProtocolFamily", 0).toInt();
routestruct.network = dict.value("Network").toString();
routestruct.netmask = dict.value("Netmask").toString();
routestruct.gateway = dict.value("Gateway").toString();
return argument;
}
QVariant convertState (const QString &key, const QVariant &value, bool toDBus)
{
QList<QPair<QVariant, QVariant> > states;
states.push_back(qMakePair(QVariant::fromValue(QStringLiteral("idle")), QVariant::fromValue(static_cast<int>(VpnConnection::Idle))));
states.push_back(qMakePair(QVariant::fromValue(QStringLiteral("failure")), QVariant::fromValue(static_cast<int>(VpnConnection::Failure))));
states.push_back(qMakePair(QVariant::fromValue(QStringLiteral("configuration")), QVariant::fromValue(static_cast<int>(VpnConnection::Configuration))));
states.push_back(qMakePair(QVariant::fromValue(QStringLiteral("ready")), QVariant::fromValue(static_cast<int>(VpnConnection::Ready))));
states.push_back(qMakePair(QVariant::fromValue(QStringLiteral("disconnect")), QVariant::fromValue(static_cast<int>(VpnConnection::Disconnect))));
auto lit = std::find_if(states.cbegin(), states.cend(), [value, toDBus](const QPair<QVariant, QVariant> &pair) { return value == (toDBus ? pair.second : pair.first); });
if (lit != states.end()) {
return toDBus ? (*lit).first : (*lit).second;
}
qDebug() << "No conversion found for" << (toDBus ? "QML" : "DBus") << "value:" << value << key;
return value;
}
QVariant convertRoutes (const QString &, const QVariant &value, bool toDBus) {
// We use qDBusRegisterMetaType in VpnConnections to convert automatically
// between QList<RouteStruture> and QDBusArgument, but we still need to
// convert to/from suitable Javascript structures
QVariant variant;
if (toDBus) {
QVariantList in = value.toList();
QList<RouteStructure> out;
for (QVariant item : in) {
QVariantMap jsRoute = item.toMap();
RouteStructure route;
route.protocolFamily = jsRoute.value("ProtocolFamily", 0).toInt();
route.network = jsRoute.value("Network").toString();
route.netmask = jsRoute.value("Netmask").toString();
route.gateway = jsRoute.value("Gateway").toString();
out << route;
}
variant.setValue(out);
}
else {
QList<RouteStructure> in = qdbus_cast<QList<RouteStructure>>(value.value<QDBusArgument>());
QVariantList out;
for (RouteStructure route : in) {
QVariantMap jsRoute;
jsRoute.insert("ProtocolFamily", route.protocolFamily);
jsRoute.insert("Network", route.network);
jsRoute.insert("Netmask", route.netmask);
jsRoute.insert("Gateway", route.gateway);
out << jsRoute;
}
variant.setValue(out);
}
return variant;
}
} // Empty namespace
template<typename T>
inline QVariant extract(const QDBusArgument &arg)
{
......@@ -82,9 +171,6 @@ QVariantMap MarshalUtils::propertiesToQml(const QVariantMap &fromDBus)
// iPv4 becomes ipv4 and iPv6 becomes ipv6
key = key.toLower();
value = extract<QVariantMap>(value.value<QDBusArgument>());
} else if (key == QStringLiteral("serverRoutes") ||
key == QStringLiteral("userRoutes")) {
value = extractArray<QVariantMap>(value.value<QDBusArgument>());
}
rv.insert(key, convertToQml(key, value));
......@@ -98,34 +184,27 @@ QVariantMap MarshalUtils::propertiesToQml(const QVariantMap &fromDBus)
}
// Conversion to/from DBus/QML
QHash<QString, QList<QPair<QVariant, QVariant> > > MarshalUtils::propertyConversions()
QHash<QString, MarshalUtils::conversionFunction> MarshalUtils::propertyConversions()
{
QHash<QString, QList<QPair<QVariant, QVariant> > > rv;
qDBusRegisterMetaType<RouteStructure>();
qDBusRegisterMetaType<QList<RouteStructure>>();
QList<QPair<QVariant, QVariant> > states;
states.push_back(qMakePair(QVariant::fromValue(QString("idle")), QVariant::fromValue(static_cast<int>(VpnConnection::Idle))));
states.push_back(qMakePair(QVariant::fromValue(QString("failure")), QVariant::fromValue(static_cast<int>(VpnConnection::Failure))));
states.push_back(qMakePair(QVariant::fromValue(QString("configuration")), QVariant::fromValue(static_cast<int>(VpnConnection::Configuration))));
states.push_back(qMakePair(QVariant::fromValue(QString("ready")), QVariant::fromValue(static_cast<int>(VpnConnection::Ready))));
states.push_back(qMakePair(QVariant::fromValue(QString("disconnect")), QVariant::fromValue(static_cast<int>(VpnConnection::Disconnect))));
rv.insert(QString("state"), states);
QHash<QString, conversionFunction> rv;
rv.insert(QStringLiteral("state"), convertState);
rv.insert(QStringLiteral("userroutes"), convertRoutes);
rv.insert(QStringLiteral("serverroutes"), convertRoutes);
return rv;
}
QVariant MarshalUtils::convertValue(const QString &key, const QVariant &value, bool toDBus)
{
static const QHash<QString, QList<QPair<QVariant, QVariant> > > conversions(propertyConversions());
static const QHash<QString, conversionFunction> conversions(propertyConversions());
auto it = conversions.find(key.toLower());
if (it != conversions.end()) {
const QList<QPair<QVariant, QVariant> > &list(it.value());
auto lit = std::find_if(list.cbegin(), list.cend(), [value, toDBus](const QPair<QVariant, QVariant> &pair) { return value == (toDBus ? pair.second : pair.first); });
if (lit != list.end()) {
return toDBus ? (*lit).first : (*lit).second;
} else {
qDebug() << "No conversion found for" << (toDBus ? "QML" : "DBus") << "value:" << value << key;
}
return it.value()(key, value, toDBus);
}
return value;
......
......@@ -51,8 +51,10 @@ namespace MarshalUtils
}
typedef QVariant (*conversionFunction)(const QString &key, const QVariant &value, bool toDBus);
QVariantMap propertiesToQml(const QVariantMap &fromDBus);
QHash<QString, QList<QPair<QVariant, QVariant> > > propertyConversions();
QHash<QString, conversionFunction> propertyConversions();
QVariant convertValue(const QString &key, const QVariant &value, bool toDBus);
QVariant convertToQml(const QString &key, const QVariant &value);
QVariant convertToDBus(const QString &key, const QVariant &value);
......
......@@ -233,7 +233,7 @@ void VpnConnection::update(const QVariantMap &updateProperties)
d->checkChanged(properties, emissions, "ipv4", &VpnConnection::ipv4Changed);
d->checkChanged(properties, emissions, "ipv6", &VpnConnection::ipv6Changed);
d->checkChanged(properties, emissions, "nameservers", &VpnConnection::nameserversChanged);
d->checkChanged(properties, emissions, "usreRoutes", &VpnConnection::userRoutesChanged);
d->checkChanged(properties, emissions, "userRoutes", &VpnConnection::userRoutesChanged);
d->checkChanged(properties, emissions, "serverRoutes", &VpnConnection::serverRoutesChanged);
d->updateVariable(properties, emissions, "autoConnect", &d->m_autoConnect, &VpnConnection::autoConnectChanged);
......@@ -332,8 +332,8 @@ DEFAULT_PROPERTY_METHODS(int, int, Index, index)
DEFAULT_PROPERTY_METHODS(QVariantMap &, QVariantMap, Ipv4, ipv4)
DEFAULT_PROPERTY_METHODS(QVariantMap &, QVariantMap, Ipv6, ipv6)
DEFAULT_PROPERTY_METHODS(QStringList &, QStringList, Nameservers, nameservers)
DEFAULT_PROPERTY_METHODS(QVariantList &, QVariantList, UserRoutes, userRoutes)
DEFAULT_PROPERTY_METHODS(QVariantList &, QVariantList, ServerRoutes, serverRoutes)
DEFAULT_PROPERTY_METHODS(QVariant &, QVariant, UserRoutes, userRoutes)
DEFAULT_PROPERTY_METHODS(QVariant &, QVariant, ServerRoutes, serverRoutes)
DEFAULT_PROPERTY_METHODS(QVariantMap &, QVariantMap, ProviderProperties, providerProperties)
// ==========================================================================
......
......@@ -38,6 +38,17 @@
class VpnConnectionPrivate;
// The userRoutes and serverRoutes properties are QVariants containing a
// QList<RouteStructure> structure
struct RouteStructure
{
int protocolFamily;
QString network;
QString netmask;
QString gateway;
};
Q_DECLARE_METATYPE(RouteStructure)
class VpnConnection : public QObject
{
Q_OBJECT
......@@ -58,8 +69,8 @@ class VpnConnection : public QObject
Q_PROPERTY(QVariantMap ipv4 READ ipv4 WRITE setIpv4 NOTIFY ipv4Changed)
Q_PROPERTY(QVariantMap ipv6 READ ipv6 WRITE setIpv6 NOTIFY ipv6Changed)
Q_PROPERTY(QStringList nameservers READ nameservers WRITE setNameservers NOTIFY nameserversChanged)
Q_PROPERTY(QVariantList userRoutes READ userRoutes WRITE setUserRoutes NOTIFY userRoutesChanged)
Q_PROPERTY(QVariantList serverRoutes READ serverRoutes WRITE setServerRoutes NOTIFY serverRoutesChanged)
Q_PROPERTY(QVariant userRoutes READ userRoutes WRITE setUserRoutes NOTIFY userRoutesChanged)
Q_PROPERTY(QVariant serverRoutes READ serverRoutes WRITE setServerRoutes NOTIFY serverRoutesChanged)
Q_PROPERTY(QVariantMap properties READ properties WRITE setProperties NOTIFY propertiesChanged)
Q_PROPERTY(QVariantMap providerProperties READ providerProperties WRITE setProviderProperties NOTIFY providerPropertiesChanged)
......@@ -123,11 +134,11 @@ public:
QStringList nameservers() const;
void setNameservers(const QStringList &nameservers);
QVariantList userRoutes() const;
void setUserRoutes(const QVariantList &userRoutes);
QVariant userRoutes() const;
void setUserRoutes(const QVariant &userRoutes);
QVariantList serverRoutes() const;
void setServerRoutes(const QVariantList &serverRoutes);
QVariant serverRoutes() const;
void setServerRoutes(const QVariant &serverRoutes);
QVariantMap properties() const;
void setProperties(const QVariantMap properties);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment