• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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.writeable) {
87         permissions |= static_cast<uint16_t>(GattPermission::WRITEABLE);
88     }
89     if (napiPermissions.readEncrypted) {
90         permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED_MITM);
91     }
92     if (napiPermissions.writeEncrypted) {
93         permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED_MITM);
94     }
95     return permissions;
96 }
ConvertGattProperties(const NapiGattProperties & napiProperties)97 uint16_t ConvertGattProperties(const NapiGattProperties &napiProperties)
98 {
99     uint16_t properties = 0;
100     if (napiProperties.read) {
101         properties |= static_cast<uint16_t>(GattCharacteristic::READ);
102     }
103     if (napiProperties.write) {
104         properties |= static_cast<uint16_t>(GattCharacteristic::WRITE);
105     }
106     if (napiProperties.writeNoResponse) {
107         properties |= static_cast<uint16_t>(GattCharacteristic::WRITE_WITHOUT_RESPONSE);
108     }
109     if (napiProperties.notify) {
110         properties |= static_cast<uint16_t>(GattCharacteristic::NOTIFY);
111     }
112     if (napiProperties.indicate) {
113         properties |= static_cast<uint16_t>(GattCharacteristic::INDICATE);
114     }
115     return properties;
116 }
117 }  // namespace {}
118 
NapiParseGattCharacteristic(napi_env env,napi_value object,NapiBleCharacteristic & outCharacteristic)119 napi_status NapiParseGattCharacteristic(napi_env env, napi_value object, NapiBleCharacteristic &outCharacteristic)
120 {
121     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
122         "characteristicValue", "descriptors", "properties", "permissions"}));
123 
124     std::string serviceUuid {};
125     std::string characterUuid {};
126     std::vector<uint8_t> characterValue {};
127     std::vector<NapiBleDescriptor> descriptors {};
128     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
129     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
130     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
131     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
132     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "descriptors", descriptors));
133 
134     NapiGattProperties properties = DEFAULT_GATT_PROPERTIES;
135     if (NapiIsObjectPropertyExist(env, object, "properties"))  {
136         NAPI_BT_CALL_RETURN(NapiParseObjectGattProperties(env, object, "properties", properties));
137     }
138     NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
139     if (NapiIsObjectPropertyExist(env, object, "permissions")) {
140         NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
141     }
142 
143     outCharacteristic.serviceUuid = UUID::FromString(serviceUuid);
144     outCharacteristic.characteristicUuid = UUID::FromString(characterUuid);
145     outCharacteristic.characteristicValue = std::move(characterValue);
146     outCharacteristic.descriptors = std::move(descriptors);
147     outCharacteristic.properties = ConvertGattProperties(properties);
148     outCharacteristic.permissions = ConvertGattPermissions(permissions);
149     return napi_ok;
150 }
151 
NapiParseGattDescriptor(napi_env env,napi_value object,NapiBleDescriptor & outDescriptor)152 napi_status NapiParseGattDescriptor(napi_env env, napi_value object, NapiBleDescriptor &outDescriptor)
153 {
154     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
155         "descriptorUuid", "descriptorValue", "permissions"}));
156 
157     std::string serviceUuid {};
158     std::string characterUuid {};
159     std::string descriptorUuid {};
160     std::vector<uint8_t> descriptorValue {};
161     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
162     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", serviceUuid));
163     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "characteristicUuid", characterUuid));
164     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "descriptorUuid", descriptorUuid));
165     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "descriptorValue", descriptorValue));
166 
167     NapiGattPermission permissions = DEFAULT_GATT_PERMISSIONS;
168     if (NapiIsObjectPropertyExist(env, object, "permissions")) {
169         NAPI_BT_CALL_RETURN(NapiParseObjectGattPermissions(env, object, "permissions", permissions));
170     }
171 
172     outDescriptor.serviceUuid = UUID::FromString(serviceUuid);
173     outDescriptor.characteristicUuid = UUID::FromString(characterUuid);
174     outDescriptor.descriptorUuid = UUID::FromString(descriptorUuid);
175     outDescriptor.descriptorValue = std::move(descriptorValue);
176     outDescriptor.permissions = ConvertGattPermissions(permissions);
177     return napi_ok;
178 }
179 
NapiParseNotifyCharacteristic(napi_env env,napi_value object,NapiNotifyCharacteristic & outCharacter)180 napi_status NapiParseNotifyCharacteristic(napi_env env, napi_value object, NapiNotifyCharacteristic &outCharacter)
181 {
182     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "characteristicUuid",
183         "characteristicValue", "confirm"}));
184 
185     std::string serviceUuid {};
186     std::string characterUuid {};
187     std::vector<uint8_t> characterValue {};
188     bool confirm = false;
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(NapiParseObjectArrayBuffer(env, object, "characteristicValue", characterValue));
193     NAPI_BT_CALL_RETURN(NapiParseObjectBoolean(env, object, "confirm", confirm));
194 
195     outCharacter.serviceUuid = UUID::FromString(serviceUuid);
196     outCharacter.characterUuid = UUID::FromString(characterUuid);
197     outCharacter.characterValue = std::move(characterValue);
198     outCharacter.confirm = confirm;
199     return napi_ok;
200 }
201 
NapiParseGattsServerResponse(napi_env env,napi_value object,NapiGattsServerResponse & rsp)202 napi_status NapiParseGattsServerResponse(napi_env env, napi_value object, NapiGattsServerResponse &rsp)
203 {
204     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"deviceId", "transId", "status", "offset",
205         "value"}));
206 
207     std::string deviceId {};
208     int transId = 0;
209     int status = 0;
210     int offset = 0;
211     std::vector<uint8_t> value {};
212     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
213     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "deviceId", deviceId));
214     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "transId", transId));
215     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "status", status));
216     NAPI_BT_CALL_RETURN(NapiParseObjectInt32(env, object, "offset", offset));
217     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "value", value));
218 
219     rsp.deviceId = deviceId;
220     rsp.transId = transId;
221     rsp.status = status;
222     rsp.offset = offset;
223     rsp.value = std::move(value);
224     return napi_ok;
225 }
226 
NapiParseObjectGattPermissions(napi_env env,napi_value object,const char * name,NapiGattPermission & outPermissions)227 napi_status NapiParseObjectGattPermissions(napi_env env, napi_value object, const char *name,
228     NapiGattPermission &outPermissions)
229 {
230     napi_value permissionObject;
231     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
232     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, permissionObject));
233     // Parse permission object
234     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, permissionObject, {"readable", "writeable",
235         "readEncrypted", "writeEncrypted"}));
236 
237     bool isExist;
238     NapiGattPermission permissions {};
239     NAPI_BT_CALL_RETURN(
240         NapiParseObjectBooleanOptional(env, permissionObject, "readable", permissions.readable, isExist));
241     NAPI_BT_CALL_RETURN(
242         NapiParseObjectBooleanOptional(env, permissionObject, "writeable", permissions.writeable, isExist));
243     NAPI_BT_CALL_RETURN(
244         NapiParseObjectBooleanOptional(env, permissionObject, "readEncrypted", permissions.readEncrypted, isExist));
245     NAPI_BT_CALL_RETURN(
246         NapiParseObjectBooleanOptional(env, permissionObject, "writeEncrypted", permissions.writeEncrypted, isExist));
247     outPermissions = permissions;
248     return napi_ok;
249 }
250 
NapiParseObjectGattProperties(napi_env env,napi_value object,const char * name,NapiGattProperties & outProperties)251 napi_status NapiParseObjectGattProperties(napi_env env, napi_value object, const char *name,
252     NapiGattProperties &outProperties)
253 {
254     napi_value propertiesObject;
255     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
256     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, propertiesObject));
257     // Parse properties object
258     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, propertiesObject, {"write", "writeNoResponse",
259         "read", "notify", "indicate"}));
260 
261     bool isExist;
262     NapiGattProperties properties {};
263     NAPI_BT_CALL_RETURN(
264         NapiParseObjectBooleanOptional(env, propertiesObject, "write", properties.write, isExist));
265     NAPI_BT_CALL_RETURN(
266         NapiParseObjectBooleanOptional(env, propertiesObject, "writeNoResponse", properties.writeNoResponse, isExist));
267     NAPI_BT_CALL_RETURN(
268         NapiParseObjectBooleanOptional(env, propertiesObject, "read", properties.read, isExist));
269     NAPI_BT_CALL_RETURN(
270         NapiParseObjectBooleanOptional(env, propertiesObject, "notify", properties.notify, isExist));
271     NAPI_BT_CALL_RETURN(
272         NapiParseObjectBooleanOptional(env, propertiesObject, "indicate", properties.indicate, isExist));
273     outProperties = properties;
274     return napi_ok;
275 }
276 
NapiParseBoolean(napi_env env,napi_value value,bool & outBoolean)277 napi_status NapiParseBoolean(napi_env env, napi_value value, bool &outBoolean)
278 {
279     bool boolean = false;
280     NAPI_BT_CALL_RETURN(NapiIsBoolean(env, value));
281     NAPI_BT_CALL_RETURN(napi_get_value_bool(env, value, &boolean));
282     outBoolean = boolean;
283     return napi_ok;
284 }
285 
NapiParseInt32(napi_env env,napi_value value,int32_t & outNum)286 napi_status NapiParseInt32(napi_env env, napi_value value, int32_t &outNum)
287 {
288     int32_t num = 0;
289     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
290     NAPI_BT_CALL_RETURN(napi_get_value_int32(env, value, &num));
291     outNum = num;
292     return napi_ok;
293 }
294 
NapiParseUint32(napi_env env,napi_value value,uint32_t & outNum)295 napi_status NapiParseUint32(napi_env env, napi_value value, uint32_t &outNum)
296 {
297     uint32_t num = 0;
298     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
299     NAPI_BT_CALL_RETURN(napi_get_value_uint32(env, value, &num));
300     outNum = num;
301     return napi_ok;
302 }
303 
NapiParseString(napi_env env,napi_value value,std::string & outStr)304 napi_status NapiParseString(napi_env env, napi_value value, std::string &outStr)
305 {
306     std::string str {};
307     NAPI_BT_CALL_RETURN(NapiIsString(env, value));
308     NAPI_BT_RETURN_IF(!ParseString(env, str, value), "parse string failed", napi_invalid_arg);
309     outStr = std::move(str);
310     return napi_ok;
311 }
312 
NapiParseStringArray(napi_env env,napi_value value,std::vector<std::string> & outStrVec)313 napi_status NapiParseStringArray(napi_env env, napi_value value, std::vector<std::string> &outStrVec)
314 {
315     NAPI_BT_CALL_RETURN(NapiIsArray(env, value));
316     uint32_t length = 0;
317     std::string param {};
318     std::vector<std::string> strVec {};
319     napi_get_array_length(env, value, &length);
320     for (size_t i = 0; i < length; i++) {
321         napi_value result;
322         napi_get_element(env, value, i, &result);
323         NAPI_BT_CALL_RETURN(NapiParseString(env, result, param));
324         strVec.push_back(param);
325     }
326     outStrVec = std::move(strVec);
327     return napi_ok;
328 }
329 
NapiParseBdAddr(napi_env env,napi_value value,std::string & outAddr)330 napi_status NapiParseBdAddr(napi_env env, napi_value value, std::string &outAddr)
331 {
332     std::string bdaddr {};
333     NAPI_BT_CALL_RETURN(NapiParseString(env, value, bdaddr));
334     NAPI_BT_RETURN_IF(!IsValidAddress(bdaddr), "Invalid bdaddr", napi_invalid_arg);
335     outAddr = std::move(bdaddr);
336     return napi_ok;
337 }
338 
NapiParseUuid(napi_env env,napi_value value,std::string & outUuid)339 napi_status NapiParseUuid(napi_env env, napi_value value, std::string &outUuid)
340 {
341     std::string uuid {};
342     NAPI_BT_CALL_RETURN(NapiParseString(env, value, uuid));
343     NAPI_BT_RETURN_IF(!IsValidUuid(uuid), "Invalid uuid", napi_invalid_arg);
344     outUuid = std::move(uuid);
345     return napi_ok;
346 }
347 
NapiParseInt64(napi_env env,napi_value value,int64_t & outNum)348 napi_status NapiParseInt64(napi_env env, napi_value value, int64_t &outNum)
349 {
350     int64_t num = 0;
351     NAPI_BT_CALL_RETURN(NapiIsNumber(env, value));
352     NAPI_BT_CALL_RETURN(napi_get_value_int64(env, value, &num));
353     outNum = num;
354     return napi_ok;
355 }
356 
NapiParseObjectInt64(napi_env env,napi_value object,const char * name,int64_t & outNum)357 napi_status NapiParseObjectInt64(napi_env env, napi_value object, const char *name, int64_t &outNum)
358 {
359     napi_value property;
360     int64_t num = 0;
361     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
362     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
363     NAPI_BT_CALL_RETURN(NapiParseInt64(env, property, num));
364     outNum = num;
365     return napi_ok;
366 }
367 
NapiParseObjectStr(napi_env env,napi_value object,const char * name,std::string & outStr)368 napi_status NapiParseObjectStr(napi_env env, napi_value object, const char *name, std::string &outStr)
369 {
370     napi_value property;
371     std::string str;
372     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
373     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
374     NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
375     outStr = std::move(str);
376     return napi_ok;
377 }
378 
NapiParseObjectUuids(napi_env env,napi_value object,const char * name,std::vector<std::string> & outUuid)379 napi_status NapiParseObjectUuids(napi_env env, napi_value object, const char *name, std::vector<std::string> &outUuid)
380 {
381     std::string uuids;
382     NAPI_BT_CALL_RETURN(NapiParseObjectStr(env, object, name, uuids));
383     NAPI_BT_CALL_RETURN(ParseAndCheckUuids(uuids, outUuid));
384     return napi_ok;
385 }
386 
ParseAndCheckUuids(const std::string & uuids,std::vector<std::string> & res)387 napi_status ParseAndCheckUuids(const std::string &uuids, std::vector<std::string> &res)
388 {
389     HILOGI("[CLOUD_PAIR] ParseAndCheckUuids %{public}s", uuids.c_str());
390     if (uuids.empty()) {
391         return napi_ok;
392     }
393     const std::regex pattern("[,]");
394     std::vector<std::string> result(
395         std::sregex_token_iterator(uuids.begin(), uuids.end(), pattern, -1),
396         std::sregex_token_iterator()
397     );
398     for (const auto &str : result) {
399         NAPI_BT_RETURN_IF(!IsValidUuid(str), "Invalid uuid", napi_invalid_arg);
400     }
401     res = std::move(result);
402     return napi_ok;
403 }
404 
NapiParseTrustPairDevice(napi_env env,napi_value object,std::vector<TrustPairDeviceParam> & outService)405 napi_status NapiParseTrustPairDevice(napi_env env, napi_value object, std::vector<TrustPairDeviceParam> &outService)
406 {
407     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"trustedPairedDevices"}));
408     NAPI_BT_CALL_RETURN(NapiParseObjectArray(env, object, "trustedPairedDevices", outService));
409     return napi_ok;
410 }
411 
NapiParseArrayBuffer(napi_env env,napi_value value,std::vector<uint8_t> & outVec)412 napi_status NapiParseArrayBuffer(napi_env env, napi_value value, std::vector<uint8_t> &outVec)
413 {
414     uint8_t *data = nullptr;
415     size_t size = 0;
416     NAPI_BT_CALL_RETURN(NapiIsArrayBuffer(env, value));
417     bool isSuccess = ParseArrayBuffer(env, &data, size, value);
418     if (!isSuccess) {
419         HILOGE("Parse arraybuffer failed");
420         return napi_invalid_arg;
421     }
422     std::vector<uint8_t> vec(data, data + size);
423     outVec = std::move(vec);
424     return napi_ok;
425 }
426 
NapiParseGattWriteType(napi_env env,napi_value value,int & outWriteType)427 napi_status NapiParseGattWriteType(napi_env env, napi_value value, int &outWriteType)
428 {
429     int writeType = -1;
430     NAPI_BT_CALL_RETURN(NapiParseInt32(env, value, writeType));
431     if (writeType == static_cast<int>(NapiGattWriteType::WRITE)) {
432         HILOGI("gattWriteType: WRITE");
433         outWriteType = GattCharacteristic::WriteType::DEFAULT;
434     } else if (writeType == static_cast<int>(NapiGattWriteType::WRITE_NO_RESPONSE)) {
435         HILOGI("gattWriteType: WRITE_NO_RESPONSE");
436         outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
437     } else {
438         HILOGE("Invalid gattWriteType: %{public}d", writeType);
439         return napi_invalid_arg;
440     }
441     return napi_ok;
442 }
443 
NapiParseAsyncCallback(napi_env env,napi_callback_info info)444 std::shared_ptr<NapiAsyncCallback> NapiParseAsyncCallback(napi_env env, napi_callback_info info)
445 {
446     size_t argc = ARGS_SIZE_FOUR;
447     napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
448     auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, NULL);
449     if (status != napi_ok) {
450         HILOGE("napi_get_cb_info failed");
451         return nullptr;
452     }
453     if (argc > ARGS_SIZE_FOUR) {
454         HILOGE("size of parameters is larger than ARGS_SIZE_FOUR");
455         return nullptr;
456     }
457 
458     // "argc - 1" is AsyncCallback parameter's index
459     auto asyncCallback = std::make_shared<NapiAsyncCallback>();
460     asyncCallback->env = env;
461     if (argc > 0 && NapiIsFunction(env, argv[argc - 1]) == napi_ok) {
462         HILOGD("callback mode");
463         asyncCallback->callback = std::make_shared<NapiCallback>(env, argv[argc - 1]);
464     } else {
465         HILOGD("promise mode");
466         asyncCallback->promise = std::make_shared<NapiPromise>(env);
467     }
468     return asyncCallback;
469 }
470 
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)471 static napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty,
472     bool &outExist)
473 {
474     bool exist = false;
475     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
476     NAPI_BT_CALL_RETURN(napi_has_named_property(env, object, name, &exist));
477     if (exist) {
478         napi_value property;
479         NAPI_BT_CALL_RETURN(napi_get_named_property(env, object, name, &property));
480         outProperty = property;
481     }
482     outExist = exist;
483     return napi_ok;
484 }
NapiGetObjectProperty(napi_env env,napi_value object,const char * name,napi_value & outProperty)485 napi_status NapiGetObjectProperty(napi_env env, napi_value object, const char *name, napi_value &outProperty)
486 {
487     bool exist = false;
488     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, outProperty, exist));
489     NAPI_BT_RETURN_IF(!exist, "no needed property", napi_invalid_arg);
490     return napi_ok;
491 }
NapiGetObjectPropertyOptional(napi_env env,napi_value object,const char * name,napi_value & outProperty,bool & outExist)492 napi_status NapiGetObjectPropertyOptional(napi_env env, napi_value object, const char *name, napi_value &outProperty,
493     bool &outExist)
494 {
495     return NapiGetObjectProperty(env, object, name, outProperty, outExist);
496 }
497 
NapiParseObjectBoolean(napi_env env,napi_value object,const char * name,bool & outBoolean)498 napi_status NapiParseObjectBoolean(napi_env env, napi_value object, const char *name, bool &outBoolean)
499 {
500     napi_value property;
501     bool boolean = true;
502     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
503     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
504     NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
505     outBoolean = boolean;
506     return napi_ok;
507 }
508 
NapiParseObjectUuid(napi_env env,napi_value object,const char * name,std::string & outUuid)509 napi_status NapiParseObjectUuid(napi_env env, napi_value object, const char *name, std::string &outUuid)
510 {
511     napi_value property;
512     std::string uuid {};
513     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
514     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
515     NAPI_BT_CALL_RETURN(NapiParseUuid(env, property, uuid));
516     outUuid = std::move(uuid);
517     return napi_ok;
518 }
519 
NapiParseObjectArrayBuffer(napi_env env,napi_value object,const char * name,std::vector<uint8_t> & outVec)520 napi_status NapiParseObjectArrayBuffer(napi_env env, napi_value object, const char *name, std::vector<uint8_t> &outVec)
521 {
522     napi_value property;
523     std::vector<uint8_t> vec {};
524     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
525     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
526     NAPI_BT_CALL_RETURN(NapiParseArrayBuffer(env, property, vec));
527     outVec = std::move(vec);
528     return napi_ok;
529 }
530 
NapiParseObjectBdAddr(napi_env env,napi_value object,const char * name,std::string & outAddr)531 napi_status NapiParseObjectBdAddr(napi_env env, napi_value object, const char *name, std::string &outAddr)
532 {
533     napi_value property;
534     std::string bdaddr {};
535     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
536     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
537     NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, property, bdaddr));
538     outAddr = std::move(bdaddr);
539     return napi_ok;
540 }
541 
NapiParseObjectInt32(napi_env env,napi_value object,const char * name,int32_t & outNum)542 napi_status NapiParseObjectInt32(napi_env env, napi_value object, const char *name, int32_t &outNum)
543 {
544     napi_value property;
545     int32_t num = 0;
546     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
547     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
548     NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
549     outNum = num;
550     return napi_ok;
551 }
552 
NapiParseObjectString(napi_env env,napi_value object,const char * name,std::string & outString)553 napi_status NapiParseObjectString(napi_env env, napi_value object, const char *name, std::string &outString)
554 {
555     napi_value property;
556     std::string str = "";
557     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
558     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
559     NAPI_BT_CALL_RETURN(NapiParseString(env, property, str));
560     outString = str;
561     return napi_ok;
562 }
563 
NapiParseObjectUint32(napi_env env,napi_value object,const char * name,uint32_t & outNum)564 napi_status NapiParseObjectUint32(napi_env env, napi_value object, const char *name, uint32_t &outNum)
565 {
566     napi_value property;
567     uint32_t num = 0;
568     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
569     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
570     NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
571     outNum = num;
572     return napi_ok;
573 }
574 
NapiParseObjectBooleanOptional(napi_env env,napi_value object,const char * name,bool & outBoolean,bool & outExist)575 napi_status NapiParseObjectBooleanOptional(napi_env env, napi_value object, const char *name, bool &outBoolean,
576     bool &outExist)
577 {
578     napi_value property;
579     bool exist = false;
580     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
581     NAPI_BT_CALL_RETURN(NapiGetObjectPropertyOptional(env, object, name, property, exist));
582     if (exist) {
583         bool boolean = true;
584         NAPI_BT_CALL_RETURN(NapiParseBoolean(env, property, boolean));
585         outBoolean = boolean;
586     }
587     outExist = exist;
588     return napi_ok;
589 }
NapiParseObjectInt32Optional(napi_env env,napi_value object,const char * name,int32_t & outNum,bool & outExist)590 napi_status NapiParseObjectInt32Optional(napi_env env, napi_value object, const char *name, int32_t &outNum,
591     bool &outExist)
592 {
593     napi_value property;
594     bool exist = false;
595     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
596     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
597     if (exist) {
598         int32_t num = 0;
599         NAPI_BT_CALL_RETURN(NapiParseInt32(env, property, num));
600         outNum = num;
601     }
602     outExist = exist;
603     return napi_ok;
604 }
NapiParseObjectUint32Optional(napi_env env,napi_value object,const char * name,uint32_t & outNum,bool & outExist)605 napi_status NapiParseObjectUint32Optional(napi_env env, napi_value object, const char *name, uint32_t &outNum,
606     bool &outExist)
607 {
608     napi_value property;
609     bool exist = false;
610     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
611     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property, exist));
612     if (exist) {
613         uint32_t num = 0;
614         NAPI_BT_CALL_RETURN(NapiParseUint32(env, property, num));
615         outNum = num;
616     }
617     outExist = exist;
618     return napi_ok;
619 }
620 
621 // Parse params template, used for NapiParseArray
622 template <typename T>
NapiParseObject(napi_env env,napi_value object,T & outObj)623 napi_status NapiParseObject(napi_env env, napi_value object, T &outObj)
624 {
625     HILOGE("Unimpleted type");
626     return napi_invalid_arg;
627 }
628 
629 template <>
NapiParseObject(napi_env env,napi_value object,std::string & outObj)630 napi_status NapiParseObject<std::string>(napi_env env, napi_value object, std::string &outObj)
631 {
632     return NapiParseString(env, object, outObj);
633 }
634 
635 template <>
NapiParseObject(napi_env env,napi_value object,UUID & outObj)636 napi_status NapiParseObject<UUID>(napi_env env, napi_value object, UUID &outObj)
637 {
638     std::string uuid {};
639     NAPI_BT_CALL_RETURN(NapiParseUuid(env, object, uuid));
640     outObj = UUID::FromString(uuid);
641     return napi_ok;
642 }
643 
644 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvManufactureData & outObj)645 napi_status NapiParseObject<NapiAdvManufactureData>(napi_env env, napi_value object, NapiAdvManufactureData &outObj)
646 {
647     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"manufactureId", "manufactureValue"}));
648     uint32_t num = 0;
649     std::vector<uint8_t> vec {};
650     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
651     NAPI_BT_CALL_RETURN(NapiParseObjectUint32(env, object, "manufactureId", num));
652     NAPI_BT_RETURN_IF(num > 0xFFFF, "Invalid manufactureId", napi_invalid_arg);
653     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "manufactureValue", vec));
654 
655     outObj.id = static_cast<uint16_t>(num);
656     outObj.value = std::string(vec.begin(), vec.end());
657     return napi_ok;
658 }
659 
660 template <>
NapiParseObject(napi_env env,napi_value object,NapiAdvServiceData & outObj)661 napi_status NapiParseObject<NapiAdvServiceData>(napi_env env, napi_value object, NapiAdvServiceData &outObj)
662 {
663     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"serviceUuid", "serviceValue"}));
664     std::string uuid {};
665     std::vector<uint8_t> vec {};
666     NAPI_BT_CALL_RETURN(NapiIsObject(env, object));
667     NAPI_BT_CALL_RETURN(NapiParseObjectUuid(env, object, "serviceUuid", uuid));
668     NAPI_BT_CALL_RETURN(NapiParseObjectArrayBuffer(env, object, "serviceValue", vec));
669 
670     outObj.uuid = std::move(uuid);
671     outObj.value = std::move(vec);
672     return napi_ok;
673 }
674 
675 template <>
NapiParseObject(napi_env env,napi_value object,NapiGattService & outObj)676 napi_status NapiParseObject<NapiGattService>(napi_env env, napi_value object, NapiGattService &outObj)
677 {
678     return NapiParseGattService(env, object, outObj);
679 }
680 
681 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleCharacteristic & outObj)682 napi_status NapiParseObject<NapiBleCharacteristic>(napi_env env, napi_value object, NapiBleCharacteristic &outObj)
683 {
684     return NapiParseGattCharacteristic(env, object, outObj);
685 }
686 
687 template <>
NapiParseObject(napi_env env,napi_value object,NapiBleDescriptor & outObj)688 napi_status NapiParseObject<NapiBleDescriptor>(napi_env env, napi_value object, NapiBleDescriptor &outObj)
689 {
690     return NapiParseGattDescriptor(env, object, outObj);
691 }
692 
693 template <>
NapiParseObject(napi_env env,napi_value object,TrustPairDeviceParam & outObj)694 napi_status NapiParseObject<TrustPairDeviceParam>(napi_env env, napi_value object, TrustPairDeviceParam &outObj)
695 {
696     NAPI_BT_CALL_RETURN(NapiCheckObjectPropertiesName(env, object, {"sn", "deviceType",
697         "modelId", "manufactory", "productId", "hiLinkVersion", "macAddress", "serviceType",
698         "serviceId", "deviceName", "uuids", "bluetoothClass", "token", "deviceNameTime",
699         "secureAdvertisingInfo", "pairState"}));
700     NapiParseObjectStr(env, object, "sn", outObj.sn_);
701     NapiParseObjectStr(env, object, "deviceType", outObj.deviceType_);
702     NapiParseObjectStr(env, object, "modelId", outObj.modelId_);
703     NapiParseObjectStr(env, object, "manufactory", outObj.manufactory_);
704     NapiParseObjectStr(env, object, "productId", outObj.productId_);
705     NapiParseObjectStr(env, object, "hiLinkVersion", outObj.hiLinkVersion_);
706     NAPI_BT_CALL_RETURN(NapiParseObjectBdAddr(env, object, "macAddress", outObj.macAddress_));
707     NapiParseObjectStr(env, object, "serviceType", outObj.serviceType_);
708     NapiParseObjectStr(env, object, "serviceId", outObj.serviceId_);
709     NapiParseObjectStr(env, object, "deviceName", outObj.deviceName_);
710     NAPI_BT_CALL_RETURN(NapiParseObjectUuids(env, object, "uuids", outObj.uuids_));
711     NapiParseObjectInt32(env, object, "bluetoothClass", outObj.bluetoothClass_);
712     NapiParseObjectInt64(env, object, "deviceNameTime", outObj.deviceNameTime_);
713     NapiParseObjectInt32(env, object, "pairState", outObj.pairState_);
714     std::vector<uint8_t> tokenValue;
715     std::vector<uint8_t> secureAdvertisingInfoValue;
716     NapiParseObjectArrayBuffer(env, object, "token", tokenValue);
717     NapiParseObjectArrayBuffer(env, object, "secureAdvertisingInfo", secureAdvertisingInfoValue);
718     outObj.token_ = std::move(tokenValue);
719     outObj.secureAdvertisingInfo_ = std::move(secureAdvertisingInfoValue);
720     return napi_ok;
721 }
722 
723 template <typename T>
NapiParseArray(napi_env env,napi_value array,std::vector<T> & outVec)724 napi_status NapiParseArray(napi_env env, napi_value array, std::vector<T> &outVec)
725 {
726     std::vector<T> vec {};
727 
728     NAPI_BT_CALL_RETURN(NapiIsArray(env, array));
729     uint32_t length = 0;
730     NAPI_BT_CALL_RETURN(napi_get_array_length(env, array, &length));
731     for (uint32_t i = 0; i < length; ++i) {
732         napi_value element;
733         NAPI_BT_CALL_RETURN(napi_get_element(env, array, i, &element));
734         T object;
735         NAPI_BT_CALL_RETURN(NapiParseObject(env, element, object));
736         vec.push_back(std::move(object));
737     }
738     outVec = std::move(vec);
739     return napi_ok;
740 }
741 // // Declaration, ohters will undefined synbol
742 template napi_status NapiParseArray<NapiBleDescriptor>(napi_env env, napi_value array,
743     std::vector<NapiBleDescriptor> &outVec);
744 template napi_status NapiParseArray<NapiBleCharacteristic>(napi_env env, napi_value array,
745     std::vector<NapiBleCharacteristic> &outVec);
746 template napi_status NapiParseArray<NapiGattService>(napi_env env, napi_value array,
747     std::vector<NapiGattService> &outVec);
748 template napi_status NapiParseArray<NapiAdvServiceData>(napi_env env, napi_value array,
749     std::vector<NapiAdvServiceData> &outVec);
750 template napi_status NapiParseArray<NapiAdvManufactureData>(napi_env env, napi_value array,
751     std::vector<NapiAdvManufactureData> &outVec);
752 template napi_status NapiParseArray<UUID>(napi_env env, napi_value array,
753     std::vector<UUID> &outVec);
754 template napi_status NapiParseArray<std::string>(napi_env env, napi_value array,
755     std::vector<std::string> &outVec);
756 template napi_status NapiParseArray<TrustPairDeviceParam>(napi_env env, napi_value array,
757     std::vector<TrustPairDeviceParam> &outVec);
758 
759 template <typename T>
NapiParseObjectArray(napi_env env,napi_value object,const char * name,std::vector<T> & outVec)760 napi_status NapiParseObjectArray(napi_env env, napi_value object, const char *name, std::vector<T> &outVec)
761 {
762     napi_value property;
763     std::vector<T> vec {};
764     NAPI_BT_CALL_RETURN(NapiGetObjectProperty(env, object, name, property));
765     NAPI_BT_CALL_RETURN(NapiParseArray(env, property, vec));
766     outVec = std::move(vec);
767     return napi_ok;
768 }
769 // Declaration, ohters will undefined synbol
770 template napi_status NapiParseObjectArray<NapiBleDescriptor>(napi_env env, napi_value object, const char *name,
771     std::vector<NapiBleDescriptor> &outVec);
772 template napi_status NapiParseObjectArray<NapiBleCharacteristic>(napi_env env, napi_value object, const char *name,
773     std::vector<NapiBleCharacteristic> &outVec);
774 template napi_status NapiParseObjectArray<NapiGattService>(napi_env env, napi_value object, const char *name,
775     std::vector<NapiGattService> &outVec);
776 template napi_status NapiParseObjectArray<NapiAdvServiceData>(napi_env env, napi_value object, const char *name,
777     std::vector<NapiAdvServiceData> &outVec);
778 template napi_status NapiParseObjectArray<NapiAdvManufactureData>(napi_env env, napi_value object, const char *name,
779     std::vector<NapiAdvManufactureData> &outVec);
780 template napi_status NapiParseObjectArray<UUID>(napi_env env, napi_value object, const char *name,
781     std::vector<UUID> &outVec);
782 template napi_status NapiParseObjectArray<std::string>(napi_env env, napi_value object, const char *name,
783     std::vector<std::string> &outVec);
784 template napi_status NapiParseObjectArray<TrustPairDeviceParam>(napi_env env, napi_value object, const char *name,
785     std::vector<TrustPairDeviceParam> &outVec);
786 }  // namespace Bluetooth
787 }  // namespace OHOS
788