Added wifi hotspot medium. Fixed mutex deadlock when bandwidth upgrade with bt classic socket

This commit is contained in:
kidfromjupiter
2026-01-05 14:17:26 +00:00
parent e2256ca83d
commit 0432c47542
9 changed files with 206 additions and 144 deletions
+21 -21
View File
@@ -70,7 +70,7 @@ cc_library(
"bluetooth_pairing.h",
"bluez.h",
"bluez_device.h",
"bluez_agent.h",
# "bluez_agent.h",
# "bluez_advertisement_monitor.h",
# "bluez_advertisement_monitor_manager.h",
# "bluez_gatt_characteristic_client.h",
@@ -80,22 +80,22 @@ cc_library(
# "bluez_gatt_service_server.h",
# "bluez_le_advertisement.h",
"dbus.h",
# "network_manager.h",
# "network_manager_active_connection.h",
# "network_manager_access_point.h",
"network_manager.h",
"network_manager_active_connection.h",
"network_manager_access_point.h",
"stream.h",
# "tcp_server_socket.h",
# "wifi_direct.h",
# "wifi_direct_server_socket.h",
# "wifi_direct_socket.h",
# "wifi_hotspot.h",
# "wifi_hotspot_server_socket.h",
# "wifi_hotspot_socket.h",
"tcp_server_socket.h",
"wifi_direct.h",
"wifi_direct_server_socket.h",
"wifi_direct_socket.h",
"wifi_hotspot.h",
"wifi_hotspot_server_socket.h",
"wifi_hotspot_socket.h",
# "wifi_lan.h",
# "wifi_lan_server_socket.h",
# "wifi_lan_socket.h",
# "wifi_medium.h",
# "wifi_socket.h",
"wifi_medium.h",
"wifi_socket.h",
],
deps = [
"//internal/platform:base",
@@ -151,7 +151,7 @@ cc_library(
"bluetooth_devices.cc",
"bluetooth_pairing.cc",
"bluez.cc",
"bluez_agent.cc",
#"bluez_agent.cc",
# "bluez_advertisement_monitor.cc",
# "bluez_gatt_characteristic_client.cc",
# "bluez_gatt_characteristic_server.cc",
@@ -159,8 +159,8 @@ cc_library(
# "bluez_le_advertisement.cc",
"dbus.cc",
"executor.cc",
# "network_manager.cc",
# "network_manager_active_connection.cc",
"network_manager.cc",
"network_manager_active_connection.cc",
"platform.cc",
"preferences_manager.cc",
"preferences_repository.cc",
@@ -170,13 +170,13 @@ cc_library(
"system_clock.cc",
"thread_pool.cc",
"utils.cc",
# "wifi_direct.cc",
# "wifi_direct_server_socket.cc",
# "wifi_hotspot.cc",
# "wifi_hotspot_server_socket.cc",
"wifi_direct.cc",
"wifi_direct_server_socket.cc",
"wifi_hotspot.cc",
"wifi_hotspot_server_socket.cc",
# "wifi_lan.cc",
# "wifi_lan_server_socket.cc",
# "wifi_medium.cc",
"wifi_medium.cc",
],
linkopts = ["-lcurl"],
visibility = [
@@ -26,7 +26,7 @@
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_classic_medium.h"
#include "bluez_agent.h"
// #include "bluez_agent.h"
#include "internal/platform/implementation/linux/bluetooth_classic_server_socket.h"
#include "internal/platform/implementation/linux/bluetooth_classic_socket.h"
#include "internal/platform/implementation/linux/bluetooth_pairing.h"
@@ -41,7 +41,7 @@ BluetoothClassicMedium::BluetoothClassicMedium(BluetoothAdapter &adapter)
devices_(std::make_shared<BluetoothDevices>(
system_bus_, adapter.GetObjectPath(), *observers_)),
device_watcher_(nullptr),
agent_manager_(std::make_unique<AgentManager>(*system_bus_)),
// agent_manager_(std::make_unique<AgentManager>(*system_bus_)),
profile_manager_(
std::make_unique<ProfileManager>(*system_bus_, *devices_)) {}
@@ -145,15 +145,6 @@ BluetoothClassicMedium::ListenForService(const std::string &service_name,
const std::string &service_uuid) {
LOG(INFO) << __func__ << ": Creating bluez agent on path: " << "/com/example/bluez_agent" ;
if (!agent_manager_ -> AgentRegistered("/com/example/bluez_agent"))
{
if (!agent_manager_ -> Register(std::nullopt, "/com/example/bluez_agent"))
{
LOG(ERROR) << __func__ << ": Could not register agent " << service_name << " "
<< service_uuid;
return nullptr;
}
}
if (!profile_manager_->ProfileRegistered(service_uuid)) {
if (!profile_manager_->Register(service_name, service_uuid)) {
LOG(ERROR) << __func__ << ": Could not register profile "
@@ -26,7 +26,7 @@
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "bluez_agent.h"
// #include "bluez_agent.h"
#include "internal/base/observer_list.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
@@ -107,7 +107,7 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
std::shared_ptr<BluetoothDevices> devices_;
std::unique_ptr<DeviceWatcher> device_watcher_;
std::unique_ptr<AgentManager> agent_manager_;
// std::unique_ptr<AgentManager> agent_manager_;
std::unique_ptr<ProfileManager> profile_manager_;
};
@@ -82,14 +82,14 @@ Exception Poller::Ready() {
ExceptionOr<ByteArray> BluetoothInputStream::Read(std::int64_t size) {
absl::MutexLock lock(&fd_mutex_);
if (!fd_.isValid()) return Exception{Exception::kIo};
int fd = fd_raw_.load();
if (fd < 0) return Exception{Exception::kIo};
auto poller = Poller::CreateInputPoller(fd_);
auto poller = Poller::CreateInputPoller(fd);
int so_type = 0;
socklen_t sl = sizeof(so_type);
if (::getsockopt(fd_.get(), SOL_SOCKET, SO_TYPE, &so_type, &sl) != 0) {
if (::getsockopt(fd, SOL_SOCKET, SO_TYPE, &so_type, &sl) != 0) {
// If unknown, default to stream-ish behavior.
so_type = SOCK_STREAM;
}
@@ -102,13 +102,15 @@ ExceptionOr<ByteArray> BluetoothInputStream::Read(std::int64_t size) {
if (packet_based) {
// Wait for readability
while (true) {
if (fd_raw_.load() != fd) return {Exception::kIo};
auto result = poller.Ready();
if (result.Raised()) return result;
if (fd_raw_.load() != fd) return {Exception::kIo};
// Peek the next message length without consuming it.
// For seqpacket/dgram, MSG_TRUNC makes recv() return the *full* message length
// even if the buffer is smaller.
ssize_t msg_len = ::recv(fd_.get(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
ssize_t msg_len = ::recv(fd, nullptr, 0, MSG_PEEK | MSG_TRUNC);
if (msg_len < 0) {
if (errno == EINTR) continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) continue;
@@ -137,7 +139,8 @@ ExceptionOr<ByteArray> BluetoothInputStream::Read(std::int64_t size) {
// Now read/consume the message. If the message is larger than to_read,
// the remainder will be discarded by the kernel for seqpacket/dgram.
// We can detect that and treat it as an error (or choose a different policy).
ssize_t n = ::recv(fd_.get(), buffer.data(), to_read, 0);
if (fd_raw_.load() != fd) return {Exception::kIo};
ssize_t n = ::recv(fd, buffer.data(), to_read, 0);
if (n < 0) {
if (errno == EINTR) continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) continue;
@@ -176,10 +179,12 @@ ExceptionOr<ByteArray> BluetoothInputStream::Read(std::int64_t size) {
size_t total_read = 0;
while (total_read < static_cast<size_t>(size)) {
if (fd_raw_.load() != fd) return {Exception::kIo};
auto result = poller.Ready();
if (result.Raised()) return result;
if (fd_raw_.load() != fd) return {Exception::kIo};
ssize_t bytes_read = ::read(fd_.get(),
ssize_t bytes_read = ::read(fd,
data + total_read,
static_cast<size_t>(size) - total_read);
if (bytes_read < 0) {
@@ -204,23 +209,24 @@ ExceptionOr<ByteArray> BluetoothInputStream::Read(std::int64_t size) {
}
Exception BluetoothInputStream::Close() {
absl::MutexLock lock(&fd_mutex_);
if (!fd_.isValid()) return {Exception::kSuccess}; // Already closed
int fd = fd_raw_.exchange(-1);
if (fd < 0) return {Exception::kSuccess}; // Already closed
::shutdown(fd, SHUT_RDWR);
fd_.reset();
return {Exception::kSuccess};
}
Exception BluetoothOutputStream::Write(const ByteArray &data) {
absl::MutexLock lock(&fd_mutex_);
if (!fd_.isValid()) return Exception{Exception::kIo};
int fd = fd_raw_.load();
if (fd < 0) return Exception{Exception::kIo};
auto poller = Poller::CreateOutputPoller(fd_);
auto poller = Poller::CreateOutputPoller(fd);
size_t total_wrote = 0;
int so_type = 0;
socklen_t sl = sizeof(so_type);
if (::getsockopt(fd_.get(), SOL_SOCKET, SO_TYPE, &so_type, &sl) != 0) {
if (::getsockopt(fd, SOL_SOCKET, SO_TYPE, &so_type, &sl) != 0) {
// If we cant detect, assume stream semantics (no per-message MTU).
so_type = SOCK_STREAM;
}
@@ -229,17 +235,23 @@ Exception BluetoothOutputStream::Write(const ByteArray &data) {
// Initialize a reasonable starting guess for packet-based sockets.
// This will be refined down on EMSGSIZE.
if (packet_based && max_chunk_ == 0) max_chunk_ = 1024;
if (packet_based) {
absl::MutexLock lock(&fd_mutex_);
if (max_chunk_ == 0) max_chunk_ = 1024;
}
size_t max_chunk = 0;
if (packet_based) {
absl::MutexLock lock(&fd_mutex_);
max_chunk = max_chunk_;
}
LOG(INFO) << "SO_TYPE=" << so_type
<< (so_type == SOCK_SEQPACKET ? " (SEQPACKET)" :
so_type == SOCK_STREAM ? " (STREAM)" :
so_type == SOCK_DGRAM ? " (DGRAM)" : " (other)")
<< (packet_based ? absl::StrFormat(" max_chunk=%zu", max_chunk_) : "");
while (total_wrote < data.size()) {
if (fd_raw_.load() != fd) return {Exception::kIo};
auto result = poller.Ready(); // should wait for POLLOUT/EPOLLOUT
if (result.Raised()) return result;
if (fd_raw_.load() != fd) return {Exception::kIo};
const char *buf = data.data();
size_t remaining = data.size() - total_wrote;
@@ -248,11 +260,12 @@ Exception BluetoothOutputStream::Write(const ByteArray &data) {
if (packet_based) {
// For SEQPACKET/DGRAM, one send() == one packet.
// Cap to discovered “MTU-like” limit to avoid EMSGSIZE.
absl::MutexLock lock(&fd_mutex_);
to_write = std::min(to_write, max_chunk_);
}
// Prefer send() to avoid SIGPIPE (MSG_NOSIGNAL is Linux).
ssize_t wrote = ::send(fd_.get(),
ssize_t wrote = ::send(fd,
buf + total_wrote,
to_write,
#ifdef MSG_NOSIGNAL
@@ -271,10 +284,14 @@ Exception BluetoothOutputStream::Write(const ByteArray &data) {
if (errno == EMSGSIZE && packet_based) {
// Our packet is too large; shrink max_chunk_ and retry.
if (max_chunk_ > 1) {
max_chunk_ = std::max<size_t>(1, max_chunk_ / 2);
LOG(INFO) << __func__ << ": EMSGSIZE; reducing max_chunk_ to " << max_chunk_;
continue; // retry with smaller chunk
{
absl::MutexLock lock(&fd_mutex_);
if (max_chunk_ > 1) {
max_chunk_ = std::max<size_t>(1, max_chunk_ / 2);
LOG(INFO) << __func__ << ": EMSGSIZE; reducing max_chunk_ to "
<< max_chunk_;
continue; // retry with smaller chunk
}
}
LOG(ERROR) << __func__ << ": EMSGSIZE even at 1 byte";
return {Exception::kIo};
@@ -304,8 +321,9 @@ Exception BluetoothOutputStream::Write(const ByteArray &data) {
}
Exception BluetoothOutputStream::Close() {
absl::MutexLock lock(&fd_mutex_);
if (!fd_.isValid()) return {Exception::kSuccess}; // Already closed
int fd = fd_raw_.exchange(-1);
if (fd < 0) return {Exception::kSuccess}; // Already closed
::shutdown(fd, SHUT_RDWR);
fd_.reset();
return {Exception::kSuccess};
}
@@ -15,6 +15,7 @@
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_SOCKET_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_SOCKET_H_
#include <atomic>
#include <memory>
#include <optional>
@@ -43,6 +44,10 @@ class Poller final {
return Poller(fd, POLLOUT);
}
static Poller CreateInputPoller(int fd) { return Poller(fd, POLLIN); }
static Poller CreateOutputPoller(int fd) { return Poller(fd, POLLOUT); }
Exception Ready();
private:
@@ -51,25 +56,32 @@ class Poller final {
fds_[0].events = event;
}
Poller(int fd, short event) : poll_event_(event) {
fds_[0].fd = fd;
fds_[0].events = event;
}
short poll_event_;
struct pollfd fds_[1];
};
class BluetoothInputStream final : public nearby::InputStream {
public:
explicit BluetoothInputStream(sdbus::UnixFd fd) : fd_(std::move(fd)){};
explicit BluetoothInputStream(sdbus::UnixFd fd)
: fd_(std::move(fd)), fd_raw_(fd_.get()) {}
ExceptionOr<ByteArray> Read(std::int64_t size) override;
Exception Close() override;
private:
mutable absl::Mutex fd_mutex_;
sdbus::UnixFd fd_ ABSL_GUARDED_BY(fd_mutex_);
sdbus::UnixFd fd_;
std::atomic<int> fd_raw_{-1};
};
class BluetoothOutputStream : public nearby::OutputStream {
public:
explicit BluetoothOutputStream(sdbus::UnixFd fd) : fd_(std::move(fd)){};
explicit BluetoothOutputStream(sdbus::UnixFd fd)
: fd_(std::move(fd)), fd_raw_(fd_.get()) {}
Exception Write(const ByteArray &data) override;
Exception Flush() override { return {Exception::kSuccess}; }
@@ -77,7 +89,8 @@ class BluetoothOutputStream : public nearby::OutputStream {
private:
mutable absl::Mutex fd_mutex_;
sdbus::UnixFd fd_ ABSL_GUARDED_BY(fd_mutex_);
sdbus::UnixFd fd_;
std::atomic<int> fd_raw_{-1};
// For packet sockets, discovered max payload per send/write.
// 0 means "unknown", well initialize on first packet write.
@@ -55,6 +55,8 @@
#include "internal/platform/implementation/wifi_lan.h"
#include "internal/platform/payload_id.h"
#include "scheduled_executor.h"
#include "wifi_direct.h"
#include "wifi_hotspot.h"
namespace nearby {
namespace api {
@@ -251,54 +253,54 @@ ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter &adapter) {
}
namespace {
// static std::unique_ptr<linux::NetworkManagerWifiMedium> createWifiMedium(
// std::shared_ptr<linux::networkmanager::NetworkManager> nm) {
// return nullptr;
// std::vector<sdbus::ObjectPath> device_paths;
//
// try {
// device_paths = nm->GetAllDevices();
// } catch (const sdbus::Error &e) {
// DBUS_LOG_METHOD_CALL_ERROR(nm, "GetAllDevices", e);
// return nullptr;
// }
//
// auto manager = linux::networkmanager::ObjectManager(nm->GetConnection());
//
// std::map<sdbus::ObjectPath,
// std::map<std::string, std::map<std::string, sdbus::Variant>>>
// objects;
// try {
// objects = manager.GetManagedObjects();
// } catch (const sdbus::Error &e) {
// DBUS_LOG_METHOD_CALL_ERROR(nm, "GetManagedObjects", e);
// return nullptr;
// }
//
// for (auto &device_path : device_paths) {
// if (objects.count(device_path) == 1) {
// auto device = objects[device_path];
// if (device.count(org::freedesktop::NetworkManager::Device::
// Wireless_proxy::INTERFACE_NAME) == 1) {
// LOG(INFO) << __func__
// << ": Found a wireless device at :" << device_path;
// return std::make_unique<linux::NetworkManagerWifiMedium>(nm,
// device_path);
// }
// }
// }
//
// LOG(ERROR) << __func__
// << ": couldn't find a wireless device on this system";
// return nullptr;
// }
static std::unique_ptr<linux::NetworkManagerWifiMedium> createWifiMedium(
std::shared_ptr<linux::networkmanager::NetworkManager> nm) {
// return nullptr;
std::vector<sdbus::ObjectPath> device_paths;
try {
device_paths = nm->GetAllDevices();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(nm, "GetAllDevices", e);
return nullptr;
}
auto manager = linux::networkmanager::ObjectManager(nm->GetConnection());
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = manager.GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(nm, "GetManagedObjects", e);
return nullptr;
}
for (auto &device_path : device_paths) {
if (objects.count(device_path) == 1) {
auto device = objects[device_path];
if (device.count(org::freedesktop::NetworkManager::Device::
Wireless_proxy::INTERFACE_NAME) == 1) {
LOG(INFO) << __func__
<< ": Found a wireless device at :" << device_path;
return std::make_unique<linux::NetworkManagerWifiMedium>(nm,
device_path);
}
}
}
LOG(ERROR) << __func__
<< ": couldn't find a wireless device on this system";
return nullptr;
}
} // namespace
std::unique_ptr<api::WifiMedium> ImplementationPlatform::CreateWifiMedium() {
return nullptr;
// auto nm =
// std::make_shared<linux::networkmanager::NetworkManager>(linux::getSystemBusConnection());
// return createWifiMedium(nm);
// return nullptr;
auto nm =
std::make_shared<linux::networkmanager::NetworkManager>(linux::getSystemBusConnection());
return createWifiMedium(nm);
}
std::unique_ptr<api::WifiLanMedium>
@@ -311,34 +313,33 @@ ImplementationPlatform::CreateWifiLanMedium() {
std::unique_ptr<api::WifiHotspotMedium>
ImplementationPlatform::CreateWifiHotspotMedium() {
return nullptr;
// auto nm =
// std::make_shared<linux::networkmanager::NetworkManager>(linux::getSystemBusConnection());
// auto wifiMedium = createWifiMedium(nm);
//
// if (wifiMedium == nullptr) {
// LOG(ERROR) << __func__ << ": Could not create a WiFi medium";
// return nullptr;
// }
//
// return std::make_unique<linux::NetworkManagerWifiHotspotMedium>(
// nm, std::move(wifiMedium));
auto nm =
std::make_shared<linux::networkmanager::NetworkManager>(linux::getSystemBusConnection());
auto wifiMedium = createWifiMedium(nm);
if (wifiMedium == nullptr) {
LOG(ERROR) << __func__ << ": Could not create a WiFi medium";
return nullptr;
}
return std::make_unique<linux::NetworkManagerWifiHotspotMedium>(
nm, std::move(wifiMedium));
}
std::unique_ptr<api::WifiDirectMedium>
ImplementationPlatform::CreateWifiDirectMedium() {
return nullptr;
// auto nm =
// std::make_shared<linux::networkmanager::NetworkManager>(linux::getSystemBusConnection());
// auto wifiMedium = createWifiMedium(nm);
//
// if (wifiMedium == nullptr) {
// LOG(ERROR) << __func__ << ": Could not create a WiFi medium";
// return nullptr;
// }
//
// return std::make_unique<linux::NetworkManagerWifiDirectMedium>(
// nm, std::move(wifiMedium));
// return nullptr;
auto nm =
std::make_shared<linux::networkmanager::NetworkManager>(linux::getSystemBusConnection());
auto wifiMedium = createWifiMedium(nm);
if (wifiMedium == nullptr) {
LOG(ERROR) << __func__ << ": Could not create a WiFi medium";
return nullptr;
}
return std::make_unique<linux::NetworkManagerWifiDirectMedium>(
nm, std::move(wifiMedium));
}
std::unique_ptr<api::Timer> ImplementationPlatform::CreateTimer() {
@@ -13,6 +13,7 @@
// limitations under the License.
#include <netinet/in.h>
#include <poll.h>
#include <sys/socket.h>
#include "internal/platform/implementation/linux/wifi_hotspot_server_socket.h"
@@ -52,22 +53,55 @@ NetworkManagerWifiHotspotServerSocket::Accept() {
struct sockaddr_in addr {};
socklen_t len = sizeof(addr);
auto conn =
accept(fd_.get(), reinterpret_cast<struct sockaddr *>(&addr), &len);
if (conn < 0) {
LOG(ERROR) << __func__
<< ": Error accepting incoming connections on socket "
<< fd_.get() << ": " << std::strerror(errno);
return nullptr;
// Poll with timeout to allow checking the closed flag periodically
while (!closed_.load()) {
struct pollfd pfd;
pfd.fd = fd_.get();
pfd.events = POLLIN;
// Poll with 1 second timeout
int poll_result = poll(&pfd, 1, 1000);
if (poll_result < 0) {
if (errno == EINTR) {
continue; // Interrupted, try again
}
LOG(ERROR) << __func__ << ": Error polling socket " << fd_.get() << ": "
<< std::strerror(errno);
return nullptr;
}
if (poll_result == 0) {
// Timeout - check closed flag and continue
continue;
}
// Data available, try to accept
auto conn =
accept(fd_.get(), reinterpret_cast<struct sockaddr *>(&addr), &len);
if (conn < 0) {
if (errno == EBADF || errno == EINVAL) {
// Socket was closed
return nullptr;
}
LOG(ERROR) << __func__
<< ": Error accepting incoming connections on socket "
<< fd_.get() << ": " << std::strerror(errno);
return nullptr;
}
return std::make_unique<WifiHotspotSocket>(conn);
}
return std::make_unique<WifiHotspotSocket>(conn);
// Socket was closed
return nullptr;
}
Exception NetworkManagerWifiHotspotServerSocket::Close() {
closed_.store(true);
int fd = fd_.release();
shutdown(fd, SHUT_RDWR);
auto ret = close(fd_.release());
auto ret = close(fd);
if (ret < 0) {
LOG(ERROR) << __func__
<< ": Error closing socket: " << std::strerror(errno);
@@ -15,6 +15,8 @@
#ifndef PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_
#include <atomic>
#include <sdbus-c++/IConnection.h>
#include "internal/platform/implementation/linux/network_manager.h"
@@ -31,7 +33,8 @@ class NetworkManagerWifiHotspotServerSocket
std::shared_ptr<networkmanager::NetworkManager> network_manager)
: fd_(socket),
active_conn_(std::move(active_conn)),
network_manager_(std::move(network_manager)) {}
network_manager_(std::move(network_manager)),
closed_(false) {}
std::string GetIPAddress() const override;
int GetPort() const override;
@@ -42,6 +45,7 @@ class NetworkManagerWifiHotspotServerSocket
sdbus::UnixFd fd_;
std::unique_ptr<networkmanager::ActiveConnection> active_conn_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
std::atomic<bool> closed_;
};
} // namespace linux
} // namespace nearby
@@ -28,6 +28,7 @@
#include <sdbus-c++/Types.h>
#include "absl/synchronization/mutex.h"
#include "absl/container/flat_hash_map.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/device_wireless_client.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_access_point.h"