Removed unnecessary files

This commit is contained in:
lasan
2024-10-26 17:12:56 +05:30
parent e91795e007
commit 195a404ad4
30 changed files with 5 additions and 3158 deletions
@@ -1,73 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_MEDIUM_H_
#define PLATFORM_IMPL_LINUX_API_BLE_MEDIUM_H_
#include "internal/platform/implementation/ble.h"
namespace nearby {
namespace linux {
// Container of operations that can be performed over the BLE medium.
class BleMedium : public api::BleMedium {
public:
BleMedium() {}
~BleMedium() = default;
bool StartAdvertising(
const std::string &service_id, const ByteArray &advertisement_bytes,
const std::string &fast_advertisement_service_uuid) override {
return false;
}
bool StopAdvertising(const std::string &service_id) override { return false; }
// Returns true once the BLE scan has been initiated.
bool StartScanning(const std::string &service_id,
const std::string &fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) override {
return false;
}
// Returns true once BLE scanning for service_id is well and truly stopped;
// after this returns, there must be no more invocations of the
// DiscoveredPeripheralCallback passed in to StartScanning() for service_id.
bool StopScanning(const std::string &service_id) override { return false; }
// Callback that is invoked when a new connection is accepted.
using AcceptedConnectionCallback = absl::AnyInvocable<void(
api::BleSocket &socket, const std::string &service_id)>;
// Returns true once BLE socket connection requests to service_id can be
// accepted.
bool StartAcceptingConnections(const std::string &service_id,
AcceptedConnectionCallback callback) override {
return false;
}
bool StopAcceptingConnections(const std::string &service_id) override {
return false;
}
// Connects to a BLE peripheral.
// On success, returns a new BleSocket.
// On error, returns nullptr.
std::unique_ptr<api::BleSocket> Connect(
api::BlePeripheral &peripheral, const std::string &service_id,
CancellationFlag *cancellation_flag) override {
return nullptr;
}
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,85 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_V2_MEDIUM_H_
#define PLATFORM_IMPL_LINUX_API_BLE_V2_MEDIUM_H_
#include "internal/platform/implementation/ble_v2.h"
namespace nearby {
namespace linux {
class BleV2Medium : public api::ble_v2::BleMedium {
bool StartAdvertising(
const api::ble_v2::BleAdvertisementData &advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters) override {
return false;
}
std::unique_ptr<AdvertisingSession> StartAdvertising(
const api::ble_v2::BleAdvertisementData &advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters,
AdvertisingCallback callback) override {
return nullptr;
}
bool StopAdvertising() override { return false; }
bool StartScanning(const Uuid &service_uuid,
api::ble_v2::TxPowerLevel tx_power_level,
ScanCallback callback) override {
return false;
}
bool StopScanning() override { return false; }
std::unique_ptr<ScanningSession> StartScanning(
const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
ScanningCallback callback) override {
return nullptr;
};
std::unique_ptr<api::ble_v2::GattServer> StartGattServer(
api::ble_v2::ServerGattConnectionCallback callback) override {
return nullptr;
}
std::unique_ptr<api::ble_v2::GattClient> ConnectToGattServer(
api::ble_v2::BlePeripheral &peripheral,
api::ble_v2::TxPowerLevel tx_power_level,
api::ble_v2::ClientGattConnectionCallback callback) override {
return nullptr;
}
std::unique_ptr<api::ble_v2::BleServerSocket> OpenServerSocket(
const std::string &service_id) override {
return nullptr;
}
std::unique_ptr<api::ble_v2::BleSocket> Connect(
const std::string &service_id, api::ble_v2::TxPowerLevel tx_power_level,
api::ble_v2::BlePeripheral &peripheral,
CancellationFlag *cancellation_flag) override {
return nullptr;
}
bool IsExtendedAdvertisementsAvailable() override { return false; }
bool GetRemotePeripheral(const std::string &mac_address,
GetRemotePeripheralCallback callback) override {
return false;
}
bool GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id,
GetRemotePeripheralCallback callback) override {
return false;
}
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,288 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IObject.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/Types.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
bool ProfileManager::ProfileRegistered(absl::string_view service_uuid) {
registered_service_uuids_mutex_.ReaderLock();
bool registered = registered_services_.count(std::string(service_uuid)) == 1;
registered_service_uuids_mutex_.ReaderUnlock();
return registered;
}
void Profile::Release() {
released_ = true;
NEARBY_LOGS(VERBOSE) << __func__ << ": Profile object " << getObjectPath()
<< " has been released";
}
void Profile::NewConnection(
const sdbus::ObjectPath &device_object_path, const sdbus::UnixFd &fd,
const std::map<std::string, sdbus::Variant> &fd_props) {
if (released_) {
NEARBY_LOGS(ERROR) << __func__
<< ": NewConnection called on released object "
<< getObjectPath();
throw sdbus::Error("org.bluez.Error.Rejected",
"NewConnection called on released object");
}
auto device = devices_.get_device_by_path(device_object_path);
if (device == nullptr) {
NEARBY_LOGS(ERROR)
<< __func__
<< ": NewConection called with a device object we don't know about: "
<< device_object_path;
throw sdbus::Error("org.bluez.Error.Rejected", "Unknown object");
}
auto alias = device->Alias();
auto mac_addr = device->Address();
NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath()
<< ": Connected to " << device->getObjectPath();
FDProperties props(fd_props);
absl::MutexLock l(&connections_lock_);
connections_[mac_addr].push_back(std::pair(fd, props));
}
void Profile::RequestDisconnection(
const sdbus::ObjectPath &device_object_path) {
auto device = devices_.get_device_by_path(device_object_path);
if (device == nullptr) {
NEARBY_LOGS(ERROR) << __func__ << ": " << getObjectPath()
<< ": RequestDisconnection called with a device object "
"we don't know about: "
<< device_object_path;
throw sdbus::Error("org.bluez.Error.Rejected", "Unknown object");
}
auto mac_addr = device->Address();
NEARBY_LOGS(VERBOSE) << __func__ << ": Disconnection requested for device "
<< device_object_path;
absl::MutexLock l(&connections_lock_);
if (connections_.count(mac_addr) == 0) {
NEARBY_LOGS(ERROR)
<< __func__
<< ": Disconnection requested, but we are not connected to this device";
return;
}
connections_.erase(mac_addr);
}
bool ProfileManager::Register(std::optional<absl::string_view> name,
absl::string_view service_uuid) {
absl::MutexLock l(&registered_service_uuids_mutex_);
if (registered_services_.count(std::string(service_uuid)) == 1) {
NEARBY_LOGS(WARNING) << __func__ << ": Trying to register profile "
<< service_uuid << " which was already registered.";
return true;
}
auto profile = std::make_shared<Profile>(
getProxy().getConnection(), bluez::profile_object_path(service_uuid),
devices_);
try {
std::map<std::string, sdbus::Variant> options;
if (name.has_value()) {
options["Name"] = std::string(*name);
options["RequireAuthorization"] = false;
options["RequireAuthentication"] = false;
options["Channel"] = static_cast<uint16_t>(0);
options["PSM"] = static_cast<uint16_t>(0);
}
RegisterProfile(profile->getObjectPath(), std::string(service_uuid),
options);
} catch (const sdbus::Error &e) {
BLUEZ_LOG_METHOD_CALL_ERROR(&getProxy(), "RegisterProfile", e);
return false;
}
registered_services_.emplace(service_uuid, profile);
NEARBY_LOGS(INFO) << __func__
<< ": Registered profile instancefor service uuid "
<< service_uuid;
return true;
}
void ProfileManager::Unregister(absl::string_view service_uuid) {
absl::MutexLock l(&registered_service_uuids_mutex_);
if (registered_services_.count(std::string(service_uuid)) == 0) {
NEARBY_LOGS(WARNING)
<< __func__
<< ": attempted to unregister a profile that is not registered";
return;
}
auto profile_object_path = bluez::profile_object_path(service_uuid);
NEARBY_LOGS(VERBOSE) << __func__ << ": Unregistering profile "
<< profile_object_path;
try {
UnregisterProfile(profile_object_path);
} catch (const sdbus::Error &e) {
BLUEZ_LOG_METHOD_CALL_ERROR(&getProxy(), "UnregisterProfile", e);
}
registered_services_.erase(std::string(service_uuid));
}
// Get a service record FD for a connected profile (identified by service_uuid)
// to the given device.
std::optional<sdbus::UnixFd> ProfileManager::GetServiceRecordFD(
api::BluetoothDevice &remote_device, absl::string_view service_uuid,
CancellationFlag *cancellation_flag) {
std::shared_ptr<Profile> profile;
{
absl::ReaderMutexLock lock(&registered_service_uuids_mutex_);
if (registered_services_.count(std::string(service_uuid)) == 0) {
NEARBY_LOGS(ERROR) << __func__ << ": Service " << service_uuid
<< " is not registered";
return std::nullopt;
}
profile = registered_services_[std::string(service_uuid)];
}
auto mac_addr = remote_device.GetMacAddress();
std::unique_ptr<CancellationFlagListener> cancel_listener;
if (cancellation_flag != nullptr)
cancel_listener = std::make_unique<CancellationFlagListener>(
cancellation_flag, [&profile]() {
profile->connections_lock_.Lock();
profile->connections_lock_.Unlock();
});
NEARBY_LOGS(VERBOSE) << __func__ << ": " << profile->getObjectPath()
<< ": Attempting to get a FD for service "
<< service_uuid << " on device " << mac_addr;
auto cond = [mac_addr, profile, cancellation_flag]() {
profile->connections_lock_.AssertReaderHeld();
return profile->connections_.count(mac_addr) != 0 ||
(cancellation_flag != nullptr && cancellation_flag->Cancelled());
};
absl::MutexLock connections_lock(&profile->connections_lock_,
absl::Condition(&cond));
if (cancellation_flag != nullptr && cancellation_flag->Cancelled()) {
NEARBY_LOGS(VERBOSE)
<< __func__ << ": " << profile->getObjectPath() << ": "
<< remote_device.GetMacAddress()
<< ": Cancelled waiting for a new connection on profile "
<< service_uuid;
return std::nullopt;
}
auto [fd, properties] = profile->connections_[mac_addr].back();
profile->connections_[mac_addr].pop_back();
if (profile->connections_[mac_addr].empty())
profile->connections_.erase(mac_addr);
return std::move(fd);
}
// Listen for a connected profile on any device, returning the connected device
// with its FD.
std::optional<std::pair<std::shared_ptr<BluetoothDevice>, sdbus::UnixFd>>
ProfileManager::GetServiceRecordFD(absl::string_view service_uuid,
CancellationFlag *cancellation_flag) {
std::shared_ptr<Profile> profile;
{
absl::ReaderMutexLock lock(&registered_service_uuids_mutex_);
if (registered_services_.count(std::string(service_uuid)) == 0) {
return std::nullopt;
}
profile = registered_services_[std::string(service_uuid)];
}
NEARBY_LOGS(VERBOSE) << __func__ << ": " << profile->getObjectPath()
<< ": Attempting to get a FD for service "
<< service_uuid;
std::unique_ptr<CancellationFlagListener> cancel_listener;
if (cancellation_flag != nullptr)
cancel_listener = std::make_unique<CancellationFlagListener>(
cancellation_flag, [&profile]() {
profile->connections_lock_.Lock();
profile->connections_lock_.Unlock();
});
profile->connections_lock_.Lock();
auto cond = [profile, &cancellation_flag]() {
profile->connections_lock_.AssertReaderHeld();
return !profile->connections_.empty() ||
(cancellation_flag != nullptr && cancellation_flag->Cancelled());
};
profile->connections_lock_.Await(absl::Condition(&cond));
if (cancellation_flag != nullptr && cancellation_flag->Cancelled()) {
NEARBY_LOGS(VERBOSE)
<< __func__ << ": Cancelled waiting for new connections on profile "
<< profile->getObjectPath();
profile->connections_lock_.Unlock();
return std::nullopt;
}
auto it = profile->connections_.begin();
auto mac_addr = it->first;
auto [fd, properties] = it->second.back();
it->second.pop_back();
if (it->second.empty()) profile->connections_.erase(it);
profile->connections_lock_.Unlock();
auto device = devices_.get_device_by_address(mac_addr);
if (device == nullptr) {
NEARBY_LOGS(ERROR) << __func__ << ": Device " << mac_addr
<< " is no longer available";
return std::nullopt;
}
return std::pair(device, std::move(fd));
}
} // namespace linux
} // namespace nearby
@@ -1,147 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_BLUEZ_PROFILE_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_BLUEZ_PROFILE_H_
#include <atomic>
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IObject.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/profile_manager_client.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/profile_server.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
class ProfileManager;
class Profile final
: public sdbus::AdaptorInterfaces<org::bluez::Profile1_adaptor,
sdbus::ManagedObject_adaptor> {
public:
Profile(const Profile &) = delete;
Profile(Profile &&) = delete;
Profile &operator=(const Profile &) = delete;
Profile &operator=(Profile &&) = delete;
Profile(sdbus::IConnection &system_bus, sdbus::ObjectPath profile_object_path,
BluetoothDevices &devices)
: AdaptorInterfaces(system_bus, std::move(profile_object_path)),
released_(false),
devices_(devices) {
registerAdaptor();
NEARBY_LOGS(VERBOSE) << __func__ << ": Created a new BlueZ profile at :"
<< getObjectPath();
}
~Profile() { unregisterAdaptor(); }
private:
friend class ProfileManager;
struct FDProperties {
explicit FDProperties(const std::map<std::string, sdbus::Variant> &fd_props)
: version(std::nullopt), features(std::nullopt) {
if (fd_props.count("Version") == 1) {
version = fd_props.at("Version");
}
if (fd_props.count("Features") == 1) {
features = fd_props.at("Features");
}
}
std::optional<uint16_t> version;
std::optional<uint16_t> features;
};
void Release() override;
void NewConnection(const sdbus::ObjectPath &, const sdbus::UnixFd &,
const std::map<std::string, sdbus::Variant> &) override
ABSL_LOCKS_EXCLUDED(connections_lock_);
void RequestDisconnection(const sdbus::ObjectPath &) override
ABSL_LOCKS_EXCLUDED(connections_lock_);
std::atomic_bool released_;
absl::Mutex connections_lock_;
std::map<std::string, std::vector<std::pair<sdbus::UnixFd, FDProperties>>>
connections_ ABSL_GUARDED_BY(connections_lock_);
BluetoothDevices &devices_;
};
class ProfileManager final
: private sdbus::ProxyInterfaces<org::bluez::ProfileManager1_proxy> {
public:
ProfileManager(const ProfileManager &) = delete;
ProfileManager(ProfileManager &&) = delete;
ProfileManager &operator=(const ProfileManager &) = delete;
ProfileManager &operator=(ProfileManager &&) = delete;
ProfileManager(sdbus::IConnection &system_bus, BluetoothDevices &devices)
: ProxyInterfaces(system_bus, bluez::SERVICE_DEST, "/org/bluez"),
devices_(devices) {
registerProxy();
}
~ProfileManager() { unregisterProxy(); }
bool ProfileRegistered(absl::string_view service_uuid)
ABSL_LOCKS_EXCLUDED(registered_service_uuids_mutex_);
bool Register(std::optional<absl::string_view> service_name,
absl::string_view service_uuid)
ABSL_LOCKS_EXCLUDED(registered_service_uuids_mutex_);
bool Register(absl::string_view service_uuid)
ABSL_LOCKS_EXCLUDED(registered_service_uuids_mutex_) {
return Register(std::nullopt, service_uuid);
}
void Unregister(absl::string_view service_uuid)
ABSL_LOCKS_EXCLUDED(registered_service_uuids_mutex_);
std::optional<sdbus::UnixFd> GetServiceRecordFD(
api::BluetoothDevice &remote_device, absl::string_view service_uuid,
CancellationFlag *cancellation_flag)
ABSL_LOCKS_EXCLUDED(registered_service_uuids_mutex_);
std::optional<std::pair<std::shared_ptr<BluetoothDevice>, sdbus::UnixFd>>
GetServiceRecordFD(absl::string_view service_uuid,
CancellationFlag *cancellation_flag)
ABSL_LOCKS_EXCLUDED(registered_service_uuids_mutex_);
private:
BluetoothDevices &devices_;
// Maps service UUIDs to RegisteredService
absl::Mutex registered_service_uuids_mutex_;
std::map<std::string, std::shared_ptr<Profile>> registered_services_
ABSL_GUARDED_BY(registered_service_uuids_mutex_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,178 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sdbus-c++/IObject.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <systemd/sd-bus.h>
#include "absl/strings/string_view.h"
#include "internal/platform/bluetooth_utils.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
BluetoothDevice::BluetoothDevice(sdbus::IConnection &system_bus,
sdbus::ObjectPath device_object_path)
: ProxyInterfaces(system_bus, bluez::SERVICE_DEST,
std::move(device_object_path)),
lost_(false) {
registerProxy();
try {
last_known_name_ = Alias();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "Alias", e);
}
try {
last_known_address_ = Address();
unique_id_ = BluetoothUtils::ToNumber(last_known_address_);
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "Address", e);
}
}
std::string BluetoothDevice::GetName() const {
auto bluez_device =
sdbus::createProxy(getProxy().getConnection(), bluez::SERVICE_DEST,
getProxy().getObjectPath());
try {
std::string alias =
bluez_device->getProperty("Alias").onInterface(bluez::DEVICE_INTERFACE);
{
absl::MutexLock l(&properties_mutex_);
last_known_name_ = alias;
}
return alias;
} catch (const sdbus::Error &e) {
if (e.getName() == "org.freedesktop.DBus.Error.UnknownObject") {
NEARBY_LOGS(VERBOSE)
<< __func__ << ": " << getObjectPath()
<< ": device is no longer known, returning last known name";
absl::ReaderMutexLock l(&properties_mutex_);
return last_known_name_;
}
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to get Alias for device "
<< bluez_device->getObjectPath();
return std::string();
}
}
std::string BluetoothDevice::GetMacAddress() const {
auto bluez_device =
sdbus::createProxy(getProxy().getConnection(), bluez::SERVICE_DEST,
getProxy().getObjectPath());
try {
std::string addr = bluez_device->getProperty("Address").onInterface(
bluez::DEVICE_INTERFACE);
{
absl::MutexLock l(&properties_mutex_);
last_known_address_ = addr;
}
return addr;
} catch (const sdbus::Error &e) {
if (e.getName() == "org.freedesktop.DBus.Error.UnknownObject") {
NEARBY_LOGS(VERBOSE)
<< __func__ << ": " << getObjectPath()
<< ": device is no longer known, returning last known address";
absl::ReaderMutexLock l(&properties_mutex_);
return last_known_address_;
}
NEARBY_LOGS(ERROR) << __func__ << "Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to get Address for device "
<< bluez_device->getObjectPath();
return std::string();
}
}
void BluetoothDevice::onConnectProfileReply(const sdbus::Error *error) {
if (error != nullptr && error->getName() != "org.bluez.Error.InProgress") {
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << error->getName()
<< "' with message '" << error->getMessage()
<< " while connecting to profile.";
}
}
bool BluetoothDevice::ConnectToProfile(absl::string_view service_uuid) {
NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath()
<< ": Attempting to connect to profile " << service_uuid;
try {
ConnectProfile(std::string(service_uuid));
return true;
} catch (const sdbus::Error &e) {
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to asynchronously connect to profile "
<< service_uuid << " on device " << getObjectPath();
return false;
}
}
MonitoredBluetoothDevice::MonitoredBluetoothDevice(
sdbus::IConnection &system_bus, const sdbus::ObjectPath &device_object_path,
ObserverList<api::BluetoothClassicMedium::Observer> &observers)
: BluetoothDevice(system_bus, device_object_path),
ProxyInterfaces<sdbus::Properties_proxy>(system_bus, bluez::SERVICE_DEST,
std::string(device_object_path)),
observers_(observers) {
registerProxy();
}
void MonitoredBluetoothDevice::onPropertiesChanged(
const std::string &interfaceName,
const std::map<std::string, sdbus::Variant> &changedProperties,
const std::vector<std::string> &invalidatedProperties) {
if (interfaceName != bluez::DEVICE_INTERFACE) {
return;
}
for (auto it = changedProperties.begin(); it != changedProperties.end();
it++) {
if (it->first == bluez::DEVICE_PROP_ADDRESS) {
NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath()
<< ": Notifying observers about address change";
std::string address = it->second;
for (auto &observer : observers_.GetObservers()) {
observer->DeviceAddressChanged(*this, address);
}
} else if (it->first == bluez::DEVICE_PROP_PAIRED) {
NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath()
<< "Notifying observers about paired status change.";
for (auto &observer : observers_.GetObservers()) {
observer->DevicePairedChanged(*this, it->second);
}
} else if (it->first == bluez::DEVICE_PROP_CONNECTED) {
NEARBY_LOGS(VERBOSE)
<< __func__ << ": " << getObjectPath()
<< "Notifying observers about connected status change";
for (auto &observer : observers_.GetObservers()) {
observer->DeviceConnectedStateChanged(*this, it->second);
}
} else if (it->first == bluez::DEVICE_NAME) {
auto callback = discovery_cb_.lock();
if (callback != nullptr && callback->device_name_changed_cb != nullptr)
callback->device_name_changed_cb(*this);
}
}
}
} // namespace linux
} // namespace nearby
@@ -1,135 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_CLASSIC_DEVICE_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_CLASSIC_DEVICE_H_
#include <atomic>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "internal/base/observer_list.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/device_client.h"
namespace nearby {
namespace linux {
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice
: public api::BluetoothDevice,
public sdbus::ProxyInterfaces<org::bluez::Device1_proxy>,
public api::ble_v2::BlePeripheral {
public:
using UniqueId = std::uint64_t;
BluetoothDevice(const BluetoothDevice &) = delete;
BluetoothDevice(BluetoothDevice &&) = delete;
BluetoothDevice &operator=(const BluetoothDevice &) = delete;
BluetoothDevice &operator=(BluetoothDevice &&) = delete;
BluetoothDevice(sdbus::IConnection &system_bus,
sdbus::ObjectPath device_object_path);
~BluetoothDevice() override { unregisterProxy(); }
// BluetoothDevice methods
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
std::string GetName() const override;
// Returns BT MAC address assigned to this device.
std::string GetMacAddress() const override;
// BlePeripheral methods
std::string GetAddress() const override { return GetMacAddress(); }
UniqueId GetUniqueId() const override { return unique_id_; };
bool ConnectToProfile(absl::string_view service_uuid);
void set_pair_reply_callback(
absl::AnyInvocable<void(const sdbus::Error *)> cb) {
absl::MutexLock l(&pair_callback_lock_);
on_pair_reply_cb_ = std::move(cb);
}
void reset_pair_reply_callback() {
absl::MutexLock l(&pair_callback_lock_);
on_pair_reply_cb_ = DefaultCallback<const sdbus::Error *>();
}
void MarkLost() { lost_ = true; }
void UnmarkLost() { lost_ = false; }
bool Lost() const { return lost_; }
protected:
void onConnectProfileReply(const sdbus::Error *error) override;
void onPairReply(const sdbus::Error *error) override {
absl::ReaderMutexLock l(&pair_callback_lock_);
on_pair_reply_cb_(error);
};
private:
absl::Mutex pair_callback_lock_;
absl::AnyInvocable<void(const sdbus::Error *)> on_pair_reply_cb_ =
DefaultCallback<const sdbus::Error *>();
UniqueId unique_id_;
std::atomic_bool lost_;
mutable absl::Mutex properties_mutex_;
mutable std::string last_known_name_ ABSL_GUARDED_BY(properties_mutex_);
mutable std::string last_known_address_ ABSL_GUARDED_BY(properties_mutex_);
};
class MonitoredBluetoothDevice final
: public BluetoothDevice,
public sdbus::ProxyInterfaces<sdbus::Properties_proxy> {
public:
using sdbus::ProxyInterfaces<sdbus::Properties_proxy>::registerProxy;
using sdbus::ProxyInterfaces<sdbus::Properties_proxy>::unregisterProxy;
using sdbus::ProxyInterfaces<sdbus::Properties_proxy>::getObjectPath;
MonitoredBluetoothDevice(const MonitoredBluetoothDevice &) = delete;
MonitoredBluetoothDevice(MonitoredBluetoothDevice &&) = delete;
MonitoredBluetoothDevice &operator=(const MonitoredBluetoothDevice &) =
delete;
MonitoredBluetoothDevice &operator=(MonitoredBluetoothDevice &&) = delete;
MonitoredBluetoothDevice(
sdbus::IConnection &system_bus, const sdbus::ObjectPath &,
ObserverList<api::BluetoothClassicMedium::Observer> &observers);
~MonitoredBluetoothDevice() override { unregisterProxy(); }
void SetDiscoveryCallback(
std::shared_ptr<api::BluetoothClassicMedium::DiscoveryCallback>
&callback) {
discovery_cb_ = callback;
};
protected:
void onPropertiesChanged(
const std::string &interfaceName,
const std::map<std::string, sdbus::Variant> &changedProperties,
const std::vector<std::string> &invalidatedProperties) override;
private:
ObserverList<api::BluetoothClassicMedium::Observer> &observers_;
std::weak_ptr<api::BluetoothClassicMedium::DiscoveryCallback> discovery_cb_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,233 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstring>
#include <memory>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/Types.h>
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_classic_medium.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"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/device_client.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
BluetoothClassicMedium::BluetoothClassicMedium(sdbus::IConnection &system_bus,
BluetoothAdapter &adapter)
: ProxyInterfaces(system_bus, "org.bluez", "/"),
adapter_(adapter),
devices_(std::make_shared<BluetoothDevices>(
system_bus, adapter.GetObjectPath(), observers_)),
profile_manager_(
std::make_unique<ProfileManager>(system_bus, *devices_)) {
registerProxy();
}
void BluetoothClassicMedium::onInterfacesAdded(
const sdbus::ObjectPath &object,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfaces) {
auto path_prefix = absl::Substitute(
"$0/dev_", adapter_.GetBluezAdapterObject().getObjectPath());
if (object.find(path_prefix) != 0) {
return;
}
if (devices_->get_device_by_path(object) != nullptr) {
// Device already exists.
return;
}
if (interfaces.count(org::bluez::Device1_proxy::INTERFACE_NAME) == 1) {
NEARBY_LOGS(INFO) << __func__ << ": Encountered new device at " << object;
auto device = devices_->add_new_device(object);
if (discovery_cb_ != nullptr &&
discovery_cb_->device_discovered_cb != nullptr) {
device->SetDiscoveryCallback(discovery_cb_);
discovery_cb_->device_discovered_cb(*device);
}
for (const auto &observer : observers_.GetObservers()) {
observer->DeviceAdded(*device);
}
}
}
void BluetoothClassicMedium::onInterfacesRemoved(
const sdbus::ObjectPath &object,
const std::vector<std::string> &interfaces) {
auto path_prefix = absl::Substitute("$0/dev_", adapter_.GetObjectPath());
if (object.find(path_prefix) != 0) {
return;
}
for (const auto &interface : interfaces) {
if (interface == org::bluez::Device1_proxy::INTERFACE_NAME) {
{
auto device = devices_->get_device_by_path(object);
if (device == nullptr) {
NEARBY_LOGS(WARNING) << __func__
<< ": received InterfacesRemoved for a device "
"we don't know about: "
<< object;
return;
}
NEARBY_LOGS(INFO) << __func__ << ": Device " << object
<< " has been removed";
if (discovery_cb_ != nullptr &&
discovery_cb_->device_lost_cb != nullptr) {
discovery_cb_->device_lost_cb(*device);
}
for (const auto &observer : observers_.GetObservers()) {
observer->DeviceRemoved(*device);
}
}
devices_->remove_device_by_path(object);
}
}
}
bool BluetoothClassicMedium::StartDiscovery(
DiscoveryCallback discovery_callback) {
discovery_cb_ =
std::make_shared<DiscoveryCallback>(std::move(discovery_callback));
std::map<std::string, sdbus::Variant> filter;
filter["Transport"] = "bredr";
auto &adapter = adapter_.GetBluezAdapterObject();
try {
adapter.SetDiscoveryFilter(filter);
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e);
return false;
}
try {
adapter.StartDiscovery();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
return false;
}
try {
NEARBY_LOGS(INFO) << __func__ << ": Starting BR/EDR discovery on "
<< adapter_.GetObjectPath();
adapter.StartDiscovery();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
discovery_cb_.reset();
return false;
}
return true;
}
bool BluetoothClassicMedium::StopDiscovery() {
auto &adapter = adapter_.GetBluezAdapterObject();
try {
NEARBY_LOGS(INFO) << __func__ << "Stopping discovery on "
<< adapter.getObjectPath();
adapter.StopDiscovery();
this->discovery_cb_.reset();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
return false;
}
return true;
}
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
api::BluetoothDevice &remote_device, const std::string &service_uuid,
CancellationFlag *cancellation_flag) {
auto device_object_path = bluez::device_object_path(
adapter_.GetObjectPath(), remote_device.GetMacAddress());
if (!profile_manager_->ProfileRegistered(service_uuid)) {
if (!profile_manager_->Register("", service_uuid)) {
NEARBY_LOGS(ERROR) << __func__ << ": Could not register profile "
<< service_uuid << " with Bluez";
return nullptr;
}
}
auto device = devices_->get_device_by_path(device_object_path);
if (device == nullptr) return nullptr;
device->ConnectToProfile(service_uuid);
auto fd = profile_manager_->GetServiceRecordFD(remote_device, service_uuid,
cancellation_flag);
if (!fd.has_value()) {
NEARBY_LOGS(WARNING) << __func__
<< ": Failed to get a new connection for profile "
<< service_uuid << " for device "
<< device_object_path;
return nullptr;
}
return std::unique_ptr<api::BluetoothSocket>(
new BluetoothSocket(device, fd.value()));
}
std::unique_ptr<api::BluetoothServerSocket>
BluetoothClassicMedium::ListenForService(const std::string &service_name,
const std::string &service_uuid) {
if (!profile_manager_->ProfileRegistered(service_uuid)) {
if (!profile_manager_->Register(service_name, service_uuid)) {
NEARBY_LOGS(ERROR) << __func__ << ": Could not register profile "
<< service_name << " " << service_uuid
<< " with Bluez";
return nullptr;
}
}
return std::unique_ptr<api::BluetoothServerSocket>(
new BluetoothServerSocket(*profile_manager_, service_uuid));
}
api::BluetoothDevice *BluetoothClassicMedium::GetRemoteDevice(
const std::string &mac_address) {
auto device = devices_->get_device_by_address(mac_address);
if (device == nullptr) return nullptr;
return device.get();
}
std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
api::BluetoothDevice &remote_device) {
auto device = devices_->get_device_by_address(remote_device.GetMacAddress());
if (device == nullptr) return nullptr;
return std::unique_ptr<api::BluetoothPairing>(
new BluetoothPairing(adapter_, device));
}
} // namespace linux
} // namespace nearby
@@ -1,133 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_CLASSIC_MEDIUM_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_CLASSIC_MEDIUM_H_
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "internal/base/observer_list.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
namespace nearby {
namespace linux {
// Container of operations that can be performed over the Bluetooth Classic
// medium.
class BluetoothClassicMedium
: public api::BluetoothClassicMedium,
protected sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
public:
BluetoothClassicMedium(const BluetoothClassicMedium &) = delete;
BluetoothClassicMedium(BluetoothClassicMedium &&) = delete;
BluetoothClassicMedium &operator=(const BluetoothClassicMedium &) = delete;
BluetoothClassicMedium &operator=(BluetoothClassicMedium &&) = delete;
BluetoothClassicMedium(sdbus::IConnection &system_bus,
BluetoothAdapter &adapter);
~BluetoothClassicMedium() override { unregisterProxy(); };
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
//
// Returns true once the process of discovery has been initiated.
bool StartDiscovery(DiscoveryCallback discovery_callback) override;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#cancelDiscovery()
//
// Returns true once discovery is well and truly stopped; after this returns,
// there must be no more invocations of the DiscoveryCallback passed in to
// StartDiscovery().
bool StopDiscovery() override;
// A combination of
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createInsecureRfcommSocketToServiceRecord
// followed by
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#connect().
//
// service_uuid is the canonical textual representation
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
// type 3 name-based
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
// UUID.
//
// On success, returns a new BluetoothSocket.
// On error, returns nullptr.
std::unique_ptr<api::BluetoothSocket> ConnectToService(
api::BluetoothDevice &remote_device, const std::string &service_uuid,
CancellationFlag *cancellation_flag) override;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
//
// service_uuid is the canonical textual representation
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
// type 3 name-based
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
// UUID.
//
// Returns nullptr error.
std::unique_ptr<api::BluetoothServerSocket> ListenForService(
const std::string &service_name,
const std::string &service_uuid) override;
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createBond()
//
// Start the bonding (pairing) process with the remote device.
// Return a Bluetooth pairing instance to handle the pairing process with the
// remote device.
std::unique_ptr<api::BluetoothPairing> CreatePairing(
api::BluetoothDevice &remote_device) override;
api::BluetoothDevice *GetRemoteDevice(
const std::string &mac_address) override;
void AddObserver(Observer *observer) override {
observers_.AddObserver(observer);
};
void RemoveObserver(Observer *observer) override {
observers_.RemoveObserver(observer);
};
protected:
void onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) override;
void onInterfacesRemoved(const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) override;
private:
BluetoothAdapter adapter_;
ObserverList<Observer> observers_;
protected:
std::shared_ptr<BluetoothDevices> devices_;
private:
std::shared_ptr<BluetoothClassicMedium::DiscoveryCallback> discovery_cb_;
std::unique_ptr<ProfileManager> profile_manager_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,55 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/implementation/linux/bluetooth_classic_server_socket.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_classic_socket.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
if (stopped_.Cancelled()) {
NEARBY_LOGS(ERROR) << __func__ << ": server socket has been stopped";
return nullptr;
}
NEARBY_LOGS(VERBOSE) << __func__
<< ": accepting new connections for service uuid "
<< service_uuid_;
auto pair = profile_manager_.GetServiceRecordFD(service_uuid_, &stopped_);
if (!pair.has_value()) {
if (!stopped_.Cancelled())
NEARBY_LOGS(ERROR) << __func__
<< ": Failed to get a new connection for profile "
<< service_uuid_;
return nullptr;
}
auto [device, fd] = *pair;
return std::make_unique<BluetoothSocket>(device, std::move(fd));
}
Exception BluetoothServerSocket::Close() {
NEARBY_LOGS(ERROR) << __func__ << ": closing bluetooth server socket";
stopped_.Cancel();
profile_manager_.Unregister(service_uuid_);
return {Exception::kSuccess};
}
} // namespace linux
} // namespace nearby
@@ -1,56 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_SERVER_SOCKET_H_
#include "absl/strings/string_view.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
namespace nearby {
namespace linux {
class BluetoothServerSocket final : public api::BluetoothServerSocket {
public:
BluetoothServerSocket(ProfileManager &profile_manager,
absl::string_view service_uuid)
: profile_manager_(profile_manager), service_uuid_(service_uuid) {}
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
//
// Blocks until either:
// - at least one incoming connection request is available, or
// - ServerSocket is closed.
// On success, returns connected socket, ready to exchange data.
// Returns nullptr on error.
// Once error is reported, it is permanent, and ServerSocket has to be
// closed.
std::unique_ptr<api::BluetoothSocket> Accept() override;
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
//
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override;
private:
CancellationFlag stopped_;
ProfileManager &profile_manager_;
std::string service_uuid_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,123 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sys/poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <array>
#include <cerrno>
#include <cstdint>
#include <cstring>
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/bluetooth_classic_socket.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
Exception Poller::Ready() {
while (true) {
auto ret = poll(fds_, 1, -1);
if (ret < 0) {
if (errno == EAGAIN) continue;
NEARBY_LOGS(ERROR) << __func__ << ": error polling socket for I/O: "
<< std::strerror(errno);
return {Exception::kIo};
}
if ((fds_[0].revents & poll_event_) != 0) {
return {Exception::kSuccess};
}
if ((fds_[0].revents & POLLHUP) != 0) {
NEARBY_LOGS(ERROR) << __func__ << ": socket disconnected";
return {Exception::kIo};
}
if ((fds_[0].revents & (POLLERR | POLLNVAL)) != 0) {
NEARBY_LOGS(ERROR) << __func__ << ": an error occured on the socket";
return {Exception::kIo};
}
}
}
ExceptionOr<ByteArray> BluetoothInputStream::Read(std::int64_t size) {
if (!fd_.isValid()) return Exception{Exception::kIo};
auto poller = Poller::CreateInputPoller(fd_);
std::string buffer;
buffer.resize(size);
char *data = buffer.data();
size_t total_read = 0;
while (total_read < size) {
auto result = poller.Ready();
if (result.Raised()) return result;
auto bytes_read = read(fd_.get(), &data[total_read], (size - total_read));
if (bytes_read < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) continue;
NEARBY_LOGS(ERROR) << __func__
<< ": error reading data on bluetooth socket: "
<< std::strerror(errno);
return {Exception::kIo};
}
total_read += bytes_read;
}
return ExceptionOr{ByteArray(std::move(buffer))};
}
Exception BluetoothInputStream::Close() {
if (!fd_.isValid()) return {Exception::kIo};
fd_.reset();
return {Exception::kSuccess};
}
Exception BluetoothOutputStream::Write(const ByteArray &data) {
if (!fd_.isValid()) return Exception{Exception::kIo};
auto poller = Poller::CreateOutputPoller(fd_);
size_t total_wrote = 0;
while (total_wrote < data.size()) {
auto result = poller.Ready();
if (result.Raised()) return result;
const char *buf = data.data();
auto wrote =
write(fd_.get(), &buf[total_wrote], (data.size() - total_wrote));
if (wrote < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) continue;
NEARBY_LOGS(ERROR) << __func__
<< ": error writing data on bluetooth socket: "
<< std::strerror(errno);
return {Exception::kIo};
}
total_wrote += wrote;
}
return {Exception::kSuccess};
}
Exception BluetoothOutputStream::Close() {
if (!fd_.isValid()) return {Exception::kIo};
fd_.reset();
return {Exception::kSuccess};
}
} // namespace linux
} // namespace nearby
@@ -1,103 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_SOCKET_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_SOCKET_H_
#include <memory>
#include <optional>
#include <sdbus-c++/Types.h>
#include <sys/poll.h>
#include <systemd/sd-bus.h>
#include "internal/platform/exception.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
namespace nearby {
namespace linux {
// BlueZ's NewConnection gives us a non-blocking FD, so we need to poll
// it to be able to write/read bytes.
class Poller final {
public:
static Poller CreateInputPoller(const sdbus::UnixFd &fd) {
return Poller(fd, POLLIN);
}
static Poller CreateOutputPoller(const sdbus::UnixFd &fd) {
return Poller(fd, POLLOUT);
}
Exception Ready();
private:
Poller(const sdbus::UnixFd &fd, short event) : poll_event_(event) {
fds_[0].fd = fd.get();
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)){};
ExceptionOr<ByteArray> Read(std::int64_t size) override;
Exception Close() override;
private:
sdbus::UnixFd fd_;
};
class BluetoothOutputStream : public nearby::OutputStream {
public:
explicit BluetoothOutputStream(sdbus::UnixFd fd) : fd_(std::move(fd)){};
Exception Write(const ByteArray &data) override;
Exception Flush() override { return {Exception::kSuccess}; }
Exception Close() override;
private:
sdbus::UnixFd fd_;
};
class BluetoothSocket final : public api::BluetoothSocket {
public:
BluetoothSocket(std::shared_ptr<BluetoothDevice> device,
const sdbus::UnixFd &fd)
: device_(std::move(device)), output_stream_(fd), input_stream_(fd) {}
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};
}
api::BluetoothDevice *GetRemoteDevice() override { return device_.get(); };
private:
std::shared_ptr<BluetoothDevice> device_;
BluetoothOutputStream output_stream_;
BluetoothInputStream input_stream_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,93 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <chrono>
#include <functional>
#include <optional>
#include <absl/time/clock.h>
#include <sdbus-c++/Types.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
static constexpr std::chrono::minutes kLostPeripheralsCleanupMinFreq(5);
std::shared_ptr<BluetoothDevice> BluetoothDevices::get_device_by_path(
const sdbus::ObjectPath &device_object_path) {
absl::ReaderMutexLock l(&devices_by_path_lock_);
if (devices_by_path_.count(device_object_path) == 0) {
return nullptr;
}
return devices_by_path_[device_object_path];
}
std::shared_ptr<BluetoothDevice> BluetoothDevices::get_device_by_address(
const std::string &addr) {
auto device_object_path =
bluez::device_object_path(adapter_object_path_, addr);
return get_device_by_path(device_object_path);
}
void BluetoothDevices::remove_device_by_path(
const sdbus::ObjectPath &device_object_path) {
absl::MutexLock l(&devices_by_path_lock_);
devices_by_path_.erase(device_object_path);
}
void BluetoothDevices::mark_peripheral_lost(
const sdbus::ObjectPath &device_object_path) {
absl::ReaderMutexLock lock(&devices_by_path_lock_);
if (devices_by_path_.count(device_object_path) == 0) {
NEARBY_LOGS(ERROR) << __func__ << ": Device " << device_object_path
<< " doesn't exist";
}
devices_by_path_[device_object_path]->MarkLost();
}
void BluetoothDevices::cleanup_lost_peripherals() {
auto now = std::chrono::steady_clock::now();
absl::MutexLock lock(&devices_by_path_lock_);
if ((now - last_cleanup_) < kLostPeripheralsCleanupMinFreq) {
return;
}
last_cleanup_ = now;
for (auto it = devices_by_path_.begin(), end = devices_by_path_.end();
it != end;) {
auto copy = it++;
if (copy->second->Lost()) devices_by_path_.erase(copy);
}
}
std::shared_ptr<MonitoredBluetoothDevice> BluetoothDevices::add_new_device(
sdbus::ObjectPath device_object_path) {
absl::MutexLock l(&devices_by_path_lock_);
auto [device_it, inserted] = devices_by_path_.emplace(
std::string(device_object_path),
std::make_shared<MonitoredBluetoothDevice>(
system_bus_, std::move(device_object_path), observers_));
if (!inserted) device_it->second->UnmarkLost();
return device_it->second;
}
} // namespace linux
} // namespace nearby
@@ -1,75 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_DEVICES_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_DEVICES_H_
#include <chrono>
#include <memory>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/Types.h>
#include "absl/container/flat_hash_map.h"
#include "absl/synchronization/mutex.h"
#include "internal/base/observer_list.h"
#include "internal/platform/bluetooth_utils.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
namespace nearby {
namespace linux {
class BluetoothDevices final {
public:
BluetoothDevices(
sdbus::IConnection &system_bus, sdbus::ObjectPath adapter_object_path,
ObserverList<api::BluetoothClassicMedium::Observer> &observers)
: system_bus_(system_bus),
observers_(observers),
adapter_object_path_(std::move(adapter_object_path)) {}
std::shared_ptr<BluetoothDevice> get_device_by_path(const sdbus::ObjectPath &)
ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
std::shared_ptr<BluetoothDevice> get_device_by_address(const std::string &);
std::shared_ptr<BluetoothDevice> get_device_by_unique_id(
api::ble_v2::BlePeripheral::UniqueId id) {
auto addr = BluetoothUtils::FromNumber(id);
return get_device_by_address(addr);
}
std::shared_ptr<MonitoredBluetoothDevice> add_new_device(sdbus::ObjectPath)
ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
void remove_device_by_path(const sdbus::ObjectPath &)
ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
void mark_peripheral_lost(const sdbus::ObjectPath &)
ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
void cleanup_lost_peripherals() ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
private:
sdbus::IConnection &system_bus_;
ObserverList<api::BluetoothClassicMedium::Observer> &observers_;
sdbus::ObjectPath adapter_object_path_;
absl::Mutex devices_by_path_lock_;
absl::flat_hash_map<std::string, std::shared_ptr<MonitoredBluetoothDevice>>
devices_by_path_ ABSL_GUARDED_BY(devices_by_path_lock_);
std::chrono::time_point<std::chrono::steady_clock> last_cleanup_
ABSL_GUARDED_BY(devices_by_path_lock_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,141 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <utility>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IProxy.h>
#include <systemd/sd-bus.h>
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluetooth_pairing.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
void BluetoothPairing::pairing_reply_handler(const sdbus::Error *error) {
if (error != nullptr && error->isValid()) {
const auto &name = error->getName();
api::BluetoothPairingCallback::PairingError err =
api::BluetoothPairingCallback::PairingError::kAuthFailed;
NEARBY_LOGS(ERROR) << __func__ << ": "
<< "Got error '" << error->getName()
<< "' with message '" << error->getMessage()
<< "' while pairing with device "
<< device_->getObjectPath();
if (name == "org.bluez.Error.AuthenticationCanceled") {
err = api::BluetoothPairingCallback::PairingError::kAuthCanceled;
} else if (name == "org.bluez.Error.AuthenticationFailed") {
err = api::BluetoothPairingCallback::PairingError::kAuthFailed;
} else if (name == "org.bluez.Error.AuthenticationRejected") {
err = api::BluetoothPairingCallback::PairingError::kAuthRejected;
} else if (name == "org.bluez.Error.AuthenticationTimeout") {
err = api::BluetoothPairingCallback::PairingError::kAuthTimeout;
}
if (pairing_cb_.on_pairing_error_cb != nullptr) {
pairing_cb_.on_pairing_error_cb(err);
}
return;
}
if (pairing_cb_.on_paired_cb != nullptr) {
pairing_cb_.on_paired_cb();
}
}
BluetoothPairing::BluetoothPairing(
BluetoothAdapter &adapter, std::shared_ptr<BluetoothDevice> remote_device)
: device_(std::move(remote_device)), adapter_(adapter) {}
bool BluetoothPairing::InitiatePairing(
api::BluetoothPairingCallback pairing_cb) {
pairing_cb_ = std::move(pairing_cb);
if (pairing_cb_.on_pairing_initiated_cb != nullptr)
pairing_cb_.on_pairing_initiated_cb(api::PairingParams{
api::PairingParams::PairingType::kConsent, std::string()});
return true;
}
bool BluetoothPairing::FinishPairing(
std::optional<absl::string_view> pin_code) {
device_->set_pair_reply_callback([this](const sdbus::Error *error) {
this->pairing_reply_handler(error);
});
try {
pair_async_call_ = device_->Pair();
} catch (const sdbus::Error &e) {
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to initiate pairing for device "
<< device_->getObjectPath();
return false;
}
return true;
}
bool BluetoothPairing::CancelPairing() {
try {
if (pair_async_call_.isPending()) {
pair_async_call_.cancel();
}
device_->CancelPairing();
} catch (const sdbus::Error &e) {
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to cancel pairing for device "
<< device_->getObjectPath();
return false;
}
return true;
}
bool BluetoothPairing::Unpair() {
try {
adapter_.RemoveDeviceByObjectPath(device_->getObjectPath());
return true;
} catch (const sdbus::Error &e) {
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to unpair device "
<< device_->getObjectPath() << " on adapter "
<< adapter_.GetObjectPath();
return false;
}
}
bool BluetoothPairing::IsPaired() {
try {
bool bonded = device_->Bonded();
return bonded;
} catch (const sdbus::Error &e) {
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while trying to get Bonded state for device "
<< device_->getObjectPath();
return false;
}
}
} // namespace linux
} // namespace nearby
@@ -1,55 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_PAIRING_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_PAIRING_H_
#include <memory>
#include <string>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IProxy.h>
#include <systemd/sd-bus.h>
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
namespace nearby {
namespace linux {
class BluetoothPairing final : public api::BluetoothPairing {
public:
BluetoothPairing(BluetoothAdapter &adapter, std::shared_ptr<BluetoothDevice> remote_device);
bool InitiatePairing(api::BluetoothPairingCallback pairing_cb) override;
bool FinishPairing(std::optional<absl::string_view> pin_code) override;
bool CancelPairing() override;
bool Unpair() override;
bool IsPaired() override;
private:
void pairing_reply_handler(const sdbus::Error *e);
sdbus::PendingAsyncCall pair_async_call_;
std::shared_ptr<BluetoothDevice> device_;
linux::BluetoothAdapter &adapter_;
api::BluetoothPairingCallback pairing_cb_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,79 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sdbus-c++/Types.h>
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "internal/platform/implementation/linux/bluez.h"
namespace nearby {
namespace linux {
namespace bluez {
std::string device_object_path(const sdbus::ObjectPath &adapter_object_path,
absl::string_view mac_address) {
return absl::Substitute(
"$0/dev_$1", adapter_object_path,
absl::StrReplaceAll(absl::AsciiStrToUpper(mac_address), {{":", "_"}}));
}
sdbus::ObjectPath profile_object_path(absl::string_view service_uuid) {
return absl::Substitute(
"/com/google/nearby/medium/bluetooth_classic/profiles/$0",
absl::StrReplaceAll(service_uuid, {{"-", "_"}}));
}
sdbus::ObjectPath adapter_object_path(absl::string_view name) {
return absl::Substitute("/org/bluez/$0", name);
}
sdbus::ObjectPath gatt_service_path(size_t num) {
return absl::Substitute("$0/service$1", NEARBY_BLE_GATT_PATH_ROOT, num);
}
sdbus::ObjectPath gatt_characteristic_path(
const sdbus::ObjectPath &service_path, size_t num) {
return absl::Substitute("$0/char$1", service_path, num);
}
sdbus::ObjectPath ble_advertisement_path(size_t num) {
return absl::Substitute("/com/google/nearby/medium/ble/advertisement/$0",
num);
}
sdbus::ObjectPath advertisement_monitor_path(absl::string_view uuid) {
return absl::Substitute(
"/com/google/nearby/medium/ble/advertisement/monitor/$0",
absl::StrReplaceAll(uuid, {{"-", "_"}}));
}
int16_t TxPowerLevelDbm(api::ble_v2::TxPowerLevel level) {
switch (level) {
case api::ble_v2::TxPowerLevel::kUnknown:
return 0;
case api::ble_v2::TxPowerLevel::kUltraLow:
return -3;
case api::ble_v2::TxPowerLevel::kLow:
return 0;
case api::ble_v2::TxPowerLevel::kMedium:
return 3;
case api::ble_v2::TxPowerLevel::kHigh:
return 6;
}
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -1,86 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_H_
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/ble_v2.h"
#include <string>
#define BLUEZ_LOG_METHOD_CALL_ERROR(proxy, method, err) \
do { \
NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << (err).getName() \
<< "' with message '" << (err).getMessage() \
<< "' while calling " << method << " on object " \
<< (proxy)->getObjectPath(); \
} while (false)
namespace nearby {
namespace linux {
namespace bluez {
static constexpr const char *SERVICE_DEST = "org.bluez";
static constexpr const char *ADAPTER_INTERFACE = "org.bluez.Adapter1";
static constexpr const char *DEVICE_INTERFACE = "org.bluez.Device1";
static constexpr const char *DEVICE_PROP_ADDRESS = "Address";
static constexpr const char *DEVICE_PROP_ALIAS = "Alias";
static constexpr const char *DEVICE_PROP_PAIRED = "Paired";
static constexpr const char *DEVICE_PROP_CONNECTED = "Connected";
static constexpr const char *DEVICE_NAME = "Name";
static constexpr const char *NEARBY_BLE_GATT_PATH_ROOT =
"/com/google/nearby/medium/ble/gatt";
std::string device_object_path(const sdbus::ObjectPath &adapter_object_path,
absl::string_view mac_address);
sdbus::ObjectPath profile_object_path(absl::string_view service_uuid);
sdbus::ObjectPath adapter_object_path(absl::string_view name);
sdbus::ObjectPath gatt_service_path(size_t num);
sdbus::ObjectPath gatt_characteristic_path(
const sdbus::ObjectPath &service_path, size_t num);
sdbus::ObjectPath ble_advertisement_path(size_t num);
sdbus::ObjectPath advertisement_monitor_path(absl::string_view uuid);
int16_t TxPowerLevelDbm(api::ble_v2::TxPowerLevel level);
class BluezObjectManager
: public sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
public:
BluezObjectManager(sdbus::IConnection &system_bus)
: ProxyInterfaces(system_bus, "org.bluez", "/") {
registerProxy();
}
~BluezObjectManager() { unregisterProxy(); }
protected:
void onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) override {}
void onInterfacesRemoved(
const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) override {}
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -1,185 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <memory>
#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::ConnectedToWifi() {
try {
auto mode = wireless_device_->Mode();
return mode == 2; // NM_802_11_MODE_INFRA
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "Mode", e);
return false;
}
}
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;
return false;
}
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();
return false;
}
} // namespace linux
} // namespace nearby
@@ -1,66 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_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_(std::move(network_manager)),
wireless_device_(std::move(wireless_device)) {}
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;
}
private:
bool ConnectedToWifi();
sdbus::IConnection &system_bus_;
std::shared_ptr<NetworkManager> network_manager_;
std::unique_ptr<NetworkManagerWifiMedium> wireless_device_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,81 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <netinet/in.h>
#include <sys/socket.h>
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/wifi_direct_server_socket.h"
#include "internal/platform/implementation/linux/wifi_direct_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
@@ -1,49 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_SERVER_SOCKET_H_
#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 NetworkManagerWifiDirectServerSocket
: public api::WifiDirectServerSocket {
public:
NetworkManagerWifiDirectServerSocket(
int socket, sdbus::IConnection &system_bus,
sdbus::ObjectPath active_connection_path,
std::shared_ptr<NetworkManager> network_manager)
: fd_(socket),
system_bus_(system_bus),
active_connection_path_(std::move(active_connection_path)),
network_manager_(std::move(network_manager)) {}
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_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,47 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_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:
explicit WifiDirectSocket(int socket)
: fd_(sdbus::UnixFd(socket)), output_stream_(fd_), input_stream_(fd_) {}
InputStream &GetInputStream() override { return input_stream_; };
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
@@ -1,336 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cstring>
#include <memory>
#include <random>
#include <systemd/sd-id128.h>
#include "internal/platform/implementation/linux/dbus.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 {
std::unique_ptr<api::WifiHotspotSocket>
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;
}
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<WifiHotspotSocket>(sock);
}
std::unique_ptr<api::WifiHotspotServerSocket>
NetworkManagerWifiHotspotMedium::ListenForService(int port) {
if (!WifiHotspotActive()) {
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<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<NetworkManagerWifiHotspotServerSocket>(
sock, system_bus_, active_connection->getObjectPath(), network_manager_);
}
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;
}
char id_cstr[SD_ID128_UUID_STRING_MAX];
sd_id128_to_string(id, id_cstr);
std::string ssid = absl::StrCat("DIRECT-", id_cstr);
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;
}
sd_id128_to_string(id, id_cstr);
std::string password = std::string(id_cstr, 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;
}
sd_id128_to_uuid_string(id, id_cstr);
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", std::string(id_cstr)},
{"id", "Google Nearby Hotspot"},
{"type", "802-11-wireless"},
{"zone", "Public"}},
},
{"802-11-wireless",
std::map<std::string, sdbus::Variant>{
{"assigned-mac-address", "random"},
{"ap-isolation",
static_cast<std::int32_t>(0)}, // NM_TERNARY_FALSE
{"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::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 (!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 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;
}
}
bool NetworkManagerWifiHotspotMedium::ConnectedToWifi() {
try {
auto mode = wireless_device_->Mode();
return mode == 2; // NM_802_11_MODE_INFRA
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "Mode", e);
return false;
}
}
} // namespace linux
} // namespace nearby
@@ -1,74 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_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 : public api::WifiHotspotMedium {
public:
NetworkManagerWifiHotspotMedium(
sdbus::IConnection &system_bus,
std::shared_ptr<NetworkManager> network_manager,
sdbus::ObjectPath wireless_device_object_path)
: system_bus_(system_bus),
wireless_device_(std::make_unique<NetworkManagerWifiMedium>(
network_manager, system_bus,
std::move(wireless_device_object_path))),
network_manager_(std::move(network_manager)) {}
NetworkManagerWifiHotspotMedium(
sdbus::IConnection &system_bus,
std::shared_ptr<NetworkManager> network_manager,
std::unique_ptr<NetworkManagerWifiMedium> wireless_device)
: system_bus_(system_bus),
wireless_device_(std::move(wireless_device)),
network_manager_(std::move(network_manager)) {}
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();
bool ConnectedToWifi();
sdbus::IConnection &system_bus_;
std::unique_ptr<NetworkManagerWifiMedium> wireless_device_;
std::shared_ptr<NetworkManager> network_manager_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,80 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <netinet/in.h>
#include <sys/socket.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"
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 {};
}
return ip4addresses[0];
}
int NetworkManagerWifiHotspotServerSocket::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::WifiHotspotSocket>
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) {
NEARBY_LOGS(ERROR) << __func__
<< ": Error accepting incoming connections on socket "
<< fd_.get() << ": " << std::strerror(errno);
return nullptr;
}
return std::make_unique<WifiHotspotSocket>(conn);
}
Exception NetworkManagerWifiHotspotServerSocket::Close() {
auto ret = close(fd_.release());
if (ret < 0) {
NEARBY_LOGS(ERROR) << __func__ << ": Error closing socket: "
<< std::strerror(errno);
return {Exception::kFailed};
}
return {Exception::kSuccess};
}
} // namespace linux
} // namespace nearby
@@ -1,51 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_
#include <sdbus-c++/IConnection.h>
#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,
sdbus::ObjectPath active_connection_path,
std::shared_ptr<NetworkManager> network_manager)
: fd_(socket),
system_bus_(system_bus),
active_connection_path_(std::move(active_connection_path)),
network_manager_(std::move(network_manager)) {}
std::string GetIPAddress() const override;
int GetPort() const override;
std::unique_ptr<api::WifiHotspotSocket> Accept() override;
Exception Close() override;
private:
sdbus::UnixFd fd_;
sdbus::IConnection &system_bus_;
sdbus::ObjectPath active_connection_path_;
std::shared_ptr<NetworkManager> network_manager_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,47 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_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:
explicit WifiHotspotSocket(int connection_fd)
: fd_(sdbus::UnixFd(connection_fd)),
output_stream_(fd_),
input_stream_(fd_) {}
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
@@ -157,7 +157,7 @@ bool WifiLanMedium::StartDiscovery(
avahi_->ServiceBrowserPrepare(-1, // AVAHI_IF_UNSPEC
-1, // AVAHI_PROTO_UNSPED
service_type, std::string(), 0);
NEARBY_LOGS(VERBOSE)
NEARBY_VLOG(1)
<< __func__
<< ": Created a new org.freedesktop.Avahi.ServiceBrowser object at "
<< browser_object_path;
@@ -177,7 +177,7 @@ bool WifiLanMedium::StartDiscovery(
service_browsers_mutex_.ReaderUnlock();
try {
NEARBY_LOGS(VERBOSE) << __func__ << ": Starting service discovery for "
NEARBY_VLOG(1) << __func__ << ": Starting service discovery for "
<< browser->getObjectPath();
browser->Start();
} catch (const sdbus::Error &e) {
@@ -211,7 +211,7 @@ std::unique_ptr<api::WifiLanSocket> WifiLanMedium::ConnectToService(
return nullptr;
}
NEARBY_LOGS(VERBOSE) << __func__ << ": Connecting to " << ip_address << ":"
NEARBY_VLOG(1) << __func__ << ": Connecting to " << ip_address << ":"
<< port;
struct sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr(ip_address.c_str());
@@ -259,7 +259,7 @@ std::unique_ptr<api::WifiLanServerSocket> WifiLanMedium::ListenForService(
return nullptr;
}
NEARBY_LOGS(VERBOSE) << __func__ << "Listening for services on port " << port;
NEARBY_VLOG(1) << __func__ << "Listening for services on port " << port;
return std::make_unique<WifiLanServerSocket>(sock, network_manager_,
system_bus_);
@@ -21,6 +21,7 @@
#include <memory>
#include <optional>
#include <ostream>
#include "absl/container/flat_hash_map.h"
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>