mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
143 lines
5.1 KiB
C++
143 lines
5.1 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
class SystemBus;
|
|
|
|
namespace sdbus {
|
|
class IProxy;
|
|
}
|
|
|
|
struct AccessPointInfo {
|
|
std::string path; // NM AP object path
|
|
std::string devicePath; // NM device object path this AP belongs to
|
|
std::string ssid;
|
|
std::uint8_t strength = 0; // 0..100
|
|
bool secured = false;
|
|
bool active = false; // currently the device's ActiveAccessPoint
|
|
|
|
bool operator==(const AccessPointInfo&) const = default;
|
|
};
|
|
|
|
struct VpnConnectionInfo {
|
|
std::string path; // NM Settings.Connection object path
|
|
std::string name;
|
|
bool active = false;
|
|
|
|
bool operator==(const VpnConnectionInfo&) const = default;
|
|
};
|
|
|
|
enum class NetworkConnectivity {
|
|
Unknown = 0,
|
|
None = 1,
|
|
Wired = 2,
|
|
Wireless = 3,
|
|
};
|
|
|
|
struct NetworkState {
|
|
NetworkConnectivity kind = NetworkConnectivity::Unknown;
|
|
bool connected = false;
|
|
bool wirelessEnabled = false;
|
|
bool scanning = false;
|
|
bool vpnActive = false; // true if a VPN is the active connection
|
|
std::string ssid; // Wi-Fi only
|
|
std::string ipv4; // dotted-quad of first address; empty if none
|
|
std::string interfaceName; // e.g. "wlan0", "eth0"
|
|
std::uint8_t signalStrength = 0; // 0..100, Wi-Fi only
|
|
|
|
bool operator==(const NetworkState&) const = default;
|
|
};
|
|
|
|
enum class NetworkChangeOrigin : std::uint8_t {
|
|
External,
|
|
Noctalia,
|
|
};
|
|
|
|
class NetworkService {
|
|
public:
|
|
using ChangeCallback = std::function<void(const NetworkState&, NetworkChangeOrigin)>;
|
|
|
|
explicit NetworkService(SystemBus& bus);
|
|
~NetworkService();
|
|
|
|
NetworkService(const NetworkService&) = delete;
|
|
NetworkService& operator=(const NetworkService&) = delete;
|
|
|
|
void setChangeCallback(ChangeCallback callback);
|
|
void refresh();
|
|
|
|
[[nodiscard]] const NetworkState& state() const noexcept { return m_state; }
|
|
[[nodiscard]] const std::vector<AccessPointInfo>& accessPoints() const noexcept { return m_accessPoints; }
|
|
[[nodiscard]] const std::vector<VpnConnectionInfo>& vpnConnections() const noexcept { return m_vpnConnections; }
|
|
[[nodiscard]] static const char* glyphForState(const NetworkState& state) noexcept;
|
|
[[nodiscard]] static const char* wifiGlyphForState(const NetworkState& state) noexcept;
|
|
[[nodiscard]] static const char* wifiGlyphForSignal(std::uint8_t signal) noexcept;
|
|
|
|
// Trigger a Wi-Fi scan on every wifi device. Results arrive via PropertiesChanged.
|
|
void requestScan();
|
|
|
|
// Activate a known saved connection for the given access point. NM picks the
|
|
// matching saved connection automatically when the first argument is "/".
|
|
// Returns false only on an immediate D-Bus error. For secured networks that
|
|
// have no saved secrets, the activation will fail asynchronously (slice 3
|
|
// handles that via a SecretAgent).
|
|
bool activateAccessPoint(const AccessPointInfo& ap);
|
|
|
|
// Activate / deactivate a saved VPN connection profile.
|
|
bool activateVpnConnection(const VpnConnectionInfo& vpn);
|
|
bool deactivateVpnConnection(const VpnConnectionInfo& vpn);
|
|
|
|
// Enable / disable the Wi-Fi radio.
|
|
void setWirelessEnabled(bool enabled);
|
|
|
|
// Deactivate the current primary connection.
|
|
void disconnect();
|
|
|
|
// Delete every saved connection whose 802-11-wireless SSID matches.
|
|
void forgetSsid(const std::string& ssid);
|
|
|
|
// Whether any saved connection matches the SSID (uses cached snapshot refreshed on every refresh()).
|
|
[[nodiscard]] bool hasSavedConnection(const std::string& ssid) const;
|
|
|
|
private:
|
|
void refreshAccessPoints(std::function<void()> onComplete);
|
|
void refreshSavedConnections(std::function<void()> onComplete);
|
|
void refreshVpnConnections(std::function<void()> onComplete);
|
|
void finishSavedConnections(std::vector<std::string>& ssids, std::function<void()> onComplete);
|
|
void finishRefreshAccessPoints(std::vector<AccessPointInfo>& aps, std::function<void()> onComplete);
|
|
void rebindActiveConnection();
|
|
void rebindActiveDevice(const std::string& devicePath);
|
|
void rebindActiveAccessPoint(const std::string& apPath);
|
|
void ensureWifiDeviceSubscribed(const std::string& devicePath);
|
|
void readStateAsync(std::function<void(NetworkState)> onComplete);
|
|
[[nodiscard]] NetworkChangeOrigin consumeWirelessEnabledChangeOrigin(bool enabled);
|
|
void emitChangedIfNeeded(NetworkState next);
|
|
|
|
SystemBus& m_bus;
|
|
std::unique_ptr<sdbus::IProxy> m_nm;
|
|
std::unique_ptr<sdbus::IProxy> m_activeConnection;
|
|
std::unique_ptr<sdbus::IProxy> m_activeDevice;
|
|
std::unique_ptr<sdbus::IProxy> m_activeAp;
|
|
std::unordered_map<std::string, std::unique_ptr<sdbus::IProxy>> m_wifiDevices;
|
|
std::string m_activeConnectionPath;
|
|
std::string m_activeDevicePath;
|
|
std::string m_activeApPath;
|
|
NetworkState m_state;
|
|
std::vector<AccessPointInfo> m_accessPoints;
|
|
std::vector<VpnConnectionInfo> m_vpnConnections;
|
|
std::vector<std::string> m_savedSsids;
|
|
std::shared_ptr<int> m_lifetimeToken;
|
|
bool m_refreshInFlight = false;
|
|
bool m_refreshQueued = false;
|
|
bool m_scanning = false;
|
|
std::int64_t m_scanBaselineLastScan = 0;
|
|
std::optional<bool> m_pendingLocalWirelessEnabled;
|
|
ChangeCallback m_changeCallback;
|
|
};
|