summaryrefslogtreecommitdiffstats
path: root/src/plugins/networkinformation/networkmanager
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/networkinformation/networkmanager')
-rw-r--r--src/plugins/networkinformation/networkmanager/CMakeLists.txt17
-rw-r--r--src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp181
-rw-r--r--src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h60
-rw-r--r--src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp220
-rw-r--r--src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h173
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