Files
noctalia-shell/src/dbus/network/network_service.h
T

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;
};