Skip to content

Commit

Permalink
Create a class to monitor an active connection.
Browse files Browse the repository at this point in the history
  • Loading branch information
oskirby committed Jan 24, 2024
1 parent 851b27d commit b7c0440
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 27 deletions.
2 changes: 2 additions & 0 deletions src/cmake/linux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ else()
pkg_check_modules(libnm REQUIRED IMPORTED_TARGET libnm)
target_link_libraries(mozillavpn PRIVATE PkgConfig::libnm)
target_sources(mozillavpn PRIVATE
${CMAKE_SOURCE_DIR}/src/platforms/linux/networkmanagerconnection.h
${CMAKE_SOURCE_DIR}/src/platforms/linux/networkmanagerconnection.cpp
${CMAKE_SOURCE_DIR}/src/platforms/linux/networkmanagercontroller.h
${CMAKE_SOURCE_DIR}/src/platforms/linux/networkmanagercontroller.cpp
)
Expand Down
44 changes: 44 additions & 0 deletions src/platforms/linux/networkmanagerconnection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "networkmanagerconnection.h"

#include "leakdetector.h"
#include "logger.h"

namespace {
Logger logger("NetworkManagerConnection");
}

NetworkManagerConnection::NetworkManagerConnection(const QString& path,
QObject* parent) :
QObject(parent), m_interface("org.freedesktop.NetworkManager", path,
"org.freedesktop.NetworkManager.Connection.Active",
QDBusConnection::systemBus(), parent) {
MZ_COUNT_CTOR(NetworkManagerConnection);

// Get the UUID.
m_uuid = property("Uuid").toString();

// Report state changes.
QDBusConnection::systemBus().connect(
"org.freedesktop.NetworkManager", path,
"org.freedesktop.NetworkManager.Connection.Active", "StateChanged", this,
SLOT(dbusStateChanged(uint, uint)));
}

NetworkManagerConnection::~NetworkManagerConnection() {
MZ_COUNT_DTOR(NetworkManagerConnection);
}

uint NetworkManagerConnection::state() const {
uint state = property("State").toUInt();
logger.debug() << "fetching state" << state;
return state;
}

void NetworkManagerConnection::dbusStateChanged(uint state, uint reason) {
logger.debug() << "state change" << state << "because" << reason;
emit stateChanged(state, reason);
}
34 changes: 34 additions & 0 deletions src/platforms/linux/networkmanagerconnection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef NETWORKMANAGERCONNECTION_H
#define NETWORKMANAGERCONNECTION_H

#include <QObject>
#include <QDBusInterface>

class NetworkManagerConnection final : public QObject {
Q_OBJECT
Q_DISABLE_COPY_MOVE(NetworkManagerConnection)

public:
NetworkManagerConnection(const QString& path, QObject* parent = nullptr);
~NetworkManagerConnection();

const QString& uuid() const { return m_uuid; }
QString path() const { return m_interface.path(); }
uint state() const;

signals:
void stateChanged(uint state, uint reason);

private slots:
void dbusStateChanged(uint state, uint reason);

private:
QDBusInterface m_interface;
QString m_uuid;
};

#endif // NETWORKMANAGERCONNECTION_H
47 changes: 21 additions & 26 deletions src/platforms/linux/networkmanagercontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "logger.h"
#include "models/device.h"
#include "models/keys.h"
#include "networkmanagerconnection.h"
#include "settingsholder.h"

#if defined(__cplusplus)
Expand Down Expand Up @@ -194,7 +195,7 @@ void NetworkManagerController::initialize(const Device* device,
}
}

emit initialized(true, !m_activeConnectionPath.isEmpty(), QDateTime());
emit initialized(true, m_connection != nullptr, QDateTime());
return;
}

Expand Down Expand Up @@ -350,7 +351,7 @@ void NetworkManagerController::peerConfigCompleted(void* result) {
if (!okay) {
logger.error() << "peer configuration failed:" << err->message;
g_error_free(err);
} else if (m_activeConnectionPath.isEmpty()) {
} else if (m_connection == nullptr) {
NMConnection* conn = NM_CONNECTION(m_remote);
const char* ifname = nm_connection_get_interface_name(conn);
NMDevice* device = nm_client_get_device_by_iface(m_client, ifname);
Expand Down Expand Up @@ -386,31 +387,24 @@ void NetworkManagerController::setActiveConnection(NMActiveConnection* active) {
}

void NetworkManagerController::setActiveConnection(const QString& path) {
if (m_activeConnectionPath == path) {
// No change - do nothing.
return;
}

// If there is an existing active connection, discard it.
if (!m_activeConnectionPath.isEmpty()) {
QDBusConnection::systemBus().disconnect(
DBUS_NM_SERVICE, m_activeConnectionPath, DBUS_NM_ACTIVE, "StateChanged",
this, SLOT(stateChanged(uint, uint)));
if (m_connection != nullptr) {
if (m_connection->path() == path) {
// No change - do nothing.
return;
}
delete m_connection;
m_connection = nullptr;
}

// Start monitoring the new connection for state changes.
m_activeConnectionPath = path;
if (!m_activeConnectionPath.isEmpty()) {
QDBusConnection::systemBus().connect(
DBUS_NM_SERVICE, m_activeConnectionPath, DBUS_NM_ACTIVE, "StateChanged",
this, SLOT(stateChanged(uint, uint)));

// Fetch the connection state.
QDBusInterface conn(DBUS_NM_SERVICE, m_activeConnectionPath, DBUS_NM_ACTIVE,
QDBusConnection::systemBus());
if (!path.isEmpty()) {
m_connection = new NetworkManagerConnection(path, this);
connect(m_connection, &NetworkManagerConnection::stateChanged,
this, &NetworkManagerController::stateChanged);

// Invoke the state changed signal with the current state.
stateChanged(conn.property("State").toInt(),
stateChanged(m_connection->state(),
NM_ACTIVE_CONNECTION_STATE_REASON_NONE);
}
}
Expand All @@ -428,7 +422,7 @@ void NetworkManagerController::stateChanged(uint state, uint reason) {
void NetworkManagerController::deactivate(Controller::Reason reason) {
Q_UNUSED(reason);

if (m_activeConnectionPath.isEmpty()) {
if (m_connection == nullptr) {
logger.warning() << "Client already disconnected";
emit disconnected();
return;
Expand All @@ -437,16 +431,17 @@ void NetworkManagerController::deactivate(Controller::Reason reason) {
QDBusMessage deactivateCall = QDBusMessage::createMethodCall(
DBUS_NM_SERVICE, DBUS_NM_PATH, DBUS_NM_INTERFACE,
"DeactivateConnection");
deactivateCall << QDBusObjectPath(m_activeConnectionPath);
deactivateCall << QDBusObjectPath(m_connection->path());

QDBusPendingReply<> reply = QDBusConnection::systemBus().asyncCall(deactivateCall);
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this,
[&]{ emit disconnected(); });
QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this,
SLOT(dnsCallCompleted(QDBusPendingCallWatcher*)));
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this,
&QObject::deleteLater);

m_activeConnectionPath.clear();
delete m_connection;
m_connection = nullptr;
}

void NetworkManagerController::propertyChanged(QString interface,
Expand Down
3 changes: 2 additions & 1 deletion src/platforms/linux/networkmanagercontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct _NMActiveConnection;
struct _NMCLient;
struct _NMRemoteConnection;
struct _NMSetting;
class NetworkManagerConnection;

class NetworkManagerController final : public ControllerImpl {
Q_DISABLE_COPY_MOVE(NetworkManagerController)
Expand Down Expand Up @@ -62,7 +63,7 @@ class NetworkManagerController final : public ControllerImpl {
QString m_serverIpv4Gateway;
QString m_tunnelUuid;

QString m_activeConnectionPath;
NetworkManagerConnection* m_connection = nullptr;
};

#endif // NETWORKMANAGERCONTROLLER_H

0 comments on commit b7c0440

Please sign in to comment.