From f884cf34739ec80613e3e5c9352edc6ee0be8176 Mon Sep 17 00:00:00 2001 From: Lasan Mahaliyana Date: Sun, 22 Mar 2026 00:50:27 +0530 Subject: [PATCH] implemented gatt but removed it from ble_v2_medium. implemented bluez_agent and bluez agent manager for accepting incoming pairing requests --- internal/platform/implementation/linux/BUILD | 4 +- .../implementation/linux/ble_gatt_client.cc | 49 +++--- .../implementation/linux/ble_gatt_client.h | 4 +- .../implementation/linux/ble_gatt_server.cc | 160 +++++++++++++++--- .../implementation/linux/ble_gatt_server.h | 28 ++- .../implementation/linux/ble_v2_medium.cc | 20 +-- .../linux/bluetooth_classic_medium.cc | 84 +++++---- .../linux/bluetooth_classic_medium.h | 4 +- .../implementation/linux/bluez_agent.cc | 99 +++++++++++ .../implementation/linux/bluez_agent.h | 85 ++++++++++ .../linux/bluez_gatt_characteristic_server.cc | 5 +- .../implementation/linux/bluez_gatt_manager.h | 39 +++++ .../linux/generated/dbus/bluez/agent_server.h | 65 +++++++ .../dbus/bluez/agentmanager_client.h | 60 +++++++ .../dbus/bluez/gatt_manager_client.h | 15 +- .../generated/dbus/bluez/org.bluez.Agent1.xml | 45 +++++ .../dbus/bluez/org.bluez.AgentManager1.xml | 21 +++ .../dbus/bluez/org.bluez.GattManager1.xml | 2 + 18 files changed, 671 insertions(+), 118 deletions(-) create mode 100644 internal/platform/implementation/linux/bluez_agent.cc create mode 100644 internal/platform/implementation/linux/bluez_agent.h create mode 100644 internal/platform/implementation/linux/generated/dbus/bluez/agent_server.h create mode 100644 internal/platform/implementation/linux/generated/dbus/bluez/agentmanager_client.h create mode 100644 internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.Agent1.xml create mode 100644 internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.AgentManager1.xml diff --git a/internal/platform/implementation/linux/BUILD b/internal/platform/implementation/linux/BUILD index d7c4db88..895c8ece 100644 --- a/internal/platform/implementation/linux/BUILD +++ b/internal/platform/implementation/linux/BUILD @@ -92,8 +92,8 @@ cc_library( "bluetooth_devices.h", "bluetooth_pairing.h", "bluez.h", + "bluez_agent.h", "bluez_device.h", - # "bluez_agent.h", "bluez_advertisement_monitor.h", "bluez_advertisement_monitor_manager.h", "bluez_gatt_characteristic_client.h", @@ -184,7 +184,7 @@ cc_library( "bluetooth_devices.cc", "bluetooth_pairing.cc", "bluez.cc", - #"bluez_agent.cc", + "bluez_agent.cc", "bluez_advertisement_monitor.cc", "bluez_gatt_characteristic_client.cc", "bluez_gatt_characteristic_server.cc", diff --git a/internal/platform/implementation/linux/ble_gatt_client.cc b/internal/platform/implementation/linux/ble_gatt_client.cc index 74047ab2..e88a1be8 100644 --- a/internal/platform/implementation/linux/ble_gatt_client.cc +++ b/internal/platform/implementation/linux/ble_gatt_client.cc @@ -208,7 +208,6 @@ bool BluezGattDiscovery::InitializeKnownServices() { return false; } - absl::flat_hash_map cached_services; absl::MutexLock lock(&mutex_); auto chr_it = std::find_if( objects.cbegin(), objects.cend(), @@ -219,29 +218,27 @@ bool BluezGattDiscovery::InitializeKnownServices() { sdbus::InterfaceName(org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME)) == 1; }); -for (; chr_it != objects.cend(); ++chr_it) { - const auto& [path, ifaces] = *chr_it; + for (; chr_it != objects.cend(); ++chr_it) { + const auto& [path, ifaces] = *chr_it; - auto iface_it = ifaces.find(sdbus::InterfaceName(org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME)); - if (iface_it == ifaces.end()) { - // Not a GattCharacteristic1 object (or interfaces map incomplete) -> skip - continue; + auto iface_it = ifaces.find(sdbus::InterfaceName( + org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME)); + if (iface_it == ifaces.end()) { + continue; + } + + const auto& properties = iface_it->second; + auto maybe_props = characteristicProperties(path, properties); + if (!maybe_props.has_value()) continue; + + auto [service_uuid, chr_uuid, device_path] = *maybe_props; + + discovered_characteristics_.emplace( + std::make_tuple(service_uuid, chr_uuid, device_path), path); + characteristics_properties_.emplace( + path, std::make_tuple(service_uuid, chr_uuid, device_path)); } - const auto& properties = iface_it->second; - - auto maybe_props = characteristicProperties(path, properties); - if (!maybe_props.has_value()) continue; - - auto [chr_uuid, service_uuid, device_path] = *maybe_props; - - discovered_characteristics_.emplace( - std::make_tuple(chr_uuid, service_uuid, device_path), path); - - characteristics_properties_.emplace( - path, std::make_tuple(chr_uuid, service_uuid, device_path)); -} - return true; } @@ -337,7 +334,7 @@ BluezGattDiscovery::GetSubscribedCharacteristic( } return std::make_unique( - system_bus_, device_object_path, std::move(on_characteristic_changed_cb)); + system_bus_, path_it->second, std::move(on_characteristic_changed_cb)); } std::optional> @@ -396,7 +393,7 @@ try { return std::nullopt; } - return std::make_tuple(*chr_uuid, service_uuid, device_path); + return std::make_tuple(service_uuid, *chr_uuid, device_path); } void BluezGattDiscovery::onInterfacesAdded( @@ -414,12 +411,12 @@ void BluezGattDiscovery::onInterfacesAdded( absl::MutexLock lock(&mutex_); auto maybe_props = characteristicProperties(objectPath, properties); if (!maybe_props.has_value()) return; - auto [chr_uuid, service_uuid, device_path] = *maybe_props; + auto [service_uuid, chr_uuid, device_path] = *maybe_props; discovered_characteristics_.emplace( - std::make_tuple(chr_uuid, service_uuid, device_path), objectPath); + std::make_tuple(service_uuid, chr_uuid, device_path), objectPath); characteristics_properties_.emplace( - objectPath, std::make_tuple(chr_uuid, service_uuid, device_path)); + objectPath, std::make_tuple(service_uuid, chr_uuid, device_path)); } void BluezGattDiscovery::onInterfacesRemoved( diff --git a/internal/platform/implementation/linux/ble_gatt_client.h b/internal/platform/implementation/linux/ble_gatt_client.h index 108b4769..20718422 100644 --- a/internal/platform/implementation/linux/ble_gatt_client.h +++ b/internal/platform/implementation/linux/ble_gatt_client.h @@ -93,7 +93,7 @@ class BluezGattDiscovery final : public bluez::BluezObjectManager { absl::Mutex mutex_; absl::flat_hash_map> cached_services_ ABSL_GUARDED_BY(mutex_); - // Tuple order: service uuid, characteristic uuid, device object path + // Tuple order: service uuid, characteristic uuid, device object path. absl::flat_hash_map, sdbus::ObjectPath> discovered_characteristics_ ABSL_GUARDED_BY(mutex_); @@ -122,7 +122,7 @@ class GattClient : public api::ble::GattClient { peripheral_object_path_(peripheral_object_path), gatt_discovery_(std::move(gatt_discovery)), discovery_cancel_(false) { - disconnected_callback_it_ = gatt_discovery->AddPeripheralConnection( + disconnected_callback_it_ = gatt_discovery_->AddPeripheralConnection( peripheral_object_path_, std::move(disconnected_callback)); } ~GattClient() override { diff --git a/internal/platform/implementation/linux/ble_gatt_server.cc b/internal/platform/implementation/linux/ble_gatt_server.cc index cc761c22..ee0a0f40 100644 --- a/internal/platform/implementation/linux/ble_gatt_server.cc +++ b/internal/platform/implementation/linux/ble_gatt_server.cc @@ -24,6 +24,19 @@ namespace nearby { namespace linux { +namespace { + +void LogAsyncGattManagerError(const bluez::GattManager& manager, + const char* method_name, + const sdbus::Error& error) { + LOG(ERROR) << method_name << ": Got error '" << error.getName() + << "' with message '" << error.getMessage() + << "' while calling " << method_name << " on object " + << manager.getProxy().getObjectPath(); +} + +} // namespace + absl::optional GattServer::CreateCharacteristic( const Uuid& service_uuid, const Uuid& characteristic_uuid, @@ -60,23 +73,53 @@ GattServer::CreateCharacteristic( if (service->AddCharacteristic(service_uuid, characteristic_uuid, permission, property)) { - try { - LOG(INFO)<< __func__ << ": Registering service on gattmanager with characteristic_uuid: " - << std::string(characteristic_uuid) << " and service_uuid: " << std::string(service_uuid); - - gatt_manager_ -> RegisterApplication(gatt_service_root_object_manager -> getObject().getObjectPath(), {}); - } catch (const sdbus::Error& e) { - LOG(ERROR) - << __func__ - << ": error calling RegisterAplication for GattManager with object path " - << gatt_manager_->getProxy().getObjectPath() << " with name '" << e.getName() - << "' and message '" << e.getMessage() << "'"; - return std::nullopt; - } - - services_.insert({service_uuid, std::move(service)}); + { + absl::MutexLock profile_lock(&profiles_mutex_); + gatt_profiles_.insert({service_uuid, std::move(profile)}); + } + bool should_register_application = false; + { + absl::MutexLock registration_lock(®istration_mutex_); + should_register_application = + !gatt_application_registered_ && !gatt_application_register_pending_; + if (should_register_application) { + gatt_application_register_pending_ = true; + } + } + + if (should_register_application) { + try { + LOG(INFO) << __func__ + << ": Registering GATT application root " + << gatt_service_root_object_manager->getObject().getObjectPath() + << " with characteristic_uuid: " + << std::string(characteristic_uuid) + << " and service_uuid: " << std::string(service_uuid); + auto call = gatt_manager_->RegisterApplication( + gatt_service_root_object_manager->getObject().getObjectPath(), {}); + absl::MutexLock registration_lock(®istration_mutex_); + register_application_call_ = std::move(call); + } catch (const sdbus::Error& e) { + { + absl::MutexLock registration_lock(®istration_mutex_); + gatt_application_register_pending_ = false; + register_application_call_.reset(); + } + services_.erase(service_uuid); + { + absl::MutexLock profile_lock(&profiles_mutex_); + gatt_profiles_.erase(service_uuid); + } + LOG(ERROR) + << __func__ + << ": error calling RegisterApplication for GattManager with object path " + << gatt_manager_->getProxy().getObjectPath() << " with name '" + << e.getName() << "' and message '" << e.getMessage() << "'"; + return std::nullopt; + } + } api::ble::GattCharacteristic characteristic{ characteristic_uuid, service_uuid, permission, property}; @@ -137,19 +180,86 @@ absl::Status GattServer::NotifyCharacteristicChanged( return chr->NotifyChanged(confirm, new_value); } +void GattServer::OnRegisterApplicationReply(std::optional error) { + { + absl::MutexLock lock(®istration_mutex_); + gatt_application_register_pending_ = false; + register_application_call_.reset(); + gatt_application_registered_ = !error.has_value() || !error->isValid(); + } + + if (error.has_value() && error->isValid()) { + LogAsyncGattManagerError(*gatt_manager_, "RegisterApplication", *error); + } +} + +void GattServer::OnUnregisterApplicationReply( + std::optional error) { + { + absl::MutexLock lock(®istration_mutex_); + gatt_application_unregister_pending_ = false; + unregister_application_call_.reset(); + } + + if (error.has_value() && error->isValid()) { + LogAsyncGattManagerError(*gatt_manager_, "UnregisterApplication", *error); + } +} + void GattServer::Stop() { - bluez::GattManager manager(system_bus_, adapter_.GetObjectPath()); - absl::MutexLock lock(&services_mutex_); - for (auto& [uuid, service] : services_) { - LOG(INFO) << __func__ << ": Unregistering service " - << service->getObject().getObjectPath(); - try { - manager.UnregisterApplication(sdbus::ObjectPath("/")); - } catch (const sdbus::Error& e) { - DBUS_LOG_METHOD_CALL_ERROR(&manager, "UnregisterApplication", e); + sdbus::ObjectPath app_path = + gatt_service_root_object_manager->getObject().getObjectPath(); + bool should_unregister = false; + + { + absl::MutexLock registration_lock(®istration_mutex_); + if (register_application_call_.has_value() && + register_application_call_->isPending()) { + register_application_call_->cancel(); + } + register_application_call_.reset(); + gatt_application_register_pending_ = false; + + should_unregister = gatt_application_registered_ && + !gatt_application_unregister_pending_; + if (should_unregister) { + gatt_application_registered_ = false; + gatt_application_unregister_pending_ = true; } } - // services_.clear(); + + { + absl::MutexLock lock(&services_mutex_); + for (auto& [uuid, service] : services_) { + LOG(INFO) << __func__ << ": Unregistering service " + << service->getObject().getObjectPath(); + } + } + + if (should_unregister) { + try { + auto call = gatt_manager_->UnregisterApplication(app_path); + absl::MutexLock registration_lock(®istration_mutex_); + unregister_application_call_ = std::move(call); + } catch (const sdbus::Error& e) { + { + absl::MutexLock registration_lock(®istration_mutex_); + gatt_application_unregister_pending_ = false; + unregister_application_call_.reset(); + } + DBUS_LOG_METHOD_CALL_ERROR(gatt_manager_.get(), "UnregisterApplication", + e); + } + } + + { + absl::MutexLock lock(&services_mutex_); + services_.clear(); + } + { + absl::MutexLock profile_lock(&profiles_mutex_); + gatt_profiles_.clear(); + } } } // namespace linux diff --git a/internal/platform/implementation/linux/ble_gatt_server.h b/internal/platform/implementation/linux/ble_gatt_server.h index 1343a4be..2d41b4c5 100644 --- a/internal/platform/implementation/linux/ble_gatt_server.h +++ b/internal/platform/implementation/linux/ble_gatt_server.h @@ -16,6 +16,7 @@ #define PLATFORM_IMPL_LINUX_API_BLE_GATT_SERVER_H_ #include +#include #include #include @@ -69,7 +70,16 @@ class GattServer : public api::ble::GattServer { sdbus::ObjectPath("/com/google/nearby/medium/ble/gatt"))), gatt_manager_(std::make_unique(system_bus_, adapter_.GetObjectPath())), server_cb_(std::make_shared( - std::move(server_cb))) {} + std::move(server_cb))) { + gatt_manager_->SetRegisterApplicationReplyCallback( + [this](std::optional error) { + OnRegisterApplicationReply(std::move(error)); + }); + gatt_manager_->SetUnregisterApplicationReplyCallback( + [this](std::optional error) { + OnUnregisterApplicationReply(std::move(error)); + }); + } ~GattServer() override = default; absl::optional CreateCharacteristic( @@ -85,6 +95,9 @@ class GattServer : public api::ble::GattServer { void Stop() override; private: + void OnRegisterApplicationReply(std::optional error); + void OnUnregisterApplicationReply(std::optional error); + sdbus::IConnection& system_bus_; std::shared_ptr devices_; BluetoothAdapter adapter_; @@ -93,9 +106,20 @@ class GattServer : public api::ble::GattServer { std::unique_ptr gatt_service_root_object_manager; absl::Mutex profiles_mutex_; absl::flat_hash_map> gatt_profiles_; - ABSL_GUARDED_BY(profiles_mutex_) + ABSL_GUARDED_BY(profiles_mutex_); std::unique_ptr gatt_manager_; std::shared_ptr server_cb_; + absl::Mutex registration_mutex_; + bool gatt_application_registered_ ABSL_GUARDED_BY(registration_mutex_) = + false; + bool gatt_application_register_pending_ ABSL_GUARDED_BY(registration_mutex_) = + false; + bool gatt_application_unregister_pending_ + ABSL_GUARDED_BY(registration_mutex_) = false; + std::optional register_application_call_ + ABSL_GUARDED_BY(registration_mutex_); + std::optional unregister_application_call_ + ABSL_GUARDED_BY(registration_mutex_); absl::Mutex services_mutex_; absl::flat_hash_map> services_ ABSL_GUARDED_BY(services_mutex_); diff --git a/internal/platform/implementation/linux/ble_v2_medium.cc b/internal/platform/implementation/linux/ble_v2_medium.cc index b936dd73..d50c3a22 100644 --- a/internal/platform/implementation/linux/ble_v2_medium.cc +++ b/internal/platform/implementation/linux/ble_v2_medium.cc @@ -27,17 +27,14 @@ #include "absl/synchronization/mutex.h" #include "internal/platform/implementation/ble.h" -// #include "internal/platform/implementation/linux/ble_gatt_client.h" -// #include "internal/platform/implementation/linux/ble_gatt_server.h" #include "internal/platform/implementation/linux/ble_v2_medium.h" #include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "absl/types/span.h" #include "absl/time/time.h" -//#include "ble_gatt_client.h" -//#include "ble_gatt_server.h" #include "ble_l2cap_server_socket.h" #include "ble_l2cap_socket.h" +#include "ble_gatt_server.h" #include "internal/base/observer_list.h" #include "internal/platform/implementation/linux/bluetooth_classic_device.h" #include "internal/platform/implementation/linux/bluetooth_devices.h" @@ -68,7 +65,6 @@ BleL2capSocket::ProtocolMode GetL2capProtocolMode() { BleV2Medium::BleV2Medium(BluetoothAdapter &adapter) : system_bus_(adapter.GetConnection()), adapter_(adapter), - //gatt_discovery_(std::make_shared(system_bus_)), observers_(std::make_shared>()), devices_(std::make_unique( system_bus_, adapter_.GetObjectPath(), *observers_)), @@ -98,10 +94,6 @@ BleV2Medium::BleV2Medium(BluetoothAdapter &adapter) } else { adv_monitor_manager_ready_notification_.Notify(); } - // if (gatt_discovery_->InitializeKnownServices()) { - // LOG(ERROR) << __func__ - // << ": Could not initialize known GATT services"; - // } } void BleV2Medium::OnRegisterMonitorReply(std::optional error) { @@ -478,12 +470,9 @@ bool BleV2Medium::StopScanning() { std::unique_ptr BleV2Medium::StartGattServer( api::ble::ServerGattConnectionCallback callback) { - // (void)callback; + (void)callback; + LOG(INFO) << __func__ << ": GATT is disabled on linux."; return nullptr; - - //return std::make_unique( - //*system_bus_, adapter_, devices_,std::move(callback) - //); } std::unique_ptr BleV2Medium::ConnectToGattServer( @@ -493,8 +482,7 @@ std::unique_ptr BleV2Medium::ConnectToGattServer( (void)peripheral_id; (void)tx_power_level; (void)callback; - LOG(WARNING) << __func__ - << ": GATT client connection is not supported on Linux yet."; + LOG(INFO) << __func__ << ": GATT is disabled on linux."; return nullptr; } diff --git a/internal/platform/implementation/linux/bluetooth_classic_medium.cc b/internal/platform/implementation/linux/bluetooth_classic_medium.cc index 0d3d23f7..208fb28e 100644 --- a/internal/platform/implementation/linux/bluetooth_classic_medium.cc +++ b/internal/platform/implementation/linux/bluetooth_classic_medium.cc @@ -21,34 +21,48 @@ #include "absl/strings/string_view.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_classic_device.h" -#include "internal/platform/implementation/linux/bluetooth_classic_medium.h" - -// #include "bluez_agent.h" -#include "internal/platform/implementation/linux/bluetooth_classic_server_socket.h" -#include "internal/platform/implementation/linux/bluetooth_classic_socket.h" -#include "internal/platform/implementation/linux/bluetooth_pairing.h" -#include "internal/platform/logging.h" - -namespace nearby { -namespace linux { -BluetoothClassicMedium::BluetoothClassicMedium(BluetoothAdapter &adapter) - : system_bus_(adapter.GetConnection()), - adapter_(adapter), - observers_(nullptr), - devices_(nullptr), - device_watcher_(nullptr), - // agent_manager_(std::make_unique(*system_bus_)), - profile_manager_(nullptr) { - auto shared = - GetSharedBluetoothDevices(system_bus_, adapter_.GetObjectPath()); - observers_ = shared->observers; - devices_ = shared->devices; - profile_manager_ = - std::make_unique(*system_bus_, *devices_); -} +#include "internal/platform/implementation/linux/bluetooth_adapter.h" +#include "internal/platform/implementation/linux/bluez_agent.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/logging.h" + +namespace nearby { +namespace linux { +namespace { + +constexpr char kBluezAgentPath[] = "/com/google/nearby/bluetooth/agent"; + +} // namespace + +BluetoothClassicMedium::BluetoothClassicMedium(BluetoothAdapter &adapter) + : system_bus_(adapter.GetConnection()), + adapter_(adapter), + observers_(nullptr), + devices_(nullptr), + device_watcher_(nullptr), + agent_manager_(std::make_unique(*system_bus_)), + profile_manager_(nullptr) { + auto shared = + GetSharedBluetoothDevices(system_bus_, adapter_.GetObjectPath()); + observers_ = shared->observers; + devices_ = shared->devices; + profile_manager_ = + std::make_unique(*system_bus_, *devices_); + + if (!agent_manager_->Register( + /*capability=*/absl::string_view("NoInputNoOutput"), + sdbus::ObjectPath(kBluezAgentPath))) { + LOG(WARNING) << __func__ + << ": Failed to register default BlueZ agent at " + << kBluezAgentPath; + } +} bool BluetoothClassicMedium::StartDiscovery( DiscoveryCallback discovery_callback) { @@ -145,14 +159,12 @@ std::unique_ptr BluetoothClassicMedium::ConnectToService( new BluetoothSocket(device, fd.value())); } -std::unique_ptr -BluetoothClassicMedium::ListenForService(const std::string &service_name, - const std::string &service_uuid) { - LOG(INFO) << __func__ << ": Creating bluez agent on path: " << "/com/example/bluez_agent" ; - - if (!profile_manager_->ProfileRegistered(service_uuid)) { - if (!profile_manager_->Register(service_name, service_uuid)) { - LOG(ERROR) << __func__ << ": Could not register profile " +std::unique_ptr +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)) { + LOG(ERROR) << __func__ << ": Could not register profile " << service_name << " " << service_uuid << " with Bluez"; return nullptr; diff --git a/internal/platform/implementation/linux/bluetooth_classic_medium.h b/internal/platform/implementation/linux/bluetooth_classic_medium.h index 42edf168..0320d765 100644 --- a/internal/platform/implementation/linux/bluetooth_classic_medium.h +++ b/internal/platform/implementation/linux/bluetooth_classic_medium.h @@ -26,7 +26,7 @@ #include #include -// #include "bluez_agent.h" +#include "internal/platform/implementation/linux/bluez_agent.h" #include "internal/base/observer_list.h" #include "internal/platform/implementation/bluetooth_classic.h" #include "internal/platform/implementation/linux/bluetooth_adapter.h" @@ -107,7 +107,7 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium { std::shared_ptr devices_; std::unique_ptr device_watcher_; - // std::unique_ptr agent_manager_; + std::unique_ptr agent_manager_; std::unique_ptr profile_manager_; }; diff --git a/internal/platform/implementation/linux/bluez_agent.cc b/internal/platform/implementation/linux/bluez_agent.cc new file mode 100644 index 00000000..ba1cc14b --- /dev/null +++ b/internal/platform/implementation/linux/bluez_agent.cc @@ -0,0 +1,99 @@ +#include "internal/platform/implementation/linux/bluez_agent.h" + +#include + +#include "internal/platform/implementation/linux/generated/dbus/bluez/agent_server.h" +#include "internal/platform/implementation/linux/generated/dbus/bluez/agentmanager_client.h" +#include "internal/platform/implementation/linux/bluez.h" +#include "internal/platform/logging.h" + +namespace nearby { +namespace linux { + +void Agent::Release() { LOG(INFO) << "[agent] Release()"; } + +std::string Agent::RequestPinCode(const sdbus::ObjectPath& device) { + LOG(INFO) << "[agent] RequestPinCode(" << device << ")"; + return "0000"; +} + +void Agent::DisplayPinCode(const sdbus::ObjectPath& device, + const std::string& pincode) { + LOG(INFO) << "[agent] DisplayPinCode(" << device << ", " << pincode << ")"; +} + +uint32_t Agent::RequestPasskey(const sdbus::ObjectPath& device) { + LOG(INFO) << "[agent] RequestPasskey(" << device << ")"; + return 123456; +} + +void Agent::DisplayPasskey(const sdbus::ObjectPath& device, + const uint32_t& passkey, + const uint16_t& entered) { + LOG(INFO) << "[agent] DisplayPasskey(" << device << ", " << passkey + << ", entered=" << entered << ")"; +} + +void Agent::RequestConfirmation(const sdbus::ObjectPath& device, + const uint32_t& passkey) { + LOG(INFO) << "[agent] RequestConfirmation(" << device << ", " << passkey + << ") -> ACCEPT"; +} + +void Agent::RequestAuthorization(const sdbus::ObjectPath& device) { + LOG(INFO) << "[agent] RequestAuthorization(" << device << ") -> ACCEPT"; +} + +void Agent::AuthorizeService(const sdbus::ObjectPath& device, + const std::string& uuid) { + LOG(INFO) << "[agent] AuthorizeService(" << device << ", " << uuid + << ") -> ACCEPT"; +} + +void Agent::Cancel() { LOG(INFO) << "[agent] Cancel()"; } + +bool AgentManager::AgentRegistered(absl::string_view agent_object_path) { + registered_agents_mutex_.ReaderLock(); + bool registered = registered_agents_.count(std::string(agent_object_path)) == 1; + registered_agents_mutex_.ReaderUnlock(); + return registered; +} + +bool AgentManager::Register(std::optional capability, + const sdbus::ObjectPath& agent_object_path) { + absl::MutexLock l(®istered_agents_mutex_); + + const std::string agent_path_str = std::string(agent_object_path); + + if (registered_agents_.count(agent_path_str) == 1) { + LOG(WARNING) << __func__ << ": Trying to register agent " << agent_path_str + << " which was already registered."; + return true; + } + + auto agent = std::make_shared(getProxy().getConnection(), + sdbus::ObjectPath(agent_object_path)); + + try { + const std::string cap = + capability.has_value() ? std::string(*capability) : "NoInputNoOutput"; + RegisterAgent(agent->getObject().getObjectPath(), cap); + RequestDefaultAgent(agent->getObject().getObjectPath()); + } catch (const sdbus::Error& e) { + LOG(ERROR) << __func__ << ": Got error '" << e.getName() + << "' with message '" << e.getMessage() + << "' while calling RegisterAgent/RequestDefaultAgent on object " + << getProxy().getObjectPath(); + return false; + } + + registered_agents_.emplace(agent_path_str, agent); + + LOG(INFO) << __func__ << ": Registered agent instance at path " + << agent_path_str; + + return true; +} + +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/bluez_agent.h b/internal/platform/implementation/linux/bluez_agent.h new file mode 100644 index 00000000..c40f79f7 --- /dev/null +++ b/internal/platform/implementation/linux/bluez_agent.h @@ -0,0 +1,85 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include "absl/strings/string_view.h" +#include "absl/synchronization/mutex.h" +#include "internal/platform/implementation/linux/generated/dbus/bluez/agent_server.h" +#include "internal/platform/implementation/linux/generated/dbus/bluez/agentmanager_client.h" +#include "internal/platform/implementation/linux/bluez.h" +#include "internal/platform/logging.h" + +namespace nearby::linux { + +class Agent final + : public sdbus::AdaptorInterfaces { + public: + Agent(const Agent&) = delete; + Agent(Agent&&) = delete; + Agent& operator=(const Agent&) = delete; + Agent& operator=(Agent&&) = delete; + + Agent(sdbus::IConnection& system_bus, sdbus::ObjectPath path) + : AdaptorInterfaces(system_bus, std::move(path)) { + registerAdaptor(); + LOG(INFO) << "Created new Agent at path: " << getObject().getObjectPath(); + } + + ~Agent() { unregisterAdaptor(); } + + private: + void Release() override; + + std::string RequestPinCode(const sdbus::ObjectPath& device) override; + void DisplayPinCode(const sdbus::ObjectPath& device, + const std::string& pincode) override; + + uint32_t RequestPasskey(const sdbus::ObjectPath& device) override; + void DisplayPasskey(const sdbus::ObjectPath& device, const uint32_t& passkey, + const uint16_t& entered) override; + + void RequestConfirmation(const sdbus::ObjectPath& device, + const uint32_t& passkey) override; + + void RequestAuthorization(const sdbus::ObjectPath& device) override; + + void AuthorizeService(const sdbus::ObjectPath& device, + const std::string& uuid) override; + + void Cancel() override; +}; + +class AgentManager final + : public sdbus::ProxyInterfaces { + public: + AgentManager(const AgentManager&) = delete; + AgentManager(AgentManager&&) = delete; + AgentManager& operator=(const AgentManager&) = delete; + AgentManager& operator=(AgentManager&&) = delete; + + explicit AgentManager(sdbus::IConnection& system_bus) + : ProxyInterfaces(system_bus, sdbus::ServiceName(bluez::SERVICE_DEST), + sdbus::ObjectPath("/org/bluez")) { + registerProxy(); + } + + ~AgentManager() { unregisterProxy(); } + + bool Register(std::optional capability, + const sdbus::ObjectPath& agent_object_path); + + bool AgentRegistered(absl::string_view agent_object_path); + + private: + absl::Mutex registered_agents_mutex_; + std::map> registered_agents_ + ABSL_GUARDED_BY(registered_agents_mutex_); +}; + +} // namespace nearby::linux diff --git a/internal/platform/implementation/linux/bluez_gatt_characteristic_server.cc b/internal/platform/implementation/linux/bluez_gatt_characteristic_server.cc index af7a8364..3bab9bf7 100644 --- a/internal/platform/implementation/linux/bluez_gatt_characteristic_server.cc +++ b/internal/platform/implementation/linux/bluez_gatt_characteristic_server.cc @@ -191,7 +191,10 @@ void GattCharacteristicServer::StopNotify() { if ((characteristic_.property | api::ble::GattCharacteristic::Property::kNotify) == api::ble::GattCharacteristic::Property::kNotify) { - if (notify_sessions_.fetch_sub(0) == 1) { + if (notify_sessions_.load() == 0) { + return; + } + if (notify_sessions_.fetch_sub(1) == 1) { if (server_cb_->characteristic_unsubscription_cb != nullptr) { server_cb_->characteristic_unsubscription_cb(characteristic_); } diff --git a/internal/platform/implementation/linux/bluez_gatt_manager.h b/internal/platform/implementation/linux/bluez_gatt_manager.h index 33116870..f47c0411 100644 --- a/internal/platform/implementation/linux/bluez_gatt_manager.h +++ b/internal/platform/implementation/linux/bluez_gatt_manager.h @@ -14,10 +14,15 @@ #ifndef PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_ #define PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_ + +#include + #include #include #include +#include "absl/functional/any_invocable.h" +#include "absl/synchronization/mutex.h" #include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h" namespace nearby { namespace linux { @@ -25,6 +30,8 @@ namespace bluez { class GattManager : public sdbus::ProxyInterfaces { public: + using ReplyCallback = absl::AnyInvocable)>; + GattManager(const GattManager &) = delete; GattManager(GattManager &&) = delete; GattManager &operator=(const GattManager &) = delete; @@ -37,6 +44,38 @@ class GattManager registerProxy(); } ~GattManager() { unregisterProxy(); } + + void SetRegisterApplicationReplyCallback(ReplyCallback callback) { + absl::MutexLock lock(&callbacks_mutex_); + register_application_reply_callback_ = std::move(callback); + } + + void SetUnregisterApplicationReplyCallback(ReplyCallback callback) { + absl::MutexLock lock(&callbacks_mutex_); + unregister_application_reply_callback_ = std::move(callback); + } + + protected: + void onRegisterApplicationReply(std::optional error) override { + absl::MutexLock lock(&callbacks_mutex_); + if (register_application_reply_callback_.has_value()) { + (*register_application_reply_callback_)(std::move(error)); + } + } + + void onUnregisterApplicationReply(std::optional error) override { + absl::MutexLock lock(&callbacks_mutex_); + if (unregister_application_reply_callback_.has_value()) { + (*unregister_application_reply_callback_)(std::move(error)); + } + } + + private: + absl::Mutex callbacks_mutex_; + std::optional register_application_reply_callback_ + ABSL_GUARDED_BY(callbacks_mutex_); + std::optional unregister_application_reply_callback_ + ABSL_GUARDED_BY(callbacks_mutex_); }; } // namespace bluez } // namespace linux diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/agent_server.h b/internal/platform/implementation/linux/generated/dbus/bluez/agent_server.h new file mode 100644 index 00000000..56d182e8 --- /dev/null +++ b/internal/platform/implementation/linux/generated/dbus/bluez/agent_server.h @@ -0,0 +1,65 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp__internal_platform_implementation_linux_generated_dbus_bluez_agent_server_h__adaptor__H__ +#define __sdbuscpp__internal_platform_implementation_linux_generated_dbus_bluez_agent_server_h__adaptor__H__ + +#include +#include +#include + +namespace org { +namespace bluez { + +class Agent1_adaptor +{ +public: + static constexpr const char* INTERFACE_NAME = "org.bluez.Agent1"; + +protected: + Agent1_adaptor(sdbus::IObject& object) + : m_object(object) + { + } + + Agent1_adaptor(const Agent1_adaptor&) = delete; + Agent1_adaptor& operator=(const Agent1_adaptor&) = delete; + Agent1_adaptor(Agent1_adaptor&&) = delete; + Agent1_adaptor& operator=(Agent1_adaptor&&) = delete; + + ~Agent1_adaptor() = default; + + void registerAdaptor() + { + m_object.addVTable( sdbus::registerMethod("Release").implementedAs([this](){ return this->Release(); }) + , sdbus::registerMethod("RequestPinCode").withInputParamNames("device").withOutputParamNames("pincode").implementedAs([this](const sdbus::ObjectPath& device){ return this->RequestPinCode(device); }) + , sdbus::registerMethod("DisplayPinCode").withInputParamNames("device", "pincode").implementedAs([this](const sdbus::ObjectPath& device, const std::string& pincode){ return this->DisplayPinCode(device, pincode); }) + , sdbus::registerMethod("RequestPasskey").withInputParamNames("device").withOutputParamNames("passkey").implementedAs([this](const sdbus::ObjectPath& device){ return this->RequestPasskey(device); }) + , sdbus::registerMethod("DisplayPasskey").withInputParamNames("device", "passkey", "entered").implementedAs([this](const sdbus::ObjectPath& device, const uint32_t& passkey, const uint16_t& entered){ return this->DisplayPasskey(device, passkey, entered); }) + , sdbus::registerMethod("RequestConfirmation").withInputParamNames("device", "passkey").implementedAs([this](const sdbus::ObjectPath& device, const uint32_t& passkey){ return this->RequestConfirmation(device, passkey); }) + , sdbus::registerMethod("RequestAuthorization").withInputParamNames("device").implementedAs([this](const sdbus::ObjectPath& device){ return this->RequestAuthorization(device); }) + , sdbus::registerMethod("AuthorizeService").withInputParamNames("device", "uuid").implementedAs([this](const sdbus::ObjectPath& device, const std::string& uuid){ return this->AuthorizeService(device, uuid); }) + , sdbus::registerMethod("Cancel").implementedAs([this](){ return this->Cancel(); }) + ).forInterface(INTERFACE_NAME); + } + +private: + virtual void Release() = 0; + virtual std::string RequestPinCode(const sdbus::ObjectPath& device) = 0; + virtual void DisplayPinCode(const sdbus::ObjectPath& device, const std::string& pincode) = 0; + virtual uint32_t RequestPasskey(const sdbus::ObjectPath& device) = 0; + virtual void DisplayPasskey(const sdbus::ObjectPath& device, const uint32_t& passkey, const uint16_t& entered) = 0; + virtual void RequestConfirmation(const sdbus::ObjectPath& device, const uint32_t& passkey) = 0; + virtual void RequestAuthorization(const sdbus::ObjectPath& device) = 0; + virtual void AuthorizeService(const sdbus::ObjectPath& device, const std::string& uuid) = 0; + virtual void Cancel() = 0; + +private: + sdbus::IObject& m_object; +}; + +}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/agentmanager_client.h b/internal/platform/implementation/linux/generated/dbus/bluez/agentmanager_client.h new file mode 100644 index 00000000..4f7f79b9 --- /dev/null +++ b/internal/platform/implementation/linux/generated/dbus/bluez/agentmanager_client.h @@ -0,0 +1,60 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp__internal_platform_implementation_linux_generated_dbus_bluez_agentmanager_client_h__proxy__H__ +#define __sdbuscpp__internal_platform_implementation_linux_generated_dbus_bluez_agentmanager_client_h__proxy__H__ + +#include +#include +#include + +namespace org { +namespace bluez { + +class AgentManager1_proxy +{ +public: + static constexpr const char* INTERFACE_NAME = "org.bluez.AgentManager1"; + +protected: + AgentManager1_proxy(sdbus::IProxy& proxy) + : m_proxy(proxy) + { + } + + AgentManager1_proxy(const AgentManager1_proxy&) = delete; + AgentManager1_proxy& operator=(const AgentManager1_proxy&) = delete; + AgentManager1_proxy(AgentManager1_proxy&&) = delete; + AgentManager1_proxy& operator=(AgentManager1_proxy&&) = delete; + + ~AgentManager1_proxy() = default; + + void registerProxy() + { + } + +public: + void RegisterAgent(const sdbus::ObjectPath& agent, const std::string& capability) + { + m_proxy.callMethod("RegisterAgent").onInterface(INTERFACE_NAME).withArguments(agent, capability); + } + + void UnregisterAgent(const sdbus::ObjectPath& agent) + { + m_proxy.callMethod("UnregisterAgent").onInterface(INTERFACE_NAME).withArguments(agent); + } + + void RequestDefaultAgent(const sdbus::ObjectPath& agent) + { + m_proxy.callMethod("RequestDefaultAgent").onInterface(INTERFACE_NAME).withArguments(agent); + } + +private: + sdbus::IProxy& m_proxy; +}; + +}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h b/internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h index cd30e950..bd59a013 100644 --- a/internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h +++ b/internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h @@ -3,8 +3,8 @@ * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! */ -#ifndef __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_gatt_manager_client_v2_h__proxy__H__ -#define __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_gatt_manager_client_v2_h__proxy__H__ +#ifndef __sdbuscpp__internal_platform_implementation_linux_generated_dbus_bluez_gatt_manager_client_h__proxy__H__ +#define __sdbuscpp__internal_platform_implementation_linux_generated_dbus_bluez_gatt_manager_client_h__proxy__H__ #include #include @@ -35,15 +35,18 @@ protected: { } + virtual void onRegisterApplicationReply(std::optional error) = 0; + virtual void onUnregisterApplicationReply(std::optional error) = 0; + public: - void RegisterApplication(const sdbus::ObjectPath& application, const std::map& options) + sdbus::PendingAsyncCall RegisterApplication(const sdbus::ObjectPath& application, const std::map& options) { - m_proxy.callMethod("RegisterApplication").onInterface(INTERFACE_NAME).withArguments(application, options); + return m_proxy.callMethodAsync("RegisterApplication").onInterface(INTERFACE_NAME).withArguments(application, options).uponReplyInvoke([this](std::optional error){ this->onRegisterApplicationReply(std::move(error)); }); } - void UnregisterApplication(const sdbus::ObjectPath& application) + sdbus::PendingAsyncCall UnregisterApplication(const sdbus::ObjectPath& application) { - m_proxy.callMethod("UnregisterApplication").onInterface(INTERFACE_NAME).withArguments(application); + return m_proxy.callMethodAsync("UnregisterApplication").onInterface(INTERFACE_NAME).withArguments(application).uponReplyInvoke([this](std::optional error){ this->onUnregisterApplicationReply(std::move(error)); }); } private: diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.Agent1.xml b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.Agent1.xml new file mode 100644 index 00000000..f5b62a11 --- /dev/null +++ b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.Agent1.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.AgentManager1.xml b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.AgentManager1.xml new file mode 100644 index 00000000..b685e942 --- /dev/null +++ b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.AgentManager1.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattManager1.xml b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattManager1.xml index e353715b..a37bf7d4 100644 --- a/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattManager1.xml +++ b/internal/platform/implementation/linux/generated/dbus/bluez/org.bluez.GattManager1.xml @@ -3,10 +3,12 @@ + +