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_manager.h"
17 #include "common_list.h"
18 #include "disc_ble_dispatcher.h"
19 #include "disc_coap.h"
20 #include "disc_event.h"
21 #include "disc_log.h"
22 #include "securec.h"
23 #include "softbus_adapter_mem.h"
24 #include "softbus_adapter_thread.h"
25 #include "softbus_adapter_timer.h"
26 #include "softbus_def.h"
27 #include "softbus_error_code.h"
28 #include "softbus_hisysevt_discreporter.h"
29 #include "softbus_utils.h"
30 
31 #define DEVICE_TYPE_SIZE_MAX 3
32 #define DUMP_STR_LEN 256
33 #define DISC_INFO_LIST_SIZE_MAX 50
34 
35 static bool g_isInited = false;
36 
37 static SoftBusList *g_publishInfoList = NULL;
38 static SoftBusList *g_discoveryInfoList = NULL;
39 
40 static DiscoveryFuncInterface *g_discCoapInterface = NULL;
41 static DiscoveryFuncInterface *g_discBleInterface = NULL;
42 
43 static DiscInnerCallback g_discMgrMediumCb;
44 
45 static ListNode g_capabilityList[CAPABILITY_MAX_BITNUM];
46 
47 static const char *g_discModuleMap[] = {
48     "MODULE_LNN",
49     "MODULE_CONN",
50 };
51 
52 typedef enum {
53     MIN_SERVICE = 0,
54     PUBLISH_SERVICE = MIN_SERVICE,
55     PUBLISH_INNER_SERVICE = 1,
56     SUBSCRIBE_SERVICE = 2,
57     SUBSCRIBE_INNER_SERVICE = 3,
58     MAX_SERVICE = SUBSCRIBE_INNER_SERVICE,
59 } ServiceType;
60 
61 typedef union {
62     PublishOption publishOption;
63     SubscribeOption subscribeOption;
64 } InnerOption;
65 
66 typedef union  {
67     IServerDiscInnerCallback serverCb;
68     DiscInnerCallback innerCb;
69 } InnerCallback;
70 
71 typedef struct {
72     ListNode node;
73     char packageName[PKG_NAME_SIZE_MAX];
74     InnerCallback callback;
75     uint32_t infoNum;
76     ListNode InfoList;
77 } DiscItem;
78 
79 typedef struct {
80     ListNode node;
81     int32_t id;
82     DiscoverMode mode;
83     ExchangeMedium medium;
84     InnerOption option;
85     ListNode capNode;
86     DiscItem *item;
87     DiscoveryStatistics statistics;
88 } DiscInfo;
89 
90 typedef struct {
91     ListNode node;
92     int32_t id;
93     char *pkgName;
94 } IdContainer;
95 
96 #define DFX_RECORD_DISC_CALL_START(infoNode, packageName, interfaceType)   \
97     do {                                                                   \
98         DiscEventExtra extra = { 0 };                                      \
99         DiscEventExtraInit(&extra);                                        \
100         BuildDiscCallEvent(&extra, infoNode, packageName, interfaceType);  \
101         DISC_EVENT(EVENT_SCENE_DISC, EVENT_STAGE_CALL_INTERFACE, extra);   \
102     } while (0)
103 
UpdateDiscEventAndReport(DiscEventExtra * extra,const DeviceInfo * device)104 static void UpdateDiscEventAndReport(DiscEventExtra *extra, const DeviceInfo *device)
105 {
106     if (device == NULL) {
107         DISC_EVENT(EVENT_SCENE_DISC, EVENT_STAGE_DEVICE_FOUND, *extra);
108         DISC_LOGI(DISC_CONTROL, "device info is null");
109         return;
110     }
111     if (device->addrNum <= CONNECTION_ADDR_WLAN || device->addrNum > CONNECTION_ADDR_MAX) {
112         DISC_EVENT(EVENT_SCENE_DISC, EVENT_STAGE_DEVICE_FOUND, *extra);
113         DISC_LOGI(DISC_CONTROL, "unknown device info");
114         return;
115     }
116 
117     for (uint32_t i = 0; i < device->addrNum; i++) {
118         switch (device->addr[i].type) {
119             case CONNECTION_ADDR_BR:
120                 extra->peerBrMac = device->addr[i].info.br.brMac;
121                 break;
122             case CONNECTION_ADDR_BLE:
123                 extra->peerBleMac = device->addr[i].info.ble.bleMac;
124                 break;
125             case CONNECTION_ADDR_WLAN:
126                 /* fall-through */
127             case CONNECTION_ADDR_ETH:
128                 extra->peerIp = device->addr[i].info.ip.ip;
129                 break;
130             default:
131                 DISC_LOGI(DISC_CONTROL, "unknown param type!");
132                 break;
133         }
134     }
135 
136     char *deviceType = SoftBusCalloc(DEVICE_TYPE_SIZE_MAX + 1);
137     DISC_CHECK_AND_RETURN_LOGE(deviceType != NULL, DISC_CONTROL, "SoftBusCalloc failed");
138     if (snprintf_s(deviceType, DEVICE_TYPE_SIZE_MAX + 1, DEVICE_TYPE_SIZE_MAX, "%03X", device->devType) >= 0) {
139         extra->peerDeviceType = deviceType;
140     }
141     DISC_EVENT(EVENT_SCENE_DISC, EVENT_STAGE_DEVICE_FOUND, *extra);
142     SoftBusFree(deviceType);
143     extra->peerDeviceType = NULL;
144 }
145 
DfxRecordStartDiscoveryDevice(DiscInfo * infoNode)146 static void DfxRecordStartDiscoveryDevice(DiscInfo *infoNode)
147 {
148     infoNode->statistics.startTime = SoftBusGetSysTimeMs();
149     infoNode->statistics.repTimes = 0;
150     infoNode->statistics.devNum = 0;
151     infoNode->statistics.discTimes = 0;
152 }
153 
UpdateDdmpStartDiscoveryTime(DiscInfo * info)154 static void UpdateDdmpStartDiscoveryTime(DiscInfo *info)
155 {
156     if (info->medium != AUTO && info->medium != COAP) {
157         DISC_LOGD(DISC_CONTROL, "no need update ddmp start discovery time");
158         return;
159     }
160 
161     DiscInfo *infoNode = NULL;
162     LIST_FOR_EACH_ENTRY(infoNode, &(g_capabilityList[DDMP_CAPABILITY_BITMAP]), DiscInfo, capNode) {
163         if (infoNode->statistics.repTimes == 0) {
164             DISC_LOGD(DISC_CONTROL, "update ddmp callback id=%{public}d", infoNode->id);
165             infoNode->statistics.startTime = info->statistics.startTime;
166         }
167     }
168 }
169 
DfxRecordDeviceFound(DiscInfo * infoNode,const DeviceInfo * device,const InnerDeviceInfoAddtions * additions)170 static void DfxRecordDeviceFound(DiscInfo *infoNode, const DeviceInfo *device, const InnerDeviceInfoAddtions *additions)
171 {
172     DISC_LOGD(DISC_CONTROL, "record device found");
173     if (infoNode->statistics.repTimes == 0) {
174         uint64_t costTime = 0;
175         uint64_t sysTime = SoftBusGetSysTimeMs();
176         if (sysTime >= infoNode->statistics.startTime) {
177             costTime = sysTime - infoNode->statistics.startTime;
178         } else {
179             DISC_LOGE(DISC_CONTROL, "CurTime < startTime");
180         }
181         SoftbusRecordFirstDiscTime((SoftBusDiscMedium)additions->medium, costTime);
182         DiscEventExtra extra = { 0 };
183         DiscEventExtraInit(&extra);
184         extra.discMode = infoNode == NULL ? 0 : infoNode->mode;
185         extra.discType = additions == NULL ? 0 : additions->medium + 1;
186         extra.costTime = (int32_t)costTime;
187         extra.result = EVENT_STAGE_RESULT_OK;
188         UpdateDiscEventAndReport(&extra, device);
189     }
190     infoNode->statistics.repTimes++;
191     infoNode->statistics.devNum++;
192 }
DfxRecordStopDiscoveryDevice(const char * packageName,DiscInfo * infoNode)193 static void DfxRecordStopDiscoveryDevice(const char *packageName, DiscInfo *infoNode)
194 {
195     DiscoveryStatistics *statistics = &infoNode->statistics;
196     uint64_t totalTime = SoftBusGetSysTimeMs() - statistics->startTime;
197     SoftbusRecordBleDiscDetails((char *)packageName, totalTime, statistics->repTimes, statistics->devNum,
198                                 statistics->discTimes);
199 }
BitmapSet(uint32_t * bitMap,uint32_t pos)200 static void BitmapSet(uint32_t *bitMap, uint32_t pos)
201 {
202     *bitMap |= 1U << pos;
203 }
204 
IsBitmapSet(const uint32_t * bitMap,uint32_t pos)205 static bool IsBitmapSet(const uint32_t *bitMap, uint32_t pos)
206 {
207     return ((1U << pos) & (*bitMap)) ? true : false;
208 }
209 
BuildDiscCallEvent(DiscEventExtra * extra,const DiscInfo * info,const char * packageName,const InterfaceFuncType type)210 static void BuildDiscCallEvent(DiscEventExtra *extra, const DiscInfo *info, const char *packageName,
211     const InterfaceFuncType type)
212 {
213     DISC_CHECK_AND_RETURN_LOGE(extra != NULL, DISC_CONTROL, "discEventExtra is null");
214 
215     if (info != NULL) {
216         extra->discType = info->medium + 1;
217         extra->discMode = info->mode;
218     }
219     if (IsValidString(packageName, PKG_NAME_SIZE_MAX - 1)) {
220         extra->callerPkg = packageName;
221     }
222     extra->interFuncType = type + 1;
223 }
224 
CallSpecificInterfaceFunc(const InnerOption * option,const DiscoveryFuncInterface * interface,const DiscoverMode mode,InterfaceFuncType type)225 static int32_t CallSpecificInterfaceFunc(const InnerOption *option,
226     const DiscoveryFuncInterface *interface, const DiscoverMode mode, InterfaceFuncType type)
227 {
228     DISC_CHECK_AND_RETURN_RET_LOGW(interface != NULL, SOFTBUS_DISCOVER_MANAGER_INNERFUNCTION_FAIL,
229         DISC_CONTROL, "interface is null");
230     switch (type) {
231         case PUBLISH_FUNC:
232             return ((mode == DISCOVER_MODE_ACTIVE) ? (interface->Publish(&(option->publishOption))) :
233                 (interface->StartScan(&(option->publishOption))));
234         case UNPUBLISH_FUNC:
235             return ((mode == DISCOVER_MODE_ACTIVE) ? (interface->Unpublish(&(option->publishOption))) :
236                 (interface->StopScan(&(option->publishOption))));
237         case STARTDISCOVERTY_FUNC:
238             return ((mode == DISCOVER_MODE_ACTIVE) ? (interface->StartAdvertise(&(option->subscribeOption))) :
239                 (interface->Subscribe(&(option->subscribeOption))));
240         case STOPDISCOVERY_FUNC:
241             return ((mode == DISCOVER_MODE_ACTIVE) ? (interface->StopAdvertise(&(option->subscribeOption))) :
242                 (interface->Unsubscribe(&(option->subscribeOption))));
243         default:
244             return SOFTBUS_DISCOVER_MANAGER_INNERFUNCTION_FAIL;
245     }
246 }
247 
DfxCallInterfaceByMedium(const DiscInfo * infoNode,const char * packageName,const InterfaceFuncType type,int32_t reason)248 static void DfxCallInterfaceByMedium(
249     const DiscInfo *infoNode, const char *packageName, const InterfaceFuncType type, int32_t reason)
250 {
251     DiscEventExtra extra = {0};
252     DiscEventExtraInit(&extra);
253     extra.errcode = reason;
254     BuildDiscCallEvent(&extra, infoNode, packageName, type);
255     extra.result = (reason == SOFTBUS_OK) ? EVENT_STAGE_RESULT_OK : EVENT_STAGE_RESULT_FAILED;
256     DISC_EVENT(EVENT_SCENE_DISC, EVENT_STAGE_CALL_INTERFACE, extra);
257 }
258 
CallInterfaceByMedium(const DiscInfo * info,const char * packageName,const InterfaceFuncType type)259 static int32_t CallInterfaceByMedium(const DiscInfo *info, const char *packageName, const InterfaceFuncType type)
260 {
261     int32_t ret = SOFTBUS_OK;
262     switch (info->medium) {
263         case COAP:
264             ret = CallSpecificInterfaceFunc(&(info->option), g_discCoapInterface, info->mode, type);
265             DfxCallInterfaceByMedium(info, packageName, type, ret);
266             return ret;
267         case BLE:
268             ret = CallSpecificInterfaceFunc(&(info->option), g_discBleInterface, info->mode, type);
269             DfxCallInterfaceByMedium(info, packageName, type, ret);
270             return ret;
271         case AUTO: {
272             int32_t coapRet = CallSpecificInterfaceFunc(&(info->option), g_discCoapInterface, info->mode, type);
273             DfxCallInterfaceByMedium(info, packageName, type, coapRet);
274             int32_t bleRet = CallSpecificInterfaceFunc(&(info->option), g_discBleInterface, info->mode, type);
275             DfxCallInterfaceByMedium(info, packageName, type, bleRet);
276 
277             DISC_CHECK_AND_RETURN_RET_LOGE(coapRet == SOFTBUS_OK || bleRet == SOFTBUS_OK,
278                 SOFTBUS_DISCOVER_MANAGER_INNERFUNCTION_FAIL, DISC_CONTROL, "all medium failed");
279             return SOFTBUS_OK;
280         }
281         default:
282             return SOFTBUS_DISCOVER_MANAGER_INNERFUNCTION_FAIL;
283     }
284 }
285 
TransferStringCapToBitmap(const char * capability)286 static int32_t TransferStringCapToBitmap(const char *capability)
287 {
288     DISC_CHECK_AND_RETURN_RET_LOGW(capability != NULL, SOFTBUS_DISCOVER_MANAGER_CAPABILITY_INVALID,
289         DISC_CONTROL, "capability is null");
290 
291     for (uint32_t i = 0; i < sizeof(g_capabilityMap) / sizeof(g_capabilityMap[0]); i++) {
292         if (strcmp(capability, g_capabilityMap[i].capability) == 0) {
293             DISC_LOGD(DISC_CONTROL, "capability=%{public}s", capability);
294             return g_capabilityMap[i].bitmap;
295         }
296     }
297 
298     return SOFTBUS_DISCOVER_MANAGER_CAPABILITY_INVALID;
299 }
300 
AddDiscInfoToCapabilityList(DiscInfo * info,const ServiceType type)301 static void AddDiscInfoToCapabilityList(DiscInfo *info, const ServiceType type)
302 {
303     if (type != SUBSCRIBE_SERVICE && type != SUBSCRIBE_INNER_SERVICE) {
304         DISC_LOGD(DISC_CONTROL, "publish no need to add");
305         return;
306     }
307 
308     for (uint32_t tmp = 0; tmp < CAPABILITY_MAX_BITNUM; tmp++) {
309         if (IsBitmapSet(&(info->option.subscribeOption.capabilityBitmap[0]), tmp) == true) {
310             if (type == SUBSCRIBE_SERVICE) {
311                 ListTailInsert(&(g_capabilityList[tmp]), &(info->capNode));
312             } else {
313                 ListNodeInsert(&(g_capabilityList[tmp]), &(info->capNode));
314             }
315             break;
316         }
317     }
318 }
319 
RemoveDiscInfoFromCapabilityList(DiscInfo * info,const ServiceType type)320 static void RemoveDiscInfoFromCapabilityList(DiscInfo *info, const ServiceType type)
321 {
322     if (type != SUBSCRIBE_SERVICE && type != SUBSCRIBE_INNER_SERVICE) {
323         DISC_LOGD(DISC_CONTROL, "publish no need to delete");
324         return;
325     }
326     ListDelete(&(info->capNode));
327 }
328 
FreeDiscInfo(DiscInfo * info,const ServiceType type)329 static void FreeDiscInfo(DiscInfo *info, const ServiceType type)
330 {
331     if ((type == PUBLISH_SERVICE) || (type == PUBLISH_INNER_SERVICE)) {
332         SoftBusFree(info->option.publishOption.capabilityData);
333         info->option.publishOption.capabilityData = NULL;
334     }
335 
336     if ((type == SUBSCRIBE_SERVICE) || (type == SUBSCRIBE_INNER_SERVICE)) {
337         SoftBusFree(info->option.subscribeOption.capabilityData);
338         info->option.subscribeOption.capabilityData = NULL;
339     }
340     SoftBusFree(info);
341     info = NULL;
342 }
343 
IsInnerModule(const DiscInfo * infoNode)344 static bool IsInnerModule(const DiscInfo *infoNode)
345 {
346     for (uint32_t i = 0; i < MODULE_MAX; i++) {
347         DISC_LOGD(DISC_CONTROL, "packageName=%{public}s", infoNode->item->packageName);
348         if (strcmp(infoNode->item->packageName, g_discModuleMap[i]) == 0) {
349             DISC_LOGD(DISC_CONTROL, "true");
350             return true;
351         }
352     }
353     DISC_LOGD(DISC_CONTROL, "false");
354     return false;
355 }
356 
InnerDeviceFound(DiscInfo * infoNode,const DeviceInfo * device,const InnerDeviceInfoAddtions * additions)357 static void InnerDeviceFound(DiscInfo *infoNode, const DeviceInfo *device, const InnerDeviceInfoAddtions *additions)
358 {
359     if (infoNode->item != NULL && infoNode->item->callback.serverCb.OnServerDeviceFound != NULL &&
360         !IsInnerModule(infoNode)) {
361         (void)infoNode->item->callback.serverCb.OnServerDeviceFound(infoNode->item->packageName, device, additions);
362         return;
363     }
364 
365     DISC_LOGD(DISC_CONTROL, "call from inner module.");
366     if (infoNode->item != NULL && infoNode->item->callback.innerCb.OnDeviceFound != NULL) {
367         DfxRecordDeviceFound(infoNode, device, additions);
368         infoNode->item->callback.innerCb.OnDeviceFound(device, additions);
369     }
370 }
371 
DiscOnDeviceFound(const DeviceInfo * device,const InnerDeviceInfoAddtions * additions)372 static void DiscOnDeviceFound(const DeviceInfo *device, const InnerDeviceInfoAddtions *additions)
373 {
374     DISC_CHECK_AND_RETURN_LOGE(device != NULL, DISC_CONTROL, "device is null");
375     DISC_CHECK_AND_RETURN_LOGE(additions != NULL, DISC_CONTROL, "additions is null");
376 
377     DISC_LOGD(DISC_CONTROL,
378         "capabilityBitmap=%{public}d, medium=%{public}d", device->capabilityBitmap[0], additions->medium);
379     for (uint32_t tmp = 0; tmp < CAPABILITY_MAX_BITNUM; tmp++) {
380         if (IsBitmapSet((uint32_t *)device->capabilityBitmap, tmp) == false) {
381             continue;
382         }
383 
384         if (SoftBusMutexLock(&(g_discoveryInfoList->lock)) != SOFTBUS_OK) {
385             DISC_LOGE(DISC_CONTROL, "lock failed");
386             return;
387         }
388         DiscInfo *infoNode = NULL;
389         LIST_FOR_EACH_ENTRY(infoNode, &(g_capabilityList[tmp]), DiscInfo, capNode) {
390             DISC_LOGD(DISC_CONTROL, "find callback id=%{public}d", infoNode->id);
391             infoNode->statistics.discTimes++;
392             InnerDeviceFound(infoNode, device, additions);
393         }
394         (void)SoftBusMutexUnlock(&(g_discoveryInfoList->lock));
395     }
396 }
397 
CheckPublishInfo(const PublishInfo * info)398 static int32_t CheckPublishInfo(const PublishInfo *info)
399 {
400     DISC_CHECK_AND_RETURN_RET_LOGW(info->mode == DISCOVER_MODE_PASSIVE || info->mode == DISCOVER_MODE_ACTIVE,
401         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "mode is invalid");
402     DISC_CHECK_AND_RETURN_RET_LOGW(info->medium >= AUTO && info->medium <= COAP,
403         SOFTBUS_DISCOVER_MANAGER_INVALID_MEDIUM, DISC_CONTROL, "mode is invalid");
404     DISC_CHECK_AND_RETURN_RET_LOGW(info->freq >= LOW && info->freq < FREQ_BUTT,
405         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "freq is invalid");
406 
407     if (info->capabilityData == NULL) {
408         if (info->dataLen == 0) {
409             return SOFTBUS_OK;
410         } else {
411             DISC_LOGE(DISC_CONTROL, "capabilityData is NULL, dataLen != 0");
412             return SOFTBUS_INVALID_PARAM;
413         }
414     } else {
415         if (info->dataLen == 0) {
416             DISC_LOGE(DISC_CONTROL, "capabilityData is not NULL, dataLen == 0");
417             return SOFTBUS_INVALID_PARAM;
418         }
419         if (info->dataLen > MAX_CAPABILITYDATA_LEN) {
420             DISC_LOGE(DISC_CONTROL, "dataLen > max length. dataLen=%{public}u", info->dataLen);
421             return SOFTBUS_INVALID_PARAM;
422         }
423         uint32_t len = strlen((char *)info->capabilityData);
424         if (info->capabilityData[info->dataLen] != '\0') {
425             DISC_LOGE(DISC_CONTROL, "capabilityData is not c-string format: len=%{public}u, dataLen=%{public}u",
426                 len, info->dataLen);
427             return SOFTBUS_INVALID_PARAM;
428         }
429         if (len != info->dataLen) {
430             DISC_LOGE(DISC_CONTROL, "capabilityData len != dataLen. len=%{public}u, dataLen=%{public}u",
431                 len, info->dataLen);
432             return SOFTBUS_INVALID_PARAM;
433         }
434     }
435     return SOFTBUS_OK;
436 }
437 
CheckSubscribeInfo(const SubscribeInfo * info)438 static int32_t CheckSubscribeInfo(const SubscribeInfo *info)
439 {
440     DISC_CHECK_AND_RETURN_RET_LOGW(info->mode == DISCOVER_MODE_PASSIVE || info->mode == DISCOVER_MODE_ACTIVE,
441         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "mode is invalid");
442     DISC_CHECK_AND_RETURN_RET_LOGW(info->medium >= AUTO && info->medium <= COAP,
443         SOFTBUS_DISCOVER_MANAGER_INVALID_MEDIUM, DISC_CONTROL, "mode is invalid");
444     DISC_CHECK_AND_RETURN_RET_LOGW(info->freq >= LOW && info->freq < FREQ_BUTT,
445         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "freq is invalid");
446 
447     if (info->capabilityData == NULL) {
448         if (info->dataLen == 0) {
449             return SOFTBUS_OK;
450         } else {
451             DISC_LOGE(DISC_CONTROL, "capabilityData is NULL, dataLen != 0");
452             return SOFTBUS_INVALID_PARAM;
453         }
454     } else {
455         if (info->dataLen == 0) {
456             DISC_LOGE(DISC_CONTROL, "capabilityData is not NULL, dataLen == 0");
457             return SOFTBUS_INVALID_PARAM;
458         }
459         if (info->dataLen > MAX_CAPABILITYDATA_LEN) {
460             DISC_LOGE(DISC_CONTROL, "dataLen > max length. dataLen=%{public}u", info->dataLen);
461             return SOFTBUS_INVALID_PARAM;
462         }
463         uint32_t len = strlen((char *)info->capabilityData);
464         if (info->capabilityData[info->dataLen] != '\0') {
465             DISC_LOGE(DISC_CONTROL, "capabilityData is not c-string format: len=%{public}u, dataLen=%{public}u",
466                 len, info->dataLen);
467             return SOFTBUS_INVALID_PARAM;
468         }
469         if (len != info->dataLen) {
470             DISC_LOGE(DISC_CONTROL, "capabilityData len != dataLen. len=%{public}u, dataLen=%{public}u",
471                 len, info->dataLen);
472             return SOFTBUS_INVALID_PARAM;
473         }
474     }
475     return SOFTBUS_OK;
476 }
477 
SetDiscItemCallback(DiscItem * itemNode,const InnerCallback * cb,const ServiceType type)478 static void SetDiscItemCallback(DiscItem *itemNode, const InnerCallback *cb, const ServiceType type)
479 {
480     if ((type != SUBSCRIBE_INNER_SERVICE && type != SUBSCRIBE_SERVICE) || cb == NULL) {
481         return;
482     }
483     if (type == SUBSCRIBE_SERVICE) {
484         itemNode->callback.serverCb.OnServerDeviceFound = cb->serverCb.OnServerDeviceFound;
485         return;
486     }
487     if ((itemNode->callback.innerCb.OnDeviceFound != NULL) && (cb->innerCb.OnDeviceFound == NULL)) {
488         return;
489     }
490     itemNode->callback.innerCb.OnDeviceFound = cb->innerCb.OnDeviceFound;
491 }
492 
CreateDiscItem(SoftBusList * serviceList,const char * packageName,const InnerCallback * cb,const ServiceType type)493 static DiscItem *CreateDiscItem(SoftBusList *serviceList, const char *packageName, const InnerCallback *cb,
494                                 const ServiceType type)
495 {
496     DiscItem *itemNode = (DiscItem *)SoftBusCalloc(sizeof(DiscItem));
497     DISC_CHECK_AND_RETURN_RET_LOGE(itemNode != NULL, NULL, DISC_CONTROL, "calloc item node failed");
498 
499     if (strcpy_s(itemNode->packageName, PKG_NAME_SIZE_MAX, packageName) != EOK) {
500         SoftBusFree(itemNode);
501         return NULL;
502     }
503 
504     if ((type == PUBLISH_INNER_SERVICE) || (type == SUBSCRIBE_INNER_SERVICE)) {
505         ListNodeInsert(&(serviceList->list), &(itemNode->node));
506     } else if ((type == PUBLISH_SERVICE) || (type == SUBSCRIBE_SERVICE)) {
507         ListTailInsert(&(serviceList->list), &(itemNode->node));
508     }
509 
510     SetDiscItemCallback(itemNode, cb, type);
511 
512     serviceList->cnt++;
513     ListInit(&(itemNode->InfoList));
514     return itemNode;
515 }
516 
CreateDiscInfoForPublish(const PublishInfo * info)517 static DiscInfo *CreateDiscInfoForPublish(const PublishInfo *info)
518 {
519     DiscInfo *infoNode = (DiscInfo *)SoftBusCalloc(sizeof(DiscInfo));
520     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, NULL, DISC_CONTROL, "calloc info node failed");
521 
522     ListInit(&(infoNode->node));
523     ListInit(&(infoNode->capNode));
524 
525     infoNode->id = info->publishId;
526     infoNode->medium = info->medium;
527     infoNode->mode = info->mode;
528 
529     PublishOption *option = &infoNode->option.publishOption;
530     option->freq = info->freq;
531     option->ranging = info->ranging;
532     option->dataLen = info->dataLen;
533 
534     if (info->dataLen != 0) {
535         option->capabilityData = (uint8_t *)SoftBusCalloc(info->dataLen + 1);
536         if (option->capabilityData == NULL) {
537             DISC_LOGE(DISC_CONTROL, "alloc capability data failed");
538             SoftBusFree(infoNode);
539             return NULL;
540         }
541         if (memcpy_s(option->capabilityData, info->dataLen, info->capabilityData, info->dataLen) != EOK) {
542             DISC_LOGE(DISC_CONTROL, "memcpy_s failed");
543             FreeDiscInfo(infoNode, PUBLISH_SERVICE);
544             return NULL;
545         }
546     }
547 
548     int32_t bitmap = TransferStringCapToBitmap(info->capability);
549     if (bitmap < 0) {
550         DISC_LOGE(DISC_CONTROL, "capability not found");
551         FreeDiscInfo(infoNode, PUBLISH_SERVICE);
552         return NULL;
553     }
554     BitmapSet(option->capabilityBitmap, (uint32_t)bitmap);
555 
556     return infoNode;
557 }
558 
CreateDiscInfoForSubscribe(const SubscribeInfo * info)559 static DiscInfo *CreateDiscInfoForSubscribe(const SubscribeInfo *info)
560 {
561     DiscInfo *infoNode = (DiscInfo *)SoftBusCalloc(sizeof(DiscInfo));
562     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, NULL, DISC_CONTROL, "alloc info node failed");
563 
564     ListInit(&(infoNode->node));
565     ListInit(&(infoNode->capNode));
566 
567     infoNode->id = info->subscribeId;
568     infoNode->medium = info->medium;
569     infoNode->mode = info->mode;
570 
571     SubscribeOption *option = &infoNode->option.subscribeOption;
572     option->freq = info->freq;
573     option->dataLen = info->dataLen;
574     option->isSameAccount = info->isSameAccount;
575     option->isWakeRemote = info->isWakeRemote;
576 
577     if (info->dataLen != 0) {
578         option->capabilityData = (uint8_t *)SoftBusCalloc(info->dataLen + 1);
579         if (option->capabilityData == NULL) {
580             DISC_LOGE(DISC_CONTROL, "alloc capability data failed");
581             SoftBusFree(infoNode);
582             return NULL;
583         }
584         if (memcpy_s(option->capabilityData, info->dataLen, info->capabilityData, info->dataLen) != EOK) {
585             DISC_LOGE(DISC_CONTROL, "memcpy_s failed");
586             FreeDiscInfo(infoNode, SUBSCRIBE_SERVICE);
587             return NULL;
588         }
589     }
590 
591     int32_t bimap = TransferStringCapToBitmap(info->capability);
592     if (bimap < 0) {
593         DISC_LOGE(DISC_CONTROL, "capability not found");
594         FreeDiscInfo(infoNode, SUBSCRIBE_SERVICE);
595         return NULL;
596     }
597     BitmapSet(option->capabilityBitmap, (uint32_t)bimap);
598     DfxRecordStartDiscoveryDevice(infoNode);
599     return infoNode;
600 }
601 
DumpDiscInfoList(const DiscItem * itemNode)602 static void DumpDiscInfoList(const DiscItem *itemNode)
603 {
604     char dumpStr[DUMP_STR_LEN] = {0};
605     int32_t dumpStrPos = 0;
606     int32_t itemStrLen = 0;
607     DiscInfo *infoNode = NULL;
608 
609     LIST_FOR_EACH_ENTRY(infoNode, &(itemNode->InfoList), DiscInfo, node) {
610         itemStrLen = sprintf_s(&dumpStr[dumpStrPos], DUMP_STR_LEN - dumpStrPos, "%d,", infoNode->id);
611         if (itemStrLen <= 0) {
612             DISC_LOGI(DISC_CONTROL, "info id=%{public}s", dumpStr);
613             dumpStrPos = 0;
614             itemStrLen = sprintf_s(&dumpStr[dumpStrPos], DUMP_STR_LEN - dumpStrPos, "%d,", infoNode->id);
615             DISC_CHECK_AND_RETURN_LOGW(itemStrLen > 0, DISC_CONTROL, "sprintf_s failed");
616         }
617         dumpStrPos += itemStrLen;
618     }
619 
620     if (dumpStrPos > 0) {
621         DISC_LOGI(DISC_CONTROL, "info id=%{public}s", dumpStr);
622     }
623 }
624 
AddDiscInfoToList(SoftBusList * serviceList,const char * packageName,const InnerCallback * cb,DiscInfo * info,ServiceType type)625 static int32_t AddDiscInfoToList(SoftBusList *serviceList, const char *packageName, const InnerCallback *cb,
626                                  DiscInfo *info, ServiceType type)
627 {
628     bool isDumpable = (strcmp(g_discModuleMap[0], packageName) != 0);
629     if (isDumpable) {
630         DISC_LOGI(DISC_CONTROL, "packageName=%{public}s, id=%{public}d", packageName, info->id);
631     }
632 
633     DiscItem *itemNode = NULL;
634     bool exist = false;
635     LIST_FOR_EACH_ENTRY(itemNode, &(serviceList->list), DiscItem, node) {
636         if (strcmp(itemNode->packageName, packageName) != 0) {
637             continue;
638         }
639 
640         if (isDumpable) {
641             DumpDiscInfoList(itemNode);
642         }
643 
644         DiscInfo *infoNode = NULL;
645         LIST_FOR_EACH_ENTRY(infoNode, &(itemNode->InfoList), DiscInfo, node) {
646             if (infoNode->id == info->id) {
647                 DISC_LOGI(DISC_CONTROL, "id already existed");
648                 return SOFTBUS_DISCOVER_MANAGER_DUPLICATE_PARAM;
649             }
650         }
651         DISC_CHECK_AND_RETURN_RET_LOGE(
652             itemNode->infoNum < DISC_INFO_LIST_SIZE_MAX, SOFTBUS_DISCOVER_MANAGER_ID_MAX_ERR,
653             DISC_CONTROL, "infolist size limit reached, packageName=%{public}s", packageName);
654 
655         SetDiscItemCallback(itemNode, cb, type);
656         exist = true;
657         itemNode->infoNum++;
658         info->item = itemNode;
659         ListTailInsert(&(itemNode->InfoList), &(info->node));
660         AddDiscInfoToCapabilityList(info, type);
661         break;
662     }
663 
664     if (exist == false) {
665         itemNode = CreateDiscItem(serviceList, packageName, cb, type);
666         if (itemNode == NULL) {
667             DISC_LOGE(DISC_CONTROL, "itemNode create failed");
668             return SOFTBUS_DISCOVER_MANAGER_ITEM_NOT_CREATE;
669         }
670 
671         itemNode->infoNum++;
672         info->item = itemNode;
673         ListTailInsert(&(itemNode->InfoList), &(info->node));
674         AddDiscInfoToCapabilityList(info, type);
675     }
676 
677     return SOFTBUS_OK;
678 }
679 
AddDiscInfoToPublishList(const char * packageName,const InnerCallback * cb,DiscInfo * info,ServiceType type)680 static int32_t AddDiscInfoToPublishList(const char *packageName, const InnerCallback *cb, DiscInfo *info,
681                                         ServiceType type)
682 {
683     return AddDiscInfoToList(g_publishInfoList, packageName, cb, info, type);
684 }
685 
AddDiscInfoToDiscoveryList(const char * packageName,const InnerCallback * cb,DiscInfo * info,ServiceType type)686 static int32_t AddDiscInfoToDiscoveryList(const char *packageName, const InnerCallback *cb, DiscInfo *info,
687                                           ServiceType type)
688 {
689     return AddDiscInfoToList(g_discoveryInfoList, packageName, cb, info, type);
690 }
691 
RemoveInfoFromList(SoftBusList * serviceList,const char * packageName,const int32_t id,const ServiceType type)692 static DiscInfo *RemoveInfoFromList(SoftBusList *serviceList, const char *packageName, const int32_t id,
693                                     const ServiceType type)
694 {
695     bool isDumpable = (strcmp(g_discModuleMap[0], packageName) != 0);
696     if (isDumpable) {
697         DISC_LOGI(DISC_CONTROL, "packageName=%{public}s, id=%{public}d", packageName, id);
698     }
699 
700     bool isIdExist = false;
701     DiscItem *itemNode = NULL;
702     DiscInfo *infoNode = NULL;
703     LIST_FOR_EACH_ENTRY(itemNode, &(serviceList->list), DiscItem, node) {
704         if (strcmp(itemNode->packageName, packageName) != 0) {
705             continue;
706         }
707 
708         if (isDumpable) {
709             DumpDiscInfoList(itemNode);
710         }
711 
712         if (itemNode->infoNum == 0) {
713             serviceList->cnt--;
714             ListDelete(&(itemNode->node));
715             SoftBusFree(itemNode);
716             return NULL;
717         }
718 
719         LIST_FOR_EACH_ENTRY(infoNode, &(itemNode->InfoList), DiscInfo, node) {
720             if (infoNode->id != id) {
721                 continue;
722             }
723             isIdExist = true;
724             itemNode->infoNum--;
725             RemoveDiscInfoFromCapabilityList(infoNode, type);
726             ListDelete(&(infoNode->node));
727 
728             if (itemNode->infoNum == 0) {
729                 serviceList->cnt--;
730                 ListDelete(&(itemNode->node));
731                 SoftBusFree(itemNode);
732             }
733             break;
734         }
735         break;
736     }
737 
738     if (isIdExist == false) {
739         DISC_LOGD(DISC_CONTROL, "can not find publishId");
740         return NULL;
741     }
742     return infoNode;
743 }
744 
RemoveInfoFromPublishList(const char * packageName,const int32_t id,const ServiceType type)745 static DiscInfo *RemoveInfoFromPublishList(const char *packageName, const int32_t id, const ServiceType type)
746 {
747     return RemoveInfoFromList(g_publishInfoList, packageName, id, type);
748 }
749 
RemoveInfoFromDiscoveryList(const char * packageName,const int32_t id,const ServiceType type)750 static DiscInfo *RemoveInfoFromDiscoveryList(const char *packageName, const int32_t id, const ServiceType type)
751 {
752     return RemoveInfoFromList(g_discoveryInfoList, packageName, id, type);
753 }
754 
InnerPublishService(const char * packageName,DiscInfo * info,const ServiceType type)755 static int32_t InnerPublishService(const char *packageName, DiscInfo *info, const ServiceType type)
756 {
757     int32_t ret = SoftBusMutexLock(&g_publishInfoList->lock);
758     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, DISC_CONTROL, "lock failed");
759 
760     do {
761         ret = AddDiscInfoToPublishList(packageName, NULL, info, type);
762         if (ret != SOFTBUS_OK) {
763             DISC_LOGE(DISC_CONTROL, "add info to list failed");
764             break;
765         }
766 
767         DFX_RECORD_DISC_CALL_START(info, packageName, PUBLISH_FUNC);
768         ret = CallInterfaceByMedium(info, packageName, PUBLISH_FUNC);
769         if (ret != SOFTBUS_OK) {
770             DISC_LOGE(DISC_CONTROL, "call interface by medium failed");
771             ListDelete(&(info->node));
772             info->item->infoNum--;
773         }
774     } while (false);
775 
776     SoftBusMutexUnlock(&g_publishInfoList->lock);
777     return ret;
778 }
779 
InnerUnPublishService(const char * packageName,int32_t publishId,const ServiceType type)780 static int32_t InnerUnPublishService(const char *packageName, int32_t publishId, const ServiceType type)
781 {
782     int32_t ret = SoftBusMutexLock(&g_publishInfoList->lock);
783     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, DISC_CONTROL, "lock failed");
784 
785     DiscInfo *infoNode = NULL;
786     do {
787         infoNode = RemoveInfoFromPublishList(packageName, publishId, type);
788         if (infoNode == NULL) {
789             DISC_LOGE(DISC_CONTROL, "delete info from list failed");
790             ret = SOFTBUS_DISCOVER_MANAGER_INFO_NOT_DELETE;
791             break;
792         }
793 
794         DFX_RECORD_DISC_CALL_START(infoNode, packageName, UNPUBLISH_FUNC);
795         ret = CallInterfaceByMedium(infoNode, packageName, UNPUBLISH_FUNC);
796         if (ret != SOFTBUS_OK) {
797             DISC_LOGE(DISC_CONTROL, "call interface by medium failed");
798         }
799         FreeDiscInfo(infoNode, type);
800     } while (false);
801 
802     SoftBusMutexUnlock(&g_publishInfoList->lock);
803     return ret;
804 }
805 
InnerStartDiscovery(const char * packageName,DiscInfo * info,const IServerDiscInnerCallback * cb,const ServiceType type)806 static int32_t InnerStartDiscovery(const char *packageName, DiscInfo *info, const IServerDiscInnerCallback *cb,
807                                    const ServiceType type)
808 {
809     InnerCallback callback;
810     callback.serverCb.OnServerDeviceFound = NULL;
811     if (cb != NULL) {
812         callback.serverCb.OnServerDeviceFound = cb->OnServerDeviceFound;
813     }
814 
815     int32_t ret = SoftBusMutexLock(&g_discoveryInfoList->lock);
816     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, DISC_CONTROL, "lock failed");
817 
818     do {
819         ret = AddDiscInfoToDiscoveryList(packageName, &callback, info, type);
820         if (ret != SOFTBUS_OK) {
821             DISC_LOGE(DISC_CONTROL, "add info to list failed");
822             break;
823         }
824 
825         UpdateDdmpStartDiscoveryTime(info);
826         DFX_RECORD_DISC_CALL_START(info, packageName, STARTDISCOVERTY_FUNC);
827         ret = CallInterfaceByMedium(info, packageName, STARTDISCOVERTY_FUNC);
828         if (ret != SOFTBUS_OK) {
829             DISC_LOGE(DISC_CONTROL, "call interface by medium failed");
830             RemoveDiscInfoFromCapabilityList(info, type);
831             ListDelete(&(info->node));
832             info->item->infoNum--;
833         }
834     } while (false);
835 
836     SoftBusMutexUnlock(&g_discoveryInfoList->lock);
837     return ret;
838 }
839 
InnerStopDiscovery(const char * packageName,int32_t subscribeId,const ServiceType type)840 static int32_t InnerStopDiscovery(const char *packageName, int32_t subscribeId, const ServiceType type)
841 {
842     int32_t ret = SoftBusMutexLock(&g_discoveryInfoList->lock);
843     DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, DISC_CONTROL, "lock failed");
844 
845     DiscInfo *infoNode = NULL;
846     do {
847         infoNode = RemoveInfoFromDiscoveryList(packageName, subscribeId, type);
848         if (infoNode == NULL) {
849             DISC_LOGE(DISC_CONTROL, "delete info from list failed");
850             ret = SOFTBUS_DISCOVER_MANAGER_INFO_NOT_DELETE;
851             break;
852         }
853 
854         DFX_RECORD_DISC_CALL_START(infoNode, packageName, STOPDISCOVERY_FUNC);
855         ret = CallInterfaceByMedium(infoNode, packageName, STOPDISCOVERY_FUNC);
856         if (ret != SOFTBUS_OK) {
857             DISC_LOGE(DISC_CONTROL, "call interface by medium failed");
858         } else {
859             DfxRecordStopDiscoveryDevice(packageName, infoNode);
860         }
861         FreeDiscInfo(infoNode, type);
862     } while (false);
863 
864     SoftBusMutexUnlock(&g_discoveryInfoList->lock);
865     return ret;
866 }
867 
TransferModuleIdToPackageName(DiscModule moduleId)868 static const char* TransferModuleIdToPackageName(DiscModule moduleId)
869 {
870     return g_discModuleMap[moduleId - 1];
871 }
872 
InnerSetDiscoveryCallback(const char * packageName,const DiscInnerCallback * cb)873 static int32_t InnerSetDiscoveryCallback(const char *packageName, const DiscInnerCallback *cb)
874 {
875     if (SoftBusMutexLock(&(g_discoveryInfoList->lock)) != SOFTBUS_OK) {
876         DISC_LOGE(DISC_CONTROL, "lock failed");
877         return SOFTBUS_LOCK_ERR;
878     }
879 
880     bool isIdExist = false;
881     DiscItem *itemNode = NULL;
882     InnerCallback callback;
883     LIST_FOR_EACH_ENTRY(itemNode, &(g_discoveryInfoList->list), DiscItem, node) {
884         if (strcmp(itemNode->packageName, packageName) != 0) {
885             continue;
886         }
887         itemNode->callback.innerCb.OnDeviceFound = cb->OnDeviceFound;
888         isIdExist = true;
889         break;
890     }
891     if (isIdExist == false) {
892         callback.innerCb.OnDeviceFound = cb->OnDeviceFound;
893         itemNode = CreateDiscItem(g_discoveryInfoList, packageName, &callback, SUBSCRIBE_INNER_SERVICE);
894         if (itemNode == NULL) {
895             DISC_LOGE(DISC_CONTROL, "itemNode create failed");
896             (void)SoftBusMutexUnlock(&(g_discoveryInfoList->lock));
897             return SOFTBUS_DISCOVER_MANAGER_ITEM_NOT_CREATE;
898         }
899     }
900     (void)SoftBusMutexUnlock(&(g_discoveryInfoList->lock));
901     return SOFTBUS_OK;
902 }
903 
DiscSetDiscoverCallback(DiscModule moduleId,const DiscInnerCallback * callback)904 int32_t DiscSetDiscoverCallback(DiscModule moduleId, const DiscInnerCallback *callback)
905 {
906     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX && callback != NULL,
907         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
908     DISC_CHECK_AND_RETURN_RET_LOGW(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
909         "manager is not inited");
910     return InnerSetDiscoveryCallback(TransferModuleIdToPackageName(moduleId), callback);
911 }
912 
DiscPublish(DiscModule moduleId,const PublishInfo * info)913 int32_t DiscPublish(DiscModule moduleId, const PublishInfo *info)
914 {
915     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX && info != NULL,
916         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
917     DISC_CHECK_AND_RETURN_RET_LOGW(info->mode == DISCOVER_MODE_ACTIVE, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
918         "mode is not active");
919     DISC_CHECK_AND_RETURN_RET_LOGE(CheckPublishInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
920         "invalid info");
921     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
922         "manager is not inited");
923 
924     DiscInfo *infoNode = CreateDiscInfoForPublish(info);
925     DISC_CHECK_AND_RETURN_RET_LOGW(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
926         "create info failed");
927 
928     int32_t ret = InnerPublishService(TransferModuleIdToPackageName(moduleId), infoNode, PUBLISH_INNER_SERVICE);
929     if (ret != SOFTBUS_OK) {
930         FreeDiscInfo(infoNode, PUBLISH_INNER_SERVICE);
931     }
932     return ret;
933 }
934 
DiscStartScan(DiscModule moduleId,const PublishInfo * info)935 int32_t DiscStartScan(DiscModule moduleId, const PublishInfo *info)
936 {
937     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX && info != NULL,
938         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
939     DISC_CHECK_AND_RETURN_RET_LOGW(info->mode == DISCOVER_MODE_PASSIVE, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
940         "mode is not passive");
941     DISC_CHECK_AND_RETURN_RET_LOGE(CheckPublishInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
942         "invalid info");
943     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
944         "manager is not inited");
945 
946     DiscInfo *infoNode = CreateDiscInfoForPublish(info);
947     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
948         "create info failed");
949 
950     int32_t ret = InnerPublishService(TransferModuleIdToPackageName(moduleId), infoNode, PUBLISH_INNER_SERVICE);
951     if (ret != SOFTBUS_OK) {
952         FreeDiscInfo(infoNode, PUBLISH_INNER_SERVICE);
953     }
954     return ret;
955 }
956 
DiscUnpublish(DiscModule moduleId,int32_t publishId)957 int32_t DiscUnpublish(DiscModule moduleId, int32_t publishId)
958 {
959     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX,
960         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid moduleId");
961     DISC_CHECK_AND_RETURN_RET_LOGW(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
962         "manager is not inited");
963 
964     return InnerUnPublishService(TransferModuleIdToPackageName(moduleId), publishId, PUBLISH_INNER_SERVICE);
965 }
966 
DiscStartAdvertise(DiscModule moduleId,const SubscribeInfo * info)967 int32_t DiscStartAdvertise(DiscModule moduleId, const SubscribeInfo *info)
968 {
969     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX && info != NULL,
970         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
971     DISC_CHECK_AND_RETURN_RET_LOGW(info->mode == DISCOVER_MODE_ACTIVE, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
972         "mode is not active");
973     DISC_CHECK_AND_RETURN_RET_LOGE(CheckSubscribeInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
974         "invalid info");
975     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
976         "manager is not inited");
977 
978     DiscInfo *infoNode = CreateDiscInfoForSubscribe(info);
979     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
980         "create info failed");
981 
982     int32_t ret = InnerStartDiscovery(TransferModuleIdToPackageName(moduleId), infoNode, NULL, SUBSCRIBE_INNER_SERVICE);
983     if (ret != SOFTBUS_OK) {
984         FreeDiscInfo(infoNode, SUBSCRIBE_INNER_SERVICE);
985     }
986     return ret;
987 }
988 
DiscSubscribe(DiscModule moduleId,const SubscribeInfo * info)989 int32_t DiscSubscribe(DiscModule moduleId, const SubscribeInfo *info)
990 {
991     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX && info != NULL,
992         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
993     DISC_CHECK_AND_RETURN_RET_LOGW(info->mode == DISCOVER_MODE_PASSIVE, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
994         "mode is not passive");
995     DISC_CHECK_AND_RETURN_RET_LOGE(CheckSubscribeInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
996         "invalid info");
997     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
998         "manager is not inited");
999 
1000     DiscInfo *infoNode = CreateDiscInfoForSubscribe(info);
1001     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
1002         "create info failed");
1003 
1004     int32_t ret = InnerStartDiscovery(TransferModuleIdToPackageName(moduleId), infoNode, NULL, SUBSCRIBE_INNER_SERVICE);
1005     if (ret != SOFTBUS_OK) {
1006         FreeDiscInfo(infoNode, SUBSCRIBE_INNER_SERVICE);
1007     }
1008     return ret;
1009 }
1010 
DiscStopAdvertise(DiscModule moduleId,int32_t subscribeId)1011 int32_t DiscStopAdvertise(DiscModule moduleId, int32_t subscribeId)
1012 {
1013     DISC_CHECK_AND_RETURN_RET_LOGW(moduleId >= MODULE_MIN && moduleId <= MODULE_MAX,
1014         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid moduleId");
1015     DISC_CHECK_AND_RETURN_RET_LOGW(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
1016         "manager is not inited");
1017 
1018     return InnerStopDiscovery(TransferModuleIdToPackageName(moduleId), subscribeId, SUBSCRIBE_INNER_SERVICE);
1019 }
1020 
DiscPublishService(const char * packageName,const PublishInfo * info)1021 int32_t DiscPublishService(const char *packageName, const PublishInfo *info)
1022 {
1023     DISC_CHECK_AND_RETURN_RET_LOGE(packageName != NULL && info != NULL, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
1024         "invalid parameters");
1025     DISC_CHECK_AND_RETURN_RET_LOGW(strlen(packageName) < PKG_NAME_SIZE_MAX,
1026         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "package name too long");
1027     DISC_CHECK_AND_RETURN_RET_LOGW(CheckPublishInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
1028         "invalid info");
1029     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
1030         "manager is not inited");
1031 
1032     DiscInfo *infoNode = CreateDiscInfoForPublish(info);
1033     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
1034         "create info failed");
1035 
1036     int32_t ret = InnerPublishService(packageName, infoNode, PUBLISH_SERVICE);
1037     if (ret != SOFTBUS_OK) {
1038         FreeDiscInfo(infoNode, PUBLISH_SERVICE);
1039     }
1040     return ret;
1041 }
1042 
DiscUnPublishService(const char * packageName,int32_t publishId)1043 int32_t DiscUnPublishService(const char *packageName, int32_t publishId)
1044 {
1045     DISC_CHECK_AND_RETURN_RET_LOGW(packageName != NULL && strlen(packageName) < PKG_NAME_SIZE_MAX,
1046         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
1047     DISC_CHECK_AND_RETURN_RET_LOGW(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
1048         "manager is not inited");
1049 
1050     return InnerUnPublishService(packageName, publishId, PUBLISH_SERVICE);
1051 }
1052 
DiscStartDiscovery(const char * packageName,const SubscribeInfo * info,const IServerDiscInnerCallback * cb)1053 int32_t DiscStartDiscovery(const char *packageName, const SubscribeInfo *info,
1054     const IServerDiscInnerCallback *cb)
1055 {
1056     DISC_CHECK_AND_RETURN_RET_LOGW(packageName != NULL && strlen(packageName) < PKG_NAME_SIZE_MAX,
1057         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid package name");
1058     DISC_CHECK_AND_RETURN_RET_LOGW(info != NULL && cb != NULL, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
1059         "invalid parameters");
1060     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
1061         "manager is not inited");
1062     DISC_CHECK_AND_RETURN_RET_LOGE(CheckSubscribeInfo(info) == SOFTBUS_OK, SOFTBUS_INVALID_PARAM, DISC_CONTROL,
1063         "invalid info");
1064 
1065     DiscInfo *infoNode = CreateDiscInfoForSubscribe(info);
1066     DISC_CHECK_AND_RETURN_RET_LOGE(infoNode != NULL, SOFTBUS_DISCOVER_MANAGER_INFO_NOT_CREATE, DISC_CONTROL,
1067         "create info failed");
1068 
1069     int32_t ret = InnerStartDiscovery(packageName, infoNode, cb, SUBSCRIBE_SERVICE);
1070     if (ret != SOFTBUS_OK) {
1071         FreeDiscInfo(infoNode, SUBSCRIBE_SERVICE);
1072     }
1073     return ret;
1074 }
1075 
DiscStopDiscovery(const char * packageName,int32_t subscribeId)1076 int32_t DiscStopDiscovery(const char *packageName, int32_t subscribeId)
1077 {
1078     DISC_CHECK_AND_RETURN_RET_LOGW(packageName != NULL && strlen(packageName) < PKG_NAME_SIZE_MAX,
1079         SOFTBUS_INVALID_PARAM, DISC_CONTROL, "invalid parameters");
1080     DISC_CHECK_AND_RETURN_RET_LOGW(g_isInited == true, SOFTBUS_DISCOVER_MANAGER_NOT_INIT, DISC_CONTROL,
1081         "manager is not inited");
1082 
1083     return InnerStopDiscovery(packageName, subscribeId, SUBSCRIBE_SERVICE);
1084 }
1085 
DiscLinkStatusChanged(LinkStatus status,ExchangeMedium medium)1086 void DiscLinkStatusChanged(LinkStatus status, ExchangeMedium medium)
1087 {
1088     if (medium == COAP) {
1089         if (g_discCoapInterface != NULL) {
1090             g_discCoapInterface->LinkStatusChanged(status);
1091         }
1092     } else {
1093         DISC_LOGE(DISC_CONTROL, "not support medium=%{public}d", medium);
1094     }
1095 }
1096 
DiscDeviceInfoChanged(InfoTypeChanged type)1097 void DiscDeviceInfoChanged(InfoTypeChanged type)
1098 {
1099     DISC_LOGI(DISC_CONTROL, "type=%{public}d", type);
1100     if (g_discBleInterface != NULL && g_discBleInterface->UpdateLocalDeviceInfo != NULL) {
1101         g_discBleInterface->UpdateLocalDeviceInfo(type);
1102     }
1103     if (g_discCoapInterface != NULL && g_discCoapInterface->UpdateLocalDeviceInfo != NULL) {
1104         g_discCoapInterface->UpdateLocalDeviceInfo(type);
1105     }
1106 }
1107 
CreateIdContainer(int32_t id,const char * pkgName)1108 static IdContainer* CreateIdContainer(int32_t id, const char *pkgName)
1109 {
1110     IdContainer *container = SoftBusCalloc(sizeof(IdContainer));
1111     if (container == NULL) {
1112         DISC_LOGE(DISC_CONTROL, "container calloc failed");
1113         return NULL;
1114     }
1115 
1116     ListInit(&container->node);
1117     container->id = id;
1118 
1119     uint32_t nameLen = strlen(pkgName) + 1;
1120     container->pkgName = SoftBusCalloc(nameLen);
1121     if (container->pkgName == NULL) {
1122         DISC_LOGE(DISC_CONTROL, "Container pkgName calloc failed");
1123         SoftBusFree(container);
1124         return NULL;
1125     }
1126 
1127     if (strcpy_s(container->pkgName, nameLen, pkgName) != EOK) {
1128         DISC_LOGE(DISC_CONTROL, "strcpy_s failed");
1129         SoftBusFree(container->pkgName);
1130         container->pkgName = NULL;
1131         SoftBusFree(container);
1132         return NULL;
1133     }
1134 
1135     return container;
1136 }
1137 
DestroyIdContainer(IdContainer * container)1138 static void DestroyIdContainer(IdContainer* container)
1139 {
1140     SoftBusFree(container->pkgName);
1141     SoftBusFree(container);
1142 }
1143 
CleanupPublishDiscovery(ListNode * ids,ServiceType type)1144 static void CleanupPublishDiscovery(ListNode *ids, ServiceType type)
1145 {
1146     IdContainer *it = NULL;
1147     int32_t ret = SOFTBUS_DISCOVER_MANAGER_INFO_NOT_DELETE;
1148 
1149     LIST_FOR_EACH_ENTRY(it, ids, IdContainer, node) {
1150         if (type == PUBLISH_SERVICE) {
1151             ret = DiscUnPublishService(it->pkgName, it->id);
1152             DISC_LOGI(DISC_CONTROL, "clean publish pkgName=%{public}s, id=%{public}d, ret=%{public}d",
1153                 it->pkgName, it->id, ret);
1154         } else if (type == SUBSCRIBE_SERVICE) {
1155             ret = DiscStopDiscovery(it->pkgName, it->id);
1156             DISC_LOGI(DISC_CONTROL, "clean subscribe pkgName=%{public}s, id=%{public}d, ret=%{public}d",
1157                 it->pkgName, it->id, ret);
1158         }
1159     }
1160 }
1161 
RemoveDiscInfoByPackageName(SoftBusList * itemList,const ServiceType type,const char * pkgName)1162 static void RemoveDiscInfoByPackageName(SoftBusList *itemList, const ServiceType type, const char *pkgName)
1163 {
1164     ListNode ids;
1165     ListInit(&ids);
1166 
1167     if (SoftBusMutexLock(&itemList->lock) != SOFTBUS_OK) {
1168         DISC_LOGE(DISC_CONTROL, "lock failed");
1169         return;
1170     }
1171 
1172     DiscItem *itemNode = NULL;
1173     IdContainer *container = NULL;
1174     LIST_FOR_EACH_ENTRY(itemNode, &itemList->list, DiscItem, node) {
1175         if (pkgName != NULL) {
1176             if (strcmp(itemNode->packageName, pkgName) != 0) {
1177                 continue;
1178             }
1179         }
1180 
1181         DiscInfo *infoNode = NULL;
1182         LIST_FOR_EACH_ENTRY(infoNode, &itemNode->InfoList, DiscInfo, node) {
1183             container = CreateIdContainer(infoNode->id, itemNode->packageName);
1184             if (container == NULL) {
1185                 DISC_LOGE(DISC_CONTROL, "CreateIdContainer failed");
1186                 (void)SoftBusMutexUnlock(&itemList->lock);
1187                 goto CLEANUP;
1188             }
1189             ListTailInsert(&ids, &container->node);
1190         }
1191     }
1192 
1193     (void)SoftBusMutexUnlock(&itemList->lock);
1194     CleanupPublishDiscovery(&ids, type);
1195 
1196 CLEANUP:
1197     while (!IsListEmpty(&ids)) {
1198         container = LIST_ENTRY(ids.next, IdContainer, node);
1199         ListDelete(&container->node);
1200         DestroyIdContainer(container);
1201     }
1202 }
1203 
RemoveAllDiscInfoForPublish(void)1204 static void RemoveAllDiscInfoForPublish(void)
1205 {
1206     RemoveDiscInfoByPackageName(g_publishInfoList, PUBLISH_SERVICE, NULL);
1207     DestroySoftBusList(g_publishInfoList);
1208     g_publishInfoList = NULL;
1209 }
1210 
RemoveAllDiscInfoForDiscovery(void)1211 static void RemoveAllDiscInfoForDiscovery(void)
1212 {
1213     RemoveDiscInfoByPackageName(g_discoveryInfoList, SUBSCRIBE_SERVICE, NULL);
1214     DestroySoftBusList(g_discoveryInfoList);
1215     g_discoveryInfoList = NULL;
1216 }
1217 
RemoveDiscInfoForPublish(const char * pkgName)1218 static void RemoveDiscInfoForPublish(const char *pkgName)
1219 {
1220     RemoveDiscInfoByPackageName(g_publishInfoList, PUBLISH_SERVICE, pkgName);
1221 }
1222 
RemoveDiscInfoForDiscovery(const char * pkgName)1223 static void RemoveDiscInfoForDiscovery(const char *pkgName)
1224 {
1225     RemoveDiscInfoByPackageName(g_discoveryInfoList, SUBSCRIBE_SERVICE, pkgName);
1226 }
1227 
DiscMgrDeathCallback(const char * pkgName)1228 void DiscMgrDeathCallback(const char *pkgName)
1229 {
1230     DISC_CHECK_AND_RETURN_LOGE(pkgName != NULL, DISC_CONTROL, "pkgName is null");
1231     DISC_CHECK_AND_RETURN_LOGE(g_isInited == true, DISC_CONTROL, "disc manager is not inited");
1232 
1233     DISC_LOGD(DISC_CONTROL, "pkg is dead. pkgName=%{public}s", pkgName);
1234     RemoveDiscInfoForPublish(pkgName);
1235     RemoveDiscInfoForDiscovery(pkgName);
1236 }
1237 
DiscMgrInit(void)1238 int32_t DiscMgrInit(void)
1239 {
1240     DISC_CHECK_AND_RETURN_RET_LOGE(g_isInited == false, SOFTBUS_OK, DISC_INIT, "already inited");
1241 
1242     g_discMgrMediumCb.OnDeviceFound = DiscOnDeviceFound;
1243 
1244     g_discCoapInterface = DiscCoapInit(&g_discMgrMediumCb);
1245     g_discBleInterface = DiscBleInit(&g_discMgrMediumCb);
1246     DISC_CHECK_AND_RETURN_RET_LOGE(g_discBleInterface != NULL || g_discCoapInterface != NULL,
1247         SOFTBUS_DISCOVER_MANAGER_INIT_FAIL, DISC_INIT, "ble and coap both init failed");
1248 
1249     g_publishInfoList = CreateSoftBusList();
1250     DISC_CHECK_AND_RETURN_RET_LOGE(g_publishInfoList != NULL, SOFTBUS_DISCOVER_MANAGER_INIT_FAIL, DISC_INIT,
1251         "init publish info list failed");
1252     g_discoveryInfoList = CreateSoftBusList();
1253     if (g_discoveryInfoList == NULL) {
1254         DISC_LOGE(DISC_INIT, "init discovery Info List failed");
1255         DestroySoftBusList(g_publishInfoList);
1256         g_publishInfoList = NULL;
1257         return SOFTBUS_DISCOVER_MANAGER_INIT_FAIL;
1258     }
1259 
1260     for (int32_t i = 0; i < CAPABILITY_MAX_BITNUM; i++) {
1261         ListInit(&g_capabilityList[i]);
1262     }
1263 
1264     g_isInited = true;
1265     return SOFTBUS_OK;
1266 }
1267 
DiscMgrDeinit(void)1268 void DiscMgrDeinit(void)
1269 {
1270     DISC_CHECK_AND_RETURN_LOGW(g_isInited == true, DISC_INIT, "disc manager is not inited");
1271 
1272     RemoveAllDiscInfoForPublish();
1273     RemoveAllDiscInfoForDiscovery();
1274 
1275     g_discCoapInterface = NULL;
1276     g_discBleInterface = NULL;
1277 
1278     DiscCoapDeinit();
1279     DiscBleDeinit();
1280 
1281     g_isInited = false;
1282     DISC_LOGI(DISC_INIT, "disc manager deinit success");
1283 }
1284