Add Wifi Direct medium

This commit is contained in:
Vibhav Pant
2023-08-27 00:32:55 +05:30
parent 6e4c035103
commit ef666b2311
6 changed files with 345 additions and 1 deletions
@@ -24,6 +24,7 @@
#include "internal/platform/implementation/linux/mutex.h"
#include "internal/platform/implementation/linux/submittable_executor.h"
#include "internal/platform/implementation/linux/timer.h"
#include "internal/platform/implementation/linux/wifi_direct.h"
#include "internal/platform/implementation/linux/wifi_hotspot.h"
#include "internal/platform/implementation/linux/wifi_lan.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
@@ -163,6 +164,7 @@ ImplementationPlatform::CreateBluetoothAdapter() {
}
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&manager, "GetManagedObjects", e);
return nullptr;
}
NEARBY_LOGS(ERROR) << __func__
@@ -259,7 +261,17 @@ ImplementationPlatform::CreateWifiHotspotMedium() {
std::unique_ptr<api::WifiDirectMedium>
ImplementationPlatform::CreateWifiDirectMedium() {
return nullptr;
auto nm =
std::make_shared<linux::NetworkManager>(linux::getSystemBusConnection());
auto wifiMedium = createWifiMedium(nm);
if (wifiMedium == nullptr) {
NEARBY_LOGS(ERROR) << __func__ << ": Could not create a WiFi medium";
return nullptr;
}
return std::make_unique<linux::NetworkManagerWifiDirectMedium>(
linux::getSystemBusConnection(), nm, std::move(wifiMedium));
}
std::unique_ptr<api::Timer> ImplementationPlatform::CreateTimer() {
@@ -0,0 +1,160 @@
#include <arpa/inet.h>
#include <memory>
#include <netinet/in.h>
#include <sys/socket.h>
#include "internal/platform/implementation/linux/wifi_direct.h"
#include "internal/platform/implementation/linux/wifi_direct_server_socket.h"
#include "internal/platform/implementation/linux/wifi_direct_socket.h"
#include "internal/platform/implementation/linux/wifi_hotspot.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
namespace linux {
std::unique_ptr<api::WifiDirectSocket>
NetworkManagerWifiDirectMedium::ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag *cancellation_flag) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
NEARBY_LOGS(ERROR) << __func__
<< ": Error opening socket: " << std::strerror(errno);
return nullptr;
}
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<struct sockaddr *>(&addr), sizeof(addr));
if (ret < 0) {
NEARBY_LOGS(ERROR) << __func__ << ": Error connecting to socket: "
<< std::strerror(errno);
return nullptr;
}
return std::make_unique<WifiDirectSocket>(sock);
}
std::unique_ptr<api::WifiDirectServerSocket>
NetworkManagerWifiDirectMedium::ListenForService(int port) {
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<struct sockaddr *>(&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;
}
return std::make_unique<NetworkManagerWifiDirectServerSocket>(
sock, system_bus_, active_connection->getObjectPath(), network_manager_);
}
bool NetworkManagerWifiDirectMedium::ConnectWifiDirect(
WifiDirectCredentials *wifi_direct_credentials) {
if (wifi_direct_credentials == nullptr) {
NEARBY_LOGS(ERROR) << __func__ << ": hotspot_credentials cannot be null";
return false;
}
auto ssid = wifi_direct_credentials->GetSSID();
auto password = wifi_direct_credentials->GetPassword();
return wireless_device_->ConnectToNetwork(ssid, password,
api::WifiAuthType::kWpaPsk) ==
api::WifiConnectionStatus::kConnected;
}
bool NetworkManagerWifiDirectMedium::DisconnectWifiDirect() {
if (!ConnectedToWifi()) {
NEARBY_LOGS(ERROR) << __func__ << ": Not connected to a WiFi hotspot";
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 NetworkManagerWifiDirectMedium::StartWifiDirect(
WifiDirectCredentials *wifi_direct_credentials) {
// According to the comments in the windows implementation, the wifi direct
// medium is currently just a regular wifi hotspot.
auto wireless_device = std::make_unique<NetworkManagerWifiMedium>(
network_manager_, system_bus_, wireless_device_->getObjectPath());
auto hotspot = NetworkManagerWifiHotspotMedium(system_bus_, network_manager_,
std::move(wireless_device));
HotspotCredentials hotspot_creds;
if (!hotspot.StartWifiHotspot(&hotspot_creds))
return false;
wifi_direct_credentials->SetSSID(hotspot_creds.GetSSID());
wifi_direct_credentials->SetPassword(hotspot_creds.GetPassword());
return true;
}
bool NetworkManagerWifiDirectMedium::StopWifiDirect() {
auto wireless_device = std::make_unique<NetworkManagerWifiMedium>(
network_manager_, system_bus_, wireless_device_->getObjectPath());
auto hotspot = NetworkManagerWifiHotspotMedium(system_bus_, network_manager_,
std::move(wireless_device));
return hotspot.DisconnectWifiHotspot();
}
} // namespace linux
} // namespace nearby
@@ -0,0 +1,48 @@
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_H_
#include <memory>
#include <optional>
#include <sdbus-c++/IConnection.h>
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_direct.h"
namespace nearby {
namespace linux {
class NetworkManagerWifiDirectMedium : public api::WifiDirectMedium {
public:
NetworkManagerWifiDirectMedium(
sdbus::IConnection &system_bus,
std::shared_ptr<NetworkManager> network_manager,
std::unique_ptr<NetworkManagerWifiMedium> wireless_device)
: system_bus_(system_bus), network_manager_(network_manager),
wireless_device_(std::move(wireless_device)) {}
~NetworkManagerWifiDirectMedium() {}
bool IsInterfaceValid() const override { return true; }
std::unique_ptr<api::WifiDirectSocket>
ConnectToService(absl::string_view ip_address, int port,
CancellationFlag *cancellation_flag) override;
std::unique_ptr<api::WifiDirectServerSocket>
ListenForService(int port) override;
bool
ConnectWifiDirect(WifiDirectCredentials *wifi_direct_credentials) override;
bool DisconnectWifiDirect() override;
bool StartWifiDirect(WifiDirectCredentials *wifi_direct_credentials) override;
bool StopWifiDirect() override;
absl::optional<std::pair<std::int32_t, std::int32_t>>
GetDynamicPortRange() override {
return std::nullopt;
}
sdbus::IConnection &system_bus_;
std::shared_ptr<NetworkManager> network_manager_;
std::unique_ptr<NetworkManagerWifiMedium> wireless_device_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -0,0 +1,66 @@
#include "internal/platform/implementation/linux/wifi_direct_server_socket.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/wifi_direct_socket.h"
#include <netinet/in.h>
#include <sys/socket.h>
namespace nearby {
namespace linux {
std::string NetworkManagerWifiDirectServerSocket::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 NetworkManagerWifiDirectServerSocket::GetPort() const {
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
auto ret =
getsockname(fd_.get(), reinterpret_cast<struct sockaddr *>(&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<api::WifiDirectSocket>
NetworkManagerWifiDirectServerSocket::Accept() {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
auto conn =
accept(fd_.get(), reinterpret_cast<struct sockaddr *>(&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<WifiDirectSocket>(conn);
}
Exception NetworkManagerWifiDirectServerSocket::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
@@ -0,0 +1,30 @@
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_SERVER_SOCKET_H_
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_direct.h"
#include <sdbus-c++/IConnection.h>
namespace nearby {
namespace linux {
class NetworkManagerWifiDirectServerSocket
: public api::WifiDirectServerSocket {
public:
NetworkManagerWifiDirectServerSocket(int socket, sdbus::IConnection &system_bus,
const sdbus::ObjectPath &active_connection_path,
std::shared_ptr<NetworkManager> network_manager) : fd_(socket), system_bus_(system_bus), active_connection_path_(active_connection_path), network_manager_(network_manager) {}
~NetworkManagerWifiDirectServerSocket() {}
std::string GetIPAddress() const override;
int GetPort() const override;
std::unique_ptr<api::WifiDirectSocket> Accept() override;
Exception Close() override;
private:
sdbus::UnixFd fd_;
sdbus::IConnection &system_bus_;
sdbus::ObjectPath active_connection_path_;
std::shared_ptr<NetworkManager> network_manager_ ;
};
}
}
#endif
@@ -0,0 +1,28 @@
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_SOCKET_H_
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/stream.h"
#include "internal/platform/implementation/wifi_direct.h"
namespace nearby {
namespace linux {
class WifiDirectSocket : public api::WifiDirectSocket {
public:
WifiDirectSocket(int socket);
~WifiDirectSocket() = default;
InputStream &GetInputStream() override;
OutputStream &GetOutputStream() override;
Exception Close() override;
private:
sdbus::UnixFd fd_;
OutputStream output_stream_;
InputStream input_stream_;
};
} // namespace linux
} // namespace nearby
#endif