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