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();
}