Split off most of NetworkManager code into their own files.

This commit is contained in:
Vibhav Pant
2023-08-30 18:48:10 +05:30
parent 1de5123935
commit b4fd1e0ced
8 changed files with 535 additions and 395 deletions
@@ -67,6 +67,9 @@ cc_library(
"bluetooth_pairing.h",
"bluez.h",
"dbus.h",
"network_manager.h",
"network_manager_active_connection.h",
"network_manager_access_point.h",
"stream.h",
"wifi_direct.h",
"wifi_direct_server_socket.h",
@@ -133,6 +136,8 @@ cc_library(
"bluez.cc",
"dbus.cc",
"executor.cc",
"network_manager.cc",
"network_manager_active_connection.cc",
"platform.cc",
"preferences_manager.cc",
"preferences_repository.cc",
@@ -0,0 +1,93 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
namespace nearby {
namespace linux {
std::unique_ptr<NetworkManagerActiveConnection>
NetworkManagerObjectManager::GetActiveConnectionForAccessPoint(
const sdbus::ObjectPath &access_point,
const sdbus::ObjectPath &device_path) {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return nullptr;
}
for (auto &[object_path, interfaces] : objects) {
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/") ==
0) {
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME) == 1) {
auto props = interfaces[org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME];
sdbus::ObjectPath specific_object = props["SpecificObject"];
if (specific_object == access_point) {
std::vector<sdbus::ObjectPath> devices = props["Devices"];
for (auto &path : devices) {
if (path == device_path) {
return std::make_unique<NetworkManagerActiveConnection>(
getProxy().getConnection(), object_path);
}
}
}
}
}
}
return nullptr;
}
std::unique_ptr<NetworkManagerIP4Config>
NetworkManagerObjectManager::GetIp4Config(
const sdbus::ObjectPath &active_connection) {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return nullptr;
}
for (auto &[object_path, interfaces] : objects) {
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/",
0) == 0) {
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME) == 1) {
auto props = interfaces[org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME];
sdbus::ObjectPath specific_object = props["SpecificObject"];
sdbus::ObjectPath ip4config = props["Ip4Config"];
if (specific_object == active_connection)
return std::make_unique<NetworkManagerIP4Config>(
getProxy().getConnection(), ip4config);
}
}
}
return nullptr;
}
} // namespace linux
} // namespace nearby
@@ -0,0 +1,147 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_NETWORK_MANAGER_H_
#define PLATFORM_IMPL_LINUX_NETWORK_MANAGER_H_
#include <atomic>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/ip4config_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/networkmanager_client.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
namespace nearby {
namespace linux {
class NetworkManager final
: public sdbus::ProxyInterfaces<org::freedesktop::NetworkManager_proxy> {
public:
NetworkManager(const NetworkManager &) = delete;
NetworkManager(NetworkManager &&) = delete;
NetworkManager &operator=(const NetworkManager &) = delete;
NetworkManager &operator=(NetworkManager &&) = delete;
explicit NetworkManager(sdbus::IConnection &system_bus)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager"),
state_(kNMStateUnknown) {
registerProxy();
try {
setState(State());
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
}
}
~NetworkManager() { unregisterProxy(); }
// https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMState
enum NMState {
kNMStateUnknown = 0,
kNMStateAsleep = 10,
kNMStateDisconnected = 20,
kNMStateDisconnecting = 30,
kNMStateConnecting = 40,
kNMStateConnectedLocal = 50,
kNMStateConnectedSite = 60,
kNMStateConnectedGlobal = 70,
};
NMState getState() const { return state_; }
protected:
void onCheckPermissions() override {}
void onStateChanged(const uint32_t &state) override { setState(state); }
void onDeviceAdded(const sdbus::ObjectPath &device_path) override {}
void onDeviceRemoved(const sdbus::ObjectPath &device_path) override {}
private:
void inline setState(std::uint32_t val) {
#define NM_STATE_CASE_SET(k) \
case (k): \
state_ = (k); \
break
switch (val) {
NM_STATE_CASE_SET(kNMStateAsleep);
NM_STATE_CASE_SET(kNMStateDisconnected);
NM_STATE_CASE_SET(kNMStateDisconnecting);
NM_STATE_CASE_SET(kNMStateConnecting);
NM_STATE_CASE_SET(kNMStateConnectedLocal);
NM_STATE_CASE_SET(kNMStateConnectedSite);
NM_STATE_CASE_SET(kNMStateConnectedGlobal);
default:
NEARBY_LOGS(ERROR) << __func__ << "invalid NMState value: " << val
<< ", setting state to unknown";
NM_STATE_CASE_SET(kNMStateUnknown);
}
#undef NM_STATE_CASE_SET
};
std::atomic<NMState> state_;
};
class NetworkManagerIP4Config
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::IP4Config_proxy> {
public:
NetworkManagerIP4Config(const NetworkManagerIP4Config &) = delete;
NetworkManagerIP4Config(NetworkManagerIP4Config &&) = delete;
NetworkManagerIP4Config &operator=(const NetworkManagerIP4Config &) = delete;
NetworkManagerIP4Config &operator=(NetworkManagerIP4Config &&) = delete;
NetworkManagerIP4Config(sdbus::IConnection &system_bus,
const sdbus::ObjectPath &config_object_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
config_object_path) {
registerProxy();
}
~NetworkManagerIP4Config() { unregisterProxy(); }
};
class NetworkManagerObjectManager final
: public sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
public:
NetworkManagerObjectManager(const NetworkManagerObjectManager &) = delete;
NetworkManagerObjectManager(NetworkManagerObjectManager &&) = delete;
NetworkManagerObjectManager &operator=(const NetworkManagerObjectManager &) =
delete;
NetworkManagerObjectManager &operator=(NetworkManagerObjectManager &&) =
delete;
explicit NetworkManagerObjectManager(sdbus::IConnection &system_bus)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
"/org/freedesktop") {
registerProxy();
}
~NetworkManagerObjectManager() { unregisterProxy(); }
std::unique_ptr<NetworkManagerIP4Config> GetIp4Config(
const sdbus::ObjectPath &access_point);
std::unique_ptr<NetworkManagerActiveConnection>
GetActiveConnectionForAccessPoint(const sdbus::ObjectPath &access_point_path,
const sdbus::ObjectPath &device_path);
protected:
void onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) override {}
void onInterfacesRemoved(
const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) override {}
};
} // namespace linux
} // namespace nearby
#endif
@@ -0,0 +1,43 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACCESS_POINT_H_
#define PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACCESS_POINT_H_
#include <sdbus-c++/ProxyInterfaces.h>
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/access_point_client.h"
namespace nearby {
namespace linux {
class NetworkManagerAccessPoint
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::AccessPoint_proxy> {
public:
NetworkManagerAccessPoint(const NetworkManagerAccessPoint &) = delete;
NetworkManagerAccessPoint(NetworkManagerAccessPoint &&) = delete;
NetworkManagerAccessPoint &operator=(const NetworkManagerAccessPoint &) =
delete;
NetworkManagerAccessPoint &operator=(NetworkManagerAccessPoint &&) = delete;
NetworkManagerAccessPoint(sdbus::IConnection &system_bus,
sdbus::ObjectPath access_point_object_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
std::move(access_point_object_path)) {
registerProxy();
}
~NetworkManagerAccessPoint() { unregisterProxy(); }
};
} // namespace linux
} // namespace nearby
#endif
@@ -0,0 +1,124 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <map>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
namespace nearby {
namespace linux {
std::ostream &operator<<(
std::ostream &stream,
const NetworkManagerActiveConnection::ActiveConnectionStateReason &reason) {
switch (reason) {
case NetworkManagerActiveConnection::kStateReasonUnknown:
return stream
<< "The reason for the active connection state change is unknown.";
case NetworkManagerActiveConnection::kStateReasonNone:
return stream
<< "No reason was given for the active connection state change.";
case NetworkManagerActiveConnection::kStateReasonUserDisconnected:
return stream << "The active connection changed state because the user "
"disconnected it.";
case NetworkManagerActiveConnection::kStateReasonDeviceDisconnected:
return stream
<< "The active connection changed state because the device it was "
"using was disconnected.";
case NetworkManagerActiveConnection::kStateReasonServiceStopped:
return stream << "The service providing the VPN connection was stopped.";
case NetworkManagerActiveConnection::kStateReasonIPConfigInvalid:
return stream << "The IP config of the active connection was invalid.";
case NetworkManagerActiveConnection::kStateReasonConnectTimeout:
return stream << "The connection attempt to the VPN service timed out.";
case NetworkManagerActiveConnection::kStateReasonServiceStartTimeout:
return stream
<< "A timeout occurred while starting the service providing the "
"VPN connection.";
case NetworkManagerActiveConnection::kStateReasonServiceStartFailed:
return stream
<< "Starting the service providing the VPN connection failed.";
case NetworkManagerActiveConnection::kStateReasonNoSecrets:
return stream
<< "Necessary secrets for the connection were not provided.";
case NetworkManagerActiveConnection::kStateReasonLoginFailed:
return stream << "Authentication to the server failed.";
case NetworkManagerActiveConnection::kStateReasonConnectionRemoved:
return stream << "The connection was deleted from settings.";
case NetworkManagerActiveConnection::kStateReasonDependencyFailed:
return stream
<< "Master connection of this connection failed to activate.";
case NetworkManagerActiveConnection::kStateReasonDeviceRealizeFailed:
return stream << "Could not create the software device link.";
case NetworkManagerActiveConnection::kStateReasonDeviceRemoved:
return stream << "The device this connection depended on disappeared.";
}
}
std::vector<std::string> NetworkManagerActiveConnection::GetIP4Addresses() {
sdbus::ObjectPath ip4config_path;
try {
ip4config_path = Ip4Config();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "Ip4Config", e);
return {};
}
NetworkManagerIP4Config ip4config(getProxy().getConnection(), ip4config_path);
std::vector<std::map<std::string, sdbus::Variant>> address_data;
try {
address_data = ip4config.AddressData();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "AddressData", e);
return {};
}
std::vector<std::string> ip4addresses;
for (auto &data : address_data) {
if (data.count("address") == 1) {
ip4addresses.push_back(data["address"]);
}
}
return ip4addresses;
}
std::pair<std::optional<NetworkManagerActiveConnection::ActiveConnectionStateReason>, bool>
NetworkManagerActiveConnection::WaitForConnection(absl::Duration timeout) {
NEARBY_LOGS(VERBOSE) << __func__ << ": Waiting for an update to "
<< getObjectPath() << "'s state";
auto state_changed = [this]() {
this->state_mutex_.AssertReaderHeld();
return this->state_ == kStateActivated || this->state_ == kStateDeactivated;
};
absl::Condition cond(&state_changed);
auto success = state_mutex_.ReaderLockWhenWithTimeout(cond, timeout);
auto reason = reason_;
auto state = state_;
state_mutex_.ReaderUnlock();
if (!success) {
return {reason, true};
}
return state == kStateActivated ? std::pair{std::nullopt, false}
: std::pair{std::optional(reason), false};
}
} // namespace linux
} // namespace nearby
@@ -0,0 +1,113 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACTIVE_CONNECTION_H_
#define PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACTIVE_CONNECTION_H_
#include <ostream>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/connection_active_client.h"
namespace nearby {
namespace linux {
class NetworkManagerActiveConnection
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::Connection::Active_proxy> {
public:
enum ActiveConnectionState {
kStateUnknown = 0,
kStateActivating = 1,
kStateActivated = 2,
kStateDeactivating = 3,
kStateDeactivated = 4
};
enum ActiveConnectionStateReason {
kStateReasonUnknown = 0,
kStateReasonNone = 1,
kStateReasonUserDisconnected = 2,
kStateReasonDeviceDisconnected = 3,
kStateReasonServiceStopped = 4,
kStateReasonIPConfigInvalid = 5,
kStateReasonConnectTimeout = 6,
kStateReasonServiceStartTimeout = 7,
kStateReasonServiceStartFailed = 8,
kStateReasonNoSecrets = 9,
kStateReasonLoginFailed = 10,
kStateReasonConnectionRemoved = 11,
kStateReasonDependencyFailed = 12,
kStateReasonDeviceRealizeFailed = 13,
kStateReasonDeviceRemoved = 14,
};
NetworkManagerActiveConnection(const NetworkManagerActiveConnection &) =
delete;
NetworkManagerActiveConnection(NetworkManagerActiveConnection &&) = delete;
NetworkManagerActiveConnection &operator=(
const NetworkManagerActiveConnection &) = delete;
NetworkManagerActiveConnection &operator=(NetworkManagerActiveConnection &&) =
delete;
explicit NetworkManagerActiveConnection(
sdbus::IConnection &system_bus, sdbus::ObjectPath active_connection_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
std::move(active_connection_path)),
state_(kStateUnknown),
reason_(kStateReasonUnknown) {
registerProxy();
try {
auto state = State();
if (state >= kStateUnknown && state <= kStateDeactivated) {
state_ = static_cast<ActiveConnectionState>(state);
}
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
}
}
virtual ~NetworkManagerActiveConnection() { unregisterProxy(); }
protected:
void onStateChanged(const uint32_t &state, const uint32_t &reason) override
ABSL_LOCKS_EXCLUDED(state_mutex_) {
absl::MutexLock l(&state_mutex_);
if (state >= kStateUnknown && state <= kStateDeactivated) {
state_ = static_cast<ActiveConnectionState>(state);
}
if (reason >= kStateReasonUnknown && reason <= kStateReasonDeviceRemoved) {
reason_ = static_cast<ActiveConnectionStateReason>(reason);
}
}
public:
std::pair<std::optional<ActiveConnectionStateReason>, bool> WaitForConnection(
absl::Duration timeout = absl::Seconds(10))
ABSL_LOCKS_EXCLUDED(state_mutex_);
std::vector<std::string> GetIP4Addresses();
private:
absl::Mutex state_mutex_;
ActiveConnectionState state_ ABSL_GUARDED_BY(state_mutex_);
ActiveConnectionStateReason reason_ ABSL_GUARDED_BY(state_mutex_);
};
extern std::ostream &operator<<(
std::ostream &stream,
const NetworkManagerActiveConnection::ActiveConnectionStateReason &reason);
} // namespace linux
} // namespace nearby
#endif
@@ -27,124 +27,12 @@
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/connection_active_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/device_wireless_client.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi.h"
namespace nearby {
namespace linux {
std::ostream &operator<<(std::ostream &s,
const ActiveConnectionStateReason &reason) {
switch (reason) {
case kStateReasonUnknown:
return s
<< "The reason for the active connection state change is unknown.";
case kStateReasonNone:
return s << "No reason was given for the active connection state change.";
case kStateReasonUserDisconnected:
return s << "The active connection changed state because the user "
"disconnected it.";
case kStateReasonDeviceDisconnected:
return s
<< "The active connection changed state because the device it was "
"using was disconnected.";
case kStateReasonServiceStopped:
return s << "The service providing the VPN connection was stopped.";
case kStateReasonIPConfigInvalid:
return s << "The IP config of the active connection was invalid.";
case kStateReasonConnectTimeout:
return s << "The connection attempt to the VPN service timed out.";
case kStateReasonServiceStartTimeout:
return s << "A timeout occurred while starting the service providing the "
"VPN connection.";
case kStateReasonServiceStartFailed:
return s << "Starting the service providing the VPN connection failed.";
case kStateReasonNoSecrets:
return s << "Necessary secrets for the connection were not provided.";
case kStateReasonLoginFailed:
return s << "Authentication to the server failed.";
case kStateReasonConnectionRemoved:
return s << "The connection was deleted from settings.";
case kStateReasonDependencyFailed:
return s << "Master connection of this connection failed to activate.";
case kStateReasonDeviceRealizeFailed:
return s << "Could not create the software device link.";
case kStateReasonDeviceRemoved:
return s << "The device this connection depended on disappeared.";
}
}
std::unique_ptr<NetworkManagerIP4Config>
NetworkManagerObjectManager::GetIp4Config(
const sdbus::ObjectPath &active_connection) {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return nullptr;
}
for (auto &[object_path, interfaces] : objects) {
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/",
0) == 0) {
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME) == 1) {
auto props = interfaces[org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME];
sdbus::ObjectPath specific_object = props["SpecificObject"];
sdbus::ObjectPath ip4config = props["Ip4Config"];
if (specific_object == active_connection)
return std::make_unique<NetworkManagerIP4Config>(
getProxy().getConnection(), ip4config);
}
}
}
return nullptr;
}
std::unique_ptr<NetworkManagerActiveConnection>
NetworkManagerObjectManager::GetActiveConnectionForAccessPoint(
const sdbus::ObjectPath &access_point,
const sdbus::ObjectPath &device_path) {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return nullptr;
}
for (auto &[object_path, interfaces] : objects) {
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/") ==
0) {
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME) == 1) {
auto props = interfaces[org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME];
sdbus::ObjectPath specific_object = props["SpecificObject"];
if (specific_object == access_point) {
std::vector<sdbus::ObjectPath> devices = props["Devices"];
for (auto &path : devices) {
if (path == device_path) {
return std::make_unique<NetworkManagerActiveConnection>(
getProxy().getConnection(), object_path);
}
}
}
}
}
}
return nullptr;
}
api::WifiCapability &NetworkManagerWifiMedium::GetCapability() {
try {
auto cap_mask = WirelessCapabilities();
@@ -222,16 +110,9 @@ void NetworkManagerWifiMedium::onPropertiesChanged(
return;
}
for (auto &[property, val] : changedProperties) {
if (property == "LastScan") {
{
absl::MutexLock l(&last_scan_lock_);
last_scan_ = val;
}
// absl::ReaderMutexLock l(&scan_result_callback_lock_);
// if (scan_result_callback_.has_value()) {
// }
}
if (changedProperties.count("LastScan") == 1) {
absl::MutexLock l(&last_scan_lock_);
last_scan_ = changedProperties.at("LastScan");
}
}
@@ -413,8 +294,8 @@ api::WifiConnectionStatus NetworkManagerWifiMedium::ConnectToNetwork(
<< active_conn_path
<< " failed to activate, NMActiveConnectionStateReason:"
<< *reason;
if (*reason == ActiveConnectionStateReason::kStateReasonNoSecrets ||
*reason == ActiveConnectionStateReason::kStateReasonLoginFailed)
if (*reason == NetworkManagerActiveConnection::kStateReasonNoSecrets ||
*reason == NetworkManagerActiveConnection::kStateReasonLoginFailed)
return api::WifiConnectionStatus::kAuthFailure;
}
@@ -20,288 +20,22 @@
#include <list>
#include <memory>
#include <optional>
#include <ostream>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include <ostream>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/access_point_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/connection_active_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/device_wireless_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/ip4config_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/networkmanager_client.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_access_point.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
#include "internal/platform/implementation/wifi.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
class NetworkManager final
: public sdbus::ProxyInterfaces<org::freedesktop::NetworkManager_proxy> {
public:
NetworkManager(const NetworkManager &) = delete;
NetworkManager(NetworkManager &&) = delete;
NetworkManager &operator=(const NetworkManager &) = delete;
NetworkManager &operator=(NetworkManager &&) = delete;
explicit NetworkManager(sdbus::IConnection &system_bus)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager"),
state_(kNMStateUnknown) {
registerProxy();
try {
setState(State());
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
}
}
~NetworkManager() { unregisterProxy(); }
// https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMState
enum NMState {
kNMStateUnknown = 0,
kNMStateAsleep = 10,
kNMStateDisconnected = 20,
kNMStateDisconnecting = 30,
kNMStateConnecting = 40,
kNMStateConnectedLocal = 50,
kNMStateConnectedSite = 60,
kNMStateConnectedGlobal = 70,
};
NMState getState() const { return state_; }
protected:
void onCheckPermissions() override {}
void onStateChanged(const uint32_t &state) override { setState(state); }
void onDeviceAdded(const sdbus::ObjectPath &device_path) override {}
void onDeviceRemoved(const sdbus::ObjectPath &device_path) override {}
private:
void inline setState(std::uint32_t val) {
#define NM_STATE_CASE_SET(k) \
case (k): \
state_ = (k); \
break
switch (val) {
NM_STATE_CASE_SET(kNMStateAsleep);
NM_STATE_CASE_SET(kNMStateDisconnected);
NM_STATE_CASE_SET(kNMStateDisconnecting);
NM_STATE_CASE_SET(kNMStateConnecting);
NM_STATE_CASE_SET(kNMStateConnectedLocal);
NM_STATE_CASE_SET(kNMStateConnectedSite);
NM_STATE_CASE_SET(kNMStateConnectedGlobal);
default:
NEARBY_LOGS(ERROR) << __func__ << "invalid NMState value: " << val
<< ", setting state to unknown";
NM_STATE_CASE_SET(kNMStateUnknown);
}
#undef NM_STATE_CASE_SET
};
std::atomic<NMState> state_;
};
class NetworkManagerIP4Config
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::IP4Config_proxy> {
public:
NetworkManagerIP4Config(const NetworkManagerIP4Config &) = delete;
NetworkManagerIP4Config(NetworkManagerIP4Config &&) = delete;
NetworkManagerIP4Config &operator=(const NetworkManagerIP4Config &) = delete;
NetworkManagerIP4Config &operator=(NetworkManagerIP4Config &&) = delete;
NetworkManagerIP4Config(sdbus::IConnection &system_bus,
const sdbus::ObjectPath &config_object_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
config_object_path) {
registerProxy();
}
~NetworkManagerIP4Config() { unregisterProxy(); }
};
class NetworkManagerAccessPoint
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::AccessPoint_proxy> {
public:
NetworkManagerAccessPoint(const NetworkManagerAccessPoint &) = delete;
NetworkManagerAccessPoint(NetworkManagerAccessPoint &&) = delete;
NetworkManagerAccessPoint &operator=(const NetworkManagerAccessPoint &) =
delete;
NetworkManagerAccessPoint &operator=(NetworkManagerAccessPoint &&) = delete;
NetworkManagerAccessPoint(sdbus::IConnection &system_bus,
sdbus::ObjectPath access_point_object_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
std::move(access_point_object_path)) {
registerProxy();
}
~NetworkManagerAccessPoint() { unregisterProxy(); }
};
enum ActiveConnectionState {
kStateUnknown = 0,
kStateActivating = 1,
kStateActivated = 2,
kStateDeactivating = 3,
kStateDeactivated = 4
};
enum ActiveConnectionStateReason {
kStateReasonUnknown = 0,
kStateReasonNone = 1,
kStateReasonUserDisconnected = 2,
kStateReasonDeviceDisconnected = 3,
kStateReasonServiceStopped = 4,
kStateReasonIPConfigInvalid = 5,
kStateReasonConnectTimeout = 6,
kStateReasonServiceStartTimeout = 7,
kStateReasonServiceStartFailed = 8,
kStateReasonNoSecrets = 9,
kStateReasonLoginFailed = 10,
kStateReasonConnectionRemoved = 11,
kStateReasonDependencyFailed = 12,
kStateReasonDeviceRealizeFailed = 13,
kStateReasonDeviceRemoved = 14,
};
extern std::ostream &operator<<(std::ostream &s,
const ActiveConnectionStateReason &reason);
class NetworkManagerActiveConnection
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::Connection::Active_proxy> {
public:
NetworkManagerActiveConnection(const NetworkManagerActiveConnection &) =
delete;
NetworkManagerActiveConnection(NetworkManagerActiveConnection &&) = delete;
NetworkManagerActiveConnection &operator=(
const NetworkManagerActiveConnection &) = delete;
NetworkManagerActiveConnection &operator=(NetworkManagerActiveConnection &&) =
delete;
explicit NetworkManagerActiveConnection(
sdbus::IConnection &system_bus, sdbus::ObjectPath active_connection_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
std::move(active_connection_path)),
state_(kStateUnknown),
reason_(kStateReasonUnknown) {
registerProxy();
try {
auto state = State();
if (state >= kStateUnknown && state <= kStateDeactivated) {
state_ = static_cast<ActiveConnectionState>(state);
}
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
}
}
virtual ~NetworkManagerActiveConnection() { unregisterProxy(); }
protected:
void onStateChanged(const uint32_t &state, const uint32_t &reason) override
ABSL_LOCKS_EXCLUDED(state_mutex_) {
absl::MutexLock l(&state_mutex_);
if (state >= kStateUnknown && state <= kStateDeactivated) {
state_ = static_cast<ActiveConnectionState>(state);
}
if (reason >= kStateReasonUnknown && reason <= kStateReasonDeviceRemoved) {
reason_ = static_cast<ActiveConnectionStateReason>(reason);
}
}
public:
std::pair<std::optional<ActiveConnectionStateReason>, bool> WaitForConnection(
absl::Duration timeout = absl::Seconds(10))
ABSL_LOCKS_EXCLUDED(state_mutex_) {
NEARBY_LOGS(VERBOSE) << __func__ << ": Waiting for an update to "
<< getObjectPath() << "'s state";
auto state_changed = [this]() {
this->state_mutex_.AssertReaderHeld();
return this->state_ == kStateActivated ||
this->state_ == kStateDeactivated;
};
absl::Condition cond(&state_changed);
auto success = state_mutex_.ReaderLockWhenWithTimeout(cond, timeout);
auto reason = reason_;
auto state = state_;
state_mutex_.ReaderUnlock();
if (!success) {
return {reason, true};
}
return state == kStateActivated ? std::pair{std::nullopt, false}
: std::pair{std::optional(reason), false};
}
std::vector<std::string> GetIP4Addresses() {
sdbus::ObjectPath ip4config_path;
try {
ip4config_path = Ip4Config();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "Ip4Config", e);
return {};
}
NetworkManagerIP4Config ip4config(getProxy().getConnection(),
ip4config_path);
std::vector<std::map<std::string, sdbus::Variant>> address_data;
try {
address_data = ip4config.AddressData();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "AddressData", e);
return {};
}
std::vector<std::string> ip4addresses;
for (auto &data : address_data) {
if (data.count("address") == 1) {
ip4addresses.push_back(data["address"]);
}
}
return ip4addresses;
}
private:
absl::Mutex state_mutex_;
ActiveConnectionState state_ ABSL_GUARDED_BY(state_mutex_);
ActiveConnectionStateReason reason_ ABSL_GUARDED_BY(state_mutex_);
};
class NetworkManagerObjectManager final
: public sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
public:
NetworkManagerObjectManager(const NetworkManagerObjectManager &) = delete;
NetworkManagerObjectManager(NetworkManagerObjectManager &&) = delete;
NetworkManagerObjectManager &operator=(const NetworkManagerObjectManager &) =
delete;
NetworkManagerObjectManager &operator=(NetworkManagerObjectManager &&) =
delete;
explicit NetworkManagerObjectManager(sdbus::IConnection &system_bus)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
"/org/freedesktop") {
registerProxy();
}
~NetworkManagerObjectManager() { unregisterProxy(); }
std::unique_ptr<NetworkManagerIP4Config> GetIp4Config(
const sdbus::ObjectPath &access_point);
std::unique_ptr<NetworkManagerActiveConnection>
GetActiveConnectionForAccessPoint(const sdbus::ObjectPath &access_point_path,
const sdbus::ObjectPath &device_path);
protected:
void onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) override {}
void onInterfacesRemoved(
const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) override {}
};
class NetworkManagerWifiMedium
: public api::WifiMedium,
public sdbus::ProxyInterfaces<