diff --git a/connections/implementation/bwu_manager.cc b/connections/implementation/bwu_manager.cc index 0cbafc7a..6c8b8a0c 100644 --- a/connections/implementation/bwu_manager.cc +++ b/connections/implementation/bwu_manager.cc @@ -217,6 +217,20 @@ void BwuManager::InitiateBwuForEndpoint(ClientProxy* client, endpoint_id, client->GetUpgradeMediums(endpoint_id).GetMediums(true)) : new_medium; + if (proposed_medium == Medium::WIFI_DIRECT && + mediums_->GetWifiDirect().IsGCONly()) { + std::vector fallback_mediums = + client->GetUpgradeMediums(endpoint_id).GetMediums(true); + fallback_mediums.erase( + std::remove(fallback_mediums.begin(), fallback_mediums.end(), + Medium::WIFI_DIRECT), + fallback_mediums.end()); + proposed_medium = ChooseBestUpgradeMedium(endpoint_id, fallback_mediums); + LOG(INFO) << "Wi-Fi Direct is GC-only; selected fallback medium " + << location::nearby::proto::connections::Medium_Name( + proposed_medium) + << " for endpoint " << endpoint_id; + } RunOnBwuManagerThread("bwu-init", [this, client, endpoint_id, proposed_medium]() { @@ -800,7 +814,12 @@ void BwuManager::ProcessBwuPathAvailableEvent( bool abort_bwu = false; if (client->IsIncomingConnection(endpoint_id)) { - if (!is_dynamic_role_switch_enabled_) { + if (upgrade_medium == Medium::WIFI_DIRECT && + mediums_->GetWifiDirect().IsGCONly()) { + // A GC-only device can consume a standard path offered by a peer GO, + // regardless of which side initiated the original connection. + abort_bwu = false; + } else if (!is_dynamic_role_switch_enabled_) { abort_bwu = true; } else { auto medium_role = client->GetMediumRole(endpoint_id); diff --git a/connections/implementation/bwu_manager_test.cc b/connections/implementation/bwu_manager_test.cc index f622ab5b..835d450a 100644 --- a/connections/implementation/bwu_manager_test.cc +++ b/connections/implementation/bwu_manager_test.cc @@ -271,6 +271,118 @@ TEST(BwuManagerBaseTest, AllowToUpgradeMedium) { bwu_manager->Shutdown(); } +TEST(BwuManagerBaseTest, GcOnlyDoesNotInitializeWifiDirectAsGO) { + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_connections_feature::kEnableWifiDirect, + true); + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly, + true); + { + ClientProxy client; + EndpointChannelManager ecm; + EndpointManager em(&ecm); + Mediums mediums; + auto fake_wifi_direct = + std::make_unique(Medium::WIFI_DIRECT); + FakeBwuHandler* fake_wifi_direct_ptr = fake_wifi_direct.get(); + absl::flat_hash_map> handlers; + handlers.emplace(Medium::WIFI_DIRECT, std::move(fake_wifi_direct)); + BwuManager::Config config; + config.allow_upgrade_to.wifi_direct = true; + auto bwu_manager = std::make_unique( + mediums, em, ecm, std::move(handlers), config); + bwu_manager->MakeSingleThreadedForTesting(); + + ConnectionOptions options; + options.allowed.wifi_direct = true; + client.OnConnectionInitiated( + std::string(kEndpointId1), + {.remote_endpoint_info = ByteArray("remote endpoint")}, options, {}, + ""); + client.OnConnectionAccepted(std::string(kEndpointId1)); + ecm.RegisterChannelForEndpoint( + &client, std::string(kEndpointId1), + std::make_unique(Medium::BLUETOOTH, + std::string(kServiceIdA))); + + bwu_manager->InitiateBwuForEndpoint(&client, std::string(kEndpointId1), + Medium::WIFI_DIRECT); + + EXPECT_TRUE(fake_wifi_direct_ptr->handle_initialize_calls().empty()); + ecm.UnregisterChannelForEndpoint( + std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); + bwu_manager->Shutdown(); + } + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly, + false); +} + +TEST(BwuManagerBaseTest, GcOnlyAcceptsPeerOfferedWifiDirectPath) { + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_connections_feature::kEnableWifiDirect, + true); + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly, + true); + { + ClientProxy client; + EndpointChannelManager ecm; + EndpointManager em(&ecm); + Mediums mediums; + auto fake_wifi_direct = + std::make_unique(Medium::WIFI_DIRECT); + FakeBwuHandler* fake_wifi_direct_ptr = fake_wifi_direct.get(); + absl::flat_hash_map> handlers; + handlers.emplace(Medium::WIFI_DIRECT, std::move(fake_wifi_direct)); + BwuManager::Config config; + config.allow_upgrade_to.wifi_direct = true; + auto bwu_manager = std::make_unique( + mediums, em, ecm, std::move(handlers), config); + bwu_manager->MakeSingleThreadedForTesting(); + + ConnectionResponseInfo response_info{ + .remote_endpoint_info = ByteArray("remote endpoint"), + .is_incoming_connection = true, + }; + client.OnConnectionInitiated(std::string(kEndpointId1), response_info, {}, + {}, ""); + client.OnConnectionAccepted(std::string(kEndpointId1)); + ecm.RegisterChannelForEndpoint( + &client, std::string(kEndpointId1), + std::make_unique(Medium::BLUETOOTH, + std::string(kServiceIdA))); + + ExceptionOr path_available = + parser::FromBytes(parser::ForBwuWifiDirectPathAvailable( + /*ssid=*/"", /*password=*/"", /*port=*/2143, + /*frequency=*/2412, /*supports_disabling_encryption=*/false, + /*gateway=*/"123.234.23.1", + /*device_name=*/"NC-WifiDirectTest", /*pin=*/"b592f7d3")); + EXPECT_TRUE(path_available.ok()); + if (path_available.ok()) { + bwu_manager->OnIncomingFrame(path_available.result(), + std::string(kEndpointId1), &client, + Medium::BLUETOOTH); + } + + EXPECT_EQ(fake_wifi_direct_ptr->create_calls().size(), 1u); + ecm.UnregisterChannelForEndpoint( + std::string(kEndpointId1), DisconnectionReason::LOCAL_DISCONNECTION, + SafeDisconnectionResult::kSafeDisconnection); + bwu_manager->Shutdown(); + } + NearbyFlags::GetInstance().OverrideBoolFlagValue( + config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly, + false); +} + TEST(BwuManagerBaseTest, InitiateBwu_NeedToSwitchRole_Success) { NearbyFlags::GetInstance().OverrideBoolFlagValue( config_package_nearby::nearby_connections_feature:: diff --git a/connections/implementation/flags/nearby_connections_feature_flags.h b/connections/implementation/flags/nearby_connections_feature_flags.h index d6cd22d4..7f15f2c0 100755 --- a/connections/implementation/flags/nearby_connections_feature_flags.h +++ b/connections/implementation/flags/nearby_connections_feature_flags.h @@ -77,6 +77,9 @@ constexpr auto kEnableStopBleScanningOnWifiUpgrade = // Enable/Disable Wi-Fi Direct in Nearby connections SDK. constexpr auto kEnableWifiDirect = flags::Flag(kConfigPackage, "45741157", false); +// When true, Wi-Fi Direct can only operate as a Group Client. +constexpr auto kEnableWifiDirectGcOnly = + flags::Flag(kConfigPackage, "45741158", false); // by default, enable Wi-Fi Hotspot client. constexpr auto kEnableWifiHotspotClient = flags::Flag(kConfigPackage, "45648734", true); diff --git a/connections/implementation/mediums/wifi_direct.cc b/connections/implementation/mediums/wifi_direct.cc index 1d1559a8..f2b0c381 100644 --- a/connections/implementation/mediums/wifi_direct.cc +++ b/connections/implementation/mediums/wifi_direct.cc @@ -14,15 +14,17 @@ #include "connections/implementation/mediums/wifi_direct.h" +#include #include #include #include #include -#include #include "absl/strings/string_view.h" #include "connections/implementation/bwu_handler.h" +#include "connections/implementation/flags/nearby_connections_feature_flags.h" #include "connections/implementation/mediums/wifi_direct_bwu_handler.h" +#include "internal/flags/nearby_flags.h" #include "internal/platform/cancellation_flag.h" #include "internal/platform/expected.h" #include "internal/platform/logging.h" @@ -36,7 +38,12 @@ namespace { using ::location::nearby::proto::connections::OperationResultCode; } // namespace -WifiDirect::WifiDirect() : is_go_started_(false), is_connected_to_go_(false) { +WifiDirect::WifiDirect() + : is_go_started_(false), + is_connected_to_go_(false), + is_gc_only_(NearbyFlags::GetInstance().GetBoolFlag( + config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly)) { supported_wifi_direct_auth_types_ = medium_.GetSupportedWifiDirectAuthTypes(); if (!supported_wifi_direct_auth_types_.empty()) { preferred_wifi_direct_auth_type_ = @@ -63,6 +70,7 @@ bool WifiDirect::IsGOAvailable() const { } bool WifiDirect::IsGOAvailableLocked() const { + if (is_gc_only_) return false; if (medium_.IsValid()) return medium_.IsInterfaceValid(); return false; } @@ -88,6 +96,10 @@ bool WifiDirect::IsGOStarted() { // connect bool WifiDirect::StartWifiDirect() { MutexLock lock(&mutex_); + if (is_gc_only_) { + LOG(INFO) << "Can't start WifiDirect GO in GC-only mode."; + return false; + } if (is_go_started_) { LOG(INFO) << "No need to start GO because it is already started."; return true; diff --git a/connections/implementation/mediums/wifi_direct.h b/connections/implementation/mediums/wifi_direct.h index 1ea6211d..5d9d7603 100644 --- a/connections/implementation/mediums/wifi_direct.h +++ b/connections/implementation/mediums/wifi_direct.h @@ -53,6 +53,8 @@ class WifiDirect { bool IsGOAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); // Returns true, if WifiDirect Group Client is supported by a platform. bool IsGCAvailable() const ABSL_LOCKS_EXCLUDED(mutex_); + // Returns true if this medium is restricted to the Group Client role. + bool IsGCONly() const { return is_gc_only_; } // If WifiDirect Group Owner started bool IsGOStarted() ABSL_LOCKS_EXCLUDED(mutex_); @@ -127,6 +129,7 @@ class WifiDirect { bool is_go_started_ ABSL_GUARDED_BY(mutex_); bool is_connected_to_go_ ABSL_GUARDED_BY(mutex_); + const bool is_gc_only_; WifiDirectMedium medium_ ABSL_GUARDED_BY(mutex_); // A thread pool dedicated to running all the accept loops from diff --git a/connections/implementation/mediums/wifi_direct_test.cc b/connections/implementation/mediums/wifi_direct_test.cc index b121930b..79297ebb 100644 --- a/connections/implementation/mediums/wifi_direct_test.cc +++ b/connections/implementation/mediums/wifi_direct_test.cc @@ -58,6 +58,10 @@ class WifiDirectTest : public testing::TestWithParam { connections::config_package_nearby::nearby_connections_feature:: kEnableWifiDirect, true); + NearbyFlags::GetInstance().OverrideBoolFlagValue( + connections::config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly, + false); env_.Start(); } ~WifiDirectTest() override { env_.Stop(); } @@ -72,6 +76,8 @@ TEST_F(WifiDirectTest, ConstructorDestructorWorks) { WifiDirect wifi_direct_a, wifi_direct_b; EXPECT_NE(&wifi_direct_a, &wifi_direct_b); + EXPECT_FALSE(wifi_direct_a.IsGCONly()); + EXPECT_FALSE(wifi_direct_b.IsGCONly()); EXPECT_TRUE(wifi_direct_a.IsGCAvailable()); EXPECT_TRUE(wifi_direct_b.IsGCAvailable()); } @@ -91,6 +97,22 @@ TEST_F(WifiDirectTest, CanStartStopGO) { } } +TEST_F(WifiDirectTest, GcOnlyCannotStartGO) { + NearbyFlags::GetInstance().OverrideBoolFlagValue( + connections::config_package_nearby::nearby_connections_feature:: + kEnableWifiDirectGcOnly, + true); + WifiDirect wifi_direct; + + EXPECT_TRUE(wifi_direct.IsGCONly()); + EXPECT_TRUE(wifi_direct.IsGCAvailable()); + EXPECT_FALSE(wifi_direct.IsGOAvailable()); + EXPECT_FALSE(wifi_direct.StartWifiDirect()); + EXPECT_FALSE( + wifi_direct.StartAcceptingConnections(std::string(kServiceID), {})); + EXPECT_FALSE(wifi_direct.IsGOStarted()); +} + TEST_F(WifiDirectTest, GCCanConnectDisconnectGO) { WifiDirectCredentials wifi_direct_credentials; std::string device_name(kDeviceName); diff --git a/internal/platform/implementation/linux/BUILD b/internal/platform/implementation/linux/BUILD index ad1b127e..ed598fa7 100644 --- a/internal/platform/implementation/linux/BUILD +++ b/internal/platform/implementation/linux/BUILD @@ -64,6 +64,7 @@ cc_library( "linux_flags.h", #"log_message.h", "utils.h", + "test_data.h" ], copts = ["-lrt"], visibility = ["//third_party/nearby/sharing/internal/impl/linux:__pkg__"], @@ -316,7 +317,7 @@ cc_test( # "http_loader_test.cc", # "preferences_manager_test.cc", # "preferences_repository_test.cc", - # "scheduled_executor_test.cc", + "scheduled_executor_test.cc", # "submittable_executor_test.cc", # "thread_pool_test.cc", "timer_test.cc", diff --git a/internal/platform/implementation/linux/ble_v2_medium.cc b/internal/platform/implementation/linux/ble_v2_medium.cc index 88710c50..ae120b00 100644 --- a/internal/platform/implementation/linux/ble_v2_medium.cc +++ b/internal/platform/implementation/linux/ble_v2_medium.cc @@ -53,35 +53,51 @@ namespace nearby { namespace linux { namespace { -using nearby::connections::config_package_nearby::nearby_connections_feature::kRefactorBleL2cap; +using nearby::connections::config_package_nearby::nearby_connections_feature:: + kRefactorBleL2cap; } // namespace +BleV2Medium::~BleV2Medium() { -BleV2Medium::BleV2Medium(BluetoothAdapter &adapter) - : system_bus_(adapter.GetConnection()), - adapter_(adapter), - observers_(std::make_shared>()), - devices_(std::make_unique( - system_bus_, adapter_.GetObjectPath(), *observers_)), - gatt_discovery_(std::make_shared(system_bus_)), - root_object_manager_(std::make_unique(*system_bus_, sdbus::ObjectPath("/com/google/nearby/medium/ble/advertisement/monitor"))), - adv_monitor_manager_( - bluez::AdvertisementMonitorManager:: - DiscoverAdvertisementMonitorManager(*system_bus_, adapter_)), - adv_manager_(std::make_unique(*system_bus_, - adapter)), - cur_adv_(nullptr) { + LOG(INFO) << __func__ << ": BleV2Medium cleanup "; + try { + StopAdvertising(); + } catch (const std::exception& error) { + LOG(ERROR) << __func__ + << ": Failed to stop advertising: " << + error.what(); + } +} + +BleV2Medium::BleV2Medium(BluetoothAdapter& adapter) + : system_bus_(adapter.GetConnection()), + adapter_(adapter), + observers_(std::make_shared< + ObserverList>()), + devices_(std::make_unique( + system_bus_, adapter_.GetObjectPath(), *observers_)), + gatt_discovery_(std::make_shared(system_bus_)), + root_object_manager_(std::make_unique( + *system_bus_, + sdbus::ObjectPath( + "/com/google/nearby/medium/ble/advertisement/monitor"))), + adv_monitor_manager_( + bluez::AdvertisementMonitorManager:: + DiscoverAdvertisementMonitorManager(*system_bus_, adapter_)), + adv_manager_(std::make_unique(*system_bus_, + adapter)), + cur_adv_(nullptr) { if (!gatt_discovery_->InitializeKnownServices()) { LOG(WARNING) << __func__ << ": Failed to initialize known GATT services cache."; } - if (adv_monitor_manager_) { - LOG(INFO) - << __func__ - << ": Registering path /com/google/nearby/medium/ble/advertisement/monitor with AdvertisementMonitorManager at " - << adv_monitor_manager_->getProxy().getObjectPath(); + LOG(INFO) << __func__ + << ": Registering path " + "/com/google/nearby/medium/ble/advertisement/monitor with " + "AdvertisementMonitorManager at " + << adv_monitor_manager_->getProxy().getObjectPath(); adv_monitor_manager_->SetRegisterMonitorReplyCallback( [this](std::optional error) { OnRegisterMonitorReply(std::move(error)); @@ -126,67 +142,70 @@ bool BleV2Medium::WaitForAdvertisementMonitorManager() { return true; } - LOG(WARNING) << __func__ - << ": AdvertisementMonitorManager registration failed with name '" - << adv_monitor_manager_error_name_ << "' and message '" - << adv_monitor_manager_error_message_ << "'"; + LOG(WARNING) + << __func__ + << ": AdvertisementMonitorManager registration failed with name '" + << adv_monitor_manager_error_name_ << "' and message '" + << adv_monitor_manager_error_message_ << "'"; return false; } - // sync api - // called twice. Once with extended regular advertisement ( when IsExtendedAdvertisementsAvailable() == true ) - // and another for GATT-backed header advertisement for legacy devices - bool BleV2Medium::StartAdvertising( - const api::ble::BleAdvertisementData &advertising_data, +// sync api +// called twice. Once with extended regular advertisement ( when +// IsExtendedAdvertisementsAvailable() == true ) and another for GATT-backed +// header advertisement for legacy devices +bool BleV2Medium::StartAdvertising( + const api::ble::BleAdvertisementData& advertising_data, api::ble::AdvertiseParameters advertise_set_parameters) { - //if (!advertising_data.is_extended_advertisement) - //{ - // // can't send two LE advertisements at the same - // return true; - //} - if (!adapter_.IsEnabled()) { - LOG(WARNING) << "BLE cannot start advertising because the " - "bluetooth adapter is not enabled."; - return false; - } - - if (advertising_data.service_data.empty()) { - LOG(WARNING) - << "BLE cannot start to advertise due to invalid service data."; - return false; - } - - absl::MutexLock l (&advs_mutex_); - advs_.push_front(bluez::LEAdvertisement::CreateLEAdvertisement( - *system_bus_, advertising_data, advertise_set_parameters)); - auto it = advs_.begin(); - - - LOG(INFO) << __func__ << ": Registering advertisement, is_extended: " << advertising_data.is_extended_advertisement - << " " << (*it) -> getObject().getObjectPath() << " on bluetooth adapter " - << adapter_.GetObjectPath(); - - try { - adv_manager_->RegisterAdvertisementSync((*it)->getObject().getObjectPath(), {}); - } catch (const sdbus::Error &e) { - advs_.erase(it); - DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "RegisterAdvertisementSync", e); - return false; - } - - return true; + // if (!advertising_data.is_extended_advertisement) + //{ + // // can't send two LE advertisements at the same + // return true; + // } + if (!adapter_.IsEnabled()) { + LOG(WARNING) << "BLE cannot start advertising because the " + "bluetooth adapter is not enabled."; + return false; } -//async api -// runs with nearby presence + if (advertising_data.service_data.empty()) { + LOG(WARNING) + << "BLE cannot start to advertise due to invalid service data."; + return false; + } + + absl::MutexLock l(&advs_mutex_); + advs_.push_front(bluez::LEAdvertisement::CreateLEAdvertisement( + *system_bus_, advertising_data, advertise_set_parameters)); + auto it = advs_.begin(); + + LOG(INFO) << __func__ << ": Registering advertisement, is_extended: " + << advertising_data.is_extended_advertisement << " " + << (*it)->getObject().getObjectPath() << " on bluetooth adapter " + << adapter_.GetObjectPath(); + + try { + adv_manager_->RegisterAdvertisementSync((*it)->getObject().getObjectPath(), + {}); + } catch (const sdbus::Error& e) { + advs_.erase(it); + DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "RegisterAdvertisementSync", e); + return false; + } + + return true; +} + +// async api +// runs with nearby presence std::unique_ptr BleV2Medium::StartAdvertising( - const api::ble::BleAdvertisementData &advertising_data, - api::ble::AdvertiseParameters advertise_set_parameters, - AdvertisingCallback callback) { + const api::ble::BleAdvertisementData& advertising_data, + api::ble::AdvertiseParameters advertise_set_parameters, + AdvertisingCallback callback) { if (!adapter_.IsEnabled()) { LOG(WARNING) << ": BLE cannot start advertising because the " - "bluetooth adapter is not enabled."; + "bluetooth adapter is not enabled."; return nullptr; } @@ -197,19 +216,20 @@ BleV2Medium::StartAdvertising( } std::shared_ptr shared_cb = - std::make_shared(std::move(callback)); + std::make_shared(std::move(callback)); absl::MutexLock lock(&advs_mutex_); advs_.push_front(bluez::LEAdvertisement::CreateLEAdvertisement( - *system_bus_, advertising_data, advertise_set_parameters)); + *system_bus_, advertising_data, advertise_set_parameters)); auto adv_it = advs_.begin(); // Keep async API surface, but register using the same typed DBus path as the // working sync implementation to avoid signature mismatch (oa{sv} vs sa{sv}). try { - adv_manager_->RegisterAdvertisementSync((*adv_it)->getObject().getObjectPath(), {}); + adv_manager_->RegisterAdvertisementSync( + (*adv_it)->getObject().getObjectPath(), {}); shared_cb->start_advertising_result(absl::OkStatus()); - } catch (const sdbus::Error &e) { + } catch (const sdbus::Error& e) { advs_.erase(adv_it); DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "RegisterAdvertisementSync", e); auto name = e.getName(); @@ -231,44 +251,46 @@ BleV2Medium::StartAdvertising( absl::AnyInvocable stop_adv = [&, adv_it]() { LOG(INFO) << __func__ << ": Unregistering advertisement object " - << (*adv_it)->getObject().getObjectPath(); + << (*adv_it)->getObject().getObjectPath(); absl::MutexLock lock(&advs_mutex_); try { - adv_manager_->UnregisterAdvertisementSync((*adv_it)->getObject().getObjectPath()); - } catch (const sdbus::Error &e) { - DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisementSync", e); + adv_manager_->UnregisterAdvertisementSync( + (*adv_it)->getObject().getObjectPath()); + } catch (const sdbus::Error& e) { + DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisementSync", + e); return absl::UnknownError(e.getMessage()); } advs_.erase(adv_it); return absl::OkStatus(); }; return std::make_unique( - api::ble::BleMedium::AdvertisingSession{std::move(stop_adv)}); + api::ble::BleMedium::AdvertisingSession{std::move(stop_adv)}); } - bool BleV2Medium::StopAdvertising() { - absl::MutexLock l(&advs_mutex_); - try { - for (auto& adv: advs_) - { - adv_manager_->UnregisterAdvertisementSync(adv->getObject().getObjectPath()); - } - } catch (const sdbus::Error &e) { - DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisementSync", e); - return false; +bool BleV2Medium::StopAdvertising() { + LOG(INFO) << __func__ << ": Stop advertising called"; + absl::MutexLock l(&advs_mutex_); + try { + for (auto& adv : advs_) { + adv_manager_->UnregisterAdvertisementSync( + adv->getObject().getObjectPath()); } - - advs_.clear(); - return true; + } catch (const sdbus::Error& e) { + DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisementSync", e); + return false; } -bool BleV2Medium::StartScanning(const Uuid &service_uuid, + advs_.clear(); + return true; +} + +bool BleV2Medium::StartScanning(const Uuid& service_uuid, api::ble::TxPowerLevel tx_power_level, ScanCallback callback) { if (cur_monitored_service_uuid_.has_value()) { - LOG(ERROR) << __func__ - << ": A sync scanning session is already active for " - << std::string{*cur_monitored_service_uuid_}; + LOG(ERROR) << __func__ << ": A sync scanning session is already active for " + << std::string{*cur_monitored_service_uuid_}; return false; } @@ -288,59 +310,58 @@ bool BleV2Medium::StartScanning(const Uuid &service_uuid, absl::MutexLock lock(&active_adv_monitors_mutex_); if (active_adv_monitors_.count(service_uuid) == 1) { LOG(ERROR) << __func__ << ": an advertising session for service " - << std::string{service_uuid} << " already exists"; + << std::string{service_uuid} << " already exists"; return false; } auto monitor = std::make_unique( - *system_bus_, service_uuid, tx_power_level, "or_patterns", devices_, - std::move(callback)); + *system_bus_, service_uuid, tx_power_level, "or_patterns", devices_, + std::move(callback)); try { // why is this emitted? - monitor->emitInterfacesAddedSignal( - {sdbus::InterfaceName(org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); + monitor->emitInterfacesAddedSignal({sdbus::InterfaceName( + org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); - // adv_monitor_manager_ -> RegisterMonitor(monitor -> getObject().getObjectPath()); - LOG(INFO)<< __func__ << ": Registered advertisement monitor with path " << monitor -> getObject().getObjectPath(); - } catch (const sdbus::Error &e) { - LOG(ERROR) - << __func__ - << ": error emitting InterfacesAdded signal for object path " - << monitor->getObject().getObjectPath() << " with name '" << e.getName() - << "' and message '" << e.getMessage() << "'"; + // adv_monitor_manager_ -> RegisterMonitor(monitor -> + // getObject().getObjectPath()); + LOG(INFO) << __func__ << ": Registered advertisement monitor with path " + << monitor->getObject().getObjectPath(); + } catch (const sdbus::Error& e) { + LOG(ERROR) << __func__ + << ": error emitting InterfacesAdded signal for object path " + << monitor->getObject().getObjectPath() << " with name '" + << e.getName() << "' and message '" << e.getMessage() << "'"; return false; } auto device_watcher = std::make_unique( - *system_bus_, adapter_.GetObjectPath(), adapter_, devices_); + *system_bus_, adapter_.GetObjectPath(), adapter_, devices_); if (!StartLEDiscovery()) { - LOG(ERROR) << __func__ - << ": Could not start LE discovery on adapter " - << adapter_.GetObjectPath(); + LOG(ERROR) << __func__ << ": Could not start LE discovery on adapter " + << adapter_.GetObjectPath(); device_watcher = nullptr; try { - monitor->emitInterfacesRemovedSignal( - {sdbus::InterfaceName(org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); - } catch (const sdbus::Error &e) { - LOG(ERROR) - << __func__ - << ": error emitting InterfacesRemoved signal for object path " - << monitor->getObject().getObjectPath() << " with name '" << e.getName() - << "' and message '" << e.getMessage() << "'"; + monitor->emitInterfacesRemovedSignal({sdbus::InterfaceName( + org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); + } catch (const sdbus::Error& e) { + LOG(ERROR) << __func__ + << ": error emitting InterfacesRemoved signal for object path " + << monitor->getObject().getObjectPath() << " with name '" + << e.getName() << "' and message '" << e.getMessage() << "'"; } return false; } - LOG(INFO) << __func__ << " :Started monitoring for service UUID: " << std::string(service_uuid); + LOG(INFO) << __func__ << " :Started monitoring for service UUID: " + << std::string(service_uuid); active_adv_monitors_[service_uuid] = - std::make_pair(std::move(monitor), std::move(device_watcher)); + std::make_pair(std::move(monitor), std::move(device_watcher)); cur_monitored_service_uuid_ = service_uuid; return true; } bool BleV2Medium::StopScanning() { if (!cur_monitored_service_uuid_.has_value()) { - LOG(ERROR) << __func__ - << ": No sync scanning session is currently active."; + LOG(ERROR) << __func__ << ": No sync scanning session is currently active."; return false; } @@ -349,12 +370,13 @@ bool BleV2Medium::StopScanning() { return false; } - auto &adapter = adapter_.GetBluezAdapterObject(); + auto& adapter = adapter_.GetBluezAdapterObject(); LOG(INFO) << __func__ << ": Stopping discovery for adapter " - << adapter.getProxy().getObjectPath(); + << adapter.getProxy().getObjectPath(); try { - adapter.StopDiscovery(); // this will stop bluetooth classic discovery as well. do we want this? - } catch (const sdbus::Error &e) { + adapter.StopDiscovery(); // this will stop bluetooth classic discovery as + // well. do we want this? + } catch (const sdbus::Error& e) { DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e); } @@ -362,120 +384,116 @@ bool BleV2Medium::StopScanning() { auto monitor_it = active_adv_monitors_.find(*cur_monitored_service_uuid_); assert(monitor_it != active_adv_monitors_.end()); { - auto &[_uuid, session] = *monitor_it; - auto &[adv_monitor, _watcher] = session; + auto& [_uuid, session] = *monitor_it; + auto& [adv_monitor, _watcher] = session; LOG(INFO) << __func__ << ": Removing advertising monitor " - << adv_monitor->getObject().getObjectPath(); - adv_monitor->emitInterfacesRemovedSignal( - {sdbus::InterfaceName(org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); + << adv_monitor->getObject().getObjectPath(); + adv_monitor->emitInterfacesRemovedSignal({sdbus::InterfaceName( + org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); } active_adv_monitors_.erase(monitor_it); cur_monitored_service_uuid_ = std::nullopt; return true; } - std::unique_ptr - BleV2Medium::StartScanning(const Uuid &service_uuid, - api::ble::TxPowerLevel tx_power_level, - ScanningCallback callback) { - if (!WaitForAdvertisementMonitorManager()) { - // TODO: Implement manual monitoring. - return nullptr; - } +std::unique_ptr +BleV2Medium::StartScanning(const Uuid& service_uuid, + api::ble::TxPowerLevel tx_power_level, + ScanningCallback callback) { + if (!WaitForAdvertisementMonitorManager()) { + // TODO: Implement manual monitoring. + return nullptr; + } - absl::MutexLock lock(&active_adv_monitors_mutex_); - if (active_adv_monitors_.count(service_uuid) == 1) { - LOG(ERROR) << __func__ << ": Service " << std::string{service_uuid} - << " is already being advertised"; - return nullptr; - } + absl::MutexLock lock(&active_adv_monitors_mutex_); + if (active_adv_monitors_.count(service_uuid) == 1) { + LOG(ERROR) << __func__ << ": Service " << std::string{service_uuid} + << " is already being advertised"; + return nullptr; + } - auto monitor = std::make_unique( + auto monitor = std::make_unique( *system_bus_, service_uuid, tx_power_level, "or_patterns", devices_, std::move(callback)); + try { + monitor->emitInterfacesAddedSignal({sdbus::InterfaceName( + org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); + } catch (const sdbus::Error& e) { + LOG(ERROR) << __func__ + << ": error emitting InterfacesAdded signal for object path " + << monitor->getObject().getObjectPath() << " with name '" + << e.getName() << "' and message '" << e.getMessage() << "'"; + return nullptr; + } + + auto device_watcher = std::make_unique( + *system_bus_, adapter_.GetObjectPath(), adapter_, devices_); + if (!StartLEDiscovery()) { + LOG(ERROR) << __func__ << ": Could not start LE discovery on adapter " + << adapter_.GetObjectPath(); try { - monitor->emitInterfacesAddedSignal( - {sdbus::InterfaceName(org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); - } catch (const sdbus::Error &e) { - LOG(ERROR) - << __func__ - << ": error emitting InterfacesAdded signal for object path " - << monitor->getObject().getObjectPath() << " with name '" << e.getName() - << "' and message '" << e.getMessage() << "'"; - return nullptr; - } - - auto device_watcher = std::make_unique( - *system_bus_, adapter_.GetObjectPath(),adapter_, devices_); - if (!StartLEDiscovery()) { + monitor->emitInterfacesRemovedSignal({sdbus::InterfaceName( + org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); + } catch (const sdbus::Error& e) { LOG(ERROR) << __func__ - << ": Could not start LE discovery on adapter " - << adapter_.GetObjectPath(); - try { - monitor->emitInterfacesRemovedSignal( - {sdbus::InterfaceName(org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); - } catch (const sdbus::Error &e) { - LOG(ERROR) - << __func__ - << ": error emitting InterfacesRemoved signal for object path " - << monitor->getObject().getObjectPath() << " with name '" << e.getName() - << "' and message '" << e.getMessage() << "'"; - } - return nullptr; + << ": error emitting InterfacesRemoved signal for object path " + << monitor->getObject().getObjectPath() << " with name '" + << e.getName() << "' and message '" << e.getMessage() << "'"; } + return nullptr; + } - active_adv_monitors_[service_uuid] = + active_adv_monitors_[service_uuid] = std::make_pair(std::move(monitor), std::move(device_watcher)); - return std::make_unique( + return std::make_unique( ScanningSession{.stop_scanning = [this, service_uuid]() { absl::MutexLock lock(&active_adv_monitors_mutex_); if (active_adv_monitors_.count(service_uuid) == 0) { - LOG(ERROR) - << __func__ << ": Advertising monitor for service " - << std::string{service_uuid} << " does not exist anymore"; + LOG(ERROR) << __func__ << ": Advertising monitor for service " + << std::string{service_uuid} << " does not exist anymore"; return absl::NotFoundError( - "Advertising monitor for this service does not exist"); + "Advertising monitor for this service does not exist"); } - auto &[monitor, watcher] = active_adv_monitors_[service_uuid]; + auto& [monitor, watcher] = active_adv_monitors_[service_uuid]; try { - monitor->emitInterfacesRemovedSignal( - {sdbus::InterfaceName(org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); - } catch (const sdbus::Error &e) { + monitor->emitInterfacesRemovedSignal({sdbus::InterfaceName( + org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME)}); + } catch (const sdbus::Error& e) { LOG(ERROR) << __func__ << ": error emitting InterfacesRemoved signal for object path " - << monitor->getObject().getObjectPath() << " with name '" << e.getName() - << "' and message '" << e.getMessage() << "'"; + << monitor->getObject().getObjectPath() << " with name '" + << e.getName() << "' and message '" << e.getMessage() << "'"; } - auto &adapter = adapter_.GetBluezAdapterObject(); + auto& adapter = adapter_.GetBluezAdapterObject(); absl::Status status; try { adapter.StopDiscovery(); status = absl::OkStatus(); - } catch (const sdbus::Error &e) { + } catch (const sdbus::Error& e) { DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e); status = absl::InternalError(e.getMessage()); } active_adv_monitors_.erase(service_uuid); return status; }}); - } +} std::unique_ptr BleV2Medium::StartGattServer( - api::ble::ServerGattConnectionCallback callback) { + api::ble::ServerGattConnectionCallback callback) { LOG(INFO) << __func__ << ": Starting Linux GATT server."; return std::make_unique(*system_bus_, adapter_, devices_, std::move(callback)); } std::unique_ptr BleV2Medium::ConnectToGattServer( - api::ble::BlePeripheral::UniqueId peripheral_id, - api::ble::TxPowerLevel tx_power_level, - api::ble::ClientGattConnectionCallback callback) { + api::ble::BlePeripheral::UniqueId peripheral_id, + api::ble::TxPowerLevel tx_power_level, + api::ble::ClientGattConnectionCallback callback) { auto device = devices_->get_device_by_unique_id(peripheral_id); if (!device) { LOG(ERROR) << __func__ << ": Failed to find device with unique ID " @@ -495,29 +513,29 @@ std::unique_ptr BleV2Medium::ConnectToGattServer( } std::unique_ptr BleV2Medium::OpenServerSocket( - const std::string &service_id) { + const std::string& service_id) { LOG(INFO) << __func__ << ": Opening BLE server socket for service " << service_id; return std::make_unique(service_id); } std::unique_ptr -BleV2Medium::OpenL2capServerSocket(const std::string &service_id) { +BleV2Medium::OpenL2capServerSocket(const std::string& service_id) { // return nullptr; LOG(INFO) << __func__ << ": Opening L2CAP server socket for service " << service_id; - auto server_socket = std::make_unique( - psm_, service_id); + auto server_socket = + std::make_unique(psm_, service_id); return server_socket; } // This is supposed to be for a socket on top of Weave protocol. std::unique_ptr BleV2Medium::Connect( - const std::string &service_id, api::ble::TxPowerLevel tx_power_level, - api::ble::BlePeripheral::UniqueId peripheral_id, - CancellationFlag *cancellation_flag) { + const std::string& service_id, api::ble::TxPowerLevel tx_power_level, + api::ble::BlePeripheral::UniqueId peripheral_id, + CancellationFlag* cancellation_flag) { LOG(INFO) << __func__ << ": Not implemented on linux "; return nullptr; } @@ -526,7 +544,7 @@ bool BleV2Medium::IsExtendedAdvertisementsAvailable() { try { auto supported_channels = adv_manager_->SupportedSecondaryChannels(); return !supported_channels.empty(); - } catch (const sdbus::Error &e) { + } catch (const sdbus::Error& e) { DBUS_LOG_PROPERTY_GET_ERROR(adv_manager_, "SupportedSecondaryChannels", e); return false; } @@ -536,20 +554,20 @@ bool BleV2Medium::StartLEDiscovery() { std::map filter; filter["Transport"] = sdbus::Variant("auto"); filter["DuplicateData"] = sdbus::Variant(true); - auto &adapter = adapter_.GetBluezAdapterObject(); + auto& adapter = adapter_.GetBluezAdapterObject(); try { adapter.SetDiscoveryFilter(filter); - } catch (const sdbus::Error &e) { + } catch (const sdbus::Error& e) { DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e); return false; } try { LOG(INFO) << __func__ << ": Starting LE discovery on " - << adapter.getProxy().getObjectPath(); + << adapter.getProxy().getObjectPath(); adapter.StartDiscovery(); - } catch (const sdbus::Error &e) { + } catch (const sdbus::Error& e) { if (e.getName() != "org.bluez.Error.InProgress") { DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e); return false; @@ -563,15 +581,15 @@ bool BleV2Medium::StartLEDiscovery() { // const std::string &service_id, api::ble::TxPowerLevel tx_power_level, // api::ble::BlePeripheral &peripheral, // CancellationFlag *cancellation_flag) { -// LOG(WARNING) << __func__ << ": BLE socket connections not implemented on Linux"; -// return nullptr; +// LOG(WARNING) << __func__ << ": BLE socket connections not implemented on +// Linux"; return nullptr; // } std::unique_ptr BleV2Medium::ConnectOverL2cap( - int psm, const std::string &service_id, + int psm, const std::string& service_id, api::ble::TxPowerLevel tx_power_level, api::ble::BlePeripheral::UniqueId peripheral_id, - CancellationFlag *cancellation_flag) { + CancellationFlag* cancellation_flag) { // return nullptr; auto device = devices_->get_device_by_unique_id(peripheral_id); if (!device) { @@ -580,40 +598,39 @@ std::unique_ptr BleV2Medium::ConnectOverL2cap( return nullptr; } - LOG(INFO) << __func__ << ": Connecting to L2CAP PSM " << psm - << " on device " << device->GetMacAddress().ToString(); - + LOG(INFO) << __func__ << ": Connecting to L2CAP PSM " << psm << " on device " + << device->GetMacAddress().ToString(); int fd = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (fd < 0) { - LOG(ERROR) << __func__ << ": Failed to create L2CAP socket: " - << std::strerror(errno); + LOG(ERROR) << __func__ + << ": Failed to create L2CAP socket: " << std::strerror(errno); return nullptr; } // Set receive MTU before connect (for LE CoC) - struct sockaddr_l2 addr; std::memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = htobs(psm); - if (device -> GetAddressType() == "random") { + if (device->GetAddressType() == "random") { addr.l2_bdaddr_type = BDADDR_LE_RANDOM; - }else { + } else { addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; } - if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { LOG(INFO) << "Failed to bind L2CAP socket"; } struct l2cap_options opts; opts.omtu = 0; opts.imtu = 672; - if (setsockopt(fd, SOL_BLUETOOTH, BT_RCVMTU, &opts.imtu, sizeof(opts.imtu)) < 0) { - LOG(WARNING) << __func__ << ": Failed to set BT_RCVMTU: " - << std::strerror(errno); + if (setsockopt(fd, SOL_BLUETOOTH, BT_RCVMTU, &opts.imtu, sizeof(opts.imtu)) < + 0) { + LOG(WARNING) << __func__ + << ": Failed to set BT_RCVMTU: " << std::strerror(errno); } std::string mac_addr = device->GetMacAddress().ToString(); if (str2ba(mac_addr.c_str(), &addr.l2_bdaddr) < 0) { @@ -630,13 +647,12 @@ std::unique_ptr BleV2Medium::ConnectOverL2cap( } LOG(INFO) << __func__ << ": Successfully connected to L2CAP socket"; - auto socket = std::make_unique( - fd, peripheral_id, service_id); + auto socket = std::make_unique(fd, peripheral_id, service_id); return socket; } bool BleV2Medium::StartMultipleServicesScanning( - const std::vector &service_uuids, + const std::vector& service_uuids, api::ble::TxPowerLevel tx_power_level, ScanCallback callback) { LOG(WARNING) << __func__ << ": Multiple services scanning not implemented on Linux. " @@ -645,24 +661,27 @@ bool BleV2Medium::StartMultipleServicesScanning( } bool BleV2Medium::PauseMediumScanning() { - LOG(INFO) << __func__ << ": Pause scanning not implemented, returning success"; + LOG(INFO) << __func__ + << ": Pause scanning not implemented, returning success"; return true; } bool BleV2Medium::ResumeMediumScanning() { - LOG(INFO) << __func__ << ": Resume scanning not implemented, returning success"; + LOG(INFO) << __func__ + << ": Resume scanning not implemented, returning success"; return true; } void BleV2Medium::AddAlternateUuidForService(uint16_t uuid, - const std::string &service_id) { - LOG(INFO) << __func__ << ": Alternate UUID mapping not implemented. UUID: " - << uuid << ", service_id: " << service_id; + const std::string& service_id) { + LOG(INFO) << __func__ + << ": Alternate UUID mapping not implemented. UUID: " << uuid + << ", service_id: " << service_id; } std::optional BleV2Medium::RetrieveBlePeripheralIdFromNativeId( - const std::string &ble_peripheral_native_id) { + const std::string& ble_peripheral_native_id) { LOG(WARNING) << __func__ << ": Retrieval from native ID not implemented. Native ID: " << ble_peripheral_native_id; diff --git a/internal/platform/implementation/linux/ble_v2_medium.h b/internal/platform/implementation/linux/ble_v2_medium.h index 686013ee..b58f3398 100644 --- a/internal/platform/implementation/linux/ble_v2_medium.h +++ b/internal/platform/implementation/linux/ble_v2_medium.h @@ -50,7 +50,7 @@ class BleV2Medium final : public api::ble::BleMedium { BleV2Medium &operator=(BleV2Medium &&) = delete; explicit BleV2Medium(BluetoothAdapter &adapter); - ~BleV2Medium() override = default; + ~BleV2Medium() override; bool StartAdvertising( const api::ble::BleAdvertisementData &advertising_data, diff --git a/internal/platform/implementation/linux/bluez_le_advertisement.h b/internal/platform/implementation/linux/bluez_le_advertisement.h index 9d66afc8..32330090 100644 --- a/internal/platform/implementation/linux/bluez_le_advertisement.h +++ b/internal/platform/implementation/linux/bluez_le_advertisement.h @@ -16,6 +16,7 @@ #define PLATFORM_IMPL_LINUX_API_BLUEZ_BLE_ADVERTISEMENT_H_ #include +#include #include #include #include @@ -54,7 +55,9 @@ class LEAdvertisement final return std::make_unique( system_bus, object_path, advertising_data, advertising_parameters); } - ~LEAdvertisement() { unregisterAdaptor(); } + ~LEAdvertisement() { + LOG(INFO) << __func__ << "Unregistering advertisement adaptor"; + unregisterAdaptor(); } private: // Methods