Skip to content

Commit b031b02

Browse files
committed
network: add WifiScanner
- Add WifiScanner to replace requestScan in API - Implement NM scanner that avoids rate limit - Add conditional visibility to networks based on scanner state - Add gates to backend-specific props in the manual test
1 parent 6e227a7 commit b031b02

File tree

15 files changed

+293
-179
lines changed

15 files changed

+293
-179
lines changed

src/network/device.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ QString DeviceType::toString(DeviceType::Enum type) {
3131
}
3232
}
3333

34+
QString NMDeviceState::toString(NMDeviceState::Enum state) {
35+
switch (state) {
36+
case Unknown: return QStringLiteral("Unknown");
37+
case Unmanaged: return QStringLiteral("Not managed by NetworkManager");
38+
case Unavailable: return QStringLiteral("Unavailable");
39+
case Disconnected: return QStringLiteral("Disconnected");
40+
case Prepare: return QStringLiteral("Preparing to connect");
41+
case Config: return QStringLiteral("Connecting to a network");
42+
case NeedAuth: return QStringLiteral("Waiting for authentication");
43+
case IPConfig: return QStringLiteral("Requesting IPv4 and/or IPv6 addresses from the network");
44+
case IPCheck:
45+
return QStringLiteral("Checking whether further action is required for the requested connection"
46+
);
47+
case Secondaries:
48+
return QStringLiteral("Waiting for a required secondary connection to activate");
49+
case Activated: return QStringLiteral("Connected");
50+
case Deactivating: return QStringLiteral("Disconnecting");
51+
case Failed: return QStringLiteral("Failed to connect");
52+
};
53+
}
54+
3455
NetworkDevice::NetworkDevice(DeviceType::Enum type, QObject* parent)
3556
: QObject(parent)
3657
, mType(type) {};

src/network/device.hpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
#include <qtmetamacros.h>
77
#include <qtypes.h>
88

9-
#include "nm/enums.hpp"
10-
119
namespace qs::network {
1210

1311
///! Connection state of a NetworkDevice.
@@ -43,6 +41,33 @@ class DeviceType: public QObject {
4341
Q_INVOKABLE static QString toString(DeviceType::Enum type);
4442
};
4543

44+
///! NetworkManager-specific device state.
45+
/// In sync with https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMDeviceState.
46+
class NMDeviceState: public QObject {
47+
Q_OBJECT;
48+
QML_ELEMENT;
49+
QML_SINGLETON;
50+
51+
public:
52+
enum Enum : quint8 {
53+
Unknown = 0,
54+
Unmanaged = 10,
55+
Unavailable = 20,
56+
Disconnected = 30,
57+
Prepare = 40,
58+
Config = 50,
59+
NeedAuth = 60,
60+
IPConfig = 70,
61+
IPCheck = 80,
62+
Secondaries = 90,
63+
Activated = 100,
64+
Deactivating = 110,
65+
Failed = 120,
66+
};
67+
Q_ENUM(Enum);
68+
Q_INVOKABLE static QString toString(NMDeviceState::Enum state);
69+
};
70+
4671
///! A network device.
4772
class NetworkDevice: public QObject {
4873
Q_OBJECT;

src/network/nm/backend.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void NetworkManager::registerDevice(const QString& path) {
114114
while (!xml.atEnd() && !xml.hasError()) {
115115
xml.readNext();
116116

117-
if (xml.isStartElement() && xml.name() == "interface") {
117+
if (xml.isStartElement() && xml.name() == u"interface") {
118118
const QString name = xml.attributes().value("name").toString();
119119
if (name.startsWith("org.freedesktop.NetworkManager.Device.Wireless")) {
120120
this->registerWifiDevice(path);
@@ -139,6 +139,7 @@ void NetworkManager::registerWifiDevice(const QString& path) {
139139
}
140140

141141
auto* device = new WifiDevice(this);
142+
auto* scanner = device->wifiScanner();
142143
wireless->setParent(device);
143144
this->mDeviceHash.insert(path, device);
144145

@@ -154,13 +155,12 @@ void NetworkManager::registerWifiDevice(const QString& path) {
154155
case 110 ... 120: return DeviceConnectionState::Disconnecting;
155156
}
156157
});
157-
device->bindableScanning().setBinding([wireless]() { return wireless->scanning(); });
158158
// clang-format off
159159
QObject::connect(wireless, &NMWirelessDevice::addAndActivateConnection, this, &NetworkManager::addAndActivateConnection);
160160
QObject::connect(wireless, &NMWirelessDevice::activateConnection, this, &NetworkManager::activateConnection);
161-
QObject::connect(wireless, &NMWirelessDevice::wifiNetworkAdded, device, &WifiDevice::networkAdded);
162-
QObject::connect(wireless, &NMWirelessDevice::wifiNetworkRemoved, device, &WifiDevice::networkRemoved);
163-
QObject::connect(device, &WifiDevice::requestScan, wireless, &NMWirelessDevice::scan);
161+
QObject::connect(wireless, &NMWirelessDevice::networkAdded, device, &WifiDevice::networkAdded);
162+
QObject::connect(wireless, &NMWirelessDevice::networkRemoved, device, &WifiDevice::networkRemoved);
163+
QObject::connect(scanner, &WifiScanner::requestEnabled, wireless, &NMWirelessDevice::handleScanner);
164164
QObject::connect(device, &WifiDevice::requestDisconnect, wireless, &NMWirelessDevice::disconnect);
165165
// clang-format on
166166

src/network/nm/connection.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "../../core/logcat.hpp"
1616
#include "../../dbus/properties.hpp"
17+
#include "../wifi.hpp"
1718
#include "dbus_types.hpp"
1819
#include "enums.hpp"
1920
#include "nm/dbus_nm_active_connection.h"

src/network/nm/connection.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <qtypes.h>
1010

1111
#include "../../dbus/properties.hpp"
12+
#include "../wifi.hpp"
1213
#include "dbus_types.hpp"
1314
#include "enums.hpp"
1415
#include "nm/dbus_nm_active_connection.h"

src/network/nm/device.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#include "../../core/logcat.hpp"
1616
#include "../../dbus/properties.hpp"
17-
#include "enums.hpp"
1817
#include "nm/dbus_nm_device.h"
1918

2019
namespace qs::network {

src/network/nm/device.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#include "../../dbus/properties.hpp"
1111
#include "connection.hpp"
12-
#include "enums.hpp"
1312
#include "nm/dbus_nm_device.h"
1413

1514
namespace qs::dbus {

src/network/nm/enums.hpp

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -33,52 +33,6 @@ class NMWirelessCapabilities: public QObject {
3333
Q_ENUM(Enum);
3434
};
3535

36-
// In sync with https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMDeviceState.
37-
class NMDeviceState: public QObject {
38-
Q_OBJECT;
39-
QML_ELEMENT;
40-
QML_SINGLETON;
41-
42-
public:
43-
enum Enum : quint8 {
44-
Unknown = 0,
45-
Unmanaged = 10,
46-
Unavailable = 20,
47-
Disconnected = 30,
48-
Prepare = 40,
49-
Config = 50,
50-
NeedAuth = 60,
51-
IPConfig = 70,
52-
IPCheck = 80,
53-
Secondaries = 90,
54-
Activated = 100,
55-
Deactivating = 110,
56-
Failed = 120,
57-
};
58-
Q_ENUM(Enum);
59-
Q_INVOKABLE static QString toString(NMDeviceState::Enum state) {
60-
switch (state) {
61-
case Unknown: return QStringLiteral("Unknown");
62-
case Unmanaged: return QStringLiteral("Not managed by NetworkManager");
63-
case Unavailable: return QStringLiteral("Unavailable");
64-
case Disconnected: return QStringLiteral("Disconnected");
65-
case Prepare: return QStringLiteral("Preparing to connect");
66-
case Config: return QStringLiteral("Connecting to a network");
67-
case NeedAuth: return QStringLiteral("Waiting for authentication");
68-
case IPConfig: return QStringLiteral("Requesting IPv4 and/or IPv6 addresses from the network");
69-
case IPCheck:
70-
return QStringLiteral(
71-
"Checking whether further action is required for the requested connection"
72-
);
73-
case Secondaries:
74-
return QStringLiteral("Waiting for a required secondary connection to activate");
75-
case Activated: return QStringLiteral("Connected");
76-
case Deactivating: return QStringLiteral("Disconnecting");
77-
case Failed: return QStringLiteral("Failed to connect");
78-
};
79-
};
80-
};
81-
8236
// Indicates the 802.11 mode an access point is currently in.
8337
// In sync with https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NM80211Mode.
8438
class NM80211Mode: public QObject {
@@ -142,8 +96,6 @@ class NM80211ApSecurityFlags: public QObject {
14296
// In sync with https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMActiveConnectionState.
14397
class NMConnectionState: public QObject {
14498
Q_OBJECT;
145-
QML_ELEMENT;
146-
QML_SINGLETON;
14799

148100
public:
149101
enum Enum : quint8 {
@@ -154,63 +106,6 @@ class NMConnectionState: public QObject {
154106
Deactivated = 4
155107
};
156108
Q_ENUM(Enum);
157-
Q_INVOKABLE static QString toString(NMConnectionState::Enum state) {
158-
switch (state) {
159-
case Unknown: return "Unknown";
160-
case Activating: return "Activating";
161-
case Activated: return "Activated";
162-
case Deactivating: return "Deactivating";
163-
case Deactivated: return "Deactivated";
164-
}
165-
}
166-
};
167-
168-
// Active connection state reasons.
169-
// In sync with https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMActiveConnectionStateReason.
170-
class NMConnectionStateReason: public QObject {
171-
Q_OBJECT;
172-
QML_ELEMENT;
173-
QML_SINGLETON;
174-
175-
public:
176-
enum Enum : quint8 {
177-
Unknown = 0,
178-
None = 1,
179-
UserDisconnected = 2,
180-
DeviceDisconnected = 3,
181-
ServiceStopped = 4,
182-
IpConfigInvalid = 5,
183-
ConnectTimeout = 6,
184-
ServiceStartTimeout = 7,
185-
ServiceStartFailed = 8,
186-
NoSecrets = 9,
187-
LoginFailed = 10,
188-
ConnectionRemoved = 11,
189-
DependencyFailed = 12,
190-
DeviceRealizeFailed = 13,
191-
DeviceRemoved = 14
192-
};
193-
Q_ENUM(Enum);
194-
Q_INVOKABLE static QString toString(NMConnectionStateReason::Enum reason) {
195-
switch (reason) {
196-
case Unknown: return "Unknown";
197-
case None: return "No reason";
198-
case UserDisconnected: return "User disconnection";
199-
case DeviceDisconnected: return "The device the connection was using was disconnected.";
200-
case ServiceStopped: return "The service providing the VPN connection was stopped.";
201-
case IpConfigInvalid: return "The IP config of the active connection was invalid.";
202-
case ConnectTimeout: return "The connection attempt to the VPN service timed out.";
203-
case ServiceStartTimeout:
204-
return "A timeout occurred while starting the service providing the VPN connection.";
205-
case ServiceStartFailed: return "Starting the service providing the VPN connection failed.";
206-
case NoSecrets: return "Necessary secrets for the connection were not provided.";
207-
case LoginFailed: return "Authentication to the server failed.";
208-
case ConnectionRemoved: return "Necessary secrets for the connection were not provided.";
209-
case DependencyFailed: return " Master connection of this connection failed to activate.";
210-
case DeviceRealizeFailed: return "Could not create the software device link.";
211-
case DeviceRemoved: return "The device this connection depended on disappeared.";
212-
};
213-
};
214109
};
215110

216111
} // namespace qs::network

src/network/nm/utils.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
#include "utils.hpp"
22

3+
// We depend on non-std Linux extensions that ctime doesn't put in the global namespace
4+
// NOLINTNEXTLINE(modernize-deprecated-headers)
5+
#include <time.h>
6+
37
#include <qcontainerfwd.h>
8+
#include <qdatetime.h>
49
#include <qdbusservicewatcher.h>
510
#include <qobject.h>
611
#include <qqmlintegration.h>
12+
#include <qtypes.h>
713

814
#include "../wifi.hpp"
915
#include "dbus_types.hpp"
@@ -218,4 +224,25 @@ WifiSecurityType::Enum findBestWirelessSecurity(
218224
return WifiSecurityType::Unknown;
219225
}
220226

227+
// NOLINTBEGIN
228+
QDateTime clockBootTimeToDateTime(qint64 clockBootTime) {
229+
clockid_t clkId = CLOCK_BOOTTIME;
230+
struct timespec tp {};
231+
232+
const QDateTime now = QDateTime::currentDateTime();
233+
int r = clock_gettime(clkId, &tp);
234+
if (r == -1 && errno == EINVAL) {
235+
clkId = CLOCK_MONOTONIC;
236+
r = clock_gettime(clkId, &tp);
237+
}
238+
239+
// Convert to milliseconds
240+
const qint64 nowInMs = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
241+
242+
// Return a QDateTime of the millisecond diff
243+
const qint64 offset = clockBootTime - nowInMs;
244+
return QDateTime::fromMSecsSinceEpoch(now.toMSecsSinceEpoch() + offset);
245+
}
246+
// NOLINTEND
247+
221248
} // namespace qs::network

src/network/nm/utils.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
#pragma once
32

43
#include <qcontainerfwd.h>
@@ -41,4 +40,6 @@ WifiSecurityType::Enum findBestWirelessSecurity(
4140
NM80211ApSecurityFlags::Enum apRsn
4241
);
4342

43+
QDateTime clockBootTimeToDateTime(qint64 clockBootTime);
44+
4445
} // namespace qs::network

0 commit comments

Comments
 (0)