QNetworkInformation: support transportMedium with NetworkManager

Task-number: QTBUG-91023
Change-Id: Ie50e29ec321768ec6d0358d96a8c36b9b7cb10ba
Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Mårten Nordheim 2021-09-24 17:44:54 +02:00
parent 5b8a4c2063
commit 5d2fa94297
3 changed files with 135 additions and 6 deletions

View File

@ -70,6 +70,54 @@ QNetworkInformation::Reachability reachabilityFromNMState(QNetworkManagerInterfa
}
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;
}
}
static QString backendName = QStringLiteral("networkmanager");
@ -92,7 +140,8 @@ public:
static QNetworkInformation::Features featuresSupportedStatic()
{
using Feature = QNetworkInformation::Feature;
return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal);
return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal
| Feature::TransportMedium);
}
bool isValid() const { return iface.isValid(); }
@ -154,6 +203,14 @@ QNetworkManagerNetworkInformationBackend::QNetworkManagerNetworkInformationBacke
const bool behindPortal = (state == ConnectivityState::NM_CONNECTIVITY_PORTAL);
setBehindCaptivePortal(behindPortal);
});
using NMDeviceType = QNetworkManagerInterface::NMDeviceType;
setTransportMedium(transportMediumFromDeviceType(iface.deviceType()));
connect(&iface, &QNetworkManagerInterface::deviceTypeChanged, this,
[this](NMDeviceType newDevice) {
setTransportMedium(transportMediumFromDeviceType(newDevice));
});
}
QT_END_NAMESPACE

View File

@ -52,6 +52,13 @@
#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager"
#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"
#define NM_DBUS_INTERFACE NM_DBUS_SERVICE
#define NM_CONNECTION_DBUS_INTERFACE NM_DBUS_SERVICE ".Connection.Active"
#define NM_DEVICE_DBUS_INTERFACE NM_DBUS_SERVICE ".Device"
QT_BEGIN_NAMESPACE
QNetworkManagerInterfaceBase::QNetworkManagerInterfaceBase(QObject *parent)
@ -112,6 +119,34 @@ QNetworkManagerInterface::NMConnectivityState QNetworkManagerInterface::connecti
return QNetworkManagerInterface::NM_CONNECTIVITY_UNKNOWN;
}
QNetworkManagerInterface::NMDeviceType QNetworkManagerInterface::deviceType() const
{
auto it = propertyMap.constFind("PrimaryConnection");
if (it != propertyMap.cend())
return extractDeviceType(it->value<QDBusObjectPath>());
return NM_DEVICE_TYPE_UNKNOWN;
}
auto QNetworkManagerInterface::extractDeviceType(QDBusObjectPath devicePath) const -> NMDeviceType
{
const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(),
NM_CONNECTION_DBUS_INTERFACE, QDBusConnection::systemBus());
if (!connection.isValid())
return NM_DEVICE_TYPE_UNKNOWN;
const auto devicePaths = connection.property("Devices").value<QList<QDBusObjectPath>>();
if (devicePaths.isEmpty())
return NM_DEVICE_TYPE_UNKNOWN;
const QDBusObjectPath primaryDevicePath = devicePaths.front();
const QDBusInterface device(NM_DBUS_SERVICE, primaryDevicePath.path(), NM_DEVICE_DBUS_INTERFACE,
QDBusConnection::systemBus());
const QVariant deviceType = device.property("DeviceType");
if (!deviceType.isValid())
return NM_DEVICE_TYPE_UNKNOWN;
return static_cast<NMDeviceType>(deviceType.toUInt());
}
void QNetworkManagerInterface::setProperties(const QMap<QString, QVariant> &map)
{
for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) {
@ -132,6 +167,8 @@ void QNetworkManagerInterface::setProperties(const QMap<QString, QVariant> &map)
} else if (i.key() == QLatin1String("Connectivity")) {
quint32 state = i.value().toUInt();
Q_EMIT connectivityChanged(static_cast<NMConnectivityState>(state));
} else if (i.key() == QLatin1String("PrimaryConnection")) {
Q_EMIT deviceTypeChanged(extractDeviceType(i->value<QDBusObjectPath>()));
}
}
}

View File

@ -55,11 +55,6 @@
#include <QtDBus/QDBusPendingCallWatcher>
#include <QtDBus/QDBusObjectPath>
#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager"
#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"
#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
// Matches 'NMDeviceState' from https://developer.gnome.org/NetworkManager/stable/nm-dbus-types.html
enum NMDeviceState {
NM_DEVICE_STATE_UNKNOWN = 0,
@ -119,16 +114,54 @@ public:
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,
};
QNetworkManagerInterface(QObject *parent = nullptr);
~QNetworkManagerInterface();
NMState state() const;
NMConnectivityState connectivityState() const;
NMDeviceType deviceType() const;
Q_SIGNALS:
void stateChanged(NMState);
void connectivityChanged(NMConnectivityState);
void deviceTypeChanged(NMDeviceType);
private Q_SLOTS:
void setProperties(const QMap<QString, QVariant> &map);
@ -136,6 +169,8 @@ private Q_SLOTS:
private:
Q_DISABLE_COPY_MOVE(QNetworkManagerInterface)
NMDeviceType extractDeviceType(QDBusObjectPath devicePath) const;
QVariantMap propertyMap;
};