mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 15:16:12 -04:00
Split off most of NetworkManager code into their own files.
This commit is contained in:
@@ -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<
|
||||
|
||||
Reference in New Issue
Block a user