From: Pawel Wasowski Date: Thu, 27 Feb 2020 10:47:47 +0000 (+0100) Subject: [Bluetooth][ACR: TWDAPI-256] Sanitize UUIDs in BLE APIs X-Git-Tag: submit/tizen/20200708.105445~7^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=58d2b5093ee2ba1beaeab4a5f5a759a61f33abcd;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Bluetooth][ACR: TWDAPI-256] Sanitize UUIDs in BLE APIs The ACR defines ways, in which Bluetooth APIs will handle UUIDs passed as arguments and returned from functions and adds clarifications about converisons of UUIDs passed to the Web API, that are made before advertising. It also adds tizen.bluetooth.BASE_UUID constant. APIs modified in this commit: BluetoothLEDevice::getService(): - now it accepts UUIDs in any of the 3 formats defined in BluetoothUUID BluetoothLEDevice::getServiceAllUuids(): - a bugfix and slight change of behavior: In the past, this function has always trimmed UUIDs retrieved from native API to 16 bit format. In case of UUIDs not built with Bluetooth's BASE_UUID the conversions were erroneous, for example: "198d3a9c-e21a-4f72-a48b-39a6bad7e583" was converted to "3a9c" which (almost surely) did not correspond to any service on the device. The function now returns UUIDs in their shortest formats. BluetoothLEAdvertiseData::uuids and BluetoothLEAdvertiseData::solicitationuuids: - now they accept UUIDs in any of the 3 formats defined in BluetoothUUID BluetoothLEAdvertiseData::serviceData: - it accepts UUIDs in any of the 3 formats defined in BluetoothUUID Verification: tct-bluetooth-tizen-tests pass rate: Auto: 100% (BLE suite) Manual: 10/11 tests passed. The fail is due to a bug in TCT tests Manual tests in Chrome DevTools: tizen.bluetooth.BASE_UUID exists and its value is correct BluetoothLEAdapter::startAdvertise: BluetoothLEAdvertiseData::uuids: 16 bit: advertised as 16 bit (OK) 32 bit: advertised as 32 bit Random 128 bit: advertised as 128 bit (OK) 16 bit as 128 bit: advertised as 16 bit (OK) 32 bit as 128 bit: advertised as 32 bit BluetoothLEAdvertiseData::solicitationuuids: 16 bit: advertised as 16 bit (OK) 32 bit: advertised as 32 bit Random 128 bit: advertised as 128 bit (OK) 16 bit as 128 bit: advertised as 16 bit (OK) 32 bit as 128 bit: advertised as 32 bit BluetoothLEAdvertiseData::BluetoothLEServiceData::uuid: 16 bit: advertised as 16 bit (OK) 32 bit: InvalidValuesErrror, Invalid parameter (OK) Random 128 bit: InvalidValuesErrror: Invalid parameter (OK) 16 bit as 128 bit: advertised as 16 bit (OK) 32 bit as 128 bit: InvalidValuesErrror: Invalid parameter (OK) BluetoothLEAdapter::startScan() and BluetoothLEScanCallback(): BluetoothLEDevice::uuids: 16 bit: found as 16 bit (OK) 32 bit: not found at all (OK - native API does not support detecting 32 bit UUIDs at all) Random 128 bit: found as 128 bit (OK) 16 bit as 128 bit: found as 128 bit (OK) 32 bit as 128 bit: found as 128 bit (OK) BluetoothLEDevice::solicitationuuids: 16 bit: found as 16 bit (OK) 32 bit: not found at all (OK - native API does not support detecting 32 bit UUIDs at all) Random 128 bit: found as 128 bit (OK) 16 bit as 128 bit: found as 128 bit (OK) 32 bit as 128 bit: found as 128 bit (OK) BluetoothLEDevice::BluetoothLEServiceData::uuid: 16 bit: found as 16 bit (OK) 32 bit: not found at all (probably OK - native API supports only 128 bit UUIDs) Random 128 bit: not found at all (native support for 128 bit UUIDs will be introduced in Tizen 6.0) 16 bit as 128 bit: not found at all (native support for 128 bit UUIDs will be introduced in Tizen 6.0) 32 bit as 128 bit: not found at all (native support for 128 bit UUIDs will be introduced in Tizen 6.0) BluetoothLEDevice::getServiceAllUuids(): 16 bit: found as 16 bit (OK) 32 bit: According to the Bluetooth Core Specification (Version 5.2, Vol 3, Part G, chapter 3.1 "Service Definition"), GATT servers can only provide 16 and 128 bit services, so a 32 bit service UUID could not be created. Random 128 bit: found as 128 bit (OK) 16 bit as 128 bit: found as 16 bit (OK) 32 bit as 128 bit: found as 32 bit (OK) BluetoothLEDevice::getService(): TEST 1 - passing UUID as a parameter: 16 bit to retrieve 16 bit service: OK 16 bit to retrieve 128 bit built with BASE_UUID service: OK 128 bit to retrieve 128 bit built with BASE_UUID service: OK Random 128 bit: OK BluetoothLEDevice::getService(): TEST 2 - the value of BluetoothGATTService::uuid: The same as passed to the getService() for all cases. BluetoothLEDevice::getService(): TEST 3 - values of BluetoothGATTService::uuid in the service objects from services included in a service I was unable to test this functionality. I have tried to create a GATT service incluing secondary services, but was unable to do that neither using a BLE adapter and bluetoothctl command on my PC, nor the Android app I use for tests. Change-Id: Ic0b75867cb4be3e2fb3fa9ea046b515503363edb Signed-off-by: Pawel Wasowski --- diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js index ea34b94e..e347f03b 100755 --- a/src/bluetooth/bluetooth_api.js +++ b/src/bluetooth/bluetooth_api.js @@ -2724,6 +2724,11 @@ var BluetoothManager = function() { value: new BluetoothClassDeviceService(), writable: false, enumerable: true + }, + BASE_UUID: { + value: '00000000-0000-1000-8000-00805F9B34FB', + writable: false, + enumerable: true } }); }; diff --git a/src/bluetooth/bluetooth_gatt_service.cc b/src/bluetooth/bluetooth_gatt_service.cc index d7c0222c..07a73305 100644 --- a/src/bluetooth/bluetooth_gatt_service.cc +++ b/src/bluetooth/bluetooth_gatt_service.cc @@ -117,7 +117,7 @@ void BluetoothGATTService::TryDestroyClient(const std::string& address) { } PlatformResult BluetoothGATTService::GetSpecifiedGATTService(const std::string& address, - const std::string& uuid, + const UUID& uuid, picojson::object* result) { ScopeLogger(); @@ -128,7 +128,7 @@ PlatformResult BluetoothGATTService::GetSpecifiedGATTService(const std::string& } bt_gatt_h service = nullptr; - int ret = bt_gatt_client_get_service(client, uuid.c_str(), &service); + int ret = bt_gatt_client_get_service(client, uuid.uuid_128_bit.c_str(), &service); if (BT_ERROR_NONE != ret) { LoggerE("bt_gatt_client_get_service() error: %d", ret); switch (ret) { @@ -149,8 +149,13 @@ PlatformResult BluetoothGATTService::GetSpecifiedGATTService(const std::string& } } - // report BluetoothGattService - result->insert(std::make_pair(kUuid, picojson::value(uuid))); + /* + * BACKWARD COMPATIBILITY + * + * BluetoothGATTService::uuid has always been set to source format in this + * function. + */ + result->insert(std::make_pair(kUuid, picojson::value(uuid.uuid_in_source_format))); // handle is passed to upper layer because there is no need to delete it result->insert(std::make_pair(kHandle, picojson::value((double)(long)service))); // address is necessary to later check if device is still connected @@ -189,20 +194,23 @@ PlatformResult BluetoothGATTService::GetServicesHelper(bt_gatt_h handle, const s "Entered into asynchronous function, argument in " "bt_gatt_service_foreach_included_services"); - picojson::value result = picojson::value(picojson::object()); + picojson::value result = picojson::value{picojson::object{}}; picojson::object& result_obj = result.get(); - char* uuid = nullptr; - - if (BT_ERROR_NONE == bt_gatt_get_uuid(gatt_handle, &uuid) && nullptr != uuid) { - result_obj.insert(std::make_pair(kUuid, picojson::value(uuid))); - free(uuid); + const auto uuid = UUID::createFromGatt(gatt_handle); + if (uuid) { + /* + * BACKWARD COMPATIBILITY + * + * UUID has always been set to source format in this function. + */ + result_obj.insert(std::make_pair(kUuid, picojson::value{uuid->uuid_in_source_format})); } else { - result_obj.insert(std::make_pair(kUuid, picojson::value("FFFF"))); + result_obj.insert(std::make_pair(kUuid, picojson::value{})); } // handle is passed to upper layer because there is no need of deletion - result_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)gatt_handle))); + result_obj.insert(std::make_pair(kHandle, picojson::value{(double)(long)gatt_handle})); static_cast(data)->push_back(result); return true; }, @@ -545,18 +553,23 @@ common::PlatformResult BluetoothGATTService::GetServiceAllUuids(const std::strin ScopeLogger("Entered into asynchronous function, foreach_callback, total: %d, index: %d", total, index); - char* uuid = nullptr; - int ret = bt_gatt_get_uuid(gatt_handle, &uuid); - - if (BT_ERROR_NONE != ret || nullptr == uuid) { - LoggerE("Failed to get UUID: %d", ret); + auto& uuids = *static_cast(user_data); + auto uuid = UUID::createFromGatt(gatt_handle); + if (uuid) { + /* + * BACKWARD COMPATIBILITY + * + * In the past, this function has always trimmed UUIDs retrieved + * from native API to 16 bit format. UUIDs that were not created + * from 16 bit UUID and BASE_UUID were converted to invalid values. + * + * We return UUIDs in shortest possible format to comply with past + * behaviour when possible. If the UUID is not convertible + * to 16 bit UUID, we return a longer form. + */ + uuids.push_back(picojson::value{uuid->ShortestPossibleFormat()}); } else { - std::string u = std::string(uuid); - free(uuid); - if (u.length() > 4) { // 128-bit UUID, needs to be converted to 16-bit - u = u.substr(4, 4); - } - static_cast(user_data)->push_back(picojson::value(u)); + LoggerE("Couldn't get UUID from bt_gatt_h"); } return true; diff --git a/src/bluetooth/bluetooth_gatt_service.h b/src/bluetooth/bluetooth_gatt_service.h index db2ab482..40ca9652 100644 --- a/src/bluetooth/bluetooth_gatt_service.h +++ b/src/bluetooth/bluetooth_gatt_service.h @@ -21,6 +21,7 @@ #include +#include "bluetooth/uuid.h" #include "common/picojson.h" #include "common/platform_result.h" @@ -34,8 +35,8 @@ class BluetoothGATTService { BluetoothGATTService(BluetoothInstance& instance); ~BluetoothGATTService(); - common::PlatformResult GetSpecifiedGATTService(const std::string& address, - const std::string& uuid, picojson::object* result); + common::PlatformResult GetSpecifiedGATTService(const std::string& address, const UUID& uuid, + picojson::object* result); void TryDestroyClient(const std::string& address); void GetServices(const picojson::value& data, picojson::object& out); diff --git a/src/bluetooth/bluetooth_le_adapter.cc b/src/bluetooth/bluetooth_le_adapter.cc index b2f0be32..2a0fcd67 100644 --- a/src/bluetooth/bluetooth_le_adapter.cc +++ b/src/bluetooth/bluetooth_le_adapter.cc @@ -23,12 +23,19 @@ #include "bluetooth/bluetooth_le_device.h" #include "bluetooth/bluetooth_privilege.h" #include "bluetooth/bluetooth_util.h" +using common::optional; namespace extension { namespace bluetooth { namespace { +const std::string kData = "data"; +const std::string kUuid = "uuid"; +const std::string kUuids = "uuids"; +const std::string kSolicitationUuids = "solicitationuuids"; +const std::string kServiceData = "serviceData"; + class ParsedDataHolder { public: ParsedDataHolder() : valid_(false) { @@ -84,7 +91,7 @@ class HexData { class BluetoothLEServiceData : public ParsedDataHolder { public: - const std::string& uuid() const { + const UUID& uuid() const { return uuid_; } @@ -92,42 +99,34 @@ class BluetoothLEServiceData : public ParsedDataHolder { return data_; } - static bool Construct(const picojson::value& obj, BluetoothLEServiceData* out) { - if (!obj.is() || !ParseUUID(obj, out) || !ParseData(obj, out)) { - return false; + static optional Construct(const picojson::value& service_data_obj) { + ScopeLogger(); + + const auto& data = service_data_obj.get(kData); + const auto& uuid_str = service_data_obj.get(kUuid); + if (!data.is() || !uuid_str.is()) { + LoggerE("Invalid data type in service data"); + return {}; } - out->set_valid(); + auto uuid = UUID::create(uuid_str.get()); + if (!uuid) { + return {}; + } - return true; + return BluetoothLEServiceData{std::move(*uuid), data.get()}; } private: - static bool ParseUUID(const picojson::value& obj, BluetoothLEServiceData* out) { - ScopeLogger(); - const auto& uuid = obj.get("uuid"); - if (uuid.is()) { - out->uuid_ = uuid.get(); - } else { - return false; - } + BluetoothLEServiceData(UUID&& uuid, const std::string& data_str) : uuid_{std::move(uuid)} { + ScopeLogger("UUID: %s, data_str: %s", uuid.uuid_128_bit.c_str(), data_str.c_str()); - return true; - } - - static bool ParseData(const picojson::value& obj, BluetoothLEServiceData* out) { - ScopeLogger(); - const auto& data = obj.get("data"); - if (data.is()) { - out->data_.Parse(data.get()); - } else { - return false; - } + data_.Parse(data_str); - return true; + set_valid(); } - std::string uuid_; + const UUID uuid_; HexData data_; }; @@ -196,11 +195,11 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder { return include_name_; } - const std::vector& service_uuids() const { + const std::vector& service_uuids() const { return service_uuids_; } - const std::vector& solicitation_uuids() const { + const std::vector& solicitation_uuids() const { return solicitation_uuids_; } @@ -212,7 +211,7 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder { return include_tx_power_level_; } - const BluetoothLEServiceData& service_data() const { + const std::vector& service_data() const { return service_data_; } @@ -249,16 +248,23 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder { static bool ParseServiceUUIDs(const picojson::value& obj, BluetoothLEAdvertiseData* out) { ScopeLogger(); - const auto& service_uuids = obj.get("uuids"); + const auto& service_uuids = obj.get(kUuids); if (service_uuids.is()) { - for (const auto& i : service_uuids.get()) { - if (i.is()) { - out->service_uuids_.push_back(i.get()); + for (const auto& uuid : service_uuids.get()) { + if (!uuid.is()) { + LoggerE("uuid is not a string"); + return false; + } + + auto uuid_obj = UUID::create(uuid.get()); + if (uuid_obj) { + out->service_uuids_.push_back(*uuid_obj); } else { return false; } } } else if (!service_uuids.is()) { + LoggerE("Invalid service_uuids type"); return false; } @@ -267,11 +273,17 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder { static bool ParseSolicitationUUIDs(const picojson::value& obj, BluetoothLEAdvertiseData* out) { ScopeLogger(); - const auto& solicitation_uuids = obj.get("solicitationuuids"); + const auto& solicitation_uuids = obj.get(kSolicitationUuids); if (solicitation_uuids.is()) { - for (const auto& i : solicitation_uuids.get()) { - if (i.is()) { - out->solicitation_uuids_.push_back(i.get()); + for (const auto& uuid : solicitation_uuids.get()) { + if (!uuid.is()) { + LoggerE("uuid is not a string"); + return false; + } + + auto uuid_obj = UUID::create(uuid.get()); + if (uuid_obj) { + out->solicitation_uuids_.push_back(*uuid_obj); } else { return false; } @@ -309,14 +321,27 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder { static bool ParseServiceData(const picojson::value& obj, BluetoothLEAdvertiseData* out) { ScopeLogger(); - const auto& service_data = obj.get("serviceData"); - BluetoothLEServiceData data; - if (BluetoothLEServiceData::Construct(service_data, &data)) { - out->service_data_ = std::move(data); - } else if (!service_data.is()) { + + const auto& service_data_obj = obj.get(kServiceData); + if (service_data_obj.is()) { + return true; + } else if (!service_data_obj.is()) { return false; } + /* + * Currently, only advertising of a single service data object is supported + * by the Web API. In the future, support for advertising arrays of those + * may be added. + * + * TODO: if supported, parse here the whole array of service data instances. + */ + auto service_data = BluetoothLEServiceData::Construct(service_data_obj); + if (!service_data) { + return false; + } + + out->service_data_.emplace_back(std::move(*service_data)); return true; } @@ -334,11 +359,11 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder { } bool include_name_; - std::vector service_uuids_; - std::vector solicitation_uuids_; + std::vector service_uuids_; + std::vector solicitation_uuids_; int appearance_; bool include_tx_power_level_; - BluetoothLEServiceData service_data_; + std::vector service_data_; BluetoothLEManufacturerData manufacturer_data_; }; @@ -349,9 +374,7 @@ bool ToBool(bt_adapter_le_state_e state) { } // constants - const std::string kAction = "action"; -const std::string kData = "data"; // scan-related const std::string kOnScanSuccess = "onsuccess"; const std::string kOnScanError = "onerror"; @@ -529,8 +552,21 @@ void BluetoothLEAdapter::StartAdvertise(const picojson::value& data, picojson::o } } - for (const auto& i : advertise_data.service_uuids()) { - ret = bt_adapter_le_add_advertising_service_uuid(advertiser, packet_type, i.c_str()); + for (const auto& uuid : advertise_data.service_uuids()) { + /* + * This native function accepts 16 or 128 bit UUIDs. + * To handle also 32 bit UUIDs, we pass all UUIDs in their canonical form. + * + * Note: + * The documentation of Native Bluetooth API says, this function advertises 128-bit UUIDs, + * that have 32-bit equivalents in the full 128-bit form. + * However, as of the day of writing this comment, packets advertised + * by the device contain these UUIDs in their 32-bit formats, + * i.e. AD fields with 0x04 («Incomplete List of 32-bit Service Class UUIDs») type. + * For example, "12345678-0000-1000-8000-00805F9B34FB" is advertised as "12345678". + */ + ret = bt_adapter_le_add_advertising_service_uuid(advertiser, packet_type, + uuid.uuid_128_bit.c_str()); if (BT_ERROR_NONE != ret) { LogAndReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out, ("bt_adapter_le_add_advertising_service_uuid() failed with: %d (%s)", ret, @@ -539,9 +575,21 @@ void BluetoothLEAdapter::StartAdvertise(const picojson::value& data, picojson::o } } - for (const auto& i : advertise_data.solicitation_uuids()) { - ret = - bt_adapter_le_add_advertising_service_solicitation_uuid(advertiser, packet_type, i.c_str()); + for (const auto& uuid : advertise_data.solicitation_uuids()) { + /* + * This native function accepts 16 or 128 bit UUIDs. + * To handle also 32 bit UUIDs, we pass all UUIDs in their canonical form. + * + * Note: + * The documentation of Native Bluetooth API says, it advertises 128-bit UUIDs, + * that have 32-bit equivalents in the full 128-bit form. + * However, as of the day of writing this comment, packets advertised + * by the device contain these UUIDs in their 32-bit formats, + * i.e. AD fields with 0x1F («List of 32-bit Service Solicitation UUIDs») type. + * For example, "12345678-0000-1000-8000-00805F9B34FB" is advertised as "12345678". + */ + ret = bt_adapter_le_add_advertising_service_solicitation_uuid(advertiser, packet_type, + uuid.uuid_128_bit.c_str()); if (BT_ERROR_NONE != ret) { LogAndReportError( util::GetBluetoothError(ret, "Failed to create advertiser"), &out, @@ -571,18 +619,26 @@ void BluetoothLEAdapter::StartAdvertise(const picojson::value& data, picojson::o } } - const auto& service_data = advertise_data.service_data(); - if (service_data.uuid().empty() && nullptr == service_data.data().pointer()) { + if (advertise_data.service_data().empty()) { LoggerD("service data is empty"); } else { - ret = bt_adapter_le_add_advertising_service_data( - advertiser, packet_type, service_data.uuid().c_str(), service_data.data().pointer(), - service_data.data().length()); - if (BT_ERROR_NONE != ret) { - LogAndReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out, - ("bt_adapter_le_add_advertising_service_data() failed with: %d (%s)", ret, - get_error_message(ret))); - return; + for (const auto& service_data_obj : advertise_data.service_data()) { + ret = bt_adapter_le_add_advertising_service_data( + advertiser, packet_type, service_data_obj.uuid().ShortestPossibleFormat().c_str(), + service_data_obj.data().pointer(), service_data_obj.data().length()); + if (BT_ERROR_NONE != ret) { + std::string error_message = "Failed to create advertiser"; + if (BT_ERROR_QUOTA_EXCEEDED == ret && !service_data_obj.uuid().To16Bit()) { + error_message = + "Failed to start advertising: only 16 bit values of BluetoothLEServiceData::uuid are " + "supported"; + } + + LogAndReportError(util::GetBluetoothError(ret, error_message), &out, + ("bt_adapter_le_add_advertising_service_data() failed with: %d (%s)", ret, + get_error_message(ret))); + return; + } } } @@ -701,12 +757,12 @@ void BluetoothLEAdapter::OnScanResult(int result, bt_adapter_le_device_scan_resu // device found LoggerD("Device found"); picojson::value data{picojson::object{}}; - const auto& r = BluetoothLEDevice::ToJson(info, &data.get()); - if (r) { + const auto& ret = BluetoothLEDevice::ToJson(info, &data.get()); + if (ret) { data_obj->insert(std::make_pair(kAction, picojson::value(kOnScanSuccess))); data_obj->insert(std::make_pair(kData, data)); } else { - LogAndReportError(r, data_obj, ("Failed to parse Bluetooth LE device")); + LogAndReportError(ret, data_obj, ("Failed to parse Bluetooth LE device")); data_obj->insert(std::make_pair(kAction, picojson::value(kOnScanError))); } } diff --git a/src/bluetooth/bluetooth_le_adapter.h b/src/bluetooth/bluetooth_le_adapter.h index ed303cc7..b26fffdc 100644 --- a/src/bluetooth/bluetooth_le_adapter.h +++ b/src/bluetooth/bluetooth_le_adapter.h @@ -19,6 +19,7 @@ #include #include +#include "bluetooth/uuid.h" #include "common/picojson.h" namespace extension { diff --git a/src/bluetooth/bluetooth_le_device.cc b/src/bluetooth/bluetooth_le_device.cc index f680cc1b..413a3059 100644 --- a/src/bluetooth/bluetooth_le_device.cc +++ b/src/bluetooth/bluetooth_le_device.cc @@ -72,16 +72,21 @@ BluetoothLEDevice::~BluetoothLEDevice() { } } -static void UUIDsToJson(char** service_uuid, int service_count, const std::string& field, +static void UUIDsToJson(char** uuids, int uuids_count, const std::string& field, picojson::object* le_device) { - ScopeLogger(); + ScopeLogger("uuids_count: %d, field: %s", uuids_count, field.c_str()); picojson::array& array = le_device->insert(std::make_pair(field, picojson::value(picojson::array()))) .first->second.get(); - for (int i = 0; i < service_count; i++) { - array.push_back(picojson::value(service_uuid[i])); + for (int i = 0; i < uuids_count; i++) { + auto uuid = UUID::create(uuids[i]); + if (!uuid) { + LoggerE("Invalid UUID format: (%s)", uuids[i]); + } else { + array.push_back(picojson::value{uuid->uuid_in_source_format}); + } } } @@ -369,7 +374,13 @@ void BluetoothLEDevice::GetService(const picojson::value& data, picojson::object const auto& args = util::GetArguments(data); const auto& address = common::FromJson(args, "address"); - const auto& uuid = common::FromJson(args, "uuid"); + const auto& uuid_str = common::FromJson(args, "uuid"); + const auto& uuid = UUID::create(uuid_str); + + if (!uuid) { + LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Invalid UUID: " + uuid_str), &out); + return; + } auto it = is_connected_.find(address); if (it == is_connected_.end()) { @@ -382,7 +393,7 @@ void BluetoothLEDevice::GetService(const picojson::value& data, picojson::object picojson::value response = picojson::value(picojson::object()); picojson::object* data_obj = &response.get(); - PlatformResult result = service_.GetSpecifiedGATTService(address, uuid, data_obj); + PlatformResult result = service_.GetSpecifiedGATTService(address, *uuid, data_obj); if (result.IsError()) { LogAndReportError(result, &out); diff --git a/src/bluetooth/bluetooth_le_device.h b/src/bluetooth/bluetooth_le_device.h index e2a161ae..25d0f5fc 100644 --- a/src/bluetooth/bluetooth_le_device.h +++ b/src/bluetooth/bluetooth_le_device.h @@ -24,6 +24,7 @@ #include "bluetooth/bluetooth_gatt_service.h" +#include "bluetooth/uuid.h" #include "common/picojson.h" #include "common/platform_result.h" diff --git a/src/bluetooth/uuid.cc b/src/bluetooth/uuid.cc index 9945c24e..619fb020 100644 --- a/src/bluetooth/uuid.cc +++ b/src/bluetooth/uuid.cc @@ -48,8 +48,8 @@ namespace extension { namespace bluetooth { -UUID::UUID(const std::string& uuid_in_source_format, std::string&& uuid_128_bit) - : uuid_in_source_format{uuid_in_source_format}, uuid_128_bit{std::move(uuid_128_bit)} { +UUID::UUID(const std::string& uuid_in_source_format_str, std::string&& uuid_128_bit_str) + : uuid_in_source_format{uuid_in_source_format_str}, uuid_128_bit{std::move(uuid_128_bit_str)} { ScopeLogger("UUID in source format: %s; 128 bit UUID: %s", uuid_in_source_format.c_str(), uuid_128_bit.c_str()); } diff --git a/src/common/optional.h b/src/common/optional.h index f476eb0b..44241f5f 100644 --- a/src/common/optional.h +++ b/src/common/optional.h @@ -50,6 +50,9 @@ class optional { optional(const T& v) : exist_(true) { create(v); } + optional(T&& v) : exist_(true) { + create(std::move(v)); + } ~optional() { if (exist_) destroy(); }