1 /*
2  * Copyright (c) 2021-2024 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 "disc_nstackx_adapter.h"
17 
18 #include <locale.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <wchar.h>
23 
24 #include "nstackx.h"
25 #include "anonymizer.h"
26 #include "bus_center_manager.h"
27 #include "disc_coap_capability.h"
28 #include "disc_coap_parser.h"
29 #include "disc_log.h"
30 #include "securec.h"
31 #include "softbus_adapter_mem.h"
32 #include "softbus_adapter_thread.h"
33 #include "softbus_def.h"
34 #include "softbus_errcode.h"
35 #include "softbus_feature_config.h"
36 #include "softbus_hidumper_disc.h"
37 #include "softbus_hisysevt_discreporter.h"
38 #include "softbus_json_utils.h"
39 #include "softbus_utils.h"
40 
41 #define WLAN_IFACE_NAME_PREFIX "wlan"
42 #define INVALID_IP_ADDR        "0.0.0.0"
43 #define LOOPBACK_IP_ADDR       "127.0.0.1"
44 #define DISC_FREQ_COUNT_MASK   0xFFFF
45 #define DISC_FREQ_DURATION_BIT 16
46 #define DISC_USECOND           1000
47 #define MULTI_BYTE_CHAR_LEN    8
48 #define MAX_WIDE_STR_LEN       128
49 #define DEFAULT_MAX_DEVICE_NUM 20
50 
51 #define NSTACKX_LOCAL_DEV_INFO "NstackxLocalDevInfo"
52 
53 static NSTACKX_LocalDeviceInfo *g_localDeviceInfo = NULL;
54 static DiscInnerCallback *g_discCoapInnerCb = NULL;
55 static SoftBusMutex g_localDeviceInfoLock = {0};
56 static SoftBusMutex g_discCoapInnerCbLock = {0};
57 static int32_t NstackxLocalDevInfoDump(int fd);
58 
FillRspSettings(NSTACKX_ResponseSettings * settings,const DeviceInfo * deviceInfo,uint8_t bType)59 static int32_t FillRspSettings(NSTACKX_ResponseSettings *settings, const DeviceInfo *deviceInfo, uint8_t bType)
60 {
61     settings->businessData = NULL;
62     settings->length = 0;
63     settings->businessType = bType;
64     char localNetifName[NET_IF_NAME_LEN] = {0};
65     int32_t ret = LnnGetLocalStrInfo(STRING_KEY_NET_IF_NAME, localNetifName, sizeof(localNetifName));
66     if (ret != SOFTBUS_OK) {
67         DISC_LOGE(DISC_COAP, "get local network name from LNN failed, ret=%{public}d", ret);
68         return ret;
69     }
70     if (strcpy_s(settings->localNetworkName, sizeof(settings->localNetworkName), localNetifName) != EOK) {
71         DISC_LOGE(DISC_COAP, "copy disc response settings network name failed");
72         goto EXIT;
73     }
74     if (strcpy_s(settings->remoteIp, sizeof(settings->remoteIp), deviceInfo->addr[0].info.ip.ip) != EOK) {
75         DISC_LOGE(DISC_COAP, "copy disc response settings remote IP failed");
76         goto EXIT;
77     }
78     return SOFTBUS_OK;
79 EXIT:
80     return SOFTBUS_STRCPY_ERR;
81 }
82 
DiscCoapSendRsp(const DeviceInfo * deviceInfo,uint8_t bType)83 int32_t DiscCoapSendRsp(const DeviceInfo *deviceInfo, uint8_t bType)
84 {
85     DISC_CHECK_AND_RETURN_RET_LOGE(deviceInfo, SOFTBUS_INVALID_PARAM, DISC_COAP, "DiscRsp devInfo is null");
86     NSTACKX_ResponseSettings *settings = (NSTACKX_ResponseSettings *)SoftBusCalloc(sizeof(NSTACKX_ResponseSettings));
87     DISC_CHECK_AND_RETURN_RET_LOGE(settings, SOFTBUS_MALLOC_ERR, DISC_COAP, "malloc disc response settings failed");
88 
89     int32_t ret = FillRspSettings(settings, deviceInfo, bType);
90     if (ret != SOFTBUS_OK) {
91         DISC_LOGE(DISC_COAP, "fill nstackx response settings failed");
92         SoftBusFree(settings);
93         return ret;
94     }
95 
96     DISC_LOGI(DISC_COAP, "send rsp with bType=%{public}u", bType);
97     ret = NSTACKX_SendDiscoveryRsp(settings);
98     if (ret != SOFTBUS_OK) {
99         DISC_LOGE(DISC_COAP, "disc send response failed, ret=%{public}d", ret);
100     }
101     SoftBusFree(settings);
102     return ret;
103 }
104 
ParseReservedInfo(const NSTACKX_DeviceInfo * nstackxDevice,DeviceInfo * device)105 static int32_t ParseReservedInfo(const NSTACKX_DeviceInfo *nstackxDevice, DeviceInfo *device)
106 {
107     cJSON *reserveInfo = cJSON_Parse(nstackxDevice->reservedInfo);
108     DISC_CHECK_AND_RETURN_RET_LOGE(reserveInfo != NULL, SOFTBUS_PARSE_JSON_ERR, DISC_COAP,
109         "parse reserve data failed.");
110 
111     DiscCoapParseWifiIpAddr(reserveInfo, device);
112     DiscCoapParseHwAccountHash(reserveInfo, device);
113     if (DiscCoapParseServiceData(reserveInfo, device) != SOFTBUS_OK) {
114         DISC_LOGD(DISC_COAP, "parse service data failed");
115     }
116     cJSON_Delete(reserveInfo);
117     return SOFTBUS_OK;
118 }
119 
ParseDiscDevInfo(const NSTACKX_DeviceInfo * nstackxDevInfo,DeviceInfo * discDevInfo)120 static int32_t ParseDiscDevInfo(const NSTACKX_DeviceInfo *nstackxDevInfo, DeviceInfo *discDevInfo)
121 {
122     if (strcpy_s(discDevInfo->devName, sizeof(discDevInfo->devName), nstackxDevInfo->deviceName) != EOK ||
123         memcpy_s(discDevInfo->capabilityBitmap, sizeof(discDevInfo->capabilityBitmap),
124                  nstackxDevInfo->capabilityBitmap, sizeof(nstackxDevInfo->capabilityBitmap)) != EOK) {
125         DISC_LOGE(DISC_COAP, "strcpy_s devName or memcpy_s capabilityBitmap failed.");
126         return SOFTBUS_MEM_ERR;
127     }
128 
129     discDevInfo->devType = (DeviceType)nstackxDevInfo->deviceType;
130     discDevInfo->capabilityBitmapNum = nstackxDevInfo->capabilityBitmapNum;
131 
132     if (strncmp(nstackxDevInfo->networkName, WLAN_IFACE_NAME_PREFIX, strlen(WLAN_IFACE_NAME_PREFIX)) == 0) {
133         discDevInfo->addr[0].type = CONNECTION_ADDR_WLAN;
134     } else {
135         discDevInfo->addr[0].type = CONNECTION_ADDR_ETH;
136     }
137 
138     int32_t ret = DiscCoapParseDeviceUdid(nstackxDevInfo->deviceId, discDevInfo);
139     if (ret != SOFTBUS_OK) {
140         DISC_LOGE(DISC_COAP, "parse device udid failed.");
141         return ret;
142     }
143 
144     ret = ParseReservedInfo(nstackxDevInfo, discDevInfo);
145     if (ret != SOFTBUS_OK) {
146         DISC_LOGE(DISC_COAP, "parse reserve information failed.");
147         return ret;
148     }
149     // coap not support range now, just assign -1 as unknown
150     discDevInfo->range = -1;
151 
152     return SOFTBUS_OK;
153 }
154 
OnDeviceFound(const NSTACKX_DeviceInfo * deviceList,uint32_t deviceCount)155 static void OnDeviceFound(const NSTACKX_DeviceInfo *deviceList, uint32_t deviceCount)
156 {
157     DISC_CHECK_AND_RETURN_LOGE(deviceList != NULL && deviceCount != 0, DISC_COAP, "invalid param.");
158     DISC_LOGD(DISC_COAP, "Disc device found, count=%{public}u", deviceCount);
159     DeviceInfo *discDeviceInfo = (DeviceInfo *)SoftBusCalloc(sizeof(DeviceInfo));
160     DISC_CHECK_AND_RETURN_LOGE(discDeviceInfo != NULL, DISC_COAP, "malloc device info failed.");
161 
162     int32_t ret;
163     for (uint32_t i = 0; i < deviceCount; i++) {
164         const NSTACKX_DeviceInfo *nstackxDeviceInfo = deviceList + i;
165         if (nstackxDeviceInfo == NULL) {
166             DISC_LOGE(DISC_COAP, "device count from nstackx is invalid");
167             SoftBusFree(discDeviceInfo);
168             return;
169         }
170 
171         if ((nstackxDeviceInfo->update & 0x1) == 0) {
172             char *anonymizedName = NULL;
173             Anonymize(nstackxDeviceInfo->deviceName, &anonymizedName);
174             DISC_LOGI(DISC_COAP, "duplicate device do not need report. deviceName=%{public}s",
175                 AnonymizeWrapper(anonymizedName));
176             AnonymizeFree(anonymizedName);
177             continue;
178         }
179         (void)memset_s(discDeviceInfo, sizeof(DeviceInfo), 0, sizeof(DeviceInfo));
180         ret = ParseDiscDevInfo(nstackxDeviceInfo, discDeviceInfo);
181         if (ret != SOFTBUS_OK) {
182             DISC_LOGW(DISC_COAP, "parse discovery device info failed.");
183             continue;
184         }
185         ret = DiscCoapProcessDeviceInfo(nstackxDeviceInfo, discDeviceInfo, g_discCoapInnerCb,
186             &g_discCoapInnerCbLock);
187         if (ret != SOFTBUS_OK) {
188             DISC_LOGD(DISC_COAP, "DiscRecv: process device info failed, ret=%{public}d", ret);
189         }
190     }
191 
192     SoftBusFree(discDeviceInfo);
193 }
194 
OnNotificationReceived(const NSTACKX_NotificationConfig * notification)195 static void OnNotificationReceived(const NSTACKX_NotificationConfig *notification)
196 {
197     DiscCoapReportNotification(notification);
198 }
199 
200 static NSTACKX_Parameter g_nstackxCallBack = {
201     .onDeviceListChanged = OnDeviceFound,
202     .onDeviceFound = NULL,
203     .onMsgReceived = NULL,
204     .onDFinderMsgReceived = NULL,
205     .onNotificationReceived = OnNotificationReceived,
206 };
207 
DiscCoapRegisterCb(const DiscInnerCallback * discCoapCb)208 int32_t DiscCoapRegisterCb(const DiscInnerCallback *discCoapCb)
209 {
210     DISC_CHECK_AND_RETURN_RET_LOGE(discCoapCb != NULL, SOFTBUS_INVALID_PARAM, DISC_COAP, "invalid param");
211     DISC_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_discCoapInnerCbLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR,
212         DISC_COAP, "lock failed");
213     if (g_discCoapInnerCb == NULL) {
214         DISC_LOGE(DISC_COAP, "coap inner callback not init.");
215         (void)SoftBusMutexUnlock(&g_discCoapInnerCbLock);
216         return SOFTBUS_DISCOVER_COAP_NOT_INIT;
217     }
218     if (memcpy_s(g_discCoapInnerCb, sizeof(DiscInnerCallback), discCoapCb, sizeof(DiscInnerCallback)) != EOK) {
219         DISC_LOGE(DISC_COAP, "memcpy_s failed.");
220         (void)SoftBusMutexUnlock(&g_discCoapInnerCbLock);
221         return SOFTBUS_MEM_ERR;
222     }
223     (void)SoftBusMutexUnlock(&g_discCoapInnerCbLock);
224     return SOFTBUS_OK;
225 }
226 
DiscCoapRegisterCapability(uint32_t capabilityBitmapNum,uint32_t capabilityBitmap[])227 int32_t DiscCoapRegisterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
228 {
229     DISC_CHECK_AND_RETURN_RET_LOGE(capabilityBitmapNum != 0, SOFTBUS_INVALID_PARAM,
230         DISC_COAP, "capabilityBitmapNum=0");
231 
232     if (NSTACKX_RegisterCapability(capabilityBitmapNum, capabilityBitmap) != SOFTBUS_OK) {
233         DISC_LOGE(DISC_COAP, "NSTACKX Register Capability failed");
234         return SOFTBUS_DISCOVER_COAP_REGISTER_CAP_FAIL;
235     }
236     return SOFTBUS_OK;
237 }
238 
DiscCoapSetFilterCapability(uint32_t capabilityBitmapNum,uint32_t capabilityBitmap[])239 int32_t DiscCoapSetFilterCapability(uint32_t capabilityBitmapNum, uint32_t capabilityBitmap[])
240 {
241     DISC_CHECK_AND_RETURN_RET_LOGE(capabilityBitmapNum != 0, SOFTBUS_INVALID_PARAM,
242         DISC_COAP, "capabilityBitmapNum=0");
243 
244     if (NSTACKX_SetFilterCapability(capabilityBitmapNum, capabilityBitmap) != SOFTBUS_OK) {
245         DISC_LOGE(DISC_COAP, "NSTACKX SetFilter Capability failed");
246         SoftbusReportDiscFault(SOFTBUS_HISYSEVT_DISC_MEDIUM_COAP, SOFTBUS_HISYSEVT_DISCOVER_COAP_SET_FILTER_CAP_FAIL);
247         return SOFTBUS_DISCOVER_COAP_SET_FILTER_CAP_FAIL;
248     }
249     return SOFTBUS_OK;
250 }
251 
DiscCoapRegisterServiceData(const PublishOption * option,uint32_t allCap)252 int32_t DiscCoapRegisterServiceData(const PublishOption *option, uint32_t allCap)
253 {
254     int32_t authPort = 0;
255     int32_t ret = LnnGetLocalNumInfo(NUM_KEY_AUTH_PORT, &authPort);
256     if (ret != SOFTBUS_OK) {
257         DISC_LOGW(DISC_COAP, "get auth port from lnn failed. ret=%{public}d", ret);
258     }
259 
260     char serviceData[NSTACKX_MAX_SERVICE_DATA_LEN] = {0};
261     if (sprintf_s(serviceData, NSTACKX_MAX_SERVICE_DATA_LEN, "port:%d,", authPort) == -1) {
262         DISC_LOGE(DISC_COAP, "write auth port to service data failed.");
263         return SOFTBUS_STRCPY_ERR;
264     }
265     // capabilityData can be NULL, it will be check in this func
266     ret = DiscCoapFillServiceData(option, serviceData, NSTACKX_MAX_SERVICE_DATA_LEN, allCap);
267     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, DISC_COAP, "fill service data failed. ret=%{public}d", ret);
268 
269     ret = NSTACKX_RegisterServiceData(serviceData);
270     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, DISC_COAP,
271         "register service data to nstackx failed. ret=%{public}d", ret);
272     return SOFTBUS_OK;
273 }
274 
DiscCoapRegisterCapabilityData(const unsigned char * capabilityData,uint32_t dataLen,uint32_t capability)275 int32_t DiscCoapRegisterCapabilityData(const unsigned char *capabilityData, uint32_t dataLen, uint32_t capability)
276 {
277     if (capabilityData == NULL || dataLen == 0) {
278         // no capability data, no need to parse and register
279         return SOFTBUS_OK;
280     }
281     char *registerCapaData = (char *)SoftBusCalloc(MAX_CAPABILITYDATA_LEN);
282     DISC_CHECK_AND_RETURN_RET_LOGE(registerCapaData, SOFTBUS_MALLOC_ERR, DISC_COAP, "malloc capability data failed");
283     int32_t ret = DiscCoapAssembleCapData(capability, (const char *)capabilityData, dataLen, registerCapaData,
284         DISC_MAX_CUST_DATA_LEN);
285     if (ret == SOFTBUS_FUNC_NOT_SUPPORT) {
286         DISC_LOGI(DISC_COAP, "the capability not support yet. capability=%{public}u", capability);
287         SoftBusFree(registerCapaData);
288         return SOFTBUS_OK;
289     }
290     if (ret != SOFTBUS_OK) {
291         DISC_LOGE(DISC_COAP, "assemble the data of capability failed. capability=%{public}u", capability);
292         SoftBusFree(registerCapaData);
293         return ret;
294     }
295 
296     if (NSTACKX_RegisterExtendServiceData(registerCapaData) != SOFTBUS_OK) {
297         DISC_LOGE(DISC_COAP, "register extend service data to nstackx failed");
298         SoftBusFree(registerCapaData);
299         return SOFTBUS_DISCOVER_COAP_REGISTER_CAP_DATA_FAIL;
300     }
301     DISC_LOGI(DISC_COAP, "register extend service data to nstackx succ.");
302     SoftBusFree(registerCapaData);
303     return SOFTBUS_OK;
304 }
305 
IsNetworkValid(void)306 static bool IsNetworkValid(void)
307 {
308     char localIp[IP_LEN] = {0};
309     if (LnnGetLocalStrInfo(STRING_KEY_WLAN_IP, localIp, IP_LEN) != SOFTBUS_OK) {
310         DISC_LOGE(DISC_COAP, "get local ip failed");
311         return false;
312     }
313     if (strcmp(localIp, LOOPBACK_IP_ADDR) == 0 ||
314         strcmp(localIp, INVALID_IP_ADDR) == 0 ||
315         strcmp(localIp, "") == 0) {
316         DISC_LOGE(DISC_COAP, "invalid localIp: loopback or null");
317         return false;
318     }
319     return true;
320 }
321 
GetDiscFreq(int32_t freq,uint32_t * discFreq)322 static int32_t GetDiscFreq(int32_t freq, uint32_t *discFreq)
323 {
324     uint32_t arrayFreq[FREQ_BUTT] = {0};
325     int32_t ret = SoftbusGetConfig(SOFTBUS_INT_DISC_FREQ, (unsigned char *)arrayFreq, sizeof(arrayFreq));
326     if (ret != SOFTBUS_OK) {
327         DISC_LOGE(DISC_COAP, "disc get freq failed");
328         return ret;
329     }
330     *discFreq = arrayFreq[freq];
331     return SOFTBUS_OK;
332 }
333 
ConvertDiscoverySettings(NSTACKX_DiscoverySettings * discSet,const DiscCoapOption * option)334 static int32_t ConvertDiscoverySettings(NSTACKX_DiscoverySettings *discSet, const DiscCoapOption *option)
335 {
336     if (option->mode == ACTIVE_PUBLISH) {
337         discSet->discoveryMode = PUBLISH_MODE_PROACTIVE;
338     } else {
339         discSet->discoveryMode = DISCOVER_MODE;
340     }
341     uint32_t discFreq;
342     int32_t ret = GetDiscFreq(option->freq, &discFreq);
343     if (ret != SOFTBUS_OK) {
344         DISC_LOGE(DISC_COAP, "get discovery freq config failed");
345         return ret;
346     }
347     discSet->advertiseCount = discFreq & DISC_FREQ_COUNT_MASK;
348     discSet->advertiseDuration = (discFreq >> DISC_FREQ_DURATION_BIT) * DISC_USECOND;
349     DiscFillBtype(option->capability, option->allCap, discSet);
350     return SOFTBUS_OK;
351 }
352 
FreeDiscSet(NSTACKX_DiscoverySettings * discSet)353 static void FreeDiscSet(NSTACKX_DiscoverySettings *discSet)
354 {
355     if (discSet != NULL) {
356         SoftBusFree(discSet->businessData);
357         SoftBusFree(discSet);
358     }
359 }
360 
DiscCoapStartDiscovery(DiscCoapOption * option)361 int32_t DiscCoapStartDiscovery(DiscCoapOption *option)
362 {
363     DISC_CHECK_AND_RETURN_RET_LOGE(option != NULL, SOFTBUS_INVALID_PARAM, DISC_COAP, "option is null.");
364     DISC_CHECK_AND_RETURN_RET_LOGE(option->mode >= ACTIVE_PUBLISH && option->mode <= ACTIVE_DISCOVERY,
365         SOFTBUS_INVALID_PARAM, DISC_COAP, "option->mode is invalid");
366     DISC_CHECK_AND_RETURN_RET_LOGE(LOW <= option->freq && option->freq < FREQ_BUTT, SOFTBUS_INVALID_PARAM,
367         DISC_COAP, "invalid freq. freq=%{public}d", option->freq);
368     DISC_CHECK_AND_RETURN_RET_LOGE(IsNetworkValid(), SOFTBUS_NETWORK_NOT_FOUND, DISC_COAP, "netif not works");
369 
370     NSTACKX_DiscoverySettings *discSet = (NSTACKX_DiscoverySettings *)SoftBusCalloc(sizeof(NSTACKX_DiscoverySettings));
371     DISC_CHECK_AND_RETURN_RET_LOGE(discSet != NULL, SOFTBUS_MEM_ERR, DISC_COAP, "malloc disc settings failed");
372 
373     int32_t ret = ConvertDiscoverySettings(discSet, option);
374     if (ret != SOFTBUS_OK) {
375         DISC_LOGE(DISC_COAP, "set discovery settings failed");
376         FreeDiscSet(discSet);
377         return ret;
378     }
379     if (NSTACKX_StartDeviceDiscovery(discSet) != SOFTBUS_OK) {
380         DISC_LOGE(DISC_COAP, "start device discovery failed");
381         FreeDiscSet(discSet);
382         return (option->mode == ACTIVE_PUBLISH) ? SOFTBUS_DISCOVER_COAP_START_PUBLISH_FAIL :
383             SOFTBUS_DISCOVER_COAP_START_DISCOVER_FAIL;
384     }
385     FreeDiscSet(discSet);
386     return SOFTBUS_OK;
387 }
388 
DiscCoapStopDiscovery(void)389 int32_t DiscCoapStopDiscovery(void)
390 {
391     if (NSTACKX_StopDeviceFind() != SOFTBUS_OK) {
392         DISC_LOGE(DISC_COAP, "stop device discovery failed");
393         return SOFTBUS_DISCOVER_COAP_STOP_DISCOVER_FAIL;
394     }
395 
396     return SOFTBUS_OK;
397 }
398 
GetDeviceId(void)399 static char *GetDeviceId(void)
400 {
401     char *formatString = NULL;
402     char udid[UDID_BUF_LEN] = {0};
403     int32_t ret = LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, udid, sizeof(udid));
404     if (ret != SOFTBUS_OK) {
405         DISC_LOGE(DISC_COAP, "get udid failed, ret=%{public}d", ret);
406         return NULL;
407     }
408     cJSON *deviceId = cJSON_CreateObject();
409     DISC_CHECK_AND_RETURN_RET_LOGW(deviceId != NULL, NULL, DISC_COAP, "create json object failed: deviceId=NULL");
410 
411     if (!AddStringToJsonObject(deviceId, DEVICE_UDID, udid)) {
412         DISC_LOGE(DISC_COAP, "add udid to device id json object failed.");
413         goto GET_DEVICE_ID_END;
414     }
415     formatString = cJSON_PrintUnformatted(deviceId);
416     if (formatString == NULL) {
417         DISC_LOGE(DISC_COAP, "format device id json object failed.");
418     }
419 
420 GET_DEVICE_ID_END:
421     cJSON_Delete(deviceId);
422     return formatString;
423 }
424 
SetLocalDeviceInfo(void)425 static int32_t SetLocalDeviceInfo(void)
426 {
427     DISC_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_localDeviceInfoLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR,
428         DISC_COAP, "lock failed");
429     if (g_localDeviceInfo == NULL) {
430         DISC_LOGE(DISC_COAP, "disc coap not init");
431         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
432         return SOFTBUS_DISCOVER_COAP_NOT_INIT;
433     }
434     int32_t res = memset_s(g_localDeviceInfo, sizeof(NSTACKX_LocalDeviceInfo), 0, sizeof(NSTACKX_LocalDeviceInfo));
435     if (res != EOK) {
436         DISC_LOGE(DISC_COAP, "memset_s local device info failed");
437         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
438         return SOFTBUS_MEM_ERR;
439     }
440 
441     char *deviceIdStr = GetDeviceId();
442     if (deviceIdStr == NULL) {
443         DISC_LOGE(DISC_COAP, "get device id string failed.");
444         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
445         return SOFTBUS_DISCOVER_COAP_GET_DEVICE_INFO_FAIL;
446     }
447 
448     if (strcpy_s(g_localDeviceInfo->deviceId, sizeof(g_localDeviceInfo->deviceId), deviceIdStr) != EOK) {
449         cJSON_free(deviceIdStr);
450         DISC_LOGE(DISC_COAP, "strcpy_s deviceId failed.");
451         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
452         return SOFTBUS_STRCPY_ERR;
453     }
454     cJSON_free(deviceIdStr);
455     int32_t deviceType = 0;
456     int32_t ret = LnnGetLocalNumInfo(NUM_KEY_DEV_TYPE_ID, &deviceType);
457     if (ret != SOFTBUS_OK) {
458         DISC_LOGE(DISC_COAP, "get local device type failed.");
459         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
460         return ret;
461     }
462     g_localDeviceInfo->deviceType = (uint32_t)deviceType;
463     g_localDeviceInfo->businessType = (uint8_t)NSTACKX_BUSINESS_TYPE_NULL;
464     if (LnnGetLocalStrInfo(STRING_KEY_WLAN_IP, g_localDeviceInfo->localIfInfo[0].networkIpAddr,
465             sizeof(g_localDeviceInfo->localIfInfo[0].networkIpAddr)) != SOFTBUS_OK ||
466         LnnGetLocalStrInfo(STRING_KEY_HICE_VERSION, g_localDeviceInfo->version, sizeof(g_localDeviceInfo->version)) !=
467         SOFTBUS_OK ||
468         LnnGetLocalStrInfo(STRING_KEY_NET_IF_NAME, g_localDeviceInfo->localIfInfo[0].networkName,
469             sizeof(g_localDeviceInfo->localIfInfo[0].networkName)) != SOFTBUS_OK) {
470         DISC_LOGE(DISC_COAP, "get local device info from lnn failed.");
471         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
472         return SOFTBUS_DISCOVER_GET_LOCAL_STR_FAILED;
473     }
474     g_localDeviceInfo->ifNums = 1;
475 
476     (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
477     return SOFTBUS_OK;
478 }
479 
DiscCoapUpdateLocalIp(LinkStatus status)480 void DiscCoapUpdateLocalIp(LinkStatus status)
481 {
482     DISC_CHECK_AND_RETURN_LOGE(status == LINK_STATUS_UP || status == LINK_STATUS_DOWN, DISC_COAP,
483         "invlaid link status, status=%{public}d.", status);
484 
485     if (status == LINK_STATUS_DOWN) {
486         DISC_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_localDeviceInfoLock) == SOFTBUS_OK, DISC_COAP, "lock failed");
487         if (strcpy_s(g_localDeviceInfo->localIfInfo[0].networkIpAddr,
488             sizeof(g_localDeviceInfo->localIfInfo[0].networkIpAddr), INVALID_IP_ADDR) != EOK) {
489             DISC_LOGE(DISC_COAP, "link status down: strcpy_s networkIpAddr failed.");
490             (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
491             return;
492         }
493         (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
494     } else {
495         DISC_CHECK_AND_RETURN_LOGE(SetLocalDeviceInfo() == SOFTBUS_OK, DISC_COAP,
496             "link status up: set local device info failed");
497     }
498 
499     int64_t accountId = 0;
500     int32_t ret = LnnGetLocalNum64Info(NUM_KEY_ACCOUNT_LONG, &accountId);
501     DISC_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, DISC_COAP, "get local account failed");
502     DISC_LOGI(DISC_COAP, "register local device info. status=%{public}s, accountInfo=%{public}s",
503         status == LINK_STATUS_UP ? "up" : "down", accountId == 0 ? "without" : "with");
504     DISC_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_localDeviceInfoLock) == SOFTBUS_OK, DISC_COAP, "lock failed");
505     ret = NSTACKX_RegisterDeviceAn(g_localDeviceInfo, (uint64_t)accountId);
506     (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
507     DISC_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, DISC_COAP, "register local device info to dfinder failed");
508     DiscCoapUpdateDevName();
509 }
510 
SetLocale(char ** localeBefore)511 static int32_t SetLocale(char **localeBefore)
512 {
513     *localeBefore = setlocale(LC_CTYPE, NULL);
514     if (*localeBefore == NULL) {
515         DISC_LOGW(DISC_COAP, "get locale failed");
516     }
517 
518     char *localeAfter = setlocale(LC_CTYPE, "C.UTF-8");
519     return (localeAfter != NULL) ? SOFTBUS_OK : SOFTBUS_DISCOVER_SET_LOCALE_FAILED;
520 }
521 
RestoreLocale(const char * localeBefore)522 static void RestoreLocale(const char *localeBefore)
523 {
524     if (setlocale(LC_CTYPE, localeBefore) == NULL) {
525         DISC_LOGW(DISC_COAP, "restore locale failed");
526     }
527 }
528 
CalculateMbsTruncateSize(const char * multiByteStr,uint32_t capacity,uint32_t * truncatedSize)529 static int32_t CalculateMbsTruncateSize(const char *multiByteStr, uint32_t capacity, uint32_t *truncatedSize)
530 {
531     size_t multiByteStrLen = strlen(multiByteStr);
532     if (multiByteStrLen == 0) {
533         *truncatedSize = 0;
534         return SOFTBUS_OK;
535     }
536     DISC_CHECK_AND_RETURN_RET_LOGE(multiByteStrLen <= MAX_WIDE_STR_LEN, SOFTBUS_INVALID_PARAM, DISC_COAP,
537         "multi byte str too long: %zu", multiByteStrLen);
538 
539     char *localeBefore = NULL;
540     int32_t ret = SetLocale(&localeBefore);
541     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, DISC_COAP, "set locale failed");
542 
543     // convert multi byte str to wide str
544     wchar_t wideStr[MAX_WIDE_STR_LEN] = {0};
545     size_t numConverted = mbstowcs(wideStr, multiByteStr, multiByteStrLen);
546     if (numConverted <= 0 || numConverted > INT32_MAX) {
547         DISC_LOGE(DISC_COAP, "mbstowcs failed");
548         RestoreLocale(localeBefore);
549         return SOFTBUS_DISCOVER_CHAR_CONVERT_FAILED;
550     }
551 
552     uint32_t truncateTotal = 0;
553     int32_t truncateIndex = (int32_t)numConverted - 1;
554     char multiByteChar[MULTI_BYTE_CHAR_LEN] = {0};
555     while (capacity < multiByteStrLen - truncateTotal && truncateIndex >= 0) {
556         int32_t truncateCharLen = wctomb(multiByteChar, wideStr[truncateIndex]);
557         if (truncateCharLen <= 0) {
558             DISC_LOGE(DISC_COAP, "wctomb failed");
559             RestoreLocale(localeBefore);
560             return SOFTBUS_DISCOVER_CHAR_CONVERT_FAILED;
561         }
562         truncateTotal += (uint32_t)truncateCharLen;
563         truncateIndex--;
564     }
565 
566     *truncatedSize = (multiByteStrLen >= truncateTotal) ? (multiByteStrLen - truncateTotal) : 0;
567     RestoreLocale(localeBefore);
568     return SOFTBUS_OK;
569 }
570 
DiscCoapUpdateDevName(void)571 void DiscCoapUpdateDevName(void)
572 {
573     char localDevName[DEVICE_NAME_BUF_LEN] = {0};
574     int32_t ret = LnnGetLocalStrInfo(STRING_KEY_DEV_NAME, localDevName, sizeof(localDevName));
575     DISC_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, DISC_COAP, "get local device name failed, ret=%{public}d.", ret);
576 
577     uint32_t truncateLen = 0;
578     if (CalculateMbsTruncateSize((const char *)localDevName, NSTACKX_MAX_DEVICE_NAME_LEN - 1, &truncateLen)
579         != SOFTBUS_OK) {
580         DISC_LOGE(DISC_COAP, "truncate device name failed");
581         return;
582     }
583     localDevName[truncateLen] = '\0';
584     char *anonymizedName = NULL;
585     Anonymize(localDevName, &anonymizedName);
586     DISC_LOGI(DISC_COAP, "register new local device name. localDevName=%{public}s", AnonymizeWrapper(anonymizedName));
587     AnonymizeFree(anonymizedName);
588     ret = NSTACKX_RegisterDeviceName(localDevName);
589     DISC_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, DISC_COAP, "register local device name failed, ret=%{public}d.", ret);
590 }
591 
DiscCoapUpdateAccount(void)592 void DiscCoapUpdateAccount(void)
593 {
594     DiscCoapUpdateLocalIp(LINK_STATUS_UP);
595 }
596 
DeinitLocalInfo(void)597 static void DeinitLocalInfo(void)
598 {
599     DISC_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_localDeviceInfoLock) == SOFTBUS_OK, DISC_COAP, "lock failed");
600     if (g_localDeviceInfo != NULL) {
601         SoftBusFree(g_localDeviceInfo);
602         g_localDeviceInfo = NULL;
603     }
604     (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
605 
606     DISC_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_discCoapInnerCbLock) == SOFTBUS_OK, DISC_COAP, "lock failed");
607     if (g_discCoapInnerCb != NULL) {
608         SoftBusFree(g_discCoapInnerCb);
609         g_discCoapInnerCb = NULL;
610     }
611     (void)SoftBusMutexUnlock(&g_discCoapInnerCbLock);
612 
613     (void)SoftBusMutexDestroy(&g_localDeviceInfoLock);
614     (void)SoftBusMutexDestroy(&g_discCoapInnerCbLock);
615 }
616 
InitLocalInfo(void)617 static int32_t InitLocalInfo(void)
618 {
619     if (SoftBusMutexInit(&g_localDeviceInfoLock, NULL) != SOFTBUS_OK) {
620         DISC_LOGE(DISC_COAP, "g_localDeviceInfoLock init failed");
621         return SOFTBUS_NO_INIT;
622     }
623     if (SoftBusMutexInit(&g_discCoapInnerCbLock, NULL) != SOFTBUS_OK) {
624         DISC_LOGE(DISC_COAP, "g_discCoapInnerCbLock init failed");
625         (void)SoftBusMutexDestroy(&g_localDeviceInfoLock);
626         return SOFTBUS_NO_INIT;
627     }
628 
629     DISC_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_localDeviceInfoLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR,
630         DISC_COAP, "lock failed");
631     if (g_localDeviceInfo == NULL) {
632         g_localDeviceInfo = (NSTACKX_LocalDeviceInfo *)SoftBusCalloc(sizeof(NSTACKX_LocalDeviceInfo));
633         if (g_localDeviceInfo == NULL) {
634             (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
635             DeinitLocalInfo();
636             return SOFTBUS_MEM_ERR;
637         }
638     }
639     (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
640 
641     DISC_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_discCoapInnerCbLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR,
642         DISC_COAP, "lock failed");
643     if (g_discCoapInnerCb == NULL) {
644         g_discCoapInnerCb = (DiscInnerCallback *)SoftBusCalloc(sizeof(DiscInnerCallback));
645         if (g_discCoapInnerCb == NULL) {
646             (void)SoftBusMutexUnlock(&g_discCoapInnerCbLock);
647             DeinitLocalInfo();
648             return SOFTBUS_MEM_ERR;
649         }
650     }
651     (void)SoftBusMutexUnlock(&g_discCoapInnerCbLock);
652     return SOFTBUS_OK;
653 }
654 
DiscNstackxInit(void)655 int32_t DiscNstackxInit(void)
656 {
657     if (InitLocalInfo() != SOFTBUS_OK) {
658         return SOFTBUS_DISCOVER_COAP_INIT_FAIL;
659     }
660 
661     NSTACKX_DFinderRegisterLog(NstackxLogInnerImpl);
662     if (SoftbusGetConfig(SOFTBUS_INT_DISC_COAP_MAX_DEVICE_NUM, (unsigned char *)&g_nstackxCallBack.maxDeviceNum,
663         sizeof(g_nstackxCallBack.maxDeviceNum)) != SOFTBUS_OK) {
664         DISC_LOGI(DISC_COAP, "get disc max device num config failed, use default %{public}u", DEFAULT_MAX_DEVICE_NUM);
665         g_nstackxCallBack.maxDeviceNum = DEFAULT_MAX_DEVICE_NUM;
666     }
667     if (NSTACKX_Init(&g_nstackxCallBack) != SOFTBUS_OK) {
668         DeinitLocalInfo();
669         return SOFTBUS_DISCOVER_COAP_INIT_FAIL;
670     }
671     SoftBusRegDiscVarDump((char *)NSTACKX_LOCAL_DEV_INFO, &NstackxLocalDevInfoDump);
672     return SOFTBUS_OK;
673 }
674 
DiscNstackxDeinit(void)675 void DiscNstackxDeinit(void)
676 {
677     NSTACKX_Deinit();
678     DeinitLocalInfo();
679 }
680 
NstackxLocalDevInfoDump(int fd)681 static int32_t NstackxLocalDevInfoDump(int fd)
682 {
683     char deviceId[NSTACKX_MAX_DEVICE_ID_LEN] = {0};
684     DISC_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_localDeviceInfoLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR,
685         DISC_COAP, "lock failed");
686     SOFTBUS_DPRINTF(fd, "\n-----------------NstackxLocalDevInfo-------------------\n");
687     SOFTBUS_DPRINTF(fd, "name                                : %s\n", g_localDeviceInfo->name);
688     DataMasking(g_localDeviceInfo->deviceId, NSTACKX_MAX_DEVICE_ID_LEN, ID_DELIMITER, deviceId);
689     SOFTBUS_DPRINTF(fd, "deviceId                            : %s\n", deviceId);
690     SOFTBUS_DPRINTF(fd, "localIfInfo networkName             : %s\n", g_localDeviceInfo->localIfInfo->networkName);
691     SOFTBUS_DPRINTF(fd, "ifNums                              : %d\n", g_localDeviceInfo->ifNums);
692     SOFTBUS_DPRINTF(fd, "networkName                         : %s\n", g_localDeviceInfo->networkName);
693     SOFTBUS_DPRINTF(fd, "is5GHzBandSupported                 : %d\n", g_localDeviceInfo->is5GHzBandSupported);
694     SOFTBUS_DPRINTF(fd, "deviceType                          : %d\n", g_localDeviceInfo->deviceType);
695     SOFTBUS_DPRINTF(fd, "version                             : %s\n", g_localDeviceInfo->version);
696     SOFTBUS_DPRINTF(fd, "businessType                        : %d\n", g_localDeviceInfo->businessType);
697     (void)SoftBusMutexUnlock(&g_localDeviceInfoLock);
698 
699     return SOFTBUS_OK;
700 }
701