Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/network/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ qt_add_library(quickshell-network STATIC
network.cpp
device.cpp
wifi.cpp
connection.cpp
)

target_include_directories(quickshell-network PRIVATE
Expand Down
20 changes: 20 additions & 0 deletions src/network/connection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "connection.hpp"

#include <qobject.h>
#include <qtmetamacros.h>

#include "nm/types.hpp"

namespace qs::network {

NMConnection::NMConnection(QObject* parent): QObject(parent) {}

void NMConnection::updateSettings(const ConnectionSettingsMap& settings) {
emit this->requestUpdateSettings(settings);
}

void NMConnection::clearSecrets() { emit this->requestClearSecrets(); }

void NMConnection::forget() { emit this->requestForget(); }

} // namespace qs::network
58 changes: 58 additions & 0 deletions src/network/connection.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#pragma once

#include <qobject.h>
#include <qproperty.h>
#include <qqmlintegration.h>
#include <qtypes.h>

#include "nm/types.hpp"

namespace qs::network {

///! A NetworkManager connection settings profile.
class NMConnection: public QObject {
Q_OBJECT;
QML_ELEMENT;
QML_UNCREATABLE("");

// clang-format off
/// A settings map describing this network configuration.
Q_PROPERTY(ConnectionSettingsMap settings READ default NOTIFY settingsChanged BINDABLE bindableSettings);
/// A settings map describing the secrets belonging to this network configuration.
Q_PROPERTY(ConnectionSettingsMap secretSettings READ default NOTIFY secretSettingsChanged BINDABLE bindableSecretSettings);
/// A human readable unique identifier for the connection.
Q_PROPERTY(QString id READ default NOTIFY idChanged BINDABLE bindableId);
// clang-format on

public:
explicit NMConnection(QObject* parent = nullptr);
/// Attempt to update the connection with new settings and save the connection to disk. Secrets may be a part of the update request,
/// and will either be stored in persistent storage tor sent to a Secret Agent for storage, depending on the flags
/// associated with each secret and the presence of a registered Secret Agent.
Q_INVOKABLE void updateSettings(const ConnectionSettingsMap& settings);
/// Attempt to clear all of the secrets belonging to this connection.
Q_INVOKABLE void clearSecrets();
/// Delete the connection.
Q_INVOKABLE void forget();

QBindable<ConnectionSettingsMap> bindableSettings() { return &this->bSettings; }
QBindable<ConnectionSettingsMap> bindableSecretSettings() { return &this->bSecretSettings; }
QBindable<QString> bindableId() { return &this->bId; }

signals:
void requestUpdateSettings(ConnectionSettingsMap settings);
void requestClearSecrets();
void requestForget();
void settingsChanged();
void secretSettingsChanged();
void idChanged();

private:
// clang-format off
Q_OBJECT_BINDABLE_PROPERTY(NMConnection, ConnectionSettingsMap, bSettings, &NMConnection::settingsChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMConnection, ConnectionSettingsMap, bSecretSettings, &NMConnection::secretSettingsChanged);
Q_OBJECT_BINDABLE_PROPERTY(NMConnection, QString, bId, &NMConnection::idChanged);
// clang-format on
};

} // namespace qs::network
5 changes: 5 additions & 0 deletions src/network/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ void NetworkDevice::setAutoconnect(bool autoconnect) {
emit this->requestSetAutoconnect(autoconnect);
}

void NetworkDevice::setNmManaged(bool managed) {
if (this->bNmManaged == managed) return;
emit this->requestSetNmManaged(managed);
}

void NetworkDevice::disconnect() {
if (this->bState == DeviceConnectionState::Disconnected) {
qCCritical(logNetworkDevice) << "Device" << this << "is already disconnected";
Expand Down
18 changes: 15 additions & 3 deletions src/network/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,15 @@ class NetworkDevice: public QObject {
Q_PROPERTY(bool connected READ default NOTIFY connectedChanged BINDABLE bindableConnected);
/// Connection state of the device.
Q_PROPERTY(qs::network::DeviceConnectionState::Enum state READ default NOTIFY stateChanged BINDABLE bindableState);
/// A more specific device state when the backend is NetworkManager.
/// A more specific device state.
///
/// > [!WARNING] Only valid for the NetworkManager backend.
Q_PROPERTY(qs::network::NMDeviceState::Enum nmState READ default NOTIFY nmStateChanged BINDABLE bindableNmState);
/// True if the device is allowed to autoconnect.
/// True if the device is managed by NetworkManager.
///
/// > [!WARNING] Only valid for the NetworkManager backend.
Q_PROPERTY(bool nmManaged READ nmManaged WRITE setNmManaged NOTIFY nmManagedChanged)
/// True if the device is allowed to autoconnect to a network.
Q_PROPERTY(bool autoconnect READ autoconnect WRITE setAutoconnect NOTIFY autoconnectChanged);
// clang-format on

Expand All @@ -104,18 +110,23 @@ class NetworkDevice: public QObject {
QBindable<bool> bindableConnected() { return &this->bConnected; };
QBindable<DeviceConnectionState::Enum> bindableState() { return &this->bState; };
QBindable<NMDeviceState::Enum> bindableNmState() { return &this->bNmState; };
[[nodiscard]] bool autoconnect() const { return this->bAutoconnect; };
QBindable<bool> bindableNmManaged() { return &this->bNmManaged; };
[[nodiscard]] bool nmManaged() { return this->bNmManaged; };
void setNmManaged(bool managed);
QBindable<bool> bindableAutoconnect() { return &this->bAutoconnect; };
[[nodiscard]] bool autoconnect() { return this->bAutoconnect; };
void setAutoconnect(bool autoconnect);

signals:
void requestDisconnect();
void requestSetAutoconnect(bool autoconnect);
void requestSetNmManaged(bool managed);
void nameChanged();
void addressChanged();
void connectedChanged();
void stateChanged();
void nmStateChanged();
void nmManagedChanged();
void autoconnectChanged();

private:
Expand All @@ -126,6 +137,7 @@ class NetworkDevice: public QObject {
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bConnected, &NetworkDevice::connectedChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, DeviceConnectionState::Enum, bState, &NetworkDevice::stateChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, NMDeviceState::Enum, bNmState, &NetworkDevice::nmStateChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bNmManaged, &NetworkDevice::nmManagedChanged);
Q_OBJECT_BINDABLE_PROPERTY(NetworkDevice, bool, bAutoconnect, &NetworkDevice::autoconnectChanged);
// clang-format on
};
Expand Down
78 changes: 78 additions & 0 deletions src/network/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <qtmetamacros.h>

#include "../core/logcat.hpp"
#include "connection.hpp"
#include "device.hpp"
#include "nm/backend.hpp"

Expand All @@ -27,6 +28,37 @@ QString NetworkState::toString(NetworkState::Enum state) {
}
}

QString NMNetworkStateReason::toString(NMNetworkStateReason::Enum reason) {
switch (reason) {
case Unknown: return QStringLiteral("Unknown");
case None: return QStringLiteral("No reason");
case UserDisconnected: return QStringLiteral("User disconnection");
case DeviceDisconnected:
return QStringLiteral("The device the connection was using was disconnected.");
case ServiceStopped:
return QStringLiteral("The service providing the VPN connection was stopped.");
case IpConfigInvalid:
return QStringLiteral("The IP config of the active connection was invalid.");
case ConnectTimeout:
return QStringLiteral("The connection attempt to the VPN service timed out.");
case ServiceStartTimeout:
return QStringLiteral(
"A timeout occurred while starting the service providing the VPN connection."
);
case ServiceStartFailed:
return QStringLiteral("Starting the service providing the VPN connection failed.");
case NoSecrets: return QStringLiteral("Necessary secrets for the connection were not provided.");
case LoginFailed: return QStringLiteral("Authentication to the server failed.");
case ConnectionRemoved:
return QStringLiteral("Necessary secrets for the connection were not provided.");
case DependencyFailed:
return QStringLiteral("Master connection of this connection failed to activate.");
case DeviceRealizeFailed: return QStringLiteral("Could not create the software device link.");
case DeviceRemoved: return QStringLiteral("The device this connection depended on disappeared.");
default: return QStringLiteral("Unknown");
};
};

Networking::Networking(QObject* parent): QObject(parent) {
// Try to create the NetworkManager backend and bind to it.
auto* nm = new NetworkManager(this);
Expand Down Expand Up @@ -62,4 +94,50 @@ Network::Network(QString name, QObject* parent): QObject(parent), mName(std::mov
});
};

void Network::setNmDefaultConnection(NMConnection* conn) {
if (this->bNmDefaultConnection == conn) return;
if (!this->mNmConnections.valueList().contains(conn)) return;
emit this->requestSetNmDefaultConnection(conn);
}

void Network::connect() {
if (this->bConnected) {
qCCritical(logNetwork) << this << "is already connected.";
return;
}

this->requestConnect();
}

void Network::disconnect() {
if (!this->bConnected) {
qCCritical(logNetwork) << this << "is not currently connected";
return;
}

this->requestDisconnect();
}

void Network::forget() { this->requestForget(); }

void Network::connectionAdded(NMConnection* conn) { this->mNmConnections.insertObject(conn); }
void Network::connectionRemoved(NMConnection* conn) { this->mNmConnections.removeObject(conn); }

NMConnectionContext::NMConnectionContext(QObject* parent): QObject(parent) {}

void NMConnectionContext::setNetwork(Network* network) {
if (this->bNetwork == network) return;
if (this->bNetwork) disconnect(this->bNetwork, nullptr, this, nullptr);
this->bNetwork = network;

connect(network, &Network::stateChanged, this, [network, this]() {
if (network->state() == NetworkState::Connected) emit this->success();
});
connect(network, &Network::stateReasonChanged, this, [network, this]() {
if (network->stateReason() == NMNetworkStateReason::NoSecrets) emit this->noSecrets();
if (network->stateReason() == NMNetworkStateReason::LoginFailed) emit this->loginFailed();
});
connect(network, &Network::destroyed, this, [this]() { this->bNetwork = nullptr; });
}

} // namespace qs::network
Loading
Loading