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