diff options
Diffstat (limited to 'src/plugins/networkinformation/networkmanager')
5 files changed, 651 insertions, 0 deletions
diff --git a/src/plugins/networkinformation/networkmanager/CMakeLists.txt b/src/plugins/networkinformation/networkmanager/CMakeLists.txt new file mode 100644 index 0000000000..9d76dbe7b4 --- /dev/null +++ b/src/plugins/networkinformation/networkmanager/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_plugin(QNetworkManagerNetworkInformationPlugin + OUTPUT_NAME qnetworkmanager + CLASS_NAME QNetworkManagerNetworkInformationBackendFactory + PLUGIN_TYPE networkinformation + DEFAULT_IF LINUX + SOURCES + qnetworkmanagernetworkinformationbackend.h + qnetworkmanagernetworkinformationbackend.cpp + qnetworkmanagerservice.h + qnetworkmanagerservice.cpp + LIBRARIES + Qt::DBus + Qt::NetworkPrivate +) diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp new file mode 100644 index 0000000000..f583d1dcf6 --- /dev/null +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp @@ -0,0 +1,181 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnetworkmanagernetworkinformationbackend.h" + +#include <QtCore/qglobal.h> +#include <QtCore/private/qobject_p.h> + +#include <QtDBus/qdbusmessage.h> + +QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcNetInfoNLM) +Q_LOGGING_CATEGORY(lcNetInfoNM, "qt.network.info.networkmanager"); + +namespace { +QNetworkInformation::Reachability reachabilityFromNMState(QNetworkManagerInterface::NMState state) +{ + switch (state) { + case QNetworkManagerInterface::NM_STATE_UNKNOWN: + case QNetworkManagerInterface::NM_STATE_ASLEEP: + case QNetworkManagerInterface::NM_STATE_CONNECTING: + return QNetworkInformation::Reachability::Unknown; + case QNetworkManagerInterface::NM_STATE_DISCONNECTING: // No point in starting new connections: + case QNetworkManagerInterface::NM_STATE_DISCONNECTED: + return QNetworkInformation::Reachability::Disconnected; + case QNetworkManagerInterface::NM_STATE_CONNECTED_LOCAL: + return QNetworkInformation::Reachability::Local; + case QNetworkManagerInterface::NM_STATE_CONNECTED_SITE: + return QNetworkInformation::Reachability::Site; + case QNetworkManagerInterface::NM_STATE_CONNECTED_GLOBAL: + return QNetworkInformation::Reachability::Online; + } + return QNetworkInformation::Reachability::Unknown; +} + +QNetworkInformation::TransportMedium +transportMediumFromDeviceType(QNetworkManagerInterface::NMDeviceType type) +{ + switch (type) { + case QNetworkManagerInterface::NM_DEVICE_TYPE_ETHERNET: + return QNetworkInformation::TransportMedium::Ethernet; + case QNetworkManagerInterface::NM_DEVICE_TYPE_WIFI: + return QNetworkInformation::TransportMedium::WiFi; + case QNetworkManagerInterface::NM_DEVICE_TYPE_BT: + return QNetworkInformation::TransportMedium::Bluetooth; + case QNetworkManagerInterface::NM_DEVICE_TYPE_MODEM: + return QNetworkInformation::TransportMedium::Cellular; + + case QNetworkManagerInterface::NM_DEVICE_TYPE_UNKNOWN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_GENERIC: + case QNetworkManagerInterface::NM_DEVICE_TYPE_UNUSED1: + case QNetworkManagerInterface::NM_DEVICE_TYPE_UNUSED2: + case QNetworkManagerInterface::NM_DEVICE_TYPE_OLPC_MESH: + case QNetworkManagerInterface::NM_DEVICE_TYPE_WIMAX: + case QNetworkManagerInterface::NM_DEVICE_TYPE_INFINIBAND: + case QNetworkManagerInterface::NM_DEVICE_TYPE_BOND: + case QNetworkManagerInterface::NM_DEVICE_TYPE_VLAN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_ADSL: + case QNetworkManagerInterface::NM_DEVICE_TYPE_BRIDGE: + case QNetworkManagerInterface::NM_DEVICE_TYPE_TEAM: + case QNetworkManagerInterface::NM_DEVICE_TYPE_TUN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_IP_TUNNEL: + case QNetworkManagerInterface::NM_DEVICE_TYPE_MACVLAN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_VXLAN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_VETH: + case QNetworkManagerInterface::NM_DEVICE_TYPE_MACSEC: + case QNetworkManagerInterface::NM_DEVICE_TYPE_DUMMY: + case QNetworkManagerInterface::NM_DEVICE_TYPE_PPP: + case QNetworkManagerInterface::NM_DEVICE_TYPE_OVS_INTERFACE: + case QNetworkManagerInterface::NM_DEVICE_TYPE_OVS_PORT: + case QNetworkManagerInterface::NM_DEVICE_TYPE_OVS_BRIDGE: + case QNetworkManagerInterface::NM_DEVICE_TYPE_WPAN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_6LOWPAN: + case QNetworkManagerInterface::NM_DEVICE_TYPE_WIREGUARD: + case QNetworkManagerInterface::NM_DEVICE_TYPE_WIFI_P2P: + case QNetworkManagerInterface::NM_DEVICE_TYPE_VRF: + break; + } + // While the list is exhaustive of the enum there can be additional + // entries added in NetworkManager that isn't listed here + return QNetworkInformation::TransportMedium::Unknown; +} + +bool isMeteredFromNMMetered(QNetworkManagerInterface::NMMetered metered) +{ + switch (metered) { + case QNetworkManagerInterface::NM_METERED_YES: + case QNetworkManagerInterface::NM_METERED_GUESS_YES: + return true; + case QNetworkManagerInterface::NM_METERED_NO: + case QNetworkManagerInterface::NM_METERED_GUESS_NO: + case QNetworkManagerInterface::NM_METERED_UNKNOWN: + return false; + } + Q_UNREACHABLE_RETURN(false); +} +} // unnamed namespace + +static QString backendName() +{ + return QStringView(QNetworkInformationBackend::PluginNames + [QNetworkInformationBackend::PluginNamesLinuxIndex]).toString(); +} + +QString QNetworkManagerNetworkInformationBackend::name() const +{ + return backendName(); +} + +class QNetworkManagerNetworkInformationBackendFactory : public QNetworkInformationBackendFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QNetworkInformationBackendFactory_iid) + Q_INTERFACES(QNetworkInformationBackendFactory) +public: + QNetworkManagerNetworkInformationBackendFactory() = default; + ~QNetworkManagerNetworkInformationBackendFactory() = default; + QString name() const override { return backendName(); } + QNetworkInformation::Features featuresSupported() const override + { + if (!QNetworkManagerInterfaceBase::networkManagerAvailable()) + return {}; + return QNetworkManagerNetworkInformationBackend::featuresSupportedStatic(); + } + + QNetworkInformationBackend *create(QNetworkInformation::Features requiredFeatures) const override + { + if ((requiredFeatures & featuresSupported()) != requiredFeatures) + return nullptr; + if (!QNetworkManagerInterfaceBase::networkManagerAvailable()) + return nullptr; + auto backend = new QNetworkManagerNetworkInformationBackend(); + if (!backend->isValid()) + delete std::exchange(backend, nullptr); + return backend; + } +private: + Q_DISABLE_COPY_MOVE(QNetworkManagerNetworkInformationBackendFactory) +}; + +QNetworkManagerNetworkInformationBackend::QNetworkManagerNetworkInformationBackend() +{ + if (!iface.isValid()) + return; + iface.setBackend(this); + onStateChanged(iface.state()); + onConnectivityChanged(iface.connectivityState()); + onDeviceTypeChanged(iface.deviceType()); + onMeteredChanged(iface.meteredState()); +} + +void QNetworkManagerNetworkInformationBackend::onStateChanged( + QNetworkManagerInterface::NMState newState) +{ + setReachability(reachabilityFromNMState(newState)); +} + +void QNetworkManagerNetworkInformationBackend::onConnectivityChanged( + QNetworkManagerInterface::NMConnectivityState connectivityState) +{ + const bool behindPortal = + (connectivityState == QNetworkManagerInterface::NM_CONNECTIVITY_PORTAL); + setBehindCaptivePortal(behindPortal); +} + +void QNetworkManagerNetworkInformationBackend::onDeviceTypeChanged( + QNetworkManagerInterface::NMDeviceType newDevice) +{ + setTransportMedium(transportMediumFromDeviceType(newDevice)); +} + +void QNetworkManagerNetworkInformationBackend::onMeteredChanged( + QNetworkManagerInterface::NMMetered metered) +{ + setMetered(isMeteredFromNMMetered(metered)); +}; + +QT_END_NAMESPACE + +#include "qnetworkmanagernetworkinformationbackend.moc" +#include "moc_qnetworkmanagernetworkinformationbackend.cpp" diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h new file mode 100644 index 0000000000..3b60f0949c --- /dev/null +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h @@ -0,0 +1,60 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNETWORKMANAGERINFORMATIONBACKEND_H +#define QNETWORKMANAGERINFORMATIONBACKEND_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtNetwork/private/qnetworkinformation_p.h> +#include "qnetworkmanagerservice.h" + +QT_BEGIN_NAMESPACE + +class QNetworkManagerNetworkInformationBackend : public QNetworkInformationBackend +{ + Q_OBJECT +public: + QNetworkManagerNetworkInformationBackend(); + ~QNetworkManagerNetworkInformationBackend() = default; + + QString name() const override; + QNetworkInformation::Features featuresSupported() const override + { + if (!isValid()) + return {}; + return featuresSupportedStatic(); + } + + static QNetworkInformation::Features featuresSupportedStatic() + { + using Feature = QNetworkInformation::Feature; + return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal + | Feature::TransportMedium | Feature::Metered); + } + + bool isValid() const { return iface.isValid(); } + + void onStateChanged(QNetworkManagerInterface::NMState state); + void onConnectivityChanged(QNetworkManagerInterface::NMConnectivityState connectivityState); + void onDeviceTypeChanged(QNetworkManagerInterface::NMDeviceType deviceType); + void onMeteredChanged(QNetworkManagerInterface::NMMetered metered); + +private: + Q_DISABLE_COPY_MOVE(QNetworkManagerNetworkInformationBackend) + + QNetworkManagerInterface iface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp new file mode 100644 index 0000000000..c055555cac --- /dev/null +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp @@ -0,0 +1,220 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qnetworkmanagerservice.h" +#include "qnetworkmanagernetworkinformationbackend.h" + +#include <QObject> +#include <QList> +#include <QtDBus/QDBusConnection> +#include <QtDBus/QDBusError> +#include <QtDBus/QDBusInterface> +#include <QtDBus/QDBusMessage> +#include <QtDBus/QDBusReply> +#include <QtDBus/QDBusPendingCallWatcher> +#include <QtDBus/QDBusObjectPath> +#include <QtDBus/QDBusPendingCall> + +#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"_L1 + +#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" +#define NM_DBUS_SERVICE NM_DBUS_INTERFACE ""_L1 + +#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"_L1 +#define NM_CONNECTION_DBUS_INTERFACE NM_DBUS_SERVICE ".Connection.Active"_L1 +#define NM_DEVICE_DBUS_INTERFACE NM_DBUS_SERVICE ".Device"_L1 + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +namespace { +constexpr QLatin1StringView propertiesChangedKey = "PropertiesChanged"_L1; +const QString &stateKey() +{ + static auto key = u"State"_s; + return key; +} +const QString &connectivityKey() +{ + static auto key = u"Connectivity"_s; + return key; +} +const QString &primaryConnectionKey() +{ + static auto key = u"PrimaryConnection"_s; + return key; +} +} + +QNetworkManagerInterfaceBase::QNetworkManagerInterfaceBase(QObject *parent) + : QDBusAbstractInterface(NM_DBUS_SERVICE, NM_DBUS_PATH, + NM_DBUS_INTERFACE, QDBusConnection::systemBus(), parent) +{ +} + +bool QNetworkManagerInterfaceBase::networkManagerAvailable() +{ + return QNetworkManagerInterfaceBase().isValid(); +} + +QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent) + : QNetworkManagerInterfaceBase(parent) +{ + if (!QDBusAbstractInterface::isValid()) + return; + + PropertiesDBusInterface managerPropertiesInterface( + NM_DBUS_SERVICE, NM_DBUS_PATH, DBUS_PROPERTIES_INTERFACE, + QDBusConnection::systemBus()); + QList<QVariant> argumentList; + argumentList << NM_DBUS_SERVICE; + QDBusPendingReply<QVariantMap> propsReply = managerPropertiesInterface.callWithArgumentList( + QDBus::Block, "GetAll"_L1, argumentList); + if (propsReply.isError()) { + validDBusConnection = false; + if (auto error = propsReply.error(); error.type() != QDBusError::AccessDenied) + qWarning() << "Failed to query NetworkManager properties:" << error.message(); + return; + } + propertyMap = propsReply.value(); + + validDBusConnection = QDBusConnection::systemBus().connect(NM_DBUS_SERVICE, NM_DBUS_PATH, + DBUS_PROPERTIES_INTERFACE, propertiesChangedKey, this, + SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>))); +} + +QNetworkManagerInterface::~QNetworkManagerInterface() +{ + QDBusConnection::systemBus().disconnect(NM_DBUS_SERVICE, NM_DBUS_PATH, + DBUS_PROPERTIES_INTERFACE, propertiesChangedKey, this, + SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>))); +} + +QNetworkManagerInterface::NMState QNetworkManagerInterface::state() const +{ + auto it = propertyMap.constFind(stateKey()); + if (it != propertyMap.cend()) + return static_cast<QNetworkManagerInterface::NMState>(it->toUInt()); + return QNetworkManagerInterface::NM_STATE_UNKNOWN; +} + +QNetworkManagerInterface::NMConnectivityState QNetworkManagerInterface::connectivityState() const +{ + auto it = propertyMap.constFind(connectivityKey()); + if (it != propertyMap.cend()) + return static_cast<NMConnectivityState>(it->toUInt()); + return QNetworkManagerInterface::NM_CONNECTIVITY_UNKNOWN; +} + +static std::optional<QDBusInterface> getPrimaryDevice(const QDBusObjectPath &devicePath) +{ + const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(), + NM_CONNECTION_DBUS_INTERFACE, QDBusConnection::systemBus()); + if (!connection.isValid()) + return std::nullopt; + + const auto devicePaths = connection.property("Devices").value<QList<QDBusObjectPath>>(); + if (devicePaths.isEmpty()) + return std::nullopt; + + const QDBusObjectPath primaryDevicePath = devicePaths.front(); + return std::make_optional<QDBusInterface>(NM_DBUS_SERVICE, primaryDevicePath.path(), + NM_DEVICE_DBUS_INTERFACE, + QDBusConnection::systemBus()); +} + +std::optional<QDBusObjectPath> QNetworkManagerInterface::primaryConnectionDevicePath() const +{ + auto it = propertyMap.constFind(primaryConnectionKey()); + if (it != propertyMap.cend()) + return it->value<QDBusObjectPath>(); + return std::nullopt; +} + +auto QNetworkManagerInterface::deviceType() const -> NMDeviceType +{ + if (const auto path = primaryConnectionDevicePath()) + return extractDeviceType(*path); + return NM_DEVICE_TYPE_UNKNOWN; +} + +auto QNetworkManagerInterface::meteredState() const -> NMMetered +{ + if (const auto path = primaryConnectionDevicePath()) + return extractDeviceMetered(*path); + return NM_METERED_UNKNOWN; +} + +auto QNetworkManagerInterface::extractDeviceType(const QDBusObjectPath &devicePath) const + -> NMDeviceType +{ + const auto primaryDevice = getPrimaryDevice(devicePath); + if (!primaryDevice) + return NM_DEVICE_TYPE_UNKNOWN; + if (!primaryDevice->isValid()) + return NM_DEVICE_TYPE_UNKNOWN; + const QVariant deviceType = primaryDevice->property("DeviceType"); + if (!deviceType.isValid()) + return NM_DEVICE_TYPE_UNKNOWN; + return static_cast<NMDeviceType>(deviceType.toUInt()); +} + +auto QNetworkManagerInterface::extractDeviceMetered(const QDBusObjectPath &devicePath) const + -> NMMetered +{ + const auto primaryDevice = getPrimaryDevice(devicePath); + if (!primaryDevice) + return NM_METERED_UNKNOWN; + if (!primaryDevice->isValid()) + return NM_METERED_UNKNOWN; + const QVariant metered = primaryDevice->property("Metered"); + if (!metered.isValid()) + return NM_METERED_UNKNOWN; + return static_cast<NMMetered>(metered.toUInt()); +} + +void QNetworkManagerInterface::setBackend(QNetworkManagerNetworkInformationBackend *ourBackend) +{ + backend = ourBackend; +} + +void QNetworkManagerInterface::setProperties(const QString &interfaceName, + const QMap<QString, QVariant> &map, + const QStringList &invalidatedProperties) +{ + Q_UNUSED(interfaceName); + Q_UNUSED(invalidatedProperties); + + for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) { + bool valueChanged = true; + + auto it = propertyMap.lowerBound(i.key()); + if (it != propertyMap.end() && it.key() == i.key()) { + valueChanged = (it.value() != i.value()); + *it = *i; + } else { + propertyMap.insert(it, i.key(), i.value()); + } + + if (valueChanged) { + if (i.key() == stateKey()) { + quint32 state = i.value().toUInt(); + backend->onStateChanged(static_cast<NMState>(state)); + } else if (i.key() == connectivityKey()) { + quint32 state = i.value().toUInt(); + backend->onConnectivityChanged(static_cast<NMConnectivityState>(state)); + } else if (i.key() == primaryConnectionKey()) { + const QDBusObjectPath devicePath = i->value<QDBusObjectPath>(); + backend->onDeviceTypeChanged(extractDeviceType(devicePath)); + backend->onMeteredChanged(extractDeviceMetered(devicePath)); + } else if (i.key() == "Metered"_L1) { + backend->onMeteredChanged(static_cast<NMMetered>(i->toUInt())); + } + } + } +} + +QT_END_NAMESPACE + +#include "moc_qnetworkmanagerservice.cpp" diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h new file mode 100644 index 0000000000..5201e8485b --- /dev/null +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h @@ -0,0 +1,173 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QNETWORKMANAGERSERVICE_H +#define QNETWORKMANAGERSERVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qvariant.h> +#include <QtCore/qmap.h> +#include <QtDBus/qdbusabstractinterface.h> + +#include <optional> + +// Matches 'NMDeviceState' from https://developer.gnome.org/NetworkManager/stable/nm-dbus-types.html +enum NMDeviceState { + NM_DEVICE_STATE_UNKNOWN = 0, + NM_DEVICE_STATE_UNMANAGED = 10, + NM_DEVICE_STATE_UNAVAILABLE = 20, + NM_DEVICE_STATE_DISCONNECTED = 30, + NM_DEVICE_STATE_PREPARE = 40, + NM_DEVICE_STATE_CONFIG = 50, + NM_DEVICE_STATE_NEED_AUTH = 60, + NM_DEVICE_STATE_IP_CONFIG = 70, + NM_DEVICE_STATE_ACTIVATED = 100, + NM_DEVICE_STATE_DEACTIVATING = 110, + NM_DEVICE_STATE_FAILED = 120 +}; + +QT_BEGIN_NAMESPACE + +class QDBusObjectPath; +class QNetworkManagerNetworkInformationBackend; + +// This tiny class exists for the purpose of seeing if NetworkManager is available without +// initializing everything the derived/full class needs. +class QNetworkManagerInterfaceBase : public QDBusAbstractInterface +{ + Q_OBJECT +public: + explicit QNetworkManagerInterfaceBase(QObject *parent = nullptr); + ~QNetworkManagerInterfaceBase() = default; + + static bool networkManagerAvailable(); + +private: + Q_DISABLE_COPY_MOVE(QNetworkManagerInterfaceBase) +}; + +class QNetworkManagerInterface final : public QNetworkManagerInterfaceBase +{ + Q_OBJECT + +public: + // Matches 'NMState' from https://developer.gnome.org/NetworkManager/stable/nm-dbus-types.html + enum NMState { + NM_STATE_UNKNOWN = 0, + NM_STATE_ASLEEP = 10, + NM_STATE_DISCONNECTED = 20, + NM_STATE_DISCONNECTING = 30, + NM_STATE_CONNECTING = 40, + NM_STATE_CONNECTED_LOCAL = 50, + NM_STATE_CONNECTED_SITE = 60, + NM_STATE_CONNECTED_GLOBAL = 70 + }; + Q_ENUM(NMState); + // Matches 'NMConnectivityState' from + // https://developer.gnome.org/NetworkManager/stable/nm-dbus-types.html#NMConnectivityState + enum NMConnectivityState { + NM_CONNECTIVITY_UNKNOWN = 0, + NM_CONNECTIVITY_NONE = 1, + NM_CONNECTIVITY_PORTAL = 2, + NM_CONNECTIVITY_LIMITED = 3, + NM_CONNECTIVITY_FULL = 4, + }; + Q_ENUM(NMConnectivityState); + // Matches 'NMDeviceType' from + // https://developer-old.gnome.org/NetworkManager/stable/nm-dbus-types.html#NMDeviceType + enum NMDeviceType { + NM_DEVICE_TYPE_UNKNOWN = 0, + NM_DEVICE_TYPE_GENERIC = 14, + NM_DEVICE_TYPE_ETHERNET = 1, + NM_DEVICE_TYPE_WIFI = 2, + NM_DEVICE_TYPE_UNUSED1 = 3, + NM_DEVICE_TYPE_UNUSED2 = 4, + NM_DEVICE_TYPE_BT = 5, + NM_DEVICE_TYPE_OLPC_MESH = 6, + NM_DEVICE_TYPE_WIMAX = 7, + NM_DEVICE_TYPE_MODEM = 8, + NM_DEVICE_TYPE_INFINIBAND = 9, + NM_DEVICE_TYPE_BOND = 10, + NM_DEVICE_TYPE_VLAN = 11, + NM_DEVICE_TYPE_ADSL = 12, + NM_DEVICE_TYPE_BRIDGE = 13, + NM_DEVICE_TYPE_TEAM = 15, + NM_DEVICE_TYPE_TUN = 16, + NM_DEVICE_TYPE_IP_TUNNEL = 17, + NM_DEVICE_TYPE_MACVLAN = 18, + NM_DEVICE_TYPE_VXLAN = 19, + NM_DEVICE_TYPE_VETH = 20, + NM_DEVICE_TYPE_MACSEC = 21, + NM_DEVICE_TYPE_DUMMY = 22, + NM_DEVICE_TYPE_PPP = 23, + NM_DEVICE_TYPE_OVS_INTERFACE = 24, + NM_DEVICE_TYPE_OVS_PORT = 25, + NM_DEVICE_TYPE_OVS_BRIDGE = 26, + NM_DEVICE_TYPE_WPAN = 27, + NM_DEVICE_TYPE_6LOWPAN = 28, + NM_DEVICE_TYPE_WIREGUARD = 29, + NM_DEVICE_TYPE_WIFI_P2P = 30, + NM_DEVICE_TYPE_VRF = 31, + }; + // Matches 'NMMetered' from + // https://developer-old.gnome.org/NetworkManager/stable/nm-dbus-types.html#NMMetered + enum NMMetered { + NM_METERED_UNKNOWN, + NM_METERED_YES, + NM_METERED_NO, + NM_METERED_GUESS_YES, + NM_METERED_GUESS_NO, + }; + + explicit QNetworkManagerInterface(QObject *parent = nullptr); + ~QNetworkManagerInterface(); + + void setBackend(QNetworkManagerNetworkInformationBackend *ourBackend); + + NMState state() const; + NMConnectivityState connectivityState() const; + NMDeviceType deviceType() const; + NMMetered meteredState() const; + + bool isValid() const { return QDBusAbstractInterface::isValid() && validDBusConnection; } + +private Q_SLOTS: + void setProperties(const QString &interfaceName, const QMap<QString, QVariant> &map, + const QStringList &invalidatedProperties); + +private: + Q_DISABLE_COPY_MOVE(QNetworkManagerInterface) + + NMDeviceType extractDeviceType(const QDBusObjectPath &devicePath) const; + NMMetered extractDeviceMetered(const QDBusObjectPath &devicePath) const; + + std::optional<QDBusObjectPath> primaryConnectionDevicePath() const; + + QVariantMap propertyMap; + QNetworkManagerNetworkInformationBackend *backend = nullptr; + bool validDBusConnection = true; +}; + +class PropertiesDBusInterface : public QDBusAbstractInterface +{ +public: + PropertiesDBusInterface(const QString &service, const QString &path, const QString &interface, + const QDBusConnection &connection, QObject *parent = nullptr) + : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent) + { + } +}; + +QT_END_NAMESPACE + +#endif |