mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Add additional WiFi code.
This commit is contained in:
+126
@@ -0,0 +1,126 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__networkmanager_connection_active_client_glue_h__proxy__H__
|
||||
#define __sdbuscpp__networkmanager_connection_active_client_glue_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace freedesktop {
|
||||
namespace NetworkManager {
|
||||
namespace Connection {
|
||||
|
||||
class Active_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager.Connection.Active";
|
||||
|
||||
protected:
|
||||
Active_proxy(sdbus::IProxy& proxy)
|
||||
: proxy_(proxy)
|
||||
{
|
||||
proxy_.uponSignal("StateChanged").onInterface(INTERFACE_NAME).call([this](const uint32_t& state, const uint32_t& reason){ this->onStateChanged(state, reason); });
|
||||
}
|
||||
|
||||
~Active_proxy() = default;
|
||||
|
||||
virtual void onStateChanged(const uint32_t& state, const uint32_t& reason) = 0;
|
||||
|
||||
public:
|
||||
sdbus::ObjectPath Connection()
|
||||
{
|
||||
return proxy_.getProperty("Connection").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath SpecificObject()
|
||||
{
|
||||
return proxy_.getProperty("SpecificObject").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::string Id()
|
||||
{
|
||||
return proxy_.getProperty("Id").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::string Uuid()
|
||||
{
|
||||
return proxy_.getProperty("Uuid").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::string Type()
|
||||
{
|
||||
return proxy_.getProperty("Type").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
std::vector<sdbus::ObjectPath> Devices()
|
||||
{
|
||||
return proxy_.getProperty("Devices").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
uint32_t State()
|
||||
{
|
||||
return proxy_.getProperty("State").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
uint32_t StateFlags()
|
||||
{
|
||||
return proxy_.getProperty("StateFlags").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
bool Default()
|
||||
{
|
||||
return proxy_.getProperty("Default").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Ip4Config()
|
||||
{
|
||||
return proxy_.getProperty("Ip4Config").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Dhcp4Config()
|
||||
{
|
||||
return proxy_.getProperty("Dhcp4Config").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
bool Default6()
|
||||
{
|
||||
return proxy_.getProperty("Default6").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Ip6Config()
|
||||
{
|
||||
return proxy_.getProperty("Ip6Config").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Dhcp6Config()
|
||||
{
|
||||
return proxy_.getProperty("Dhcp6Config").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
bool Vpn()
|
||||
{
|
||||
return proxy_.getProperty("Vpn").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Controller()
|
||||
{
|
||||
return proxy_.getProperty("Controller").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath Master()
|
||||
{
|
||||
return proxy_.getProperty("Master").onInterface(INTERFACE_NAME);
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IProxy& proxy_;
|
||||
};
|
||||
|
||||
}}}} // namespaces
|
||||
|
||||
#endif
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<node name="/">
|
||||
|
||||
<!--
|
||||
org.freedesktop.NetworkManager.Connection.Active:
|
||||
@short_description: Active Connection.
|
||||
|
||||
Objects that implement the Connection.Active interface represent an
|
||||
attempt to connect to a network using the details provided by a Connection
|
||||
object. The Connection.Active object tracks the life-cycle of the
|
||||
connection attempt and if successful indicates whether the connected
|
||||
network is the "default" or preferred network for access. NetworkManager
|
||||
has the concept of connections, which can be thought of as settings, a
|
||||
profile or a configuration that can be applied on a networking device.
|
||||
Such settings-connections are exposed as D-Bus object and the
|
||||
active-connection expresses this relationship between device and
|
||||
settings-connection. At any time a settings-connection can only be
|
||||
activated on one device and vice versa. However, during activation and
|
||||
deactivation multiple active-connections can reference the same device or
|
||||
settings-connection as they are waiting to be activated or to be
|
||||
deactivated.
|
||||
-->
|
||||
<interface name="org.freedesktop.NetworkManager.Connection.Active">
|
||||
<annotation name="org.gtk.GDBus.C.Name" value="ActiveConnection"/>
|
||||
|
||||
<!--
|
||||
Connection:
|
||||
|
||||
The path of the connection.
|
||||
-->
|
||||
<property name="Connection" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
SpecificObject:
|
||||
|
||||
A specific object associated with the active connection. This property
|
||||
reflects the specific object used during connection activation, and will
|
||||
not change over the lifetime of the ActiveConnection once set.
|
||||
-->
|
||||
<property name="SpecificObject" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
Id:
|
||||
|
||||
The ID of the connection, provided as a convenience so that clients do not
|
||||
have to retrieve all connection details.
|
||||
-->
|
||||
<property name="Id" type="s" access="read"/>
|
||||
|
||||
<!--
|
||||
Uuid:
|
||||
|
||||
The UUID of the connection, provided as a convenience so that clients do
|
||||
not have to retrieve all connection details.
|
||||
-->
|
||||
<property name="Uuid" type="s" access="read"/>
|
||||
|
||||
<!--
|
||||
Type:
|
||||
|
||||
The type of the connection, provided as a convenience so that clients do
|
||||
not have to retrieve all connection details.
|
||||
-->
|
||||
<property name="Type" type="s" access="read"/>
|
||||
|
||||
<!--
|
||||
Devices:
|
||||
|
||||
Array of object paths representing devices which are part of this active
|
||||
connection.
|
||||
-->
|
||||
<property name="Devices" type="ao" access="read"/>
|
||||
|
||||
<!--
|
||||
State:
|
||||
|
||||
The state of this active connection.
|
||||
|
||||
Returns: <link linkend="NMActiveConnectionState">NMActiveConnectionState</link>
|
||||
-->
|
||||
<property name="State" type="u" access="read"/>
|
||||
|
||||
<!--
|
||||
StateFlags:
|
||||
|
||||
The state flags of this active connection.
|
||||
|
||||
Returns: <link linkend="NMActivationStateFlags">NMActivationStateFlags</link>
|
||||
-->
|
||||
<property name="StateFlags" type="u" access="read"/>
|
||||
|
||||
<!--
|
||||
StateChanged:
|
||||
@state: (<link linkend="NMActiveConnectionState">NMActiveConnectionState</link>) The new state of the active connection.
|
||||
@reason: (<link linkend="NMActiveConnectionStateReason">NMActiveConnectionStateReason</link>) Reason code describing the change to the new state.
|
||||
@since: 1.8
|
||||
|
||||
Emitted when the state of the active connection has changed.
|
||||
|
||||
-->
|
||||
<signal name="StateChanged">
|
||||
<arg name="state" type="u"/>
|
||||
<arg name="reason" type="u"/>
|
||||
</signal>
|
||||
|
||||
<!--
|
||||
Default:
|
||||
|
||||
Whether this active connection is the default IPv4 connection, i.e.
|
||||
whether it currently owns the default IPv4 route.
|
||||
-->
|
||||
<property name="Default" type="b" access="read"/>
|
||||
|
||||
<!--
|
||||
Ip4Config:
|
||||
|
||||
Object path of the Ip4Config object describing the configuration of the
|
||||
connection. Only valid when the connection is in the
|
||||
NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
|
||||
-->
|
||||
<property name="Ip4Config" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
Dhcp4Config:
|
||||
|
||||
Object path of the Dhcp4Config object describing the DHCP options returned
|
||||
by the DHCP server (assuming the connection used DHCP). Only valid when
|
||||
the connection is in the NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
|
||||
-->
|
||||
<property name="Dhcp4Config" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
Default6:
|
||||
|
||||
Whether this active connection is the default IPv6 connection, i.e.
|
||||
whether it currently owns the default IPv6 route.
|
||||
-->
|
||||
<property name="Default6" type="b" access="read"/>
|
||||
|
||||
<!--
|
||||
Ip6Config:
|
||||
|
||||
Object path of the Ip6Config object describing the configuration of the
|
||||
connection. Only valid when the connection is in the
|
||||
NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
|
||||
-->
|
||||
<property name="Ip6Config" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
Dhcp6Config:
|
||||
|
||||
Object path of the Dhcp6Config object describing the DHCP options returned
|
||||
by the DHCP server (assuming the connection used DHCP). Only valid when
|
||||
the connection is in the NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
|
||||
-->
|
||||
<property name="Dhcp6Config" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
Vpn:
|
||||
|
||||
Whether this active connection is also a VPN connection.
|
||||
-->
|
||||
<property name="Vpn" type="b" access="read"/>
|
||||
|
||||
<!--
|
||||
Controller:
|
||||
@Since: 1.44, 1.42.2
|
||||
|
||||
The path to the controller device if the connection is a port. This
|
||||
property replaces the deprecated 'Master' property.
|
||||
-->
|
||||
<property name="Controller" type="o" access="read"/>
|
||||
|
||||
<!--
|
||||
Master:
|
||||
|
||||
The path to the controller device if the connection is a port.
|
||||
|
||||
This property is deprecated in favor of the 'Controller'
|
||||
property since 1.44 and 1.42.2.
|
||||
-->
|
||||
<property name="Master" type="o" access="read"/>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
@@ -0,0 +1,191 @@
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <random>
|
||||
#include <systemd/sd-id128.h>
|
||||
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_connection_active_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/wifi_hotspot.h"
|
||||
#include "internal/platform/implementation/linux/wifi_medium.h"
|
||||
#include "internal/platform/implementation/wifi.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
bool NetworkManagerWifiHotspotMedium::ConnectWifiHotspot(
|
||||
HotspotCredentials *hotspot_credentials) {
|
||||
if (hotspot_credentials == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": hotspot_credentials cannot be null";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ssid = hotspot_credentials->GetSSID();
|
||||
auto password = hotspot_credentials->GetPassword();
|
||||
|
||||
return wireless_device_->ConnectToNetwork(ssid, password,
|
||||
api::WifiAuthType::kWpaPsk) ==
|
||||
api::WifiConnectionStatus::kConnected;
|
||||
}
|
||||
|
||||
bool NetworkManagerWifiHotspotMedium::DisconnectWifiHotspot() {
|
||||
if (!WifiHotspotActive()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": WiFi hotspot is not active";
|
||||
return false;
|
||||
}
|
||||
|
||||
sdbus::ObjectPath active_ap_path;
|
||||
|
||||
try {
|
||||
active_ap_path = wireless_device_->ActiveAccessPoint();
|
||||
if (active_ap_path.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Not connected to any access points on "
|
||||
<< wireless_device_->getObjectPath();
|
||||
return false;
|
||||
}
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "ActiveAccessPoint", e);
|
||||
}
|
||||
|
||||
auto object_manager = NetworkManagerObjectManager(system_bus_);
|
||||
|
||||
auto objects = object_manager.GetManagedObjects();
|
||||
|
||||
for (auto &[path, interfaces] : objects) {
|
||||
if (path.find("/org/freedesktop/NetworkManager/ActiveConnection/") == 0) {
|
||||
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
|
||||
Active_proxy::INTERFACE_NAME) == 1) {
|
||||
sdbus::ObjectPath specific_object =
|
||||
interfaces[org::freedesktop::NetworkManager::Connection::
|
||||
Active_proxy::INTERFACE_NAME]["SpecificObject"];
|
||||
if (specific_object == active_ap_path) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Deactivating active connection "
|
||||
<< active_ap_path;
|
||||
|
||||
try {
|
||||
network_manager_->DeactivateConnection(path);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "DeactiveConnection",
|
||||
e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Could not find an active connection with the access point "
|
||||
<< active_ap_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkManagerWifiHotspotMedium::StartWifiHotspot(
|
||||
HotspotCredentials *hotspot_credentials) {
|
||||
if (WifiHotspotActive()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": " << wireless_device_->getObjectPath()
|
||||
<< ": cannot start WiFi hotspot, a hotspot is already "
|
||||
"active on this device";
|
||||
return false;
|
||||
}
|
||||
|
||||
sd_id128_t id;
|
||||
if (auto ret = sd_id128_randomize(&id); ret < 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": error generating a 128-bit ID: "
|
||||
<< std::strerror(ret);
|
||||
return false;
|
||||
}
|
||||
std::string ssid = absl::StrCat("DIRECT-", SD_ID128_TO_STRING(id));
|
||||
ssid.resize(32);
|
||||
hotspot_credentials->SetSSID(ssid);
|
||||
|
||||
if (auto ret = sd_id128_randomize(&id); ret < 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": error generating a 128-bit ID: "
|
||||
<< std::strerror(ret);
|
||||
return false;
|
||||
}
|
||||
std::string password = std::string(SD_ID128_TO_STRING(id), 15);
|
||||
hotspot_credentials->SetPassword(password);
|
||||
|
||||
if (auto ret = sd_id128_randomize(&id); ret < 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": error generating a 128-bit ID: "
|
||||
<< std::strerror(ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ssid_bytes(ssid.begin(), ssid.end());
|
||||
std::map<std::string, std::map<std::string, sdbus::Variant>>
|
||||
connection_settings{
|
||||
{
|
||||
"connection",
|
||||
std::map<std::string, sdbus::Variant>{
|
||||
{"uuid", SD_ID128_TO_UUID_STRING(id)},
|
||||
{"id", "Google Nearby Hotspot"},
|
||||
{"type", "802-11-wireless"},
|
||||
{"zone", "Public"}},
|
||||
},
|
||||
{"802-11-wireless",
|
||||
std::map<std::string, sdbus::Variant>{
|
||||
{"assigned-mac-address", "random"},
|
||||
{"mode", "ap"},
|
||||
{"ssid", ssid_bytes},
|
||||
{"security", "802-11-wireless-security"}}},
|
||||
{"802-11-wireless-security",
|
||||
std::map<std::string, sdbus::Variant>{
|
||||
{"group", std::vector<std::string>{"ccmp"}},
|
||||
{"key-mgmt", "wpa-psk"},
|
||||
{
|
||||
"pairwise",
|
||||
std::vector<std::string>{"ccmp"},
|
||||
},
|
||||
{"proto", std::vector<std::string>{"rsn"}},
|
||||
{"psk", password}}},
|
||||
{"ipv4", std::map<std::string, sdbus::Variant>{"method", "shared"}},
|
||||
{"ipv6", std::map<std::string, sdbus::Variant>{
|
||||
{"addr-gen-mode", static_cast<std::int32_t>(1)},
|
||||
{"method", "shared"},
|
||||
}}};
|
||||
std::unique_ptr<NetworkManagerActiveConnection> active_conn;
|
||||
try {
|
||||
auto [path, active_path, result] = network_manager_->AddAndActivateConnection2(
|
||||
connection_settings, wireless_device_->getObjectPath(), "/",
|
||||
{{"persist", "volatile"}, {"bind-activation", "dbus-client"}});
|
||||
active_conn = std::make_unique<NetworkManagerActiveConnection>(system_bus_,
|
||||
active_path);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "AddAndActivateConnection2",
|
||||
e);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto [reason, timeout] = active_conn->WaitForConnection();
|
||||
if (timeout) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": "
|
||||
<< ": timed out while waiting for connection "
|
||||
<< active_conn->getObjectPath()
|
||||
<< " to be activated, last NMActiveConnectionStateReason: "
|
||||
<< reason.value();
|
||||
DisconnectWifiHotspot();
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Started a WiFi hotspot on device "
|
||||
<< wireless_device_->getObjectPath() << " at "
|
||||
<< active_conn->getObjectPath();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkManagerWifiHotspotMedium::WifiHotspotActive() {
|
||||
try {
|
||||
auto mode = wireless_device_->Mode();
|
||||
return mode == 3; // NM_802_11_MODE_AP
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "Mode", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_H_
|
||||
#define PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_H_
|
||||
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "internal/platform/implementation/linux/wifi_medium.h"
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
class NetworkManagerWifiHotspotMedium : api::WifiHotspotMedium {
|
||||
public:
|
||||
NetworkManagerWifiHotspotMedium(
|
||||
sdbus::IConnection &system_bus,
|
||||
std::shared_ptr<NetworkManager> network_manager,
|
||||
const sdbus::ObjectPath &wireless_device_object_path)
|
||||
: system_bus_(system_bus),
|
||||
wireless_device_(std::make_unique<NetworkManagerWifiMedium>(
|
||||
network_manager, system_bus, wireless_device_object_path)),
|
||||
network_manager_(network_manager) {}
|
||||
~NetworkManagerWifiHotspotMedium() {}
|
||||
|
||||
bool IsInterfaceValid() const override { return true; }
|
||||
std::unique_ptr<api::WifiHotspotSocket>
|
||||
ConnectToService(absl::string_view ip_address, int port,
|
||||
CancellationFlag *cancellation_flag) override;
|
||||
std::unique_ptr<api::WifiHotspotServerSocket>
|
||||
ListenForService(int port) override;
|
||||
|
||||
bool StartWifiHotspot(HotspotCredentials *hotspot_credentials) override;
|
||||
bool StopWifiHotspot() override;
|
||||
|
||||
bool ConnectWifiHotspot(HotspotCredentials *hotspot_credentials) override;
|
||||
bool DisconnectWifiHotspot() override;
|
||||
|
||||
absl::optional<std::pair<std::int32_t, std::int32_t>>
|
||||
GetDynamicPortRange() override {return absl::nullopt;}
|
||||
|
||||
private:
|
||||
bool WifiHotspotActive();
|
||||
|
||||
sdbus::IConnection &system_bus_;
|
||||
std::unique_ptr<NetworkManagerWifiMedium> wireless_device_;
|
||||
std::shared_ptr<NetworkManager> network_manager_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -16,14 +16,15 @@
|
||||
#include "internal/platform/implementation/linux/wifi_lan.h"
|
||||
#include "internal/platform/implementation/linux/wifi_lan_server_socket.h"
|
||||
#include "internal/platform/implementation/linux/wifi_lan_socket.h"
|
||||
#include "internal/platform/implementation/linux/wifi_medium.h"
|
||||
#include "internal/platform/implementation/wifi_lan.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
WifiLanMedium::WifiLanMedium(sdbus::IConnection &system_bus,
|
||||
NetworkManager &network_manager)
|
||||
: system_bus_(system_bus), network_manager_(network_manager),
|
||||
WifiLanMedium::WifiLanMedium(sdbus::IConnection &system_bus)
|
||||
: system_bus_(system_bus),
|
||||
network_manager_(std::make_shared<linux::NetworkManager>(system_bus)),
|
||||
avahi_(std::make_shared<avahi::Server>(system_bus)),
|
||||
entry_group_(nullptr) {}
|
||||
|
||||
@@ -34,7 +35,7 @@ WifiLanMedium::~WifiLanMedium() {
|
||||
}
|
||||
|
||||
bool WifiLanMedium::IsNetworkConnected() const {
|
||||
auto state = network_manager_.getState();
|
||||
auto state = network_manager_->getState();
|
||||
return state >= 50; // NM_STATE_CONNECTED_LOCAL
|
||||
}
|
||||
|
||||
@@ -171,7 +172,7 @@ bool WifiLanMedium::StopDiscovery(const std::string &service_type) {
|
||||
|
||||
std::unique_ptr<api::WifiLanSocket>
|
||||
WifiLanMedium::ConnectToService(const std::string &ip_address, int port,
|
||||
CancellationFlag *cancellation_flag) {
|
||||
CancellationFlag *cancellation_flag) {
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
@@ -180,7 +181,7 @@ WifiLanMedium::ConnectToService(const std::string &ip_address, int port,
|
||||
}
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Connecting to " << ip_address << ":"
|
||||
<< port;
|
||||
<< port;
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_addr.s_addr = inet_addr(ip_address.c_str());
|
||||
addr.sin_family = AF_INET;
|
||||
@@ -198,7 +199,7 @@ WifiLanMedium::ConnectToService(const std::string &ip_address, int port,
|
||||
return std::make_unique<WifiLanSocket>(std::move(fd));
|
||||
}
|
||||
|
||||
std::unique_ptr<api::WifiLanServerSocket> ListenForService(int port = 0) {
|
||||
std::unique_ptr<api::WifiLanServerSocket> WifiLanMedium::ListenForService(int port) {
|
||||
auto sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
@@ -206,7 +207,7 @@ std::unique_ptr<api::WifiLanServerSocket> ListenForService(int port = 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Listening for services ";
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Listening for services";
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
@@ -228,11 +229,10 @@ std::unique_ptr<api::WifiLanServerSocket> ListenForService(int port = 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<WifiLanServerSocket>(sdbus::UnixFd(sock));
|
||||
return std::make_unique<WifiLanServerSocket>(sock, network_manager_);
|
||||
}
|
||||
|
||||
absl::optional<std::pair<std::int32_t, std::int32_t>>
|
||||
GetDynamicPortRange() {
|
||||
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange() {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@ namespace nearby {
|
||||
namespace linux {
|
||||
class WifiLanMedium : public api::WifiLanMedium {
|
||||
public:
|
||||
WifiLanMedium(sdbus::IConnection &system_bus,
|
||||
NetworkManager &network_manager);
|
||||
WifiLanMedium(sdbus::IConnection &system_bus);
|
||||
~WifiLanMedium() override;
|
||||
|
||||
bool IsNetworkConnected() const override;
|
||||
@@ -42,7 +41,7 @@ private:
|
||||
|
||||
sdbus::IConnection &system_bus_;
|
||||
|
||||
NetworkManager &network_manager_;
|
||||
std::shared_ptr<NetworkManager> network_manager_;
|
||||
|
||||
std::shared_ptr<avahi::Server> avahi_;
|
||||
std::unique_ptr<avahi::EntryGroup> entry_group_;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <ifaddrs.h>
|
||||
@@ -5,35 +6,54 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "internal/platform/implementation/linux/wifi_lan_server_socket.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/wifi_lan_server_socket.h"
|
||||
#include "internal/platform/implementation/linux/wifi_lan_socket.h"
|
||||
#include "internal/platform/implementation/linux/wifi_medium.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
std::string WifiLanServerSocket::GetIPAddress() const {
|
||||
struct ifaddrs *addrs = nullptr;
|
||||
getifaddrs(&addrs);
|
||||
std::vector<sdbus::ObjectPath> connection_paths;
|
||||
try {
|
||||
connection_paths = network_manager_->ActiveConnections();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(network_manager_, "ActiveConnections", e);
|
||||
return std::string();
|
||||
}
|
||||
|
||||
for (auto ifaddr = addrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
|
||||
if (ifaddr->ifa_addr == nullptr) {
|
||||
for (auto &path : connection_paths) {
|
||||
auto active_connection =
|
||||
std::make_unique<NetworkManagerActiveConnection>(system_bus_, path);
|
||||
std::string conn_type;
|
||||
try {
|
||||
conn_type = active_connection->Type();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(active_connection, "Type", e);
|
||||
continue;
|
||||
}
|
||||
if (ifaddr->ifa_addr->sa_family == AF_INET) {
|
||||
auto addr =
|
||||
&(reinterpret_cast<struct sockaddr_in *>(ifaddr->ifa_addr))->sin_addr;
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
|
||||
if (conn_type == "802-11-wireless" || conn_type == "802-3-ethernet") {
|
||||
auto ip4config_path = active_connection->Ip4Config();
|
||||
NetworkManagerIP4Config ip4config(system_bus_, ip4config_path);
|
||||
std::vector<std::map<std::string, sdbus::Variant>> address_data;
|
||||
|
||||
return std::string(buf);
|
||||
try {
|
||||
address_data = ip4config.AddressData();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "IP4Config", e);
|
||||
}
|
||||
|
||||
return address_data[0]["address"];
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Could not find any active IP addresses for this device";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,30 +3,34 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/linux/wifi_medium.h"
|
||||
#include "internal/platform/implementation/wifi_lan.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
class WifiLanServerSocket : public api::WifiLanServerSocket {
|
||||
public:
|
||||
WifiLanServerSocket(int socket) {
|
||||
fd_ = sdbus::UnixFd(socket);
|
||||
}
|
||||
|
||||
WifiLanServerSocket(int socket,
|
||||
std::shared_ptr<NetworkManager> network_manager,
|
||||
sdbus::IConnection &system_bus)
|
||||
: fd_(sdbus::UnixFd(socket)), network_manager_(network_manager),
|
||||
system_bus_(system_bus) {}
|
||||
~WifiLanServerSocket() override = default;
|
||||
|
||||
std::string GetIPAddress() const override;
|
||||
|
||||
int GetPort() const override;
|
||||
|
||||
std::unique_ptr<api::WifiLanSocket> Accept() override;
|
||||
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
sdbus::UnixFd fd_;
|
||||
std::shared_ptr<NetworkManager> network_manager_;
|
||||
sdbus::IConnection &system_bus_;
|
||||
};
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
#include <sdbus-c++/Error.h>
|
||||
#include <sdbus-c++/IProxy.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
#include <systemd/sd-id128.h>
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_connection_active_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_device_wireless_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/wifi_medium.h"
|
||||
#include "internal/platform/implementation/wifi.h"
|
||||
@@ -17,21 +19,60 @@
|
||||
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 &access_point) {
|
||||
const sdbus::ObjectPath &active_connection) {
|
||||
auto objects = GetManagedObjects();
|
||||
for (auto &[object_path, interfaces] : objects) {
|
||||
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/",
|
||||
0) == 0) {
|
||||
if (interfaces.count(
|
||||
"org.freedesktop.NetworkManager.Connection.Active") == 1) {
|
||||
auto props =
|
||||
interfaces["org.freedesktop.NetworkManager.Connection.Active"];
|
||||
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 == access_point)
|
||||
if (specific_object == active_connection)
|
||||
return std::make_unique<NetworkManagerIP4Config>(
|
||||
getProxy().getConnection(), ip4config);
|
||||
}
|
||||
@@ -56,25 +97,29 @@ api::WifiCapability &NetworkManagerWifiMedium::GetCapability() {
|
||||
}
|
||||
|
||||
api::WifiInformation &NetworkManagerWifiMedium::GetInformation() {
|
||||
{
|
||||
absl::ReaderMutexLock l(&active_access_point_lock_);
|
||||
if (!active_access_point_.has_value()) {
|
||||
std::unique_ptr<NetworkManagerAccessPoint> active_access_point;
|
||||
|
||||
try {
|
||||
auto ap_path = ActiveAccessPoint();
|
||||
if (ap_path.empty()) {
|
||||
information_ = api::WifiInformation{false};
|
||||
return information_;
|
||||
}
|
||||
active_access_point = std::make_unique<NetworkManagerAccessPoint>(
|
||||
getProxy().getConnection(), ap_path);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(this, "ActiveAccessPoint", e);
|
||||
}
|
||||
try {
|
||||
absl::MutexLock l(&active_access_point_lock_);
|
||||
|
||||
auto ssid_vec = active_access_point_->Ssid();
|
||||
try {
|
||||
auto ssid_vec = active_access_point->Ssid();
|
||||
std::string ssid{ssid_vec.begin(), ssid_vec.end()};
|
||||
|
||||
information_ =
|
||||
api::WifiInformation{true, ssid, active_access_point_->HwAddress(),
|
||||
(int32_t)(active_access_point_->Frequency())};
|
||||
api::WifiInformation{true, ssid, active_access_point->HwAddress(),
|
||||
(int32_t)(active_access_point->Frequency())};
|
||||
NetworkManagerObjectManager manager(getProxy().getConnection());
|
||||
auto ip4config =
|
||||
manager.GetIp4Config(active_access_point_->getObjectPath());
|
||||
auto ip4config = manager.GetIp4Config(active_access_point->getObjectPath());
|
||||
|
||||
if (ip4config != nullptr) {
|
||||
auto address_data = ip4config->AddressData();
|
||||
@@ -90,17 +135,16 @@ api::WifiInformation &NetworkManagerWifiMedium::GetInformation() {
|
||||
information_.ip_address_4_bytes = std::string(addr_bytes, 4);
|
||||
}
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": " << getObjectPath()
|
||||
<< ": Could not find the Ip4Config object for "
|
||||
<< active_access_point_->getObjectPath();
|
||||
<< active_access_point->getObjectPath();
|
||||
}
|
||||
} catch (const sdbus::Error &e) {
|
||||
absl::ReaderMutexLock l(&active_access_point_lock_);
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Got error '" << e.getName() << "' with message '"
|
||||
<< e.getMessage()
|
||||
<< __func__ << ": " << getObjectPath() << ": Got error '" << e.getName()
|
||||
<< "' with message '" << e.getMessage()
|
||||
<< "' while populating network information for access point "
|
||||
<< active_access_point_->getObjectPath();
|
||||
<< active_access_point->getObjectPath();
|
||||
}
|
||||
|
||||
return information_;
|
||||
@@ -115,8 +159,12 @@ void NetworkManagerWifiMedium::onPropertiesChanged(
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &[property, _val] : changedProperties) {
|
||||
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()) {
|
||||
// scan_result_callback_->get().OnScanResults()
|
||||
@@ -140,23 +188,181 @@ bool NetworkManagerWifiMedium::Scan(
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<NetworkManagerAccessPoint>
|
||||
NetworkManagerWifiMedium::SearchBySSIDNoScan(
|
||||
std::vector<std::uint8_t> &ssid_bytes) {
|
||||
absl::ReaderMutexLock l(&known_access_points_lock_);
|
||||
for (auto &[object_path, ap] : known_access_points_) {
|
||||
if (ap->Ssid() == ssid_bytes) {
|
||||
return ap;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<NetworkManagerAccessPoint>
|
||||
NetworkManagerWifiMedium::SearchBySSID(absl::string_view ssid,
|
||||
absl::Duration scan_timeout) {
|
||||
std::vector<std::uint8_t> ssid_bytes(ssid.begin(), ssid.end());
|
||||
// First, try to see if we already know an AP with this SSID.
|
||||
auto ap = SearchBySSIDNoScan(ssid_bytes);
|
||||
if (ap != nullptr) {
|
||||
return ap;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": " << getObjectPath() << ": SSID " << ssid
|
||||
<< " not currently known by device " << getObjectPath()
|
||||
<< ", requesting a scan";
|
||||
|
||||
std::int64_t cur_last_scan;
|
||||
{
|
||||
absl::ReaderMutexLock l(&last_scan_lock_);
|
||||
cur_last_scan = last_scan_;
|
||||
}
|
||||
|
||||
// Otherwise, request a Scan first and wait for it to finish.
|
||||
try {
|
||||
RequestScan(
|
||||
{{"ssids", std::vector<std::vector<std::uint8_t>>{ssid_bytes}}});
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(this, "RequestScan", e);
|
||||
}
|
||||
|
||||
auto scan_finish = [cur_last_scan, this]() {
|
||||
this->last_scan_lock_.AssertReaderHeld();
|
||||
return cur_last_scan != this->last_scan_;
|
||||
};
|
||||
|
||||
absl::Condition cond(&scan_finish);
|
||||
bool success = last_scan_lock_.ReaderLockWhenWithTimeout(cond, scan_timeout);
|
||||
last_scan_lock_.ReaderUnlock();
|
||||
|
||||
if (!success) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": " << getObjectPath()
|
||||
<< ": timed out waiting for scan to finish";
|
||||
}
|
||||
|
||||
ap = SearchBySSIDNoScan(ssid_bytes);
|
||||
if (ap == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__ << ": " << getObjectPath()
|
||||
<< ": Couldn't find SSID " << ssid;
|
||||
}
|
||||
|
||||
return ap;
|
||||
}
|
||||
|
||||
static inline std::pair<std::string, std::string>
|
||||
AuthAlgAndKeyMgmt(api::WifiAuthType auth_type) {
|
||||
switch (auth_type) {
|
||||
case api::WifiAuthType::kUnknown:
|
||||
return {"open", "none"};
|
||||
case api::WifiAuthType::kOpen:
|
||||
return {"open", "none"};
|
||||
case api::WifiAuthType::kWpaPsk:
|
||||
return {"shared", "wpa-psk"};
|
||||
case api::WifiAuthType::kWep:
|
||||
return {"none", "wep"};
|
||||
}
|
||||
}
|
||||
|
||||
api::WifiConnectionStatus
|
||||
NetworkManagerWifiMedium::ConnectToNetwork(absl::string_view ssid,
|
||||
absl::string_view password,
|
||||
api::WifiAuthType auth_type) {
|
||||
return api::WifiConnectionStatus::kUnknown;
|
||||
|
||||
auto ap = SearchBySSID(ssid);
|
||||
if (ap == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": " << getObjectPath()
|
||||
<< ": Couldn't find SSID " << ssid;
|
||||
return api::WifiConnectionStatus::kConnectionFailure;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> ssid_bytes(ssid.begin(), ssid.end());
|
||||
std::string connection_id;
|
||||
|
||||
{
|
||||
sd_id128_t id;
|
||||
if (auto ret = sd_id128_randomize(&id); ret < 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": could not generation a connection UUID";
|
||||
return api::WifiConnectionStatus::kUnknown;
|
||||
}
|
||||
connection_id = SD_ID128_TO_UUID_STRING(id);
|
||||
}
|
||||
|
||||
auto [auth_alg, key_mgmt] = AuthAlgAndKeyMgmt(auth_type);
|
||||
|
||||
std::map<std::string, std::map<std::string, sdbus::Variant>>
|
||||
connection_settings{
|
||||
{"connection",
|
||||
std::map<std::string, sdbus::Variant>{
|
||||
{"uuid", connection_id},
|
||||
{"autoconnect", true},
|
||||
{"id", ssid},
|
||||
{"type", "802-11-wireless"},
|
||||
{"zone", "Public"},
|
||||
}},
|
||||
{"802-11-wireless",
|
||||
std::map<std::string, sdbus::Variant>{
|
||||
{"ssid", ssid_bytes},
|
||||
{"mode", "infrastructure"},
|
||||
{"security", "802-11-wireless-security"},
|
||||
{"assigned-mac-address", "random"},
|
||||
}},
|
||||
{"802-11-wireless-security",
|
||||
std::map<std::string, sdbus::Variant>{{"auth-alg", auth_alg},
|
||||
{"key-mgmt", key_mgmt}}}};
|
||||
if (!password.empty()) {
|
||||
connection_settings["802-11-wireless-security"]["psk"] =
|
||||
std::string(password);
|
||||
}
|
||||
|
||||
sdbus::ObjectPath connection_path, active_conn_path;
|
||||
try {
|
||||
auto [cp, acp, _r] = network_manager_->AddAndActivateConnection2(
|
||||
connection_settings, getObjectPath(), ap->getObjectPath(),
|
||||
{{"persist", "volatile"}, {"bind-activation", "dbus-client"}});
|
||||
connection_path = std::move(cp);
|
||||
active_conn_path = std::move(acp);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(this, "AddAndActivateConnection2", e);
|
||||
return api::WifiConnectionStatus::kUnknown;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": " << getObjectPath()
|
||||
<< ": Added a new connection at " << connection_path;
|
||||
auto active_connection = NetworkManagerActiveConnection(
|
||||
getProxy().getConnection(), active_conn_path);
|
||||
auto [reason, timeout] = active_connection.WaitForConnection();
|
||||
if (timeout) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": " << getObjectPath()
|
||||
<< ": timed out while waiting for connection " << active_conn_path
|
||||
<< " to be activated, last NMActiveConnectionStateReason: "
|
||||
<< reason.value();
|
||||
return api::WifiConnectionStatus::kUnknown;
|
||||
}
|
||||
|
||||
if (reason.has_value()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": " << getObjectPath() << ": connection "
|
||||
<< active_conn_path
|
||||
<< " failed to activate, NMActiveConnectionStateReason:"
|
||||
<< *reason;
|
||||
if (*reason == ActiveConnectionStateReason::kStateReasonNoSecrets ||
|
||||
*reason == ActiveConnectionStateReason::kStateReasonLoginFailed)
|
||||
return api::WifiConnectionStatus::kAuthFailure;
|
||||
}
|
||||
|
||||
return api::WifiConnectionStatus::kConnected;
|
||||
}
|
||||
|
||||
bool NetworkManagerWifiMedium::VerifyInternetConnectivity() {
|
||||
auto network_manager_proxy_ = sdbus::createProxy(
|
||||
"org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager");
|
||||
network_manager_proxy_->finishRegistration();
|
||||
|
||||
try {
|
||||
std::uint32_t connectivity = network_manager_.CheckConnectivity();
|
||||
std::uint32_t connectivity = network_manager_->CheckConnectivity();
|
||||
return connectivity == 4; // NM_CONNECTIVITY_FULL
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(network_manager_proxy_, "CheckConnectivity", e);
|
||||
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "CheckConnectivity", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,25 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#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 "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_accesspoint_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_connection_active_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_device_wireless_client_glue.h"
|
||||
#include "internal/platform/implementation/linux/networkmanager_ip4config_client_glue.h"
|
||||
#include "internal/platform/implementation/wifi.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
@@ -27,6 +32,11 @@ public:
|
||||
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
|
||||
"/org/freedesktop/NetworkManager") {
|
||||
registerProxy();
|
||||
try {
|
||||
state_ = State();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
|
||||
}
|
||||
}
|
||||
~NetworkManager() { unregisterProxy(); }
|
||||
|
||||
@@ -91,19 +101,112 @@ public:
|
||||
~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(
|
||||
sdbus::IConnection &system_bus,
|
||||
const sdbus::ObjectPath &active_connection_path)
|
||||
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
|
||||
active_connection_path) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
~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};
|
||||
};
|
||||
|
||||
private:
|
||||
absl::Mutex state_mutex_;
|
||||
ActiveConnectionState state_ ABSL_GUARDED_BY(state_mutex_);
|
||||
ActiveConnectionStateReason reason_ ABSL_GUARDED_BY(state_mutex_);
|
||||
};
|
||||
|
||||
class NetworkManagerWifiMedium
|
||||
: public api::WifiMedium,
|
||||
sdbus::ProxyInterfaces<
|
||||
org::freedesktop::NetworkManager::Device::Wireless_proxy,
|
||||
sdbus::Properties_proxy> {
|
||||
public sdbus::ProxyInterfaces<
|
||||
org::freedesktop::NetworkManager::Device::Wireless_proxy,
|
||||
sdbus::Properties_proxy> {
|
||||
public:
|
||||
NetworkManagerWifiMedium(NetworkManager &network_manager,
|
||||
NetworkManagerWifiMedium(std::shared_ptr<NetworkManager> network_manager,
|
||||
sdbus::IConnection &system_bus,
|
||||
const sdbus::ObjectPath &wireless_device_object_path)
|
||||
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
|
||||
wireless_device_object_path),
|
||||
network_manager_(network_manager) {
|
||||
active_access_point_ = std::nullopt;
|
||||
network_manager_(std::move(network_manager)) {
|
||||
registerProxy();
|
||||
}
|
||||
|
||||
@@ -121,10 +224,14 @@ public:
|
||||
bool IsInterfaceValid() const override { return true; };
|
||||
api::WifiCapability &GetCapability() override;
|
||||
api::WifiInformation &GetInformation() override;
|
||||
|
||||
bool Scan(
|
||||
const api::WifiMedium::ScanResultCallback &scan_result_callback) override;
|
||||
|
||||
std::shared_ptr<NetworkManagerAccessPoint>
|
||||
SearchBySSID(absl::string_view ssid,
|
||||
absl::Duration scan_timeout = absl::Seconds(15))
|
||||
ABSL_LOCKS_EXCLUDED(known_access_points_lock_);
|
||||
|
||||
api::WifiConnectionStatus
|
||||
ConnectToNetwork(absl::string_view ssid, absl::string_view password,
|
||||
api::WifiAuthType auth_type) override;
|
||||
@@ -138,19 +245,40 @@ protected:
|
||||
const std::map<std::string, sdbus::Variant> &changedProperties,
|
||||
const std::vector<std::string> &invalidatedProperties) override;
|
||||
|
||||
void onAccessPointAdded(const sdbus::ObjectPath &access_point) override
|
||||
ABSL_LOCKS_EXCLUDED(known_access_points_lock_) {
|
||||
absl::MutexLock l(&known_access_points_lock_);
|
||||
known_access_points_.erase(access_point);
|
||||
known_access_points_.emplace(access_point, getProxy().getConnection(),
|
||||
access_point);
|
||||
}
|
||||
void onAccessPointRemoved(const sdbus::ObjectPath &access_point) override
|
||||
ABSL_LOCKS_EXCLUDED(known_access_points_lock_) {
|
||||
absl::MutexLock l(&known_access_points_lock_);
|
||||
known_access_points_.erase(access_point);
|
||||
}
|
||||
|
||||
private:
|
||||
NetworkManager &network_manager_;
|
||||
std::shared_ptr<NetworkManagerAccessPoint>
|
||||
SearchBySSIDNoScan(std::vector<std::uint8_t> &ssid)
|
||||
ABSL_LOCKS_EXCLUDED(known_access_points_lock_);
|
||||
|
||||
std::shared_ptr<NetworkManager> network_manager_;
|
||||
|
||||
api::WifiCapability capability_;
|
||||
api::WifiInformation information_{false};
|
||||
|
||||
absl::Mutex active_access_point_lock_;
|
||||
std::optional<NetworkManagerAccessPoint> active_access_point_;
|
||||
absl::Mutex known_access_points_lock_;
|
||||
std::map<sdbus::ObjectPath, std::shared_ptr<NetworkManagerAccessPoint>>
|
||||
known_access_points_ ABSL_GUARDED_BY(known_access_points_lock_);
|
||||
|
||||
absl::Mutex scan_result_callback_lock_;
|
||||
std::optional<
|
||||
std::reference_wrapper<const api::WifiMedium::ScanResultCallback>>
|
||||
scan_result_callback_;
|
||||
scan_result_callback_ ABSL_GUARDED_BY(scan_result_callback_lock_);
|
||||
|
||||
absl::Mutex last_scan_lock_;
|
||||
std::int64_t last_scan_ ABSL_GUARDED_BY(last_scan_lock_);
|
||||
};
|
||||
|
||||
} // namespace linux
|
||||
|
||||
Reference in New Issue
Block a user