diff --git a/internal/platform/implementation/linux/wifi_hotspot.cc b/internal/platform/implementation/linux/wifi_hotspot.cc index 61735b0f..3d4ce648 100644 --- a/internal/platform/implementation/linux/wifi_hotspot.cc +++ b/internal/platform/implementation/linux/wifi_hotspot.cc @@ -1,86 +1,114 @@ +#include #include #include +#include #include +#include #include #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_hotspot_server_socket.h" +#include "internal/platform/implementation/linux/wifi_hotspot_socket.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; +std::unique_ptr +NetworkManagerWifiHotspotMedium::ConnectToService( + absl::string_view ip_address, int port, + CancellationFlag *cancellation_flag) { + if (!WifiHotspotActive()) { + NEARBY_LOGS(ERROR) + << __func__ + << ": Cannot connect to service without an active WiFi hotspot"; + return nullptr; } - auto ssid = hotspot_credentials->GetSSID(); - auto password = hotspot_credentials->GetPassword(); + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error opening socket: " << std::strerror(errno); + return nullptr; + } - return wireless_device_->ConnectToNetwork(ssid, password, - api::WifiAuthType::kWpaPsk) == - api::WifiConnectionStatus::kConnected; + NEARBY_LOGS(VERBOSE) << __func__ << ": Connecting to " << ip_address << ":" + << port; + struct sockaddr_in addr; + addr.sin_addr.s_addr = inet_addr(std::string(ip_address).c_str()); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + auto ret = + connect(sock, reinterpret_cast(&addr), sizeof(addr)); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error connecting to socket: " + << std::strerror(errno); + return nullptr; + } + + return std::make_unique(sock); } -bool NetworkManagerWifiHotspotMedium::DisconnectWifiHotspot() { +std::unique_ptr +NetworkManagerWifiHotspotMedium::ListenForService(int port) { if (!WifiHotspotActive()) { - NEARBY_LOGS(ERROR) << __func__ << ": WiFi hotspot is not active"; - return false; + NEARBY_LOGS(ERROR) + << __func__ + << ": Cannot connect to service without an active WiFi hotspot"; + return nullptr; + } + + auto active_connection = wireless_device_->GetActiveConnection(); + if (active_connection == nullptr) { + return nullptr; + } + + auto ip4addresses = active_connection->GetIP4Addresses(); + if (ip4addresses.empty()) { + NEARBY_LOGS(ERROR) + << __func__ + << "Could not find any IPv4 addresses for active connection " + << active_connection->getObjectPath(); + return nullptr; + } + + auto sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error opening socket: " << std::strerror(errno); + return nullptr; + } + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(ip4addresses[0].c_str()); + addr.sin_port = htons(port); + + auto ret = + bind(sock, reinterpret_cast(&addr), sizeof(addr)); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error binding to socket: " << std::strerror(errno); + return nullptr; + } + + NEARBY_LOGS(VERBOSE) << __func__ << ": Listening for services on " + << ip4addresses[0] << ":" << port << " on device " + << wireless_device_->getObjectPath(); + + ret = listen(sock, 0); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error listening on socket: " + << std::strerror(errno); + return nullptr; } - 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; + return std::make_unique(sock, + system_bus_, active_connection->getObjectPath(), network_manager_); } bool NetworkManagerWifiHotspotMedium::StartWifiHotspot( @@ -150,11 +178,12 @@ bool NetworkManagerWifiHotspotMedium::StartWifiHotspot( }}}; std::unique_ptr active_conn; try { - auto [path, active_path, result] = network_manager_->AddAndActivateConnection2( - connection_settings, wireless_device_->getObjectPath(), "/", - {{"persist", "volatile"}, {"bind-activation", "dbus-client"}}); + auto [path, active_path, result] = + network_manager_->AddAndActivateConnection2( + connection_settings, wireless_device_->getObjectPath(), "/", + {{"persist", "volatile"}, {"bind-activation", "dbus-client"}}); active_conn = std::make_unique(system_bus_, - active_path); + active_path); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "AddAndActivateConnection2", e); @@ -163,13 +192,14 @@ bool NetworkManagerWifiHotspotMedium::StartWifiHotspot( auto [reason, timeout] = active_conn->WaitForConnection(); if (timeout) { - NEARBY_LOGS(ERROR) << __func__ << ": " - << ": timed out while waiting for connection " - << active_conn->getObjectPath() + NEARBY_LOGS(ERROR) + << __func__ << ": " + << ": timed out while waiting for connection " + << active_conn->getObjectPath() << " to be activated, last NMActiveConnectionStateReason: " << reason.value(); DisconnectWifiHotspot(); - return false; + return false; } NEARBY_LOGS(INFO) << __func__ << ": Started a WiFi hotspot on device " @@ -178,6 +208,87 @@ bool NetworkManagerWifiHotspotMedium::StartWifiHotspot( return true; } +bool NetworkManagerWifiHotspotMedium::StopWifiHotspot() { + if (!WifiHotspotActive()) { + NEARBY_LOGS(ERROR) + << __func__ << ": " << wireless_device_->getObjectPath() + << ": Cannot stop WiFi hotspot as a WiFi hotspot is not active"; + } + + // Get the active connection object for the hotspot AP. + sdbus::ObjectPath active_ap_path; + + try { + active_ap_path = wireless_device_->ActiveAccessPoint(); + if (active_ap_path.empty()) { + NEARBY_LOGS(ERROR) << __func__ << ": No active 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 active_connection = wireless_device_->GetActiveConnection(); + if (active_connection == nullptr) { + NEARBY_LOGS(ERROR) + << __func__ + << ": Could not find an active connection using the access point " + << active_ap_path; + return false; + } + + NEARBY_LOGS(INFO) << __func__ << ": " << wireless_device_->getObjectPath() + << ": Deactivating active connection " + << active_connection->getObjectPath(); + + try { + network_manager_->DeactivateConnection(active_connection->getObjectPath()); + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "DeactivateConnection", e); + return false; + } + + return true; +} + +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; + } + + auto active_connection = wireless_device_->GetActiveConnection(); + if (active_connection == nullptr) { + return false; + } + + try { + network_manager_->DeactivateConnection(active_connection->getObjectPath()); + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "DeactivateConnection", e); + return false; + } + + return true; +} + bool NetworkManagerWifiHotspotMedium::WifiHotspotActive() { try { auto mode = wireless_device_->Mode(); @@ -187,5 +298,6 @@ bool NetworkManagerWifiHotspotMedium::WifiHotspotActive() { return false; } } + } // namespace linux } // namespace nearby diff --git a/internal/platform/implementation/linux/wifi_hotspot.h b/internal/platform/implementation/linux/wifi_hotspot.h index 9f4f0f55..ec0af3bb 100644 --- a/internal/platform/implementation/linux/wifi_hotspot.h +++ b/internal/platform/implementation/linux/wifi_hotspot.h @@ -8,43 +8,51 @@ #include "internal/platform/implementation/wifi_hotspot.h" namespace nearby { - namespace linux { - class NetworkManagerWifiHotspotMedium : api::WifiHotspotMedium { - public: - NetworkManagerWifiHotspotMedium( - sdbus::IConnection &system_bus, - std::shared_ptr network_manager, - const sdbus::ObjectPath &wireless_device_object_path) - : system_bus_(system_bus), - wireless_device_(std::make_unique( - network_manager, system_bus, wireless_device_object_path)), - network_manager_(network_manager) {} - ~NetworkManagerWifiHotspotMedium() {} +namespace linux { +class NetworkManagerWifiHotspotMedium : public api::WifiHotspotMedium { +public: + NetworkManagerWifiHotspotMedium( + sdbus::IConnection &system_bus, + std::shared_ptr network_manager, + const sdbus::ObjectPath &wireless_device_object_path) + : system_bus_(system_bus), + wireless_device_(std::make_unique( + network_manager, system_bus, wireless_device_object_path)), + network_manager_(network_manager) {} + NetworkManagerWifiHotspotMedium( + sdbus::IConnection &system_bus, + std::shared_ptr network_manager, + std::unique_ptr wireless_device) + : system_bus_(system_bus), wireless_device_(std::move(wireless_device)), + network_manager_(network_manager) {} + ~NetworkManagerWifiHotspotMedium() {} - bool IsInterfaceValid() const override { return true; } - std::unique_ptr - ConnectToService(absl::string_view ip_address, int port, - CancellationFlag *cancellation_flag) override; - std::unique_ptr - ListenForService(int port) override; + bool IsInterfaceValid() const override { return true; } + std::unique_ptr + ConnectToService(absl::string_view ip_address, int port, + CancellationFlag *cancellation_flag) override; + std::unique_ptr + ListenForService(int port) override; - bool StartWifiHotspot(HotspotCredentials *hotspot_credentials) override; - bool StopWifiHotspot() override; + bool StartWifiHotspot(HotspotCredentials *hotspot_credentials) override; + bool StopWifiHotspot() override; - bool ConnectWifiHotspot(HotspotCredentials *hotspot_credentials) override; - bool DisconnectWifiHotspot() override; + bool ConnectWifiHotspot(HotspotCredentials *hotspot_credentials) override; + bool DisconnectWifiHotspot() override; - absl::optional> - GetDynamicPortRange() override {return absl::nullopt;} - - private: - bool WifiHotspotActive(); - - sdbus::IConnection &system_bus_; - std::unique_ptr wireless_device_; - std::shared_ptr network_manager_; - }; + absl::optional> + GetDynamicPortRange() override { + return absl::nullopt; } -} + +private: + bool WifiHotspotActive(); + + sdbus::IConnection &system_bus_; + std::unique_ptr wireless_device_; + std::shared_ptr network_manager_; +}; +} // namespace linux +} // namespace nearby #endif diff --git a/internal/platform/implementation/linux/wifi_hotspot_server_socket.cc b/internal/platform/implementation/linux/wifi_hotspot_server_socket.cc new file mode 100644 index 00000000..531dd7e0 --- /dev/null +++ b/internal/platform/implementation/linux/wifi_hotspot_server_socket.cc @@ -0,0 +1,67 @@ +#include +#include + +#include "internal/platform/implementation/linux/wifi_hotspot_server_socket.h" +#include "internal/platform/implementation/linux/wifi_hotspot_socket.h" +#include "internal/platform/implementation/linux/wifi_medium.h" + +namespace nearby { +namespace linux { +std::string NetworkManagerWifiHotspotServerSocket::GetIPAddress() const { + NetworkManagerActiveConnection active_conn(system_bus_, + active_connection_path_); + auto ip4addresses = active_conn.GetIP4Addresses(); + if (ip4addresses.empty()) { + NEARBY_LOGS(ERROR) + << __func__ + << ": Could not find any IPv4 addresses for active connection " + << active_connection_path_; + return std::string(); + } + return ip4addresses[0]; +} + +int NetworkManagerWifiHotspotServerSocket::GetPort() const { + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + auto ret = + getsockname(fd_.get(), reinterpret_cast(&sin), &len); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error getting information for socket " + << fd_.get() << ": " << std::strerror(errno); + return 0; + } + + return ntohs(sin.sin_port); +} + +std::unique_ptr +NetworkManagerWifiHotspotServerSocket::Accept() { + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + + auto conn = + accept(fd_.get(), reinterpret_cast(&addr), &len); + if (conn < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error accepting incoming connections on socket " + << fd_.get() << ": " << std::strerror(errno); + return nullptr; + } + + return std::make_unique(conn); +} + +Exception NetworkManagerWifiHotspotServerSocket::Close() { + int fd = fd_.release(); + auto ret = close(fd); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error closing socket " << fd << ": " + << std::strerror(errno); + return {Exception::kFailed}; + } + + return {Exception::kSuccess}; +} +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/wifi_hotspot_server_socket.h b/internal/platform/implementation/linux/wifi_hotspot_server_socket.h new file mode 100644 index 00000000..7a8f2ac3 --- /dev/null +++ b/internal/platform/implementation/linux/wifi_hotspot_server_socket.h @@ -0,0 +1,37 @@ +#ifndef PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_ +#define PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_ + +#include + +#include "internal/platform/implementation/linux/wifi_medium.h" +#include "internal/platform/implementation/wifi_hotspot.h" + +namespace nearby { +namespace linux { +class NetworkManagerWifiHotspotServerSocket + : public api::WifiHotspotServerSocket { +public: + NetworkManagerWifiHotspotServerSocket( + int socket, sdbus::IConnection &system_bus, + const sdbus::ObjectPath &active_connection_path, + std::shared_ptr network_manager) + : fd_(socket), system_bus_(system_bus), + active_connection_path_(active_connection_path), + network_manager_(network_manager) {} + ~NetworkManagerWifiHotspotServerSocket() {} + + std::string GetIPAddress() const override; + int GetPort() const override; + std::unique_ptr Accept() override; + Exception Close() override; + +private: + sdbus::UnixFd fd_; + sdbus::IConnection &system_bus_; + sdbus::ObjectPath active_connection_path_; + std::shared_ptr network_manager_; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/wifi_hotspot_socket.h b/internal/platform/implementation/linux/wifi_hotspot_socket.h new file mode 100644 index 00000000..7e0d2d56 --- /dev/null +++ b/internal/platform/implementation/linux/wifi_hotspot_socket.h @@ -0,0 +1,33 @@ +#ifndef PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_SOCKET_H_ +#define PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_SOCKET_H_ + +#include "internal/platform/implementation/linux/stream.h" +#include "internal/platform/implementation/wifi_hotspot.h" + +namespace nearby { +namespace linux { +class WifiHotspotSocket : public api::WifiHotspotSocket { +public: + WifiHotspotSocket(int connection_fd) + : fd_(sdbus::UnixFd(connection_fd)), output_stream_(fd_), + input_stream_(fd_) {} + ~WifiHotspotSocket() {} + + nearby::InputStream &GetInputStream() override { return input_stream_; }; + nearby::OutputStream &GetOutputStream() override { return output_stream_; }; + Exception Close() override { + input_stream_.Close(); + output_stream_.Close(); + + return Exception{Exception::kSuccess}; + }; + +private: + sdbus::UnixFd fd_; + OutputStream output_stream_; + InputStream input_stream_; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/wifi_lan.cc b/internal/platform/implementation/linux/wifi_lan.cc index 4e9df5ec..079772dc 100644 --- a/internal/platform/implementation/linux/wifi_lan.cc +++ b/internal/platform/implementation/linux/wifi_lan.cc @@ -79,6 +79,7 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo &nsd_service_info) { NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName() << "' with message '" << e.getMessage() << "' while adding service"; + return false; } advertising_ = true; @@ -107,6 +108,7 @@ bool WifiLanMedium::StopAdvertising(const NsdServiceInfo &nsd_service_info) { NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName() << "' with message '" << e.getMessage() << "' while removing service"; + return false; } advertising_ = false; @@ -137,6 +139,7 @@ bool WifiLanMedium::StartDiscovery( std::move(callback)); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(avahi_, "ServiceBrowserPrepare", e); + return false; } auto &browser = service_browsers_[service_type]; @@ -146,6 +149,7 @@ bool WifiLanMedium::StartDiscovery( browser->Start(); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(browser, "Start", e); + return false; } return true; @@ -163,6 +167,7 @@ bool WifiLanMedium::StopDiscovery(const std::string &service_type) { browser->Free(); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(browser, "Free", e); + return false; } service_browsers_.erase(service_type); @@ -199,7 +204,8 @@ WifiLanMedium::ConnectToService(const std::string &ip_address, int port, return std::make_unique(std::move(fd)); } -std::unique_ptr WifiLanMedium::ListenForService(int port) { +std::unique_ptr +WifiLanMedium::ListenForService(int port) { auto sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { NEARBY_LOGS(ERROR) << __func__ @@ -229,7 +235,8 @@ std::unique_ptr WifiLanMedium::ListenForService(int po return nullptr; } - return std::make_unique(sock, network_manager_); + return std::make_unique(sock, network_manager_, + system_bus_); } absl::optional> GetDynamicPortRange() { diff --git a/internal/platform/implementation/linux/wifi_lan_server_socket.cc b/internal/platform/implementation/linux/wifi_lan_server_socket.cc index 20313149..89ac1ca6 100644 --- a/internal/platform/implementation/linux/wifi_lan_server_socket.cc +++ b/internal/platform/implementation/linux/wifi_lan_server_socket.cc @@ -46,9 +46,12 @@ std::string WifiLanServerSocket::GetIPAddress() const { address_data = ip4config.AddressData(); } catch (const sdbus::Error &e) { DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "IP4Config", e); + continue; } - return address_data[0]["address"]; + if (address_data.size() > 0) { + return address_data[0]["address"]; + } } } diff --git a/internal/platform/implementation/linux/wifi_medium.cc b/internal/platform/implementation/linux/wifi_medium.cc index 4aa0d5a8..b79fb7a9 100644 --- a/internal/platform/implementation/linux/wifi_medium.cc +++ b/internal/platform/implementation/linux/wifi_medium.cc @@ -61,7 +61,16 @@ std::ostream &operator<<(std::ostream &s, std::unique_ptr NetworkManagerObjectManager::GetIp4Config( const sdbus::ObjectPath &active_connection) { - auto objects = GetManagedObjects(); + std::map>> + 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) { @@ -82,6 +91,44 @@ NetworkManagerObjectManager::GetIp4Config( return nullptr; } +std::unique_ptr +NetworkManagerObjectManager::GetActiveConnectionForAccessPoint( + const sdbus::ObjectPath &access_point, + const sdbus::ObjectPath &device_path) { + std::map>> + 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 devices = props["Devices"]; + for (auto &path : devices) { + if (path == device_path) { + return std::make_unique( + getProxy().getConnection(), object_path); + } + } + } + } + } + } + + return nullptr; +} + api::WifiCapability &NetworkManagerWifiMedium::GetCapability() { try { auto cap_mask = WirelessCapabilities(); @@ -331,7 +378,7 @@ NetworkManagerWifiMedium::ConnectToNetwork(absl::string_view ssid, } NEARBY_LOGS(INFO) << __func__ << ": " << getObjectPath() - << ": Added a new connection at " << connection_path; + << ": Added a new connection at " << connection_path; auto active_connection = NetworkManagerActiveConnection( getProxy().getConnection(), active_conn_path); auto [reason, timeout] = active_connection.WaitForConnection(); @@ -372,5 +419,34 @@ std::string NetworkManagerWifiMedium::GetIpAddress() { return information_.ip_address_dot_decimal; } +std::unique_ptr +NetworkManagerWifiMedium::GetActiveConnection() { + sdbus::ObjectPath active_ap_path; + + try { + active_ap_path = ActiveAccessPoint(); + if (active_ap_path.empty()) { + NEARBY_LOGS(ERROR) << __func__ << ": No active access points on " + << getObjectPath(); + return nullptr; + } + } catch (const sdbus::Error &e) { + DBUS_LOG_PROPERTY_GET_ERROR(this, "ActiveAccessPoint", e); + return nullptr; + } + + auto object_manager = NetworkManagerObjectManager(getProxy().getConnection()); + auto conn = object_manager.GetActiveConnectionForAccessPoint(active_ap_path, + getObjectPath()); + + if (conn == nullptr) { + NEARBY_LOGS(ERROR) + << __func__ + << ": Could not find an active connection using the access point " + << active_ap_path << " and device " << getObjectPath(); + } + return conn; +} + } // namespace linux } // namespace nearby diff --git a/internal/platform/implementation/linux/wifi_medium.h b/internal/platform/implementation/linux/wifi_medium.h index 2af8ff6b..b9aa318f 100644 --- a/internal/platform/implementation/linux/wifi_medium.h +++ b/internal/platform/implementation/linux/wifi_medium.h @@ -65,29 +65,6 @@ public: ~NetworkManagerIP4Config() { unregisterProxy(); } }; -class NetworkManagerObjectManager - : public sdbus::ProxyInterfaces { -public: - NetworkManagerObjectManager(sdbus::IConnection &system_bus) - : ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager", - "/org/freedesktop") { - registerProxy(); - } - ~NetworkManagerObjectManager() { unregisterProxy(); } - - std::unique_ptr - GetIp4Config(const sdbus::ObjectPath &access_point); - -protected: - void onInterfacesAdded( - const sdbus::ObjectPath &objectPath, - const std::map> - &interfacesAndProperties) override {} - void - onInterfacesRemoved(const sdbus::ObjectPath &objectPath, - const std::vector &interfaces) override {} -}; - class NetworkManagerAccessPoint : public sdbus::ProxyInterfaces< org::freedesktop::NetworkManager::AccessPoint_proxy> { @@ -187,7 +164,35 @@ public: return state == kStateActivated ? std::pair{std::nullopt, false} : std::pair{std::optional(reason), false}; - }; + } + + std::vector 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> address_data; + try { + address_data = ip4config.AddressData(); + } catch (const sdbus::Error &e) { + DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "AddressData", e); + return {}; + } + + std::vector ip4addresses; + for (auto &data : address_data) { + if (data.count("address") == 1) { + ip4addresses.push_back(data["address"]); + } + } + return ip4addresses; + } private: absl::Mutex state_mutex_; @@ -195,11 +200,37 @@ private: ActiveConnectionStateReason reason_ ABSL_GUARDED_BY(state_mutex_); }; +class NetworkManagerObjectManager + : public sdbus::ProxyInterfaces { +public: + NetworkManagerObjectManager(sdbus::IConnection &system_bus) + : ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager", + "/org/freedesktop") { + registerProxy(); + } + ~NetworkManagerObjectManager() { unregisterProxy(); } + + std::unique_ptr + GetIp4Config(const sdbus::ObjectPath &access_point); + std::unique_ptr + GetActiveConnectionForAccessPoint(const sdbus::ObjectPath &access_point_path, + const sdbus::ObjectPath &device_path); + +protected: + void onInterfacesAdded( + const sdbus::ObjectPath &objectPath, + const std::map> + &interfacesAndProperties) override {} + void + onInterfacesRemoved(const sdbus::ObjectPath &objectPath, + const std::vector &interfaces) override {} +}; + class NetworkManagerWifiMedium : public api::WifiMedium, public sdbus::ProxyInterfaces< - org::freedesktop::NetworkManager::Device::Wireless_proxy, - sdbus::Properties_proxy> { + org::freedesktop::NetworkManager::Device::Wireless_proxy, + sdbus::Properties_proxy> { public: NetworkManagerWifiMedium(std::shared_ptr network_manager, sdbus::IConnection &system_bus, @@ -239,6 +270,8 @@ public: bool VerifyInternetConnectivity() override; std::string GetIpAddress() override; + std::unique_ptr GetActiveConnection(); + protected: void onPropertiesChanged( const std::string &interfaceName,