1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtNetwork/private/qnetworkinformation_p.h>
5
6#include "qnetworkmanagerservice.h"
7
8#include <QtCore/qglobal.h>
9#include <QtCore/private/qobject_p.h>
10
11#include <QtDBus/qdbusmessage.h>
12
13QT_BEGIN_NAMESPACE
14Q_DECLARE_LOGGING_CATEGORY(lcNetInfoNLM)
15Q_LOGGING_CATEGORY(lcNetInfoNM, "qt.network.info.networkmanager");
16
17namespace {
18QNetworkInformation::Reachability reachabilityFromNMState(QNetworkManagerInterface::NMState state)
19{
20 switch (state) {
21 case QNetworkManagerInterface::NM_STATE_UNKNOWN:
22 case QNetworkManagerInterface::NM_STATE_ASLEEP:
23 case QNetworkManagerInterface::NM_STATE_CONNECTING:
24 return QNetworkInformation::Reachability::Unknown;
25 case QNetworkManagerInterface::NM_STATE_DISCONNECTING: // No point in starting new connections:
26 case QNetworkManagerInterface::NM_STATE_DISCONNECTED:
27 return QNetworkInformation::Reachability::Disconnected;
28 case QNetworkManagerInterface::NM_STATE_CONNECTED_LOCAL:
29 return QNetworkInformation::Reachability::Local;
30 case QNetworkManagerInterface::NM_STATE_CONNECTED_SITE:
31 return QNetworkInformation::Reachability::Site;
32 case QNetworkManagerInterface::NM_STATE_CONNECTED_GLOBAL:
33 return QNetworkInformation::Reachability::Online;
34 }
35 return QNetworkInformation::Reachability::Unknown;
36}
37
38QNetworkInformation::TransportMedium
39transportMediumFromDeviceType(QNetworkManagerInterface::NMDeviceType type)
40{
41 switch (type) {
42 case QNetworkManagerInterface::NM_DEVICE_TYPE_ETHERNET:
43 return QNetworkInformation::TransportMedium::Ethernet;
44 case QNetworkManagerInterface::NM_DEVICE_TYPE_WIFI:
45 return QNetworkInformation::TransportMedium::WiFi;
46 case QNetworkManagerInterface::NM_DEVICE_TYPE_BT:
47 return QNetworkInformation::TransportMedium::Bluetooth;
48 case QNetworkManagerInterface::NM_DEVICE_TYPE_MODEM:
49 return QNetworkInformation::TransportMedium::Cellular;
50
51 case QNetworkManagerInterface::NM_DEVICE_TYPE_UNKNOWN:
52 case QNetworkManagerInterface::NM_DEVICE_TYPE_GENERIC:
53 case QNetworkManagerInterface::NM_DEVICE_TYPE_UNUSED1:
54 case QNetworkManagerInterface::NM_DEVICE_TYPE_UNUSED2:
55 case QNetworkManagerInterface::NM_DEVICE_TYPE_OLPC_MESH:
56 case QNetworkManagerInterface::NM_DEVICE_TYPE_WIMAX:
57 case QNetworkManagerInterface::NM_DEVICE_TYPE_INFINIBAND:
58 case QNetworkManagerInterface::NM_DEVICE_TYPE_BOND:
59 case QNetworkManagerInterface::NM_DEVICE_TYPE_VLAN:
60 case QNetworkManagerInterface::NM_DEVICE_TYPE_ADSL:
61 case QNetworkManagerInterface::NM_DEVICE_TYPE_BRIDGE:
62 case QNetworkManagerInterface::NM_DEVICE_TYPE_TEAM:
63 case QNetworkManagerInterface::NM_DEVICE_TYPE_TUN:
64 case QNetworkManagerInterface::NM_DEVICE_TYPE_IP_TUNNEL:
65 case QNetworkManagerInterface::NM_DEVICE_TYPE_MACVLAN:
66 case QNetworkManagerInterface::NM_DEVICE_TYPE_VXLAN:
67 case QNetworkManagerInterface::NM_DEVICE_TYPE_VETH:
68 case QNetworkManagerInterface::NM_DEVICE_TYPE_MACSEC:
69 case QNetworkManagerInterface::NM_DEVICE_TYPE_DUMMY:
70 case QNetworkManagerInterface::NM_DEVICE_TYPE_PPP:
71 case QNetworkManagerInterface::NM_DEVICE_TYPE_OVS_INTERFACE:
72 case QNetworkManagerInterface::NM_DEVICE_TYPE_OVS_PORT:
73 case QNetworkManagerInterface::NM_DEVICE_TYPE_OVS_BRIDGE:
74 case QNetworkManagerInterface::NM_DEVICE_TYPE_WPAN:
75 case QNetworkManagerInterface::NM_DEVICE_TYPE_6LOWPAN:
76 case QNetworkManagerInterface::NM_DEVICE_TYPE_WIREGUARD:
77 case QNetworkManagerInterface::NM_DEVICE_TYPE_WIFI_P2P:
78 case QNetworkManagerInterface::NM_DEVICE_TYPE_VRF:
79 break;
80 }
81 // While the list is exhaustive of the enum there can be additional
82 // entries added in NetworkManager that isn't listed here
83 return QNetworkInformation::TransportMedium::Unknown;
84}
85
86bool isMeteredFromNMMetered(QNetworkManagerInterface::NMMetered metered)
87{
88 switch (metered) {
89 case QNetworkManagerInterface::NM_METERED_YES:
90 case QNetworkManagerInterface::NM_METERED_GUESS_YES:
91 return true;
92 case QNetworkManagerInterface::NM_METERED_NO:
93 case QNetworkManagerInterface::NM_METERED_GUESS_NO:
94 case QNetworkManagerInterface::NM_METERED_UNKNOWN:
95 return false;
96 }
97 Q_UNREACHABLE_RETURN(false);
98}
99} // unnamed namespace
100
101static QString backendName()
102{
103 return QString::fromUtf16(QNetworkInformationBackend::PluginNames
104 [QNetworkInformationBackend::PluginNamesLinuxIndex]);
105}
106
107class QNetworkManagerNetworkInformationBackend : public QNetworkInformationBackend
108{
109 Q_OBJECT
110public:
111 QNetworkManagerNetworkInformationBackend();
112 ~QNetworkManagerNetworkInformationBackend() = default;
113
114 QString name() const override { return backendName(); }
115 QNetworkInformation::Features featuresSupported() const override
116 {
117 if (!isValid())
118 return {};
119 return featuresSupportedStatic();
120 }
121
122 static QNetworkInformation::Features featuresSupportedStatic()
123 {
124 using Feature = QNetworkInformation::Feature;
125 return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal
126 | Feature::TransportMedium | Feature::Metered);
127 }
128
129 bool isValid() const { return iface.isValid(); }
130
131private:
132 Q_DISABLE_COPY_MOVE(QNetworkManagerNetworkInformationBackend)
133
134 QNetworkManagerInterface iface;
135};
136
137class QNetworkManagerNetworkInformationBackendFactory : public QNetworkInformationBackendFactory
138{
139 Q_OBJECT
140 Q_PLUGIN_METADATA(IID QNetworkInformationBackendFactory_iid)
141 Q_INTERFACES(QNetworkInformationBackendFactory)
142public:
143 QNetworkManagerNetworkInformationBackendFactory() = default;
144 ~QNetworkManagerNetworkInformationBackendFactory() = default;
145 QString name() const override { return backendName(); }
146 QNetworkInformation::Features featuresSupported() const override
147 {
148 if (!QNetworkManagerInterfaceBase::networkManagerAvailable())
149 return {};
150 return QNetworkManagerNetworkInformationBackend::featuresSupportedStatic();
151 }
152
153 QNetworkInformationBackend *create(QNetworkInformation::Features requiredFeatures) const override
154 {
155 if ((requiredFeatures & featuresSupported()) != requiredFeatures)
156 return nullptr;
157 if (!QNetworkManagerInterfaceBase::networkManagerAvailable())
158 return nullptr;
159 auto backend = new QNetworkManagerNetworkInformationBackend();
160 if (!backend->isValid())
161 delete std::exchange(obj&: backend, new_val: nullptr);
162 return backend;
163 }
164private:
165 Q_DISABLE_COPY_MOVE(QNetworkManagerNetworkInformationBackendFactory)
166};
167
168QNetworkManagerNetworkInformationBackend::QNetworkManagerNetworkInformationBackend()
169{
170 auto updateReachability = [this](QNetworkManagerInterface::NMState newState) {
171 setReachability(reachabilityFromNMState(state: newState));
172 };
173 updateReachability(iface.state());
174 connect(sender: &iface, signal: &QNetworkManagerInterface::stateChanged, context: this, slot: std::move(updateReachability));
175
176 auto updateBehindCaptivePortal = [this](QNetworkManagerInterface::NMConnectivityState state) {
177 const bool behindPortal = (state == QNetworkManagerInterface::NM_CONNECTIVITY_PORTAL);
178 setBehindCaptivePortal(behindPortal);
179 };
180 updateBehindCaptivePortal(iface.connectivityState());
181 connect(sender: &iface, signal: &QNetworkManagerInterface::connectivityChanged, context: this,
182 slot: std::move(updateBehindCaptivePortal));
183
184 auto updateTransportMedium = [this](QNetworkManagerInterface::NMDeviceType newDevice) {
185 setTransportMedium(transportMediumFromDeviceType(type: newDevice));
186 };
187 updateTransportMedium(iface.deviceType());
188 connect(sender: &iface, signal: &QNetworkManagerInterface::deviceTypeChanged, context: this,
189 slot: std::move(updateTransportMedium));
190
191 auto updateMetered = [this](QNetworkManagerInterface::NMMetered metered) {
192 setMetered(isMeteredFromNMMetered(metered));
193 };
194 updateMetered(iface.meteredState());
195 connect(sender: &iface, signal: &QNetworkManagerInterface::meteredChanged, context: this, slot: std::move(updateMetered));
196}
197
198QT_END_NAMESPACE
199
200#include "qnetworkmanagernetworkinformationbackend.moc"
201

source code of qtbase/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp