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 "coap_discover.h"
17 
18 #include <errno.h>
19 #include <string.h>
20 
21 #include "coap_adapter.h"
22 #include "coap_app.h"
23 #include "json_payload.h"
24 #include "lwip/sockets.h"
25 #include "nstackx_device.h"
26 #include "nstackx_error.h"
27 #include "nstackx_dfinder_log.h"
28 #include "nstackx_timer.h"
29 #include "securec.h"
30 #include "nstackx_statistics.h"
31 #include "nstackx_device_local.h"
32 #include "nstackx_device_remote.h"
33 
34 #define TAG "nStackXCoAP"
35 
36 #define COAP_URI_BUFFER_LENGTH 64 /* the size of the buffer or variable used to save uri. */
37 
38 /*
39  * 1st discover interval: 100ms
40  * 2nd ~ 3rd discover interval: 200ms
41  * Remaining discover interval (9 times): 500ms
42  */
43 #define COAP_DEFAULT_DISCOVER_COUNT 12
44 #define COAP_FIRST_DISCOVER_COUNT_RANGE 1
45 #define COAP_SECOND_DISCOVER_COUNT_RANGE 3
46 #define COAP_FIRST_DISCOVER_INTERVAL 100
47 #define COAP_SECOND_DISCOVER_INTERVAL 200
48 #define COAP_LAST_DISCOVER_INTERVAL 500
49 
50 static Timer *g_discoverTimer = NULL;
51 static uint32_t g_discoverCount;
52 static uint32_t g_coapMaxDiscoverCount = COAP_DEFAULT_DISCOVER_COUNT;
53 static uint32_t g_coapDiscoverType = COAP_BROADCAST_TYPE_DEFAULT;
54 static uint32_t g_coapUserMaxDiscoverCount;
55 static uint32_t g_coapUserDiscoverInterval;
56 static uint32_t *g_coapIntervalArr = NULL;
57 static uint32_t g_coapDiscoverTargetCount;
58 static uint8_t g_userRequest;
59 static uint8_t g_forceUpdate;
60 
HndPostServiceDiscoverInner(const uint8_t * buf,size_t size,char ** remoteUrl,DeviceInfo * deviceInfo)61 static int32_t HndPostServiceDiscoverInner(const uint8_t *buf, size_t size, char **remoteUrl, DeviceInfo *deviceInfo)
62 {
63     if (GetServiceDiscoverInfo(buf, size, deviceInfo, remoteUrl) != NSTACKX_EOK) {
64         return NSTACKX_EFAILED;
65     }
66     /* receive coap broadcast, set peer device's discovery type to passive,
67      * to identify the local device is in passive discovery
68      */
69     deviceInfo->discoveryType = (*remoteUrl != NULL) ? NSTACKX_DISCOVERY_TYPE_PASSIVE : NSTACKX_DISCOVERY_TYPE_ACTIVE;
70     if (deviceInfo->mode == PUBLISH_MODE_UPLINE || deviceInfo->mode == PUBLISH_MODE_OFFLINE) {
71         DFINDER_LOGD(TAG, "peer is not DISCOVER_MODE");
72         size_t deviceListLen = sizeof(NSTACKX_DeviceInfo) * PUBLISH_DEVICE_NUM;
73         NSTACKX_DeviceInfo *deviceList = (NSTACKX_DeviceInfo *)malloc(deviceListLen);
74         if (deviceList == NULL) {
75             DFINDER_LOGE(TAG, "malloc device list failed");
76             return NSTACKX_ENOMEM;
77         }
78         (void)memset_s(deviceList, deviceListLen, 0, deviceListLen);
79         if (GetNotifyDeviceInfo(deviceList, deviceInfo) == NSTACKX_EOK) {
80             NotifyDeviceFound(deviceList, PUBLISH_DEVICE_NUM);
81         } else {
82             DFINDER_LOGE(TAG, "GetNotifyDeviceInfo failed");
83         }
84         free(deviceList);
85         return NSTACKX_EFAILED;
86     }
87     return NSTACKX_EOK;
88 }
89 
GetBuildCoapParam(const CoapPacket * pkt,const char * remoteUrl,const char * remoteIp,CoapBuildParam * param)90 static void GetBuildCoapParam(const CoapPacket *pkt, const char *remoteUrl, const char *remoteIp, CoapBuildParam *param)
91 {
92     param->remoteIp = remoteIp;
93     param->uriPath = COAP_DEVICE_DISCOVER_URI;
94     if (remoteUrl != NULL) {
95         param->msgType = COAP_TYPE_CON;
96         param->methodType = COAP_METHOD_POST;
97         param->msgId = CoapSoftBusMsgId();
98     } else {
99         param->msgType = COAP_TYPE_ACK;
100         param->methodType = COAP_RESPONSE_201;
101         param->msgId = pkt->header.varSection.msgId;
102     }
103 }
104 
105 /* this is a tmp func */
CreateUnicastCoapParam(const char * remoteUrl,const char * remoteIp,CoapBuildParam * param)106 static int32_t CreateUnicastCoapParam(const char *remoteUrl, const char *remoteIp, CoapBuildParam *param)
107 {
108     if ((remoteUrl == NULL) || (remoteIp == NULL)) {
109         return NSTACKX_EFAILED;
110     }
111     param->remoteIp = remoteIp;
112     param->uriPath = COAP_DEVICE_DISCOVER_URI;
113     param->msgType = COAP_TYPE_CON;
114     param->methodType = COAP_METHOD_POST;
115     param->msgId = CoapSoftBusMsgId();
116     return NSTACKX_EOK;
117 }
118 
CoapResponseServiceDiscovery(const char * remoteUrl,const CoapPacket * pkt,const struct in_addr * ip,uint8_t businessType)119 static void CoapResponseServiceDiscovery(const char *remoteUrl, const CoapPacket *pkt,
120     const struct in_addr *ip, uint8_t businessType)
121 {
122     char wifiIpAddr[NSTACKX_MAX_IP_STRING_LEN] = {0};
123     CoapBuildParam param = {0};
124     (void)inet_ntop(AF_INET, ip, wifiIpAddr, sizeof(wifiIpAddr));
125     GetBuildCoapParam(pkt, remoteUrl, wifiIpAddr, &param);
126     if (remoteUrl != NULL) {
127         if (CheckBusinessTypeReplyUnicast(businessType) == NSTACKX_EOK) {
128             (void)CoapSendMessage(&param, NSTACKX_FALSE, businessType, false);
129         }
130     } else {
131         (void)CoapSendMessage(&param, NSTACKX_FALSE, businessType, true);
132     }
133 }
134 
HndPostServiceDiscoverEx(const CoapPacket * pkt)135 static int32_t HndPostServiceDiscoverEx(const CoapPacket *pkt)
136 {
137     int32_t ret = NSTACKX_EFAILED;
138     if (pkt == NULL) {
139         return ret;
140     }
141 
142     const CoapCtxType *coapCtx = CoapGetCoapCtxType();
143     if (coapCtx == NULL) {
144         DFINDER_LOGE(TAG, "get coap ctx type failed");
145         return ret;
146     }
147 
148     char *remoteUrl = NULL;
149     DeviceInfo *deviceInfo = (DeviceInfo *)calloc(1, sizeof(DeviceInfo));
150     if (deviceInfo == NULL) {
151         DFINDER_LOGE(TAG, "malloc device info failed");
152         return ret;
153     }
154 
155     if (strcpy_s(deviceInfo->networkName, sizeof(deviceInfo->networkName),
156         GetLocalIfaceName(coapCtx->iface)) != EOK) {
157         DFINDER_LOGE(TAG, "copy network name failed");
158         goto FAIL;
159     }
160 
161     if (HndPostServiceDiscoverInner(pkt->payload.buffer, pkt->payload.len, &remoteUrl, deviceInfo) != NSTACKX_EOK) {
162         goto FAIL;
163     }
164     if (GetModeInfo() == PUBLISH_MODE_UPLINE || GetModeInfo() == PUBLISH_MODE_OFFLINE) {
165         DFINDER_LOGD(TAG, "local is not DISCOVER_MODE");
166         goto FAIL;
167     }
168 #ifdef DFINDER_SAVE_DEVICE_LIST
169     uint8_t receiveBcast = (remoteUrl == NULL) ? NSTACKX_FALSE : NSTACKX_TRUE;
170     if (UpdateDeviceDb(coapCtx, deviceInfo, g_forceUpdate, receiveBcast) != NSTACKX_EOK)
171 #else
172     if (DeviceInfoNotify(&deviceInfo) != NSTACKX_EOK)
173 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
174     {
175         goto FAIL;
176     }
177     g_forceUpdate = NSTACKX_FALSE;
178     if (deviceInfo->mode == PUBLISH_MODE_PROACTIVE) {
179         DFINDER_LOGD(TAG, "peer is PUBLISH_MODE_PROACTIVE");
180         goto FAIL;
181     }
182 
183     CoapResponseServiceDiscovery(remoteUrl, pkt, &deviceInfo->netChannelInfo.wifiApInfo.ip, deviceInfo->businessType);
184 
185     ret = NSTACKX_EOK;
186 FAIL:
187     free(remoteUrl);
188     free(deviceInfo);
189     return ret;
190 }
191 
HndPostServiceDiscover(const CoapPacket * pkt)192 void HndPostServiceDiscover(const CoapPacket *pkt)
193 {
194     if (HndPostServiceDiscoverEx(pkt) != NSTACKX_EOK) {
195         IncStatistics(STATS_HANDLE_DEVICE_DISCOVER_MSG_FAILED);
196     }
197 }
198 
GetUserDefineInterval(uint32_t discoverCount)199 static uint32_t GetUserDefineInterval(uint32_t discoverCount)
200 {
201     if (discoverCount >= (g_coapMaxDiscoverCount - 1)) {
202         DFINDER_LOGD(TAG, "discover end");
203         return NSTACKX_EOK;
204     }
205     return g_coapIntervalArr[discoverCount];
206 }
207 
GetDiscoverInterval(uint32_t discoverCount)208 static uint32_t GetDiscoverInterval(uint32_t discoverCount)
209 {
210     switch (g_coapDiscoverType) {
211         case COAP_BROADCAST_TYPE_USER:
212             return g_coapUserDiscoverInterval;
213         case COAP_BROADCAST_TYPE_USER_DEFINE_INTERVAL:
214             return GetUserDefineInterval(discoverCount);
215         case COAP_BROADCAST_TYPE_DEFAULT:
216             return GetDefaultDiscoverInterval(discoverCount);
217         default:
218             return GetDefaultDiscoverInterval(discoverCount);
219     }
220 }
221 
CoapServiceDiscoverStop(void)222 static void CoapServiceDiscoverStop(void)
223 {
224     g_discoverCount = 0;
225     g_forceUpdate = NSTACKX_FALSE;
226     SetModeInfo(DISCOVER_MODE);
227 #ifdef DFINDER_SAVE_DEVICE_LIST
228     ClearRemoteDeviceListBackup();
229     DFINDER_LOGW(TAG, "clear device list backup");
230 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
231     g_coapDiscoverType = COAP_BROADCAST_TYPE_DEFAULT;
232     g_coapMaxDiscoverCount = COAP_DEFAULT_DISCOVER_COUNT;
233     /* Can call PostDeviceFindWrapper() to notify user if needed. */
234     g_userRequest = NSTACKX_FALSE;
235     // release interval array
236     if (g_coapIntervalArr != NULL) {
237         free(g_coapIntervalArr);
238         g_coapIntervalArr = NULL;
239     }
240 }
241 
CoapPostServiceDiscoverEx()242 static int32_t CoapPostServiceDiscoverEx()
243 {
244     char ipString[NSTACKX_MAX_IP_STRING_LEN] = {0};
245     char *ifName = CoapGetLocalIfaceName();
246     if (ifName == NULL) {
247         DFINDER_LOGE(TAG, "get ifname failed");
248         return NSTACKX_EFAILED;
249     }
250     struct ifreq ifr;
251     if (strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName, strlen(ifName)) != EOK) {
252         DFINDER_LOGE(TAG, "copy netIfName:%s fail", ifName);
253         return NSTACKX_EFAILED;
254     }
255     int32_t fd = socket(AF_INET, SOCK_DGRAM, 0);
256     if (fd < 0) {
257         DFINDER_LOGE(TAG, "create socket fd failed, errno = %d", errno);
258         return NSTACKX_EFAILED;
259     }
260     if (lwip_ioctl(fd, SIOCGIFBRDADDR, (char*)&ifr) < 0) {
261         DFINDER_LOGE(TAG, "ioctl fail, errno = %d", errno);
262         lwip_close(fd);
263         fd = -1;
264         return NSTACKX_EFAILED;
265     }
266     lwip_close(fd);
267     fd = -1;
268     if (inet_ntop(AF_INET, &(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr), ipString, sizeof(ipString)) == NULL) {
269         DFINDER_LOGE(TAG, "convert address from binary to text failed");
270         return NSTACKX_EFAILED;
271     }
272     CoapBuildParam param = {0};
273     param.remoteIp = ipString;
274     param.uriPath = COAP_DEVICE_DISCOVER_URI;
275     param.msgType = COAP_TYPE_NONCON;
276     param.methodType = COAP_METHOD_POST;
277     param.msgId = CoapSoftBusMsgId();
278     if (CoapSendMessage(&param, NSTACKX_TRUE, GetLocalDeviceBusinessType(), false) != NSTACKX_EOK) {
279         DFINDER_LOGE(TAG, "coap broadcast failed");
280         return NSTACKX_EFAILED;
281     }
282     return NSTACKX_EOK;
283 }
284 
CoapPostServiceDiscover(void)285 static int32_t CoapPostServiceDiscover(void)
286 {
287     if (CoapPostServiceDiscoverEx() != NSTACKX_EOK) {
288         DFINDER_LOGE(TAG, "no iface send request");
289         IncStatistics(STATS_POST_SD_REQUEST_FAILED);
290         return NSTACKX_EFAILED;
291     }
292 
293     return NSTACKX_EOK;
294 }
295 
CoapServiceDiscoverTimerHandle(void * argument)296 static void CoapServiceDiscoverTimerHandle(void *argument)
297 {
298     uint32_t discoverInterval;
299 
300     (void)argument;
301 
302     if (g_discoverCount >= g_coapDiscoverTargetCount || !IsCoapContextReady()) {
303         /* Discover done, or wifi AP disconnected. */
304         CoapServiceDiscoverStop();
305         return;
306     }
307 
308     if (CoapPostServiceDiscover() != NSTACKX_EOK) {
309         DFINDER_LOGE(TAG, "failed to post service discover request");
310         goto L_ERR_SERVICE_DISCOVER;
311     }
312     DFINDER_LOGI(TAG, "the %u times for device discover.", g_discoverCount + 1);
313 
314     /* Restart timer */
315     discoverInterval = GetDiscoverInterval(g_discoverCount);
316 
317     ++g_discoverCount;
318     if (TimerSetTimeout(g_discoverTimer, discoverInterval, NSTACKX_FALSE) != NSTACKX_EOK) {
319         DFINDER_LOGE(TAG, "failed to set timer for service discover");
320         goto L_ERR_SERVICE_DISCOVER;
321     }
322     return;
323 
324 L_ERR_SERVICE_DISCOVER:
325     /* Abort service discover by not starting timer. */
326     DFINDER_LOGE(TAG, "abort service discover, have tried %u request", g_discoverCount);
327     /* Reset g_discoverCount to allow new request from user. */
328     g_discoverCount = 0;
329 }
330 
SetCoapMaxDiscoverCount(void)331 static void SetCoapMaxDiscoverCount(void)
332 {
333     switch (g_coapDiscoverType) {
334         case COAP_BROADCAST_TYPE_DEFAULT:
335             g_coapMaxDiscoverCount = COAP_DEFAULT_DISCOVER_COUNT;
336             break;
337         case COAP_BROADCAST_TYPE_USER:
338         case COAP_BROADCAST_TYPE_USER_DEFINE_INTERVAL:
339             g_coapMaxDiscoverCount = g_coapUserMaxDiscoverCount;
340             break;
341         default:
342             g_coapMaxDiscoverCount = COAP_DEFAULT_DISCOVER_COUNT;
343             break;
344     }
345 }
346 
CoapServiceDiscoverFirstTime(void)347 static void CoapServiceDiscoverFirstTime(void)
348 {
349     SetCoapMaxDiscoverCount();
350     g_coapDiscoverTargetCount = g_coapMaxDiscoverCount;
351     if (CoapPostServiceDiscover() != NSTACKX_EOK) {
352         DFINDER_LOGE(TAG, "failed to post service discover request");
353         return;
354     }
355 
356     uint32_t discoverInterval = GetDiscoverInterval(g_discoverCount);
357     if (TimerSetTimeout(g_discoverTimer, discoverInterval, NSTACKX_FALSE) != NSTACKX_EOK) {
358         DFINDER_LOGE(TAG, "failed to set timer for service discover");
359         return;
360     }
361     ++g_discoverCount;
362     DFINDER_LOGI(TAG, "the first time for device discover.");
363 }
364 
CoapServiceDiscoverInner(uint8_t userRequest)365 void CoapServiceDiscoverInner(uint8_t userRequest)
366 {
367     if (!IsCoapContextReady()) {
368         IncStatistics(STATS_START_SD_FAILED);
369         DFINDER_LOGI(TAG, "Network not connected when discovery inner for mini");
370         return;
371     }
372 
373     if (userRequest) {
374         DFINDER_LOGD(TAG, "user request for discovery inner");
375         g_userRequest = NSTACKX_TRUE;
376         g_forceUpdate = NSTACKX_TRUE;
377     }
378 
379     if (g_coapDiscoverTargetCount > 0 && g_discoverCount >= g_coapDiscoverTargetCount) {
380         g_discoverCount = 0;
381         SetModeInfo(DISCOVER_MODE);
382 #ifdef DFINDER_SAVE_DEVICE_LIST
383         DFINDER_LOGW(TAG, "clear device list backup for mini");
384         ClearRemoteDeviceListBackup();
385 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
386         TimerSetTimeout(g_discoverTimer, 0, NSTACKX_FALSE);
387     }
388 
389     if (g_discoverCount) {
390         /* Service discover is ongoing, return. */
391         return;
392     }
393 #ifdef DFINDER_SAVE_DEVICE_LIST
394     /* First discover */
395     BackupRemoteDeviceList();
396     DFINDER_LOGW(TAG, "clear device list");
397 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
398     SetModeInfo(DISCOVER_MODE);
399     CoapServiceDiscoverFirstTime();
400 }
401 
CoapServiceDiscoverInnerAn(uint8_t userRequest)402 void CoapServiceDiscoverInnerAn(uint8_t userRequest)
403 {
404     if (!IsCoapContextReady()) {
405         IncStatistics(STATS_START_SD_FAILED);
406         return;
407     }
408 
409     if (userRequest) {
410         g_userRequest = NSTACKX_TRUE;
411     }
412 
413     if (g_discoverCount != 0) {
414         g_discoverCount = 0;
415         /* Service discover is ongoing, reset. */
416         TimerSetTimeout(g_discoverTimer, 0, NSTACKX_FALSE);
417     }
418     CoapServiceDiscoverFirstTime();
419 }
420 
CoapServiceDiscoverInnerConfigurable(uint8_t userRequest)421 void CoapServiceDiscoverInnerConfigurable(uint8_t userRequest)
422 {
423     if (!IsCoapContextReady()) {
424         IncStatistics(STATS_START_SD_FAILED);
425         DFINDER_LOGI(TAG, "Network not connected when discovery inner for configurable");
426         return;
427     }
428 
429     if (userRequest) {
430         DFINDER_LOGD(TAG, "user request for discovery configurable");
431         g_userRequest = NSTACKX_TRUE;
432         g_forceUpdate = NSTACKX_TRUE;
433     }
434 
435     if (g_coapDiscoverTargetCount > 0 && g_discoverCount >= g_coapDiscoverTargetCount) {
436         g_discoverCount = 0;
437 #ifdef DFINDER_SAVE_DEVICE_LIST
438         ClearRemoteDeviceListBackup();
439         DFINDER_LOGW(TAG, "clear device list backup");
440 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
441         TimerSetTimeout(g_discoverTimer, 0, NSTACKX_FALSE);
442     }
443 
444     if (g_discoverCount != 0) {
445         g_discoverCount = 0;
446         /* Service discover is ongoing, return. */
447         TimerSetTimeout(g_discoverTimer, 0, NSTACKX_FALSE);
448     }
449 #ifdef DFINDER_SAVE_DEVICE_LIST
450     /* First discover */
451     BackupRemoteDeviceList();
452     DFINDER_LOGW(TAG, "clear device list");
453 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
454     CoapServiceDiscoverFirstTime();
455 }
456 
CoapServiceDiscoverStopInner(void)457 void CoapServiceDiscoverStopInner(void)
458 {
459     TimerSetTimeout(g_discoverTimer, 0, NSTACKX_FALSE);
460     CoapServiceDiscoverStop();
461     DFINDER_LOGI(TAG, "device discover stopped");
462 }
463 
CoapDiscoverRequestOngoing(void)464 uint8_t CoapDiscoverRequestOngoing(void)
465 {
466     return (g_discoverCount > 0 && g_userRequest);
467 }
468 
CoapDiscoverInit(EpollDesc epollfd)469 int32_t CoapDiscoverInit(EpollDesc epollfd)
470 {
471     (void)epollfd;
472     if (g_discoverTimer == NULL) {
473         g_discoverTimer = TimerStart(epollfd, 0, NSTACKX_FALSE, CoapServiceDiscoverTimerHandle, NULL);
474         if (g_discoverTimer == NULL) {
475             DFINDER_LOGE(TAG, "failed to start timer for service discover");
476             return NSTACKX_EFAILED;
477         }
478     }
479     CoapSoftBusInitMsgId();
480     g_userRequest = NSTACKX_FALSE;
481     g_forceUpdate = NSTACKX_FALSE;
482     g_discoverCount = 0;
483     return NSTACKX_EOK;
484 }
485 
CoapDiscoverDeinit(void)486 void CoapDiscoverDeinit(void)
487 {
488     if (g_discoverTimer != NULL) {
489         TimerDelete(g_discoverTimer);
490         g_discoverTimer = NULL;
491     }
492     if (g_coapIntervalArr != NULL) {
493         free(g_coapIntervalArr);
494         g_coapIntervalArr = NULL;
495     }
496 }
497 
ResetCoapDiscoverTaskCount(uint8_t isBusy)498 void ResetCoapDiscoverTaskCount(uint8_t isBusy)
499 {
500     if (g_discoverTimer != NULL) {
501         if (isBusy) {
502             DFINDER_LOGI(TAG, "in this busy interval: g_discoverTimer task count %llu", g_discoverTimer->task.count);
503         }
504         g_discoverTimer->task.count = 0;
505     }
506 }
507 
SetCoapDiscoverType(CoapBroadcastType type)508 void SetCoapDiscoverType(CoapBroadcastType type)
509 {
510     g_coapDiscoverType = (uint32_t)type;
511 }
512 
SetCoapDiscConfig(const DFinderDiscConfig * discConfig)513 int32_t SetCoapDiscConfig(const DFinderDiscConfig *discConfig)
514 {
515     uint32_t *tmp = (uint32_t *)malloc(discConfig->intervalArrLen * sizeof(uint32_t));
516     if (tmp != NULL) {
517         if (g_coapIntervalArr != NULL) {
518             free(g_coapIntervalArr);
519         }
520         g_coapIntervalArr = tmp;
521         for (size_t i = 0; i < discConfig->intervalArrLen; ++i) {
522             g_coapIntervalArr[i] = (discConfig->bcastInterval)[i];
523         }
524         // add 1: first broadcast starts immediately
525         g_coapUserMaxDiscoverCount = discConfig->intervalArrLen + 1;
526         return NSTACKX_EOK;
527     }
528     DFINDER_LOGE(TAG, "malloc for user define interval array failed");
529     if (g_coapIntervalArr != NULL) {
530         DFINDER_LOGD(TAG, "going to use last interval config");
531         return NSTACKX_EOK;
532     }
533     DFINDER_LOGE(TAG, "failed to use last interval config");
534     return NSTACKX_EFAILED;
535 }
536 
SendDiscoveryRspEx(const NSTACKX_ResponseSettings * responseSettings)537 static int32_t SendDiscoveryRspEx(const NSTACKX_ResponseSettings *responseSettings)
538 {
539     if (responseSettings == NULL) {
540         return NSTACKX_EFAILED;
541     }
542 
543     if (responseSettings->businessData == NULL) {
544         DFINDER_LOGE(TAG, "businessData is null");
545         return NSTACKX_EFAILED;
546     }
547 
548     if (SetLocalDeviceBusinessData(responseSettings->businessData, NSTACKX_TRUE) != NSTACKX_EOK) {
549         return NSTACKX_EFAILED;
550     }
551     char remoteUrl[NSTACKX_MAX_URI_BUFFER_LENGTH] = {0};
552     char host[NSTACKX_MAX_IP_STRING_LEN] = {0};
553     if (strncpy_s(host, sizeof(host), responseSettings->remoteIp,
554         strlen(responseSettings->remoteIp)) != EOK) {
555         DFINDER_LOGE(TAG, "discoveryRsp remoteIp copy error");
556         return NSTACKX_EFAILED;
557     }
558     if (sprintf_s(remoteUrl, sizeof(remoteUrl), "coap://%s/" COAP_DEVICE_DISCOVER_URI, host) < 0) {
559         DFINDER_LOGE(TAG, "failed to get discoveryRsp remoteUrl");
560         return NSTACKX_EFAILED;
561     }
562     CoapBuildParam param;
563     CreateUnicastCoapParam(remoteUrl, host, &param);
564     return CoapSendMessage(&param, NSTACKX_FALSE, responseSettings->businessType, false);
565 }
566 
SendDiscoveryRsp(const NSTACKX_ResponseSettings * responseSettings)567 void SendDiscoveryRsp(const NSTACKX_ResponseSettings *responseSettings)
568 {
569     if (SendDiscoveryRspEx(responseSettings) != NSTACKX_EOK) {
570         IncStatistics(STATS_SEND_SD_RESPONSE_FAILED);
571     }
572 }
573 
SetCoapUserDiscoverInfo(uint32_t advCount,uint32_t advDuration)574 void SetCoapUserDiscoverInfo(uint32_t advCount, uint32_t advDuration)
575 {
576     g_coapUserMaxDiscoverCount = advCount;
577     if (advCount == 0) {
578         return;
579     }
580     g_coapUserDiscoverInterval = advDuration / advCount;
581 }
582