1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_parser_utils"
17 #endif
18
19 #include "napi_parser_utils.h"
20
21 #include <string>
22 #include <vector>
23
24 #include "napi_async_callback.h"
25 #include <cinttypes>
26 namespace OHOS {
27 namespace Bluetooth {
28
29 // shall check object type is napi_object before, if it's other type, return false
30 // If the 'name' field is not exist, or napi function call error, return false
NapiIsObjectPropertyExist(napi_env env,napi_value object,const char * name)31 bool NapiIsObjectPropertyExist(napi_env env, napi_value object, const char *name)
32 {
33 auto status = NapiIsObject(env, object);
34 if (status != napi_ok) {
35 HILOGE("expect object");
36 return false;
37 }
38 bool exist = false;
39 status = napi_has_named_property(env, object, name, &exist);
40 if (status != napi_ok) {
41 HILOGE("Get object property failed, name: %{public}s", name);
42 return false;
43 }
44 return exist;
45 }
46
NapiParseGattService(napi_env env,napi_value object,NapiGattService & outService)47 napi_status NapiParseGattService(napi_env env, napi_value object, NapiGattService &outService)
48 {
49 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "isPrimary", "characteristics",
50 "includeServices"}));
51
52 std::string uuid {};
53 bool isPrimary = true;
54 std::vector<NapiBleCharacteristic> characteristics {};
55 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
56 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
57 NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "isPrimary", isPrimary));
58 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "characteristics", characteristics));
59 if (NapiIsObjectPropertyExist(env, object, "includeServices")) {
60 std::vector<NapiGattService> includeServices {};
61 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "includeServices", includeServices));
62 outService.includeServices = std::move(includeServices);
63 }
64 outService.serviceUuid = UUID::FromString(uuid);
65 outService.isPrimary = isPrimary;
66 outService.characteristics = std::move(characteristics);
67 return napi_ok;
68 }
69
70 namespace {
71 const NapiGattPermission DEFAULT_GATT_PERMISSIONS = {
72 .readable = true,
73 .writeable = true,
74 };
75 const NapiGattProperties DEFAULT_GATT_PROPERTIES = {
76 .write = true,
77 .writeNoResponse = true,
78 .read = true,
79 };
ConvertGattPermissions(const NapiGattPermission & napiPermissions)80 uint16_t ConvertGattPermissions(const NapiGattPermission &napiPermissions)
81 {
82 uint16_t permissions = 0;
83 if (napiPermissions.readable) {
84 permissions |= static_cast<uint16_t>(GattPermission::READABLE);
85 }
86 if (napiPermissions.readEncrypted) {
87 permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED);
88 }
89 if (napiPermissions.readEncryptedMitm) {
90 permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED_MITM);
91 }
92 if (napiPermissions.writeable) {
93 permissions |= static_cast<uint16_t>(GattPermission::WRITEABLE);
94 }
95 if (napiPermissions.writeEncrypted) {
96 permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED);
97 }
98 if (napiPermissions.writeEncryptedMitm) {
99 permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED_MITM);
100 }
101 if (napiPermissions.writeSigned) {
102 permissions |= static_cast<uint16_t>(GattPermission::WRITE_SIGNED);
103 }
104 if (napiPermissions.writeSignedMitm) {
105 permissions |= static_cast<uint16_t>(GattPermission::WRITE_SIGNED_MITM);
106 }
107 return permissions;
108 }
ConvertGattProperties(const NapiGattProperties & napiProperties)109 uint16_t ConvertGattProperties(const NapiGattProperties &napiProperties)
110 {
111 uint16_t properties = 0;
112 if (napiProperties.read) {
113 properties |= static_cast<uint16_t>(GattCharacteristic::READ);
114 }
115 if (napiProperties.write) {
116 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE);
117 }
118 if (napiProperties.writeNoResponse) {
119 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE_WITHOUT_RESPONSE);
120 }
121 if (napiProperties.notify) {
122 properties |= static_cast<uint16_t>(GattCharacteristic::NOTIFY);
123 }
124 if (napiProperties.indicate) {
125 properties |= static_cast<uint16_t>(GattCharacteristic::INDICATE);
126 }
127 if (napiProperties.broadcast) {
128 properties |= static_cast<uint16_t>(GattCharacteristic::BROADCAST);
129 }
130 if (napiProperties.authenticatedSignedWrite) {
131 properties |= static_cast<uint16_t>(GattCharacteristic::AUTHENTICATED_SIGNED_WRITES);
132 }
133 if (napiProperties.extendedProperties) {
134 properties |= static_cast<uint16_t>(GattCharacteristic::EXTENDED_PROPERTIES);
135 }
136 return properties;
137 }
138 } // namespace {}
139
NapiParseGattCharacteristic(napi_env env,napi_value object,NapiBleCharacteristic & outCharacteristic)140 napi_status NapiParseGattCharacteristic(napi_env env, napi_value object, NapiBleCharacteristic &outCharacteristic)
141 {
142 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
143 "characteristicValue", "descriptors", "properties", "characteristicValueHandle", "permissions"}));
144
145 std::string serviceUuid {};
146 std::string characterUuid {};
147 std::vector<uint8_t> characterValue {};
148 std::vector<NapiBleDescriptor> descriptors {};
149 uint32_t characteristicValueHandle = 0;
150 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
151 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
152 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
153 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
154 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors));
155
156 NapiGattProperties properties = DEFAULT_GATT_PROPERTIES;
157 if (NapiIsObjectPropertyExist(env, object, "properties")) {
158 NAPI_BT_CALL_RETURN(NapiParseObjectGattProperties(env, object, "properties", properties));
159 }
160 if (NapiIsObjectPropertyExist(env, object, "characteristicValueHandle")) {
161 NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "characteristicValueHandle", characteristicValueHandle));
162 NAPI_BT_RETURN_IF(characteristicValueHandle > 0xFFFF, "Invalid characteristicValueHandle", napi_invalid_arg);
163 }
164 NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
165 if (NapiIsObjectPropertyExist(env, object, "permissions")) {
166 NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
167 }
168
169 outCharacteristic.serviceUuid = UUID::FromString(serviceUuid);
170 outCharacteristic.characteristicUuid = UUID::FromString(characterUuid);
171 outCharacteristic.characteristicValue = std::move(characterValue);
172 outCharacteristic.descriptors = std::move(descriptors);
173 outCharacteristic.properties = ConvertGattProperties(properties);
174 outCharacteristic.characteristicValueHandle = static_cast<uint16_t>(characteristicValueHandle);
175 outCharacteristic.permissions = ConvertGattPermissions(permissions);
176 return napi_ok;
177 }
178
NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)179 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor)
180 {
181 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
182 "descriptorUuid", "descriptorValue", "descriptorHandle", "permissions"}));
183
184 std::string serviceUuid {};
185 std::string characterUuid {};
186 std::string descriptorUuid {};
187 std::vector<uint8_t> descriptorValue {};
188 uint32_t descriptorHandle = 0;
189 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
190 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
191 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
192 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid));
193 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue));
194
195 if (NapiIsObjectPropertyExist(env, object, "descriptorHandle")) {
196 NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "descriptorHandle", descriptorHandle));
197 NAPI_BT_RETURN_IF(descriptorHandle > 0xFFFF, "Invalid descriptorHandle", napi_invalid_arg);
198 }
199 NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
200 if (NapiIsObjectPropertyExist(env, object, "permissions")) {
201 NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
202 }
203
204 outDescriptor.serviceUuid = UUID::FromString(serviceUuid);
205 outDescriptor.characteristicUuid = UUID::FromString(characterUuid);
206 outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid);
207 outDescriptor.descriptorValue = std::move(descriptorValue);
208 outDescriptor.descriptorHandle = static_cast<uint16_t>(descriptorHandle);
209 outDescriptor.permissions = ConvertGattPermissions(permissions);
210 return napi_ok;
211 }
212
NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)213 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter)
214 {
215 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
216 "characteristicValue", "confirm"}));
217
218 std::string serviceUuid {};
219 std::string characterUuid {};
220 std::vector<uint8_t> characterValue {};
221 bool confirm = false;
222 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
223 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
224 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
225 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
226 NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm));
227
228 outCharacter.serviceUuid = UUID::FromString(serviceUuid);
229 outCharacter.characterUuid = UUID::FromString(characterUuid);
230 outCharacter.characterValue = std::move(characterValue);
231 outCharacter.confirm = confirm;
232 return napi_ok;
233 }
234
NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)235 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp)
236 {
237 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset",
238 "value"}));
239
240 std::string deviceId {};
241 int transId = 0;
242 int status = 0;
243 int offset = 0;
244 std::vector<uint8_t> value {};
245 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
246 NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId));
247 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId));
248 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status));
249 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset));
250 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value));
251
252 rsp.deviceId = deviceId;
253 rsp.transId = transId;
254 rsp.status = status;
255 rsp.offset = offset;
256 rsp.value = std::move(value);
257 return napi_ok;
258 }
259
NapiParseObjectGattPermissions(napi_env env,napi_value object,const char * name,NapiGattPermission & outPermissions)260 napi_status NapiParseObjectGattPermissions(napi_env env, napi_value object, const char *name,
261 NapiGattPermission &outPermissions)
262 {
263 napi_value permissionObject;
264 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
265 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, permissionObject));
266 // Parse permission object
267 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, permissionObject, {"read", "readEncrypted",
268 "readEncryptedMitm", "write", "writeEncrypted", "writeEncryptedMitm", "writeSigned", "writeSignedMitm"}));
269
270 bool isExist;
271 NapiGattPermission permissions {};
272 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
273 env, permissionObject, "read", permissions.readable, isExist));
274 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
275 env, permissionObject, "readEncrypted", permissions.readEncrypted, isExist));
276 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
277 env, permissionObject, "readEncryptedMitm", permissions.readEncryptedMitm, isExist));
278 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
279 env, permissionObject, "write", permissions.writeable, isExist));
280 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
281 env, permissionObject, "writeEncrypted", permissions.writeEncrypted, isExist));
282 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
283 env, permissionObject, "writeEncryptedMitm", permissions.writeEncryptedMitm, isExist));
284 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
285 env, permissionObject, "writeSigned", permissions.writeSigned, isExist));
286 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
287 env, permissionObject, "writeSignedMitm", permissions.writeSignedMitm, isExist));
288 outPermissions = permissions;
289 return napi_ok;
290 }
291
NapiParseObjectGattProperties(napi_env env,napi_value object,const char * name,NapiGattProperties & outProperties)292 napi_status NapiParseObjectGattProperties(napi_env env, napi_value object, const char *name,
293 NapiGattProperties &outProperties)
294 {
295 napi_value propertiesObject;
296 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
297 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, propertiesObject));
298 // Parse properties object
299 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, propertiesObject, {"write", "writeNoResponse",
300 "read", "notify", "indicate", "broadcast", "authenticatedSignedWrite", "extendedProperties"}));
301
302 bool isExist;
303 NapiGattProperties properties {};
304 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
305 env, propertiesObject, "write", properties.write, isExist));
306 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
307 env, propertiesObject, "writeNoResponse", properties.writeNoResponse, isExist));
308 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
309 env, propertiesObject, "read", properties.read, isExist));
310 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
311 env, propertiesObject, "notify", properties.notify, isExist));
312 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
313 env, propertiesObject, "indicate", properties.indicate, isExist));
314 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
315 env, propertiesObject, "broadcast", properties.broadcast, isExist));
316 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
317 env, propertiesObject, "authenticatedSignedWrite", properties.authenticatedSignedWrite, isExist));
318 NAPI_BT_CALL_RETURN(NapiParseObjectBooleanOptional(
319 env, propertiesObject, "extendedProperties", properties.extendedProperties, isExist));
320 outProperties = properties;
321 return napi_ok;
322 }
323
NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)324 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean)
325 {
326 bool boolean = false;
327 NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value));
328 NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean));
329 outBoolean = boolean;
330 return napi_ok;
331 }
332
NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)333 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum)
334 {
335 int32_t num = 0;
336 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
337 NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num));
338 outNum = num;
339 return napi_ok;
340 }
341
NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)342 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum)
343 {
344 uint32_t num = 0;
345 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
346 NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num));
347 outNum = num;
348 return napi_ok;
349 }
350
NapiParseString(napi_env env,napi_value value,std::string & outStr)351 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr)
352 {
353 std::string str {};
354 NAPI_BT_CALL_RETURN(NapiIsString(env, value));
355 NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg);
356 outStr = std::move(str);
357 return napi_ok;
358 }
359
NapiParseStringArray(napi_env env,napi_value value,std::vector<std::string> & outStrVec)360 napi_status NapiParseStringArray(napi_env env, napi_value value, std::vector<std::string> &outStrVec)
361 {
362 NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
363 uint32_t length = 0;
364 std::string param {};
365 std::vector<std::string> strVec {};
366 napi_get_array_length(env, value, &length);
367 for (size_t i = 0; i < length; i++) {
368 napi_value result;
369 napi_get_element(env, value, i, &result);
370 NAPI_BT_CALL_RETURN(NapiParseString(env, result, param));
371 strVec.push_back(param);
372 }
373 outStrVec = std::move(strVec);
374 return napi_ok;
375 }
376
NapiParseFileHolderArray(napi_env env,napi_value value,std::vector<FileHolder> & outFileHolderVec)377 napi_status NapiParseFileHolderArray(napi_env env, napi_value value, std::vector<FileHolder> &outFileHolderVec)
378 {
379 NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
380 uint32_t length = 0;
381 std::vector<FileHolder> fileHolderVec {};
382 napi_get_array_length(env, value, &length);
383 for (uint32_t i = 0; i < length; i++) {
384 FileHolder fileHolder;
385 napi_value result;
386 napi_get_element(env, value, i, &result);
387 NAPI_BT_CALL_RETURN(NapiParseFileHolder(env, result, fileHolder));
388 fileHolderVec.push_back(fileHolder);
389 }
390 outFileHolderVec = std::move(fileHolderVec);
391 return napi_ok;
392 }
393
NapiParseFileHolder(napi_env env,napi_value object,FileHolder & outFileHolder)394 napi_status NapiParseFileHolder(napi_env env, napi_value object, FileHolder &outFileHolder)
395 {
396 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"filePath", "fileSize", "fileFd"}));
397 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
398 std::string filePath {};
399 int64_t fileSize = 0;
400 int32_t fileFd = 0;
401 std::string fileType {};
402
403 NAPI_BT_CALL_RETURN(NapiParseObjectString(env, object, "filePath", filePath));
404 NAPI_BT_CALL_RETURN(NapiParseObjectInt64(env, object, "fileSize", fileSize));
405 NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "fileFd", fileFd));
406 HILOGI("fileSize: %{public}" PRId64 "fileFd: %{public}d", fileSize, fileFd);
407
408 FileHolder fileHolder;
409 fileHolder.filePath = filePath;
410 fileHolder.fileSize = fileSize;
411 fileHolder.fileFd = fileFd;
412 outFileHolder = std::move(fileHolder);
413 return napi_ok;
414 }
415
416
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)417 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
418 {
419 std::string bdaddr {};
420 NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
421 NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
422 outAddr = std::move(bdaddr);
423 return napi_ok;
424 }
425
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)426 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
427 {
428 std::string uuid {};
429 NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
430 NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
431 outUuid = std::move(uuid);
432 return napi_ok;
433 }
434
NapiParseInt64(napi_env env,napi_value value,int64_t & outNum)435 napi_status NapiParseInt64(napi_env env, napi_value value, int64_t &outNum)
436 {
437 int64_t num = 0;
438 NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
439 NAPI_BT_CALL_RETURN(napi_get_value_int64(env, value, &num));
440 outNum = num;
441 return napi_ok;
442 }
443
NapiParseObjectInt64(napi_env env,napi_value object,const char * name,int64_t & outNum)444 napi_status NapiParseObjectInt64(napi_env env, napi_value object, const char *name, int64_t &outNum)
445 {
446 napi_value property;
447 int64_t num = 0;
448 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
449 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
450 NAPI_BT_CALL_RETURN(NapiParseInt64(env, property, num));
451 outNum = num;
452 return napi_ok;
453 }
454
NapiParseObjectStr(napi_env env,napi_value object,const char * name,std::string & outStr)455 napi_status NapiParseObjectStr(napi_env env, napi_value object, const char *name, std::string &outStr)
456 {
457 napi_value property;
458 std::string str;
459 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
460 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
461 NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
462 outStr = std::move(str);
463 return napi_ok;
464 }
465
NapiParseObjectUuids(napi_env env,napi_value object,const char * name,std::vector<std::string> & outUuid)466 napi_status NapiParseObjectUuids(napi_env env, napi_value object, const char *name, std::vector<std::string> &outUuid)
467 {
468 std::string uuids;
469 NAPI_BT_CALL_RETURN(NapiParseObjectStr(env, object, name, uuids));
470 NAPI_BT_CALL_RETURN(ParseAndCheckUuids(uuids, outUuid));
471 return napi_ok;
472 }
473
ParseAndCheckUuids(const std::string & uuids,std::vector<std::string> & res)474 napi_status ParseAndCheckUuids(const std::string &uuids, std::vector<std::string> &res)
475 {
476 HILOGI("[CLOUD_PAIR] ParseAndCheckUuids %{public}s", uuids.c_str());
477 if (uuids.empty()) {
478 return napi_ok;
479 }
480 const std::regex pattern("[,]");
481 std::vector<std::string> result(
482 std::sregex_token_iterator(uuids.begin(), uuids.end(), pattern, -1),
483 std::sregex_token_iterator()
484 );
485 for (const auto &str : result) {
486 NAPI_BT_RETURN_IF(!IsValidUuid(str), "Invalid uuid", napi_invalid_arg);
487 }
488 res = std::move(result);
489 return napi_ok;
490 }
491
NapiParseTrustPairDevice(napi_env env,napi_value object,std::vector<TrustPairDeviceParam> & outService)492 napi_status NapiParseTrustPairDevice(napi_env env, napi_value object, std::vector<TrustPairDeviceParam> &outService)
493 {
494 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"trustedPairedDevices"}));
495 NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "trustedPairedDevices", outService));
496 return napi_ok;
497 }
498
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)499 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
500 {
501 uint8_t *data = nullptr;
502 size_t size = 0;
503 NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
504 bool isSuccess = ParseArrayBuffer(env, &data, size, value);
505 if (!isSuccess) {
506 HILOGE("Parse arraybuffer failed");
507 return napi_invalid_arg;
508 }
509 std::vector<uint8_t> vec(data, data + size);
510 outVec = std::move(vec);
511 return napi_ok;
512 }
513
NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)514 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType)
515 {
516 int writeType = -1;
517 NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType));
518 if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) {
519 HILOGI("gattWriteType: WRITE");
520 outWriteType = GattCharacteristic::WriteType::DEFAULT;
521 } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) {
522 HILOGI("gattWriteType: WRITE_NO_RESPONSE");
523 outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
524 } else {
525 HILOGE("Invalid gattWriteType: %{public}d", writeType);
526 return napi_invalid_arg;
527 }
528 return napi_ok;
529 }
530
NapiParseAsyncCallback(napi_env env,napi_callback_info info)531 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info)
532 {
533 size_t argc = ARGS_SIZE_FOUR;
534 napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
535 auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL);
536 if (status != napi_ok) {
537 HILOGE("napi_get_cb_info failed");
538 return nullptr;
539 }
540 if (argc > ARGS_SIZE_FOUR) {
541 HILOGE("size of parameters is larger than ARGS_SIZE_FOUR");
542 return nullptr;
543 }
544
545 // "argc - 1" is AsyncCallback parameter's index
546 auto asyncCallback = std::make_shared<NapiAsyncCallback>();
547 asyncCallback->env = env;
548 if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) {
549 HILOGD("callback mode");
550 asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]);
551 } else {
552 HILOGD("promise mode");
553 asyncCallback->promise = std::make_shared<NapiPromise>(env);
554 }
555 return asyncCallback;
556 }
557
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)558 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
559 bool &outExist)
560 {
561 bool exist = false;
562 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
563 NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
564 if (exist) {
565 napi_value property;
566 NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
567 outProperty = property;
568 }
569 outExist = exist;
570 return napi_ok;
571 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)572 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
573 {
574 bool exist = false;
575 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
576 NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
577 return napi_ok;
578 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)579 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
580 bool &outExist)
581 {
582 return NapiGetObjectProperty(env, object, name, outProperty, outExist);
583 }
584
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)585 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
586 {
587 napi_value property;
588 bool boolean = true;
589 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
590 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
591 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
592 outBoolean = boolean;
593 return napi_ok;
594 }
595
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)596 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
597 {
598 napi_value property;
599 std::string uuid {};
600 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
601 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
602 NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
603 outUuid = std::move(uuid);
604 return napi_ok;
605 }
606
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)607 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
608 {
609 napi_value property;
610 std::vector<uint8_t> vec {};
611 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
612 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
613 NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
614 outVec = std::move(vec);
615 return napi_ok;
616 }
617
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)618 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
619 {
620 napi_value property;
621 std::string bdaddr {};
622 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
623 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
624 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
625 outAddr = std::move(bdaddr);
626 return napi_ok;
627 }
628
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)629 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
630 {
631 napi_value property;
632 int32_t num = 0;
633 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
634 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
635 NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
636 outNum = num;
637 return napi_ok;
638 }
639
NapiParseObjectString(napi_env env,napi_value object,const char * name,std::string & outString)640 napi_status NapiParseObjectString(napi_env env, napi_value object, const char *name, std::string &outString)
641 {
642 napi_value property;
643 std::string str = "";
644 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
645 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
646 NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
647 outString = str;
648 return napi_ok;
649 }
650
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)651 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
652 {
653 napi_value property;
654 uint32_t num = 0;
655 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
656 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
657 NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
658 outNum = num;
659 return napi_ok;
660 }
661
NapiParseObjectUint32Check(NapiObject napiObject,const char * name,uint32_t & outNum,uint32_t min,uint32_t max)662 napi_status NapiParseObjectUint32Check(NapiObject napiObject, const char *name, uint32_t &outNum,
663 uint32_t min, uint32_t max)
664 {
665 NAPI_BT_CALL_RETURN(NapiParseObjectUint32(napiObject.env, napiObject.object, name, outNum));
666 if (outNum < min || outNum > max) {
667 return napi_invalid_arg;
668 }
669 return napi_ok;
670 }
671
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)672 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
673 bool &outExist)
674 {
675 napi_value property;
676 bool exist = false;
677 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
678 NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
679 if (exist) {
680 bool boolean = true;
681 NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
682 outBoolean = boolean;
683 }
684 outExist = exist;
685 return napi_ok;
686 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)687 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
688 bool &outExist)
689 {
690 napi_value property;
691 bool exist = false;
692 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
693 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
694 if (exist) {
695 int32_t num = 0;
696 NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
697 outNum = num;
698 }
699 outExist = exist;
700 return napi_ok;
701 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)702 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
703 bool &outExist)
704 {
705 napi_value property;
706 bool exist = false;
707 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
708 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
709 if (exist) {
710 uint32_t num = 0;
711 NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
712 outNum = num;
713 }
714 outExist = exist;
715 return napi_ok;
716 }
717
718 // Parse params template, used for NapiParseArray
719 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)720 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
721 {
722 HILOGE("Unimpleted type");
723 return napi_invalid_arg;
724 }
725
726 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)727 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
728 {
729 return NapiParseString(env, object, outObj);
730 }
731
732 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)733 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
734 {
735 std::string uuid {};
736 NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
737 outObj = UUID::FromString(uuid);
738 return napi_ok;
739 }
740
741 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)742 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
743 {
744 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
745 uint32_t num = 0;
746 std::vector<uint8_t> vec {};
747 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
748 NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
749 NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
750 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
751
752 outObj.id = static_cast<uint16_t>(num);
753 outObj.value = std::string(vec.begin(), vec.end());
754 return napi_ok;
755 }
756
757 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)758 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
759 {
760 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
761 std::string uuid {};
762 std::vector<uint8_t> vec {};
763 NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
764 NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
765 NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
766
767 outObj.uuid = std::move(uuid);
768 outObj.value = std::move(vec);
769 return napi_ok;
770 }
771
772 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)773 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
774 {
775 return NapiParseGattService(env, object, outObj);
776 }
777
778 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)779 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
780 {
781 return NapiParseGattCharacteristic(env, object, outObj);
782 }
783
784 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)785 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
786 {
787 return NapiParseGattDescriptor(env, object, outObj);
788 }
789
790 template <>
NapiParseObject(napi_env env,napi_value object,TrustPairDeviceParam & outObj)791 napi_status NapiParseObject<TrustPairDeviceParam>(napi_env env, napi_value object, TrustPairDeviceParam &outObj)
792 {
793 NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"sn", "deviceType",
794 "modelId", "manufactory", "productId", "hiLinkVersion", "macAddress", "serviceType",
795 "serviceId", "deviceName", "uuids", "bluetoothClass", "token", "deviceNameTime",
796 "secureAdvertisingInfo", "pairState"}));
797 NapiParseObjectStr(env, object, "sn", outObj.sn_);
798 NapiParseObjectStr(env, object, "deviceType", outObj.deviceType_);
799 NapiParseObjectStr(env, object, "modelId", outObj.modelId_);
800 NapiParseObjectStr(env, object, "manufactory", outObj.manufactory_);
801 NapiParseObjectStr(env, object, "productId", outObj.productId_);
802 NapiParseObjectStr(env, object, "hiLinkVersion", outObj.hiLinkVersion_);
803 NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "macAddress", outObj.macAddress_));
804 NapiParseObjectStr(env, object, "serviceType", outObj.serviceType_);
805 NapiParseObjectStr(env, object, "serviceId", outObj.serviceId_);
806 NapiParseObjectStr(env, object, "deviceName", outObj.deviceName_);
807 NAPI_BT_CALL_RETURN(NapiParseObjectUuids(env, object, "uuids", outObj.uuids_));
808 NapiParseObjectInt32(env, object, "bluetoothClass", outObj.bluetoothClass_);
809 NapiParseObjectInt64(env, object, "deviceNameTime", outObj.deviceNameTime_);
810 NapiParseObjectInt32(env, object, "pairState", outObj.pairState_);
811 std::vector<uint8_t> tokenValue;
812 std::vector<uint8_t> secureAdvertisingInfoValue;
813 NapiParseObjectArrayBuffer(env, object, "token", tokenValue);
814 NapiParseObjectArrayBuffer(env, object, "secureAdvertisingInfo", secureAdvertisingInfoValue);
815 outObj.token_ = std::move(tokenValue);
816 outObj.secureAdvertisingInfo_ = std::move(secureAdvertisingInfoValue);
817 return napi_ok;
818 }
819
820 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)821 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
822 {
823 std::vector<T> vec {};
824
825 NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
826 uint32_t length = 0;
827 NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
828 for (uint32_t i = 0; i < length; ++i) {
829 napi_value element;
830 NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
831 T object;
832 NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
833 vec.push_back(std::move(object));
834 }
835 outVec = std::move(vec);
836 return napi_ok;
837 }
838 // // Declaration, ohters will undefined synbol
839 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
840 std::vector<NapiBleDescriptor> &outVec);
841 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
842 std::vector<NapiBleCharacteristic> &outVec);
843 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
844 std::vector<NapiGattService> &outVec);
845 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
846 std::vector<NapiAdvServiceData> &outVec);
847 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
848 std::vector<NapiAdvManufactureData> &outVec);
849 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
850 std::vector<UUID> &outVec);
851 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
852 std::vector<std::string> &outVec);
853 template napi_status NapiParseArray<TrustPairDeviceParam>(napi_env env, napi_value array,
854 std::vector<TrustPairDeviceParam> &outVec);
855
856 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)857 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
858 {
859 napi_value property;
860 std::vector<T> vec {};
861 NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
862 NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
863 outVec = std::move(vec);
864 return napi_ok;
865 }
866 // Declaration, ohters will undefined synbol
867 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
868 std::vector<NapiBleDescriptor> &outVec);
869 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
870 std::vector<NapiBleCharacteristic> &outVec);
871 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
872 std::vector<NapiGattService> &outVec);
873 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
874 std::vector<NapiAdvServiceData> &outVec);
875 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
876 std::vector<NapiAdvManufactureData> &outVec);
877 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
878 std::vector<UUID> &outVec);
879 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
880 std::vector<std::string> &outVec);
881 template napi_status NapiParseObjectArray<TrustPairDeviceParam>(napi_env env, napi_value object, const char *name,
882 std::vector<TrustPairDeviceParam> &outVec);
883 } // namespace Bluetooth
884 } // namespace OHOS
885