implemented gatt but removed it from ble_v2_medium. implemented bluez_agent and bluez agent manager for accepting incoming pairing requests

This commit is contained in:
Lasan Mahaliyana
2026-03-22 00:50:27 +05:30
parent 1c8761c02d
commit f884cf3473
18 changed files with 671 additions and 118 deletions
+2 -2
View File
@@ -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",
@@ -208,7 +208,6 @@ bool BluezGattDiscovery::InitializeKnownServices() {
return false;
}
absl::flat_hash_map<sdbus::ObjectPath, GattServiceClient> 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<bluez::SubscribedGattCharacteristicClient>(
system_bus_, device_object_path, std::move(on_characteristic_changed_cb));
system_bus_, path_it->second, std::move(on_characteristic_changed_cb));
}
std::optional<std::tuple<Uuid, Uuid, sdbus::ObjectPath>>
@@ -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(
@@ -93,7 +93,7 @@ class BluezGattDiscovery final : public bluez::BluezObjectManager {
absl::Mutex mutex_;
absl::flat_hash_map<sdbus::ObjectPath, std::unique_ptr<GattServiceClient>>
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<std::tuple<Uuid, Uuid, sdbus::ObjectPath>,
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 {
@@ -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<api::ble::GattCharacteristic>
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(&registration_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(&registration_mutex_);
register_application_call_ = std::move(call);
} catch (const sdbus::Error& e) {
{
absl::MutexLock registration_lock(&registration_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<sdbus::Error> error) {
{
absl::MutexLock lock(&registration_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<sdbus::Error> error) {
{
absl::MutexLock lock(&registration_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(&registration_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(&registration_mutex_);
unregister_application_call_ = std::move(call);
} catch (const sdbus::Error& e) {
{
absl::MutexLock registration_lock(&registration_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
@@ -16,6 +16,7 @@
#define PLATFORM_IMPL_LINUX_API_BLE_GATT_SERVER_H_
#include <memory>
#include <optional>
#include <regex>
#include <sdbus-c++/IConnection.h>
@@ -69,7 +70,16 @@ class GattServer : public api::ble::GattServer {
sdbus::ObjectPath("/com/google/nearby/medium/ble/gatt"))),
gatt_manager_(std::make_unique<bluez::GattManager>(system_bus_, adapter_.GetObjectPath())),
server_cb_(std::make_shared<api::ble::ServerGattConnectionCallback>(
std::move(server_cb))) {}
std::move(server_cb))) {
gatt_manager_->SetRegisterApplicationReplyCallback(
[this](std::optional<sdbus::Error> error) {
OnRegisterApplicationReply(std::move(error));
});
gatt_manager_->SetUnregisterApplicationReplyCallback(
[this](std::optional<sdbus::Error> error) {
OnUnregisterApplicationReply(std::move(error));
});
}
~GattServer() override = default;
absl::optional<api::ble::GattCharacteristic> CreateCharacteristic(
@@ -85,6 +95,9 @@ class GattServer : public api::ble::GattServer {
void Stop() override;
private:
void OnRegisterApplicationReply(std::optional<sdbus::Error> error);
void OnUnregisterApplicationReply(std::optional<sdbus::Error> error);
sdbus::IConnection& system_bus_;
std::shared_ptr<BluetoothDevices> devices_;
BluetoothAdapter adapter_;
@@ -93,9 +106,20 @@ class GattServer : public api::ble::GattServer {
std::unique_ptr<RootObjectManager> gatt_service_root_object_manager;
absl::Mutex profiles_mutex_;
absl::flat_hash_map<Uuid, std::unique_ptr<bluez::GattProfile>> gatt_profiles_;
ABSL_GUARDED_BY(profiles_mutex_)
ABSL_GUARDED_BY(profiles_mutex_);
std::unique_ptr<bluez::GattManager> gatt_manager_;
std::shared_ptr<api::ble::ServerGattConnectionCallback> 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<sdbus::PendingAsyncCall> register_application_call_
ABSL_GUARDED_BY(registration_mutex_);
std::optional<sdbus::PendingAsyncCall> unregister_application_call_
ABSL_GUARDED_BY(registration_mutex_);
absl::Mutex services_mutex_;
absl::flat_hash_map<Uuid, std::unique_ptr<bluez::GattServiceServer>> services_
ABSL_GUARDED_BY(services_mutex_);
@@ -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<BluezGattDiscovery>(system_bus_)),
observers_(std::make_shared<ObserverList<api::BluetoothClassicMedium::Observer>>()),
devices_(std::make_unique<BluetoothDevices>(
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<sdbus::Error> error) {
@@ -478,12 +470,9 @@ bool BleV2Medium::StopScanning() {
std::unique_ptr<api::ble::GattServer> BleV2Medium::StartGattServer(
api::ble::ServerGattConnectionCallback callback) {
// (void)callback;
(void)callback;
LOG(INFO) << __func__ << ": GATT is disabled on linux.";
return nullptr;
//return std::make_unique<GattServer>(
//*system_bus_, adapter_, devices_,std::move(callback)
//);
}
std::unique_ptr<api::ble::GattClient> BleV2Medium::ConnectToGattServer(
@@ -493,8 +482,7 @@ std::unique_ptr<api::ble::GattClient> 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;
}
@@ -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<AgentManager>(*system_bus_)),
profile_manager_(nullptr) {
auto shared =
GetSharedBluetoothDevices(system_bus_, adapter_.GetObjectPath());
observers_ = shared->observers;
devices_ = shared->devices;
profile_manager_ =
std::make_unique<ProfileManager>(*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<AgentManager>(*system_bus_)),
profile_manager_(nullptr) {
auto shared =
GetSharedBluetoothDevices(system_bus_, adapter_.GetObjectPath());
observers_ = shared->observers;
devices_ = shared->devices;
profile_manager_ =
std::make_unique<ProfileManager>(*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<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
new BluetoothSocket(device, fd.value()));
}
std::unique_ptr<api::BluetoothServerSocket>
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<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)) {
LOG(ERROR) << __func__ << ": Could not register profile "
<< service_name << " " << service_uuid
<< " with Bluez";
return nullptr;
@@ -26,7 +26,7 @@
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
// #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<BluetoothDevices> devices_;
std::unique_ptr<DeviceWatcher> device_watcher_;
// std::unique_ptr<AgentManager> agent_manager_;
std::unique_ptr<AgentManager> agent_manager_;
std::unique_ptr<ProfileManager> profile_manager_;
};
@@ -0,0 +1,99 @@
#include "internal/platform/implementation/linux/bluez_agent.h"
#include <sdbus-c++/AdaptorInterfaces.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 {
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<absl::string_view> capability,
const sdbus::ObjectPath& agent_object_path) {
absl::MutexLock l(&registered_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<Agent>(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
@@ -0,0 +1,85 @@
#pragma once
#include <cstdint>
#include <map>
#include <optional>
#include <string>
#include <utility>
#include <sdbus-c++/sdbus-c++.h>
#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<org::bluez::Agent1_adaptor> {
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<org::bluez::AgentManager1_proxy> {
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<absl::string_view> capability,
const sdbus::ObjectPath& agent_object_path);
bool AgentRegistered(absl::string_view agent_object_path);
private:
absl::Mutex registered_agents_mutex_;
std::map<std::string, std::shared_ptr<Agent>> registered_agents_
ABSL_GUARDED_BY(registered_agents_mutex_);
};
} // namespace nearby::linux
@@ -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_);
}
@@ -14,10 +14,15 @@
#ifndef PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_
#define PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_
#include <optional>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/Types.h>
#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<org::bluez::GattManager1_proxy> {
public:
using ReplyCallback = absl::AnyInvocable<void(std::optional<sdbus::Error>)>;
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<sdbus::Error> 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<sdbus::Error> 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<ReplyCallback> register_application_reply_callback_
ABSL_GUARDED_BY(callbacks_mutex_);
std::optional<ReplyCallback> unregister_application_reply_callback_
ABSL_GUARDED_BY(callbacks_mutex_);
};
} // namespace bluez
} // namespace linux
@@ -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 <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
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
@@ -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 <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
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
@@ -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 <sdbus-c++/sdbus-c++.h>
#include <string>
@@ -35,15 +35,18 @@ protected:
{
}
virtual void onRegisterApplicationReply(std::optional<sdbus::Error> error) = 0;
virtual void onUnregisterApplicationReply(std::optional<sdbus::Error> error) = 0;
public:
void RegisterApplication(const sdbus::ObjectPath& application, const std::map<std::string, sdbus::Variant>& options)
sdbus::PendingAsyncCall RegisterApplication(const sdbus::ObjectPath& application, const std::map<std::string, sdbus::Variant>& 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<sdbus::Error> 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<sdbus::Error> error){ this->onUnregisterApplicationReply(std::move(error)); });
}
private:
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.Agent1">
<method name="Release"/>
<method name="RequestPinCode">
<arg name="device" type="o" direction="in"/>
<arg name="pincode" type="s" direction="out"/>
</method>
<method name="DisplayPinCode">
<arg name="device" type="o" direction="in"/>
<arg name="pincode" type="s" direction="in"/>
</method>
<method name="RequestPasskey">
<arg name="device" type="o" direction="in"/>
<arg name="passkey" type="u" direction="out"/>
</method>
<method name="DisplayPasskey">
<arg name="device" type="o" direction="in"/>
<arg name="passkey" type="u" direction="in"/>
<arg name="entered" type="q" direction="in"/>
</method>
<method name="RequestConfirmation">
<arg name="device" type="o" direction="in"/>
<arg name="passkey" type="u" direction="in"/>
</method>
<method name="RequestAuthorization">
<arg name="device" type="o" direction="in"/>
</method>
<method name="AuthorizeService">
<arg name="device" type="o" direction="in"/>
<arg name="uuid" type="s" direction="in"/>
</method>
<method name="Cancel"/>
</interface>
</node>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.AgentManager1">
<method name="RegisterAgent">
<arg name="agent" type="o" direction="in"/>
<arg name="capability" type="s" direction="in"/>
</method>
<method name="UnregisterAgent">
<arg name="agent" type="o" direction="in"/>
</method>
<method name="RequestDefaultAgent">
<arg name="agent" type="o" direction="in"/>
</method>
</interface>
</node>
@@ -3,10 +3,12 @@
<node>
<interface name="org.bluez.GattManager1">
<method name="RegisterApplication">
<annotation name="org.freedesktop.DBus.Method.Async" value="client" />
<arg name="application" type="o" direction="in" />
<arg name="options" type="a{sv}" direction="in" />
</method>
<method name="UnregisterApplication">
<annotation name="org.freedesktop.DBus.Method.Async" value="client" />
<arg name="application" type="o" direction="in" />
</method>
</interface>