1 /*
2  * Copyright (C) 2021-2023 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 
16 #include "json_payload.h"
17 #include <securec.h>
18 
19 #include "cJSON.h"
20 #ifndef DFINDER_USE_MINI_NSTACKX
21 #include "coap_client.h"
22 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
23 #include "nstackx_dfinder_log.h"
24 #include "nstackx_dfinder_mgt_msg_log.h"
25 #include "nstackx_error.h"
26 #include "nstackx_device.h"
27 #include "nstackx_statistics.h"
28 #include "nstackx_device_local.h"
29 
30 #define TAG "nStackXCoAP"
31 
32 static const int DEVICE_TYPE_DEFAULT = 0;
33 
AddDeviceType(cJSON * data,const DeviceInfo * deviceInfo)34 static int32_t AddDeviceType(cJSON *data, const DeviceInfo *deviceInfo)
35 {
36     cJSON *item = NULL;
37 
38     if (deviceInfo->deviceType <= UINT8_MAX) {
39         item = cJSON_CreateNumber(deviceInfo->deviceType);
40         if (item == NULL || !cJSON_AddItemToObject(data, JSON_DEVICE_TYPE, item)) {
41             cJSON_Delete(item);
42             return NSTACKX_EFAILED;
43         }
44     } else {
45         item = cJSON_CreateNumber(DEVICE_TYPE_DEFAULT);
46         if (item == NULL || !cJSON_AddItemToObject(data, JSON_DEVICE_TYPE, item)) {
47             cJSON_Delete(item);
48             return NSTACKX_EFAILED;
49         }
50         item = cJSON_CreateNumber(deviceInfo->deviceType);
51         if (item == NULL || !cJSON_AddItemToObject(data, JSON_DEVICE_TYPE_EXTERN, item)) {
52             cJSON_Delete(item);
53             return NSTACKX_EFAILED;
54         }
55     }
56 
57     return NSTACKX_EOK;
58 }
59 
60 
AddDeviceJsonData(cJSON * data,const DeviceInfo * deviceInfo)61 static int32_t AddDeviceJsonData(cJSON *data, const DeviceInfo *deviceInfo)
62 {
63     cJSON *item = cJSON_CreateString(deviceInfo->deviceId);
64     if (item == NULL || !cJSON_AddItemToObject(data, JSON_DEVICE_ID, item)) {
65         cJSON_Delete(item);
66         return NSTACKX_EFAILED;
67     }
68 
69     item = cJSON_CreateString(deviceInfo->deviceName);
70     if (item == NULL || !cJSON_AddItemToObject(data, JSON_DEVICE_NAME, item)) {
71         cJSON_Delete(item);
72         return NSTACKX_EFAILED;
73     }
74 
75     if (AddDeviceType(data, deviceInfo) != NSTACKX_EOK) {
76         return NSTACKX_EFAILED;
77     }
78 
79     item = cJSON_CreateString(deviceInfo->version);
80     if (item == NULL || !cJSON_AddItemToObject(data, JSON_HICOM_VERSION, item)) {
81         cJSON_Delete(item);
82         return NSTACKX_EFAILED;
83     }
84 
85     item = cJSON_CreateNumber(deviceInfo->mode);
86     if (item == NULL || !cJSON_AddItemToObject(data, JSON_REQUEST_MODE, item)) {
87         cJSON_Delete(item);
88         return NSTACKX_EFAILED;
89     }
90 
91     item = cJSON_CreateString(deviceInfo->deviceHash);
92     if (item == NULL || !cJSON_AddItemToObject(data, JSON_DEVICE_HASH, item)) {
93         cJSON_Delete(item);
94         return NSTACKX_EFAILED;
95     }
96 
97     item = cJSON_CreateString(deviceInfo->serviceData);
98     if (item == NULL || !cJSON_AddItemToObject(data, JSON_SERVICE_DATA, item)) {
99         cJSON_Delete(item);
100         DFINDER_LOGE(TAG, "cJSON_CreateString for serviceData failed");
101         return NSTACKX_EFAILED;
102     }
103 
104 #ifndef DFINDER_USE_MINI_NSTACKX
105     item = cJSON_CreateString(deviceInfo->extendServiceData);
106     if (item == NULL || !cJSON_AddItemToObject(data, JSON_EXTEND_SERVICE_DATA, item)) {
107         cJSON_Delete(item);
108         DFINDER_LOGE(TAG, "cJSON_CreateString for extendServiceData failed");
109         return NSTACKX_EFAILED;
110     }
111 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
112 
113     return NSTACKX_EOK;
114 }
115 
AddCapabilityBitmap(cJSON * data,const DeviceInfo * deviceInfo)116 static int32_t AddCapabilityBitmap(cJSON *data, const DeviceInfo *deviceInfo)
117 {
118     cJSON *capabilityArray = NULL;
119     cJSON *capability = NULL;
120     uint32_t i;
121 
122     if (deviceInfo->capabilityBitmapNum == 0) {
123         return NSTACKX_EOK;
124     }
125 
126     capabilityArray = cJSON_CreateArray();
127     if (capabilityArray == NULL) {
128         goto L_END_JSON;
129     }
130 
131     for (i = 0; i < deviceInfo->capabilityBitmapNum; i++) {
132         capability = cJSON_CreateNumber(deviceInfo->capabilityBitmap[i]);
133         if (capability == NULL || !cJSON_AddItemToArray(capabilityArray, capability)) {
134             cJSON_Delete(capability);
135             goto L_END_JSON;
136         }
137     }
138     if (!cJSON_AddItemToObject(data, JSON_CAPABILITY_BITMAP, capabilityArray)) {
139         goto L_END_JSON;
140     }
141 
142     return NSTACKX_EOK;
143 
144 L_END_JSON:
145     cJSON_Delete(capabilityArray);
146     return NSTACKX_EFAILED;
147 }
148 
AddBusinessJsonData(cJSON * data,const DeviceInfo * deviceInfo,uint8_t isBroadcast,uint8_t businessType)149 static int32_t AddBusinessJsonData(cJSON *data, const DeviceInfo *deviceInfo, uint8_t isBroadcast, uint8_t businessType)
150 {
151     uint8_t tmpType = (isBroadcast) ? deviceInfo->businessType : businessType;
152     cJSON *item = cJSON_CreateNumber(tmpType);
153     if (item == NULL || !cJSON_AddItemToObject(data, JSON_BUSINESS_TYPE, item)) {
154         cJSON_Delete(item);
155         DFINDER_LOGE(TAG, "cJSON_CreateString for businessType failed");
156         return NSTACKX_EFAILED;
157     }
158     if (isBroadcast) {
159         item = cJSON_CreateString(deviceInfo->businessData.businessDataBroadcast);
160     } else {
161         item = cJSON_CreateString(deviceInfo->businessData.businessDataUnicast);
162     }
163     if (item == NULL || !cJSON_AddItemToObject(data, JSON_BUSINESS_DATA, item)) {
164         cJSON_Delete(item);
165         DFINDER_LOGE(TAG, "cJSON_CreateString for businessData failed");
166         return NSTACKX_EFAILED;
167     }
168 
169     return NSTACKX_EOK;
170 }
171 
AddSequenceNumber(cJSON * data,uint8_t sendBcast)172 static int32_t AddSequenceNumber(cJSON *data, uint8_t sendBcast)
173 {
174     cJSON *item = cJSON_CreateNumber(GetSequenceNumber(sendBcast));
175     if (item == NULL || !cJSON_AddItemToObject(data, JSON_SEQUENCE_NUMBER, item)) {
176         cJSON_Delete(item);
177         DFINDER_LOGE(TAG, "cJSON_CreateNumber for sequence number failed");
178         return NSTACKX_EFAILED;
179     }
180     return NSTACKX_EOK;
181 }
182 
ParseDeviceJsonData(const cJSON * data,DeviceInfo * dev)183 static int32_t ParseDeviceJsonData(const cJSON *data, DeviceInfo *dev)
184 {
185     cJSON *item = NULL;
186 
187     item = cJSON_GetObjectItemCaseSensitive(data, JSON_DEVICE_ID);
188     if (!cJSON_IsString(item) || !strlen(item->valuestring)) {
189         DFINDER_LOGE(TAG, "Cannot find device ID or invalid device ID");
190         return NSTACKX_EINVAL;
191     }
192     if (strcpy_s(dev->deviceId, sizeof(dev->deviceId), item->valuestring) != EOK) {
193         return NSTACKX_EFAILED;
194     }
195 
196     item = cJSON_GetObjectItemCaseSensitive(data, JSON_DEVICE_NAME);
197     if (!cJSON_IsString(item) || !strlen(item->valuestring)) {
198         DFINDER_LOGE(TAG, "Cannot find device name or invalid device name");
199         return NSTACKX_EINVAL;
200     }
201     if (strcpy_s(dev->deviceName, sizeof(dev->deviceName), item->valuestring) != EOK) {
202         return NSTACKX_EFAILED;
203     }
204 
205     item = cJSON_GetObjectItemCaseSensitive(data, JSON_DEVICE_TYPE);
206     if (!cJSON_IsNumber(item) || (item->valuedouble < 0) || (item->valuedouble > 0xFF)) {
207         DFINDER_LOGE(TAG, "Cannot find device type or invalid device type");
208         return NSTACKX_EINVAL;
209     }
210     dev->deviceType = (uint32_t)item->valuedouble;
211     if (dev->deviceType == DEVICE_TYPE_DEFAULT) {
212         item = cJSON_GetObjectItemCaseSensitive(data, JSON_DEVICE_TYPE_EXTERN);
213         if (!cJSON_IsNumber(item) || (item->valuedouble < 0) || (item->valuedouble > UINT32_MAX)) {
214             DFINDER_LOGI(TAG, "Cannot find device type or invalid device type extern");
215         } else {
216             dev->deviceType = (uint32_t)item->valuedouble;
217         }
218     }
219 
220     item = cJSON_GetObjectItemCaseSensitive(data, JSON_HICOM_VERSION);
221     if (!cJSON_IsString(item) || !strlen(item->valuestring)) {
222         DFINDER_LOGD(TAG, "Can't find hicom version");
223         return NSTACKX_EOK;
224     }
225     if (strcpy_s(dev->version, sizeof(dev->version), item->valuestring) != EOK) {
226         return NSTACKX_EFAILED;
227     }
228 
229     return NSTACKX_EOK;
230 }
231 
ParseWifiApJsonData(const cJSON * data,DeviceInfo * dev)232 static void ParseWifiApJsonData(const cJSON *data, DeviceInfo *dev)
233 {
234     cJSON *item = NULL;
235 
236     item = cJSON_GetObjectItemCaseSensitive(data, JSON_DEVICE_WLAN_IP);
237     if (cJSON_IsString(item)) {
238         if (inet_pton(AF_INET, item->valuestring, &(dev->netChannelInfo.wifiApInfo.ip)) != 1) {
239             DFINDER_LOGW(TAG, "Invalid ip address");
240         } else {
241             dev->netChannelInfo.wifiApInfo.state = NET_CHANNEL_STATE_CONNETED;
242         }
243     }
244 }
245 
ParseModeJsonData(const cJSON * data,DeviceInfo * dev)246 static void ParseModeJsonData(const cJSON *data, DeviceInfo *dev)
247 {
248     cJSON *item = NULL;
249     item = cJSON_GetObjectItemCaseSensitive(data, JSON_REQUEST_MODE);
250     if (item == NULL) {
251         DFINDER_LOGE(TAG, "Cannot get mode json");
252         return;
253     }
254     if (!cJSON_IsNumber(item) || (item->valuedouble < 0)) {
255         DFINDER_LOGE(TAG, "Cannot find mode or invalid mode");
256     } else {
257         if (dev == NULL) {
258             DFINDER_LOGE(TAG, "device info is null");
259             return;
260         }
261         dev->mode = (uint8_t)item->valuedouble;
262     }
263 }
264 
ParseDeviceHashData(const cJSON * data,DeviceInfo * dev)265 static void ParseDeviceHashData(const cJSON *data, DeviceInfo *dev)
266 {
267     cJSON *item = NULL;
268     item = cJSON_GetObjectItemCaseSensitive(data, JSON_DEVICE_HASH);
269     if (item == NULL) {
270         DFINDER_LOGD(TAG, "Cannot get hash json");
271         return;
272     }
273     if (item->valuestring == NULL) {
274         DFINDER_LOGD(TAG, "Cannot get valuestring");
275         return;
276     }
277     if (!cJSON_IsString(item) || !strlen(item->valuestring)) {
278         DFINDER_LOGD(TAG, "Cannot find device hash or invalid hash");
279         return;
280     }
281     if (strcpy_s(dev->deviceHash, sizeof(dev->deviceHash), item->valuestring) != EOK) {
282         DFINDER_LOGE(TAG, "parse device hash data error");
283         return;
284     }
285 }
286 
ParseServiceDataJsonData(const cJSON * data,DeviceInfo * dev)287 static void ParseServiceDataJsonData(const cJSON *data, DeviceInfo *dev)
288 {
289     cJSON *item = NULL;
290     item = cJSON_GetObjectItemCaseSensitive(data, JSON_SERVICE_DATA);
291     if (item == NULL) {
292         DFINDER_LOGE(TAG, "Cannot get service data");
293         return;
294     }
295     if (!cJSON_IsString(item)) {
296         DFINDER_LOGE(TAG, "Cannot find serviceData");
297         return;
298     }
299     if (item->valuestring == NULL) {
300         DFINDER_LOGE(TAG, "item->valuestring is null");
301         return;
302     }
303     if (strcpy_s(dev->serviceData, sizeof(dev->serviceData), item->valuestring)) {
304         DFINDER_LOGE(TAG, "parse device serviceData error");
305         return;
306     }
307 }
308 
309 #ifndef DFINDER_USE_MINI_NSTACKX
ParseExtendServiceDataJsonData(const cJSON * data,DeviceInfo * dev)310 static void ParseExtendServiceDataJsonData(const cJSON *data, DeviceInfo *dev)
311 {
312     cJSON *item = NULL;
313     item = cJSON_GetObjectItemCaseSensitive(data, JSON_EXTEND_SERVICE_DATA);
314     if (item == NULL) {
315         DFINDER_LOGD(TAG, "Cannot get service data");
316         return;
317     }
318     if (!cJSON_IsString(item)) {
319         DFINDER_LOGD(TAG, "Cannot find extendServiceData");
320         return;
321     }
322     if (item->valuestring == NULL) {
323         DFINDER_LOGD(TAG, "item->valuestring is null");
324         return;
325     }
326     if (strcpy_s(dev->extendServiceData, sizeof(dev->extendServiceData), item->valuestring)) {
327         DFINDER_LOGD(TAG, "parse device extendServiceData error");
328         return;
329     }
330 }
331 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
332 
ParseCapabilityBitmap(const cJSON * data,DeviceInfo * deviceInfo)333 static void ParseCapabilityBitmap(const cJSON *data, DeviceInfo *deviceInfo)
334 {
335     cJSON *capability = NULL;
336     cJSON *item = NULL;
337     uint32_t capabilityBitmapNum = 0;
338 
339     item = cJSON_GetObjectItemCaseSensitive(data, JSON_CAPABILITY_BITMAP);
340     if (cJSON_IsArray(item)) {
341         cJSON_ArrayForEach(capability, item) {
342             if (capabilityBitmapNum >= NSTACKX_MAX_CAPABILITY_NUM) {
343                 break;
344             }
345 
346             if (!cJSON_IsNumber(capability) ||
347                 capability->valuedouble < 0 ||
348                 capability->valuedouble > 0xFFFFFFFF) {
349                 /* skip invalid capability */
350                 continue;
351             }
352             deviceInfo->capabilityBitmap[capabilityBitmapNum++] = (uint32_t)capability->valuedouble;
353         }
354     }
355     deviceInfo->capabilityBitmapNum = capabilityBitmapNum;
356 }
357 
ParseBusinessType(const cJSON * data,DeviceInfo * dev)358 static void ParseBusinessType(const cJSON *data, DeviceInfo *dev)
359 {
360     cJSON *item = NULL;
361     item = cJSON_GetObjectItemCaseSensitive(data, JSON_BUSINESS_TYPE);
362     if (item == NULL) {
363         dev->businessType = NSTACKX_BUSINESS_TYPE_NULL;
364         DFINDER_LOGD(TAG, "Cannot get businessType json");
365         return;
366     }
367     if (!cJSON_IsNumber(item) || (item->valuedouble < 0)) {
368         dev->businessType = NSTACKX_BUSINESS_TYPE_NULL;
369         DFINDER_LOGE(TAG, "Cannot find businessType or invalid Type");
370     } else {
371         dev->businessType = (uint8_t)item->valuedouble;
372     }
373 }
374 
ParseBusinessDataJsonData(const cJSON * data,DeviceInfo * dev,uint8_t isBroadcast)375 static void ParseBusinessDataJsonData(const cJSON *data, DeviceInfo *dev, uint8_t isBroadcast)
376 {
377     cJSON *item = NULL;
378     item = cJSON_GetObjectItemCaseSensitive(data, JSON_BUSINESS_DATA);
379     if (item == NULL) {
380         DFINDER_LOGD(TAG, "Cannot get businessData json");
381         return;
382     }
383     if (!cJSON_IsString(item)) {
384         DFINDER_LOGE(TAG, "Cannot find businessData");
385         return;
386     }
387     if (isBroadcast == NSTACKX_TRUE) {
388         if (strcpy_s(dev->businessData.businessDataBroadcast,
389             sizeof(dev->businessData.businessDataBroadcast), item->valuestring)) {
390             DFINDER_LOGE(TAG, "parse device businessData error");
391             return;
392         }
393     } else {
394         if (strcpy_s(dev->businessData.businessDataUnicast,
395             sizeof(dev->businessData.businessDataUnicast), item->valuestring)) {
396             DFINDER_LOGE(TAG, "parse device businessData error");
397             return;
398         }
399     }
400 }
401 
ParseSequenceNumber(const cJSON * data,DeviceInfo * dev,uint8_t isBroadcast)402 static void ParseSequenceNumber(const cJSON *data, DeviceInfo *dev, uint8_t isBroadcast)
403 {
404     cJSON *item = cJSON_GetObjectItemCaseSensitive(data, JSON_SEQUENCE_NUMBER);
405     if (item == NULL) {
406         return;
407     }
408     if (!cJSON_IsNumber(item) || (item->valueint < 0) || (item->valueint > UINT16_MAX)) {
409         DFINDER_LOGE(TAG, "invalid sequence number");
410         return;
411     }
412     dev->seq.dealBcast = isBroadcast;
413     if (isBroadcast) {
414         dev->seq.seqBcast = (uint16_t)item->valueint;
415     } else {
416         dev->seq.seqUcast = (uint16_t)item->valueint;
417     }
418 }
419 
JsonAddStr(cJSON * data,const char * key,const char * value)420 static int JsonAddStr(cJSON *data, const char *key, const char *value)
421 {
422     cJSON *item = cJSON_CreateString(value);
423     if (item == NULL || !cJSON_AddItemToObject(data, key, item)) {
424         cJSON_Delete(item);
425         return NSTACKX_EFAILED;
426     }
427 
428     return NSTACKX_EOK;
429 }
430 
431 /*
432  * Service Discover JSON format
433  * {
434  *   "deviceId":[device ID, string],
435  *   "deviceName":[device name, string],
436  *   "type": [device type, number],
437  *   "version":[hicom version, string],
438  *   "wlanIp":[WLAN IP address, string],
439  *   "capabilityBitmap":[bitmap, bitmap, bitmap, ...]
440  *   "coapUri":[coap uri for discover, string]   <-- optional. When present, means it's broadcast request.
441  * }
442  */
PrepareServiceDiscoverEx(const char * locaIpStr,uint8_t isBroadcast,uint8_t businessType)443 static char *PrepareServiceDiscoverEx(const char *locaIpStr, uint8_t isBroadcast, uint8_t businessType)
444 {
445     cJSON *data = cJSON_CreateObject();
446     if (data == NULL) {
447         DFINDER_LOGE(TAG, "create json object failed");
448         return NULL;
449     }
450 
451     char *formatString = NULL;
452     const DeviceInfo *deviceInfo = GetLocalDeviceInfo();
453     /* Prepare local device info */
454     if ((AddDeviceJsonData(data, deviceInfo) != NSTACKX_EOK) ||
455         (JsonAddStr(data, JSON_DEVICE_WLAN_IP, locaIpStr) != NSTACKX_EOK) ||
456         (AddCapabilityBitmap(data, deviceInfo) != NSTACKX_EOK) ||
457         (AddBusinessJsonData(data, deviceInfo, isBroadcast, businessType) != NSTACKX_EOK) ||
458         (AddSequenceNumber(data, isBroadcast) != NSTACKX_EOK)) {
459         DFINDER_LOGE(TAG, "Add json data failed");
460         goto L_END_JSON;
461     }
462 
463     if (isBroadcast) {
464         char coapUriBuffer[NSTACKX_MAX_URI_BUFFER_LENGTH] = {0};
465         if (sprintf_s(coapUriBuffer, sizeof(coapUriBuffer), "coap://%s/" COAP_DEVICE_DISCOVER_URI, locaIpStr) < 0) {
466             DFINDER_LOGE(TAG, "deal coap url failed");
467             goto L_END_JSON;
468         }
469 
470         cJSON *localCoapString = cJSON_CreateString(coapUriBuffer);
471         if (localCoapString == NULL || !cJSON_AddItemToObject(data, JSON_COAP_URI, localCoapString)) {
472             cJSON_Delete(localCoapString);
473             DFINDER_LOGE(TAG, "local coap string failed");
474             goto L_END_JSON;
475         }
476     }
477 
478     formatString = cJSON_PrintUnformatted(data);
479     if (formatString == NULL) {
480         DFINDER_LOGE(TAG, "cJSON_PrintUnformatted failed");
481     }
482 
483 L_END_JSON:
484     cJSON_Delete(data);
485     return formatString;
486 }
487 
PrepareServiceDiscover(const char * localIpStr,uint8_t isBroadcast,uint8_t businessType)488 char *PrepareServiceDiscover(const char *localIpStr, uint8_t isBroadcast, uint8_t businessType)
489 {
490     char *str = PrepareServiceDiscoverEx(localIpStr, isBroadcast, businessType);
491     if (str == NULL) {
492         DFINDER_LOGE(TAG, "prepare service discover ex failed");
493         IncStatistics(STATS_PREPARE_SD_MSG_FAILED);
494     }
495     return str;
496 }
497 
ParseServiceDiscoverEx(const uint8_t * buf,DeviceInfo * deviceInfo,char ** remoteUrlPtr)498 static int32_t ParseServiceDiscoverEx(const uint8_t *buf, DeviceInfo *deviceInfo, char **remoteUrlPtr)
499 {
500     char *remoteUrl = NULL;
501     cJSON *data = NULL;
502     cJSON *item = NULL;
503     uint8_t isBroadcast = NSTACKX_FALSE;
504 
505     if (buf == NULL || deviceInfo == NULL || remoteUrlPtr == NULL) {
506         DFINDER_LOGE(TAG, "invalid params passed in");
507         return NSTACKX_EINVAL;
508     }
509 
510     data = cJSON_Parse((char *)buf);
511     if (data == NULL) {
512         DFINDER_LOGE(TAG, "cJSON_Parse buf return null");
513         return NSTACKX_EINVAL;
514     }
515 
516     if (ParseDeviceJsonData(data, deviceInfo) != NSTACKX_EOK) {
517         cJSON_Delete(data);
518         return NSTACKX_EINVAL;
519     }
520 
521     ParseWifiApJsonData(data, deviceInfo);
522     ParseCapabilityBitmap(data, deviceInfo);
523     ParseModeJsonData(data, deviceInfo);
524     ParseDeviceHashData(data, deviceInfo);
525     ParseServiceDataJsonData(data, deviceInfo);
526 #ifndef DFINDER_USE_MINI_NSTACKX
527     ParseExtendServiceDataJsonData(data, deviceInfo);
528 #endif /* END OF DFINDER_USE_MINI_NSTACKX */
529     ParseBusinessType(data, deviceInfo);
530 
531     item = cJSON_GetObjectItemCaseSensitive(data, JSON_COAP_URI);
532     if (item != NULL) {
533         isBroadcast = NSTACKX_TRUE;
534         if (cJSON_IsString(item)) {
535             DFINDER_LOGD(TAG, "new device join");
536             remoteUrl = strdup(item->valuestring);
537             if (remoteUrl == NULL) {
538                 DFINDER_LOGE(TAG, "remoteUrl strdup fail");
539                 cJSON_Delete(data);
540                 return NSTACKX_ENOMEM;
541             }
542         }
543     }
544     ParseBusinessDataJsonData(data, deviceInfo, isBroadcast);
545     deviceInfo->businessData.isBroadcast = isBroadcast;
546     ParseSequenceNumber(data, deviceInfo, isBroadcast);
547     *remoteUrlPtr = remoteUrl;
548     cJSON_Delete(data);
549     DFINDER_MGT_UNPACK_LOG(deviceInfo);
550     return NSTACKX_EOK;
551 }
552 
ParseServiceDiscover(const uint8_t * buf,struct DeviceInfo * deviceInfo,char ** remoteUrlPtr)553 int32_t ParseServiceDiscover(const uint8_t *buf, struct DeviceInfo *deviceInfo, char **remoteUrlPtr)
554 {
555     int32_t ret = ParseServiceDiscoverEx(buf, deviceInfo, remoteUrlPtr);
556     if (ret != NSTACKX_EOK) {
557         IncStatistics(STATS_PARSE_SD_MSG_FAILED);
558     }
559     return ret;
560 }
561 
PrepareServiceNotificationEx(void)562 static char *PrepareServiceNotificationEx(void)
563 {
564     cJSON *data = cJSON_CreateObject();
565     if (data == NULL) {
566         DFINDER_LOGE(TAG, "cJSON_CreateObject failed");
567         return NULL;
568     }
569     const DeviceInfo *deviceInfo = GetLocalDeviceInfo();
570     if (JsonAddStr(data, JSON_NOTIFICATION, deviceInfo->notification) != NSTACKX_EOK) {
571         DFINDER_LOGE(TAG, "add json data: %s fail", JSON_NOTIFICATION);
572         cJSON_Delete(data);
573         return NULL;
574     }
575     char *formatString = cJSON_PrintUnformatted(data);
576     if (formatString == NULL) {
577         DFINDER_LOGE(TAG, "cJSON_PrintUnformatted return null");
578     }
579     cJSON_Delete(data);
580     return formatString;
581 }
582 
PrepareServiceNotification(void)583 char *PrepareServiceNotification(void)
584 {
585     char *str = PrepareServiceNotificationEx();
586     if (str == NULL) {
587         IncStatistics(STATS_PREPARE_SN_MSG_FAILED);
588     }
589     return str;
590 }
591 
ParseServiceNotification(const uint8_t * buf,NSTACKX_NotificationConfig * config)592 int32_t ParseServiceNotification(const uint8_t *buf, NSTACKX_NotificationConfig *config)
593 {
594     if (buf == NULL || config == NULL) {
595         DFINDER_LOGE(TAG, "buf or notification config is null");
596         return NSTACKX_EINVAL;
597     }
598     cJSON *data = cJSON_Parse((char *)buf);
599     if (data == NULL) {
600         DFINDER_LOGE(TAG, "cJSON_Parse buf fail");
601         return NSTACKX_EINVAL;
602     }
603     cJSON *item = cJSON_GetObjectItemCaseSensitive(data, JSON_NOTIFICATION);
604     if (item == NULL) {
605         DFINDER_LOGE(TAG, "can not get service notification");
606         goto LERR;
607     }
608     if (!cJSON_IsString(item)) {
609         DFINDER_LOGE(TAG, "json notification data not in string format");
610         goto LERR;
611     }
612     if (item->valuestring == NULL || strlen(item->valuestring) > NSTACKX_MAX_NOTIFICATION_DATA_LEN - 1) {
613         DFINDER_LOGE(TAG, "parsed out illegal notification data len");
614         goto LERR;
615     }
616     config->msgLen = strlen(item->valuestring);
617     if (strcpy_s(config->msg, NSTACKX_MAX_NOTIFICATION_DATA_LEN, item->valuestring) != EOK) {
618         DFINDER_LOGE(TAG, "copy notification fail, errno: %d, desc: %s", errno, strerror(errno));
619         goto LERR;
620     }
621     cJSON_Delete(data);
622     return NSTACKX_EOK;
623 LERR:
624     cJSON_Delete(data);
625     return NSTACKX_EFAILED;
626 }
627