1 /*
2  * Copyright (c) 2022 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 "lnn_topo_manager.h"
17 
18 #include <securec.h>
19 
20 #include "anonymizer.h"
21 #include "bus_center_event.h"
22 #include "bus_center_manager.h"
23 #include "common_list.h"
24 #include "lnn_async_callback_utils.h"
25 #include "lnn_distributed_net_ledger.h"
26 #include "lnn_log.h"
27 #include "lnn_sync_info_manager.h"
28 #include "softbus_adapter_crypto.h"
29 #include "softbus_adapter_mem.h"
30 #include "softbus_adapter_thread.h"
31 #include "softbus_def.h"
32 #include "softbus_errcode.h"
33 #include "softbus_feature_config.h"
34 #include "softbus_json_utils.h"
35 #include "softbus_adapter_json.h"
36 
37 #define JSON_KEY_TYPE "type"
38 #define JSON_KEY_SEQ "seq"
39 #define JSON_KEY_COMPLETE "complete"
40 #define JSON_KEY_INFO "info"
41 #define JSON_KEY_TYPE "type"
42 #define JSON_KEY_UDID "udid"
43 #define JSON_KEY_PEER_UDID "peerUdid"
44 #define JSON_KEY_WLAN_RELATION "wlanRelation"
45 #define JSON_KEY_BR_RELATION "brRelation"
46 #define JSON_KEY_BLE_RELATION "bleRelation"
47 #define JSON_KEY_ETH_RELATION "ethRelation"
48 
49 #define LNN_RELATION_JOIN_THREAD 1
50 #define RELATION_CHANGED_MSG_DELAY (5 * 1000)
51 
52 #define TOPO_HASH_TABLE_SIZE 16
53 
54 typedef enum {
55     TOPO_MSG_TYPE_UPDATE,
56 } TopoUpdateMsgType;
57 
58 typedef enum {
59     TOPO_MSG_FLAG_NOT_COMPLETE = 0,
60     TOPO_MSG_FLAG_COMPLETE,
61 } TopoUpdateMsgFlag;
62 
63 typedef struct {
64     ListNode table[TOPO_HASH_TABLE_SIZE];
65     bool isSupportTopo;
66     uint32_t totalCount;
67     SoftBusMutex lock;
68 } TopoHashTable;
69 
70 typedef struct {
71     ListNode node;
72     char udid[UDID_BUF_LEN];
73     uint32_t count;
74     ListNode joinList;
75 } TopoTableItem;
76 
77 typedef struct {
78     ListNode node;
79     char peerUdid[UDID_BUF_LEN];
80     uint8_t relation[CONNECTION_ADDR_MAX];
81 } TopoInfo;
82 
83 static TopoHashTable g_topoTable;
84 
RouteLnnRelationEventHandler(const LnnRelationChangedMsg * msg)85 void __attribute__((weak)) RouteLnnRelationEventHandler(const LnnRelationChangedMsg *msg)
86 {
87     (void)msg;
88 }
89 
IsSameRelation(const uint8_t * newRelation,const uint8_t * oldRelation,uint32_t len)90 static bool IsSameRelation(const uint8_t *newRelation, const uint8_t *oldRelation, uint32_t len)
91 {
92     uint32_t i;
93 
94     for (i = 0; i < len; ++i) {
95         if ((newRelation[i] != 0 && oldRelation[i] == 0) || (newRelation[i] == 0 && oldRelation[i] != 0)) {
96             return false;
97         }
98     }
99     return true;
100 }
101 
HasRelation(const uint8_t * relation,uint32_t len)102 static bool HasRelation(const uint8_t *relation, uint32_t len)
103 {
104     uint32_t i;
105 
106     for (i = 0; i < len; ++i) {
107         if (relation[i] > 0) {
108             return true;
109         }
110     }
111     return false;
112 }
113 
HashIndex(const char * udid)114 static uint32_t HashIndex(const char *udid)
115 {
116     return ((*(const uint32_t *)udid) % TOPO_HASH_TABLE_SIZE);
117 }
118 
CreateTopoItem(const char * udid)119 static TopoTableItem *CreateTopoItem(const char *udid)
120 {
121     TopoTableItem *item = (TopoTableItem *)SoftBusMalloc(sizeof(TopoTableItem));
122     if (item == NULL) {
123         LNN_LOGE(LNN_BUILDER, "malloc topo item fail");
124         return NULL;
125     }
126     ListInit(&item->joinList);
127     ListInit(&item->node);
128     item->count = 0;
129     if (strcpy_s(item->udid, UDID_BUF_LEN, udid) != EOK) {
130         LNN_LOGE(LNN_BUILDER, "copy udid to topo item fail");
131         SoftBusFree(item);
132         return NULL;
133     }
134     return item;
135 }
136 
CreateTopoInfo(const char * udid,const uint8_t * relation,uint32_t len)137 static TopoInfo *CreateTopoInfo(const char *udid, const uint8_t *relation, uint32_t len)
138 {
139     TopoInfo *info = (TopoInfo *)SoftBusMalloc(sizeof(TopoInfo));
140     if (info == NULL) {
141         LNN_LOGE(LNN_BUILDER, "malloc topo info fail");
142         return NULL;
143     }
144     ListInit(&info->node);
145     if (strcpy_s(info->peerUdid, UDID_BUF_LEN, udid) != EOK ||
146         memcpy_s(info->relation, CONNECTION_ADDR_MAX, relation, len) != EOK) {
147         LNN_LOGE(LNN_BUILDER, "copy info to topo info fail");
148         SoftBusFree(info);
149         return NULL;
150     }
151     return info;
152 }
153 
FindTopoItem(const char * udid)154 static TopoTableItem *FindTopoItem(const char *udid)
155 {
156     TopoTableItem *item = NULL;
157 
158     LIST_FOR_EACH_ENTRY(item, &g_topoTable.table[HashIndex(udid)], TopoTableItem, node) {
159         if (strcmp(item->udid, udid) == 0) {
160             return item;
161         }
162     }
163     return NULL;
164 }
165 
FindTopoInfo(const char * udid,const char * peerUdid,TopoTableItem ** item,TopoInfo ** info)166 static int32_t FindTopoInfo(const char *udid, const char *peerUdid, TopoTableItem **item, TopoInfo **info)
167 {
168     TopoTableItem *topoItem = NULL;
169     TopoInfo *topoInfo = NULL;
170     const char *compareUdid = peerUdid;
171 
172     topoItem = FindTopoItem(udid);
173     if (topoItem == NULL) {
174         topoItem = FindTopoItem(peerUdid);
175         if (topoItem != NULL) {
176             compareUdid = udid;
177         }
178     }
179     if (topoItem == NULL) {
180         LNN_LOGE(LNN_BUILDER, "topo item not exist");
181         return SOFTBUS_NOT_FIND;
182     }
183     *item = topoItem;
184     LIST_FOR_EACH_ENTRY(topoInfo, &topoItem->joinList, TopoInfo, node) {
185         if (strcmp(compareUdid, topoInfo->peerUdid) == 0) {
186             *info = topoInfo;
187             return SOFTBUS_OK;
188         }
189     }
190     return SOFTBUS_NOT_FIND;
191 }
192 
ClearTopoTable(void)193 static void ClearTopoTable(void)
194 {
195     TopoTableItem *item = NULL;
196     TopoTableItem *itemNext = NULL;
197     TopoInfo *info = NULL;
198     TopoInfo *infoNext = NULL;
199     uint32_t i;
200 
201     for (i = 0; i < TOPO_HASH_TABLE_SIZE; ++i) {
202         LIST_FOR_EACH_ENTRY_SAFE(item, itemNext, &g_topoTable.table[i], TopoTableItem, node) {
203             LIST_FOR_EACH_ENTRY_SAFE(info, infoNext, &item->joinList, TopoInfo, node) {
204                 char *anonyUdid = NULL;
205                 char *anonyPeerUdid = NULL;
206                 Anonymize(item->udid, &anonyUdid);
207                 Anonymize(info->peerUdid, &anonyPeerUdid);
208                 LNN_LOGI(LNN_BUILDER, "delete topo info, local=%{public}s, peer=%{public}s",
209                     anonyUdid, anonyPeerUdid);
210                 AnonymizeFree(anonyUdid);
211                 AnonymizeFree(anonyPeerUdid);
212                 ListDelete(&info->node);
213                 SoftBusFree(info);
214             }
215             ListDelete(&item->node);
216             SoftBusFree(item);
217         }
218     }
219     g_topoTable.totalCount = 0;
220 }
221 
PackCommonTopoMsg(cJSON ** json,cJSON ** info)222 static int32_t PackCommonTopoMsg(cJSON **json, cJSON **info)
223 {
224     int32_t seq;
225 
226     if (SoftBusGenerateRandomArray((uint8_t *)&seq, sizeof(uint32_t)) != SOFTBUS_OK) {
227         LNN_LOGE(LNN_BUILDER, "generate seq fail");
228         return SOFTBUS_ERR;
229     }
230     if (seq < 0) {
231         seq = -seq;
232     }
233     *json = cJSON_CreateObject();
234     if (*json == NULL) {
235         LNN_LOGE(LNN_BUILDER, "create topo update json fail");
236         return SOFTBUS_ERR;
237     }
238     if (!AddNumberToJsonObject(*json, JSON_KEY_TYPE, TOPO_MSG_TYPE_UPDATE) ||
239         !AddNumberToJsonObject(*json, JSON_KEY_SEQ, seq) ||
240         !AddNumberToJsonObject(*json, JSON_KEY_COMPLETE, TOPO_MSG_FLAG_COMPLETE)) {
241         LNN_LOGE(LNN_BUILDER, "pack topo common json fail");
242         cJSON_Delete(*json);
243         return SOFTBUS_ERR;
244     }
245     *info = cJSON_CreateArray();
246     if (*info == NULL) {
247         LNN_LOGE(LNN_BUILDER, "create topo info json fail");
248         cJSON_Delete(*json);
249         return SOFTBUS_ERR;
250     }
251     if (!cJSON_AddItemToObject(*json, JSON_KEY_INFO, *info)) {
252         LNN_LOGE(LNN_BUILDER, "pack topo info json to msg fail");
253         cJSON_Delete(*info);
254         cJSON_Delete(*json);
255         return SOFTBUS_ERR;
256     }
257     return SOFTBUS_OK;
258 }
259 
PackTopoInfo(cJSON * info,const char * udid,const char * peerUdid,const uint8_t * relation,uint32_t len)260 static int32_t PackTopoInfo(cJSON *info, const char *udid, const char *peerUdid,
261     const uint8_t *relation, uint32_t len)
262 {
263     cJSON *item = cJSON_CreateObject();
264     if (item == NULL) {
265         LNN_LOGE(LNN_BUILDER, "create topo info json fail");
266         return SOFTBUS_ERR;
267     }
268     if (len != CONNECTION_ADDR_MAX) {
269         cJSON_Delete(item);
270         return SOFTBUS_INVALID_PARAM;
271     }
272     if (!AddStringToJsonObject(item, JSON_KEY_UDID, udid) ||
273         !AddStringToJsonObject(item, JSON_KEY_PEER_UDID, peerUdid)) {
274         cJSON_Delete(item);
275         LNN_LOGE(LNN_BUILDER, "pack topo udid json fail");
276         return SOFTBUS_ERR;
277     }
278     if (!AddNumberToJsonObject(item, JSON_KEY_WLAN_RELATION, relation[CONNECTION_ADDR_WLAN]) ||
279         !AddNumberToJsonObject(item, JSON_KEY_BR_RELATION, relation[CONNECTION_ADDR_BR]) ||
280         !AddNumberToJsonObject(item, JSON_KEY_BLE_RELATION, relation[CONNECTION_ADDR_BLE]) ||
281         !AddNumberToJsonObject(item, JSON_KEY_ETH_RELATION, relation[CONNECTION_ADDR_ETH]) ||
282         !cJSON_AddItemToArray(info, item)) {
283         cJSON_Delete(item);
284         LNN_LOGE(LNN_BUILDER, "pack topo relation json fail");
285         return SOFTBUS_ERR;
286     }
287     return SOFTBUS_OK;
288 }
289 
PackOneLnnRelation(const char * udid,const char * peerUdid,const uint8_t * relation,uint32_t len)290 static const char *PackOneLnnRelation(const char *udid, const char *peerUdid,
291     const uint8_t *relation, uint32_t len)
292 {
293     cJSON *json = NULL;
294     cJSON *info = NULL;
295     const char *msg = NULL;
296 
297     if (PackCommonTopoMsg(&json, &info) != SOFTBUS_OK) {
298         return NULL;
299     }
300     if (PackTopoInfo(info, udid, peerUdid, relation, len) != SOFTBUS_OK) {
301         cJSON_Delete(json);
302         return NULL;
303     }
304     msg = cJSON_PrintUnformatted(json);
305     if (msg == NULL) {
306         LNN_LOGE(LNN_BUILDER, "format lnn relation json fail");
307     }
308     cJSON_Delete(json);
309     return msg;
310 }
311 
AddTopoInfo(const char * udid,const char * peerUdid,const uint8_t * relation,uint32_t len)312 static int32_t AddTopoInfo(const char *udid, const char *peerUdid, const uint8_t *relation, uint32_t len)
313 {
314     TopoTableItem *topoItem = NULL;
315     TopoInfo *topoInfo = NULL;
316     bool isKeyUdid = true;
317     bool isCreateTopoItem = false;
318 
319     topoItem = FindTopoItem(udid);
320     if (topoItem == NULL) {
321         topoItem = FindTopoItem(peerUdid);
322         if (topoItem != NULL) {
323             isKeyUdid = false;
324         }
325     }
326     if (topoItem == NULL) {
327         topoItem = CreateTopoItem(udid);
328         if (topoItem == NULL) {
329             return SOFTBUS_MEM_ERR;
330         }
331         ListAdd(&g_topoTable.table[HashIndex(udid)], &topoItem->node);
332         isCreateTopoItem = true;
333     }
334     topoInfo = CreateTopoInfo(isKeyUdid ? peerUdid : udid, relation, len);
335     if (topoInfo == NULL) {
336         if (isCreateTopoItem) {
337             ListDelete(&topoItem->node);
338             SoftBusFree(topoItem);
339         }
340         return SOFTBUS_MEM_ERR;
341     }
342     ListAdd(&topoItem->joinList, &topoInfo->node);
343     topoItem->count++;
344     g_topoTable.totalCount++;
345     return SOFTBUS_OK;
346 }
347 
UpdateLocalTopo(const char * udid,const char * peerUdid,const uint8_t * relation,uint32_t len)348 static int32_t UpdateLocalTopo(const char *udid, const char *peerUdid, const uint8_t *relation, uint32_t len)
349 {
350     TopoTableItem *topoItem = NULL;
351     TopoInfo *topoInfo = NULL;
352     bool hasRelation = HasRelation(relation, len);
353 
354     if (FindTopoInfo(udid, peerUdid, &topoItem, &topoInfo) != SOFTBUS_OK) {
355         if (!hasRelation) {
356             LNN_LOGE(LNN_BUILDER, "topo info not exist when delete");
357             return SOFTBUS_NOT_FIND;
358         }
359         if (AddTopoInfo(udid, peerUdid, relation, len) != SOFTBUS_OK) {
360             LNN_LOGE(LNN_BUILDER, "add topo info fail");
361             return SOFTBUS_MEM_ERR;
362         }
363         char *anonyUdid = NULL;
364         char *anonyPeerUdid = NULL;
365         Anonymize(udid, &anonyUdid);
366         Anonymize(peerUdid, &anonyPeerUdid);
367         LNN_LOGI(LNN_BUILDER, "add topo info: local=%{public}s peer=%{public}s", anonyUdid, anonyPeerUdid);
368         AnonymizeFree(anonyUdid);
369         AnonymizeFree(anonyPeerUdid);
370     } else {
371         if (IsSameRelation(topoInfo->relation, relation, len)) {
372             LNN_LOGE(LNN_BUILDER, "relation are same");
373             return SOFTBUS_ERR;
374         }
375         if (memcpy_s(topoInfo->relation, CONNECTION_ADDR_MAX, relation, len) != EOK) {
376             LNN_LOGE(LNN_BUILDER, "memcpy topo info relation fail");
377             return SOFTBUS_MEM_ERR;
378         }
379         if (!hasRelation) {
380             char *anonyUdid = NULL;
381             char *anonyPeerUdid = NULL;
382             Anonymize(topoItem->udid, &anonyUdid);
383             Anonymize(topoInfo->peerUdid, &anonyPeerUdid);
384             LNN_LOGI(LNN_BUILDER, "delete topo info: local=%{public}s peer=%{public}s", anonyUdid, anonyPeerUdid);
385             AnonymizeFree(anonyUdid);
386             AnonymizeFree(anonyPeerUdid);
387             ListDelete(&topoInfo->node);
388             SoftBusFree(topoInfo);
389             topoItem->count--;
390             g_topoTable.totalCount--;
391         }
392         if (IsListEmpty(&topoItem->joinList)) {
393             LNN_LOGI(LNN_BUILDER, "delete topo item");
394             ListDelete(&topoItem->node);
395             SoftBusFree(topoItem);
396         }
397     }
398     return SOFTBUS_OK;
399 }
400 
ForwardTopoMsgToAll(const char * networkId,const uint8_t * msg,uint32_t len)401 static void ForwardTopoMsgToAll(const char *networkId, const uint8_t *msg, uint32_t len)
402 {
403     NodeBasicInfo *info = NULL;
404     int32_t infoNum, i;
405 
406     if (LnnGetAllOnlineNodeInfo(&info, &infoNum) != SOFTBUS_OK) {
407         LNN_LOGE(LNN_BUILDER, "get all online node info fail");
408         return;
409     }
410     for (i = 0; i < infoNum; ++i) {
411         if (LnnIsLSANode(&info[i])) {
412             continue;
413         }
414         if (strcmp(networkId, info[i].networkId) == 0) {
415             continue;
416         }
417         LNN_LOGI(LNN_BUILDER, "forward topo update msg");
418         if (LnnSendSyncInfoMsg(LNN_INFO_TYPE_TOPO_UPDATE, info[i].networkId, msg, len, NULL) != SOFTBUS_OK) {
419             LNN_LOGE(LNN_BUILDER, "sync topo update fail");
420         }
421     }
422     SoftBusFree(info);
423 }
424 
TryCorrectRelation(const char * networkId,const char * udid,const char * peerUdid,const uint8_t * relation,uint32_t len)425 static void TryCorrectRelation(const char *networkId, const char *udid, const char *peerUdid,
426     const uint8_t *relation, uint32_t len)
427 {
428     uint8_t correctRelation[CONNECTION_ADDR_MAX] = {0};
429     const char *msg = NULL;
430     char localUdid[UDID_BUF_LEN];
431     const char *keyUdid = udid;
432 
433     if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN) != 0) {
434         LNN_LOGE(LNN_BUILDER, "read local udid fail");
435         return;
436     }
437     if (strcmp(localUdid, udid) == 0) {
438         keyUdid = peerUdid;
439     }
440     LnnGetLnnRelation(keyUdid, CATEGORY_UDID, correctRelation, CONNECTION_ADDR_MAX);
441     if (IsSameRelation(correctRelation, relation, len)) {
442         LNN_LOGI(LNN_BUILDER, "relation are ok, no need correct");
443         return;
444     }
445     LNN_LOGI(LNN_BUILDER, "relation not right and notify update=%{public}d",
446         HasRelation(correctRelation, CONNECTION_ADDR_MAX));
447     msg = PackOneLnnRelation(udid, peerUdid, correctRelation, CONNECTION_ADDR_MAX);
448     if (msg == NULL) {
449         LNN_LOGE(LNN_BUILDER, "pack correct lnn relation msg fail");
450         return;
451     }
452     if (LnnSendSyncInfoMsg(LNN_INFO_TYPE_TOPO_UPDATE, networkId, (const uint8_t *)msg,
453         strlen(msg) + 1, NULL) != SOFTBUS_OK) {
454         LNN_LOGE(LNN_BUILDER, "sync correct lnn relation msg fail");
455     }
456     cJSON_free((void *)msg);
457 }
458 
ProcessTopoUpdateInfo(cJSON * json,const char * networkId,const uint8_t * msg,uint32_t len)459 static void ProcessTopoUpdateInfo(cJSON *json, const char *networkId, const uint8_t *msg, uint32_t len)
460 {
461     char udid[UDID_BUF_LEN], peerUdid[UDID_BUF_LEN];
462     uint8_t relation[CONNECTION_ADDR_MAX];
463     int32_t value;
464     cJSON *item = NULL;
465     char localUdid[UDID_BUF_LEN];
466     bool needForward = false;
467     cJSON *info = cJSON_GetObjectItemCaseSensitive(json, JSON_KEY_INFO);
468     if (!cJSON_IsArray(info)) {
469         LNN_LOGE(LNN_BUILDER, "topo update msg not contain info");
470         return;
471     }
472     if (LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN) != 0) {
473         LNN_LOGE(LNN_BUILDER, "read local udid fail");
474         return;
475     }
476     cJSON_ArrayForEach(item, info) {
477         if (!GetJsonObjectStringItem(item, JSON_KEY_UDID, udid, UDID_BUF_LEN) ||
478             !GetJsonObjectStringItem(item, JSON_KEY_PEER_UDID, peerUdid, UDID_BUF_LEN)) {
479             LNN_LOGE(LNN_BUILDER, "parse topo update for uuid fail");
480             continue;
481         }
482         if (strlen(udid) == 0 || strlen(peerUdid) == 0) {
483             LNN_LOGE(LNN_BUILDER, "invalid uuid in topo update msg");
484             continue;
485         }
486         (void)GetJsonObjectNumberItem(item, JSON_KEY_WLAN_RELATION, &value);
487         relation[CONNECTION_ADDR_WLAN] = (uint8_t)value;
488         (void)GetJsonObjectNumberItem(item, JSON_KEY_BR_RELATION, &value);
489         relation[CONNECTION_ADDR_BR] = (uint8_t)value;
490         (void)GetJsonObjectNumberItem(item, JSON_KEY_BLE_RELATION, &value);
491         relation[CONNECTION_ADDR_BLE] = (uint8_t)value;
492         (void)GetJsonObjectNumberItem(item, JSON_KEY_ETH_RELATION, &value);
493         relation[CONNECTION_ADDR_ETH] = (uint8_t)value;
494         if (strcmp(localUdid, udid) == 0 || strcmp(localUdid, peerUdid) == 0) {
495             TryCorrectRelation(networkId, udid, peerUdid, relation, CONNECTION_ADDR_MAX);
496             continue;
497         }
498         if (UpdateLocalTopo(udid, peerUdid, relation, CONNECTION_ADDR_MAX) == SOFTBUS_OK) {
499             needForward = true;
500         }
501     }
502     if (needForward) {
503         LNN_LOGI(LNN_BUILDER, "notify local topo to others");
504         ForwardTopoMsgToAll(networkId, msg, len);
505     }
506 }
507 
OnReceiveTopoUpdateMsg(LnnSyncInfoType type,const char * networkId,const uint8_t * msg,uint32_t len)508 static void OnReceiveTopoUpdateMsg(LnnSyncInfoType type, const char *networkId, const uint8_t *msg, uint32_t len)
509 {
510     cJSON *json = NULL;
511     int32_t topoMsgType, seq, complete;
512 
513     LNN_LOGI(LNN_BUILDER, "recv topo update msg, type=%{public}d, len=%{public}d", type, len);
514     if (type != LNN_INFO_TYPE_TOPO_UPDATE) {
515         return;
516     }
517     json =  cJSON_ParseWithLength((char *)msg, (size_t)len);
518     if (json == NULL) {
519         LNN_LOGE(LNN_BUILDER, "cjson parse topo msg fail");
520         return;
521     }
522     LNN_LOGI(LNN_BUILDER, "recv topo update msg");
523     if (!GetJsonObjectNumberItem(json, JSON_KEY_TYPE, &topoMsgType) ||
524         !GetJsonObjectNumberItem(json, JSON_KEY_SEQ, &seq) ||
525         !GetJsonObjectNumberItem(json, JSON_KEY_COMPLETE, &complete)) {
526         LNN_LOGE(LNN_BUILDER, "cjson parse topo common info fail");
527         cJSON_Delete(json);
528         return;
529     }
530     LNN_LOGI(LNN_BUILDER, "topoMsgType=%{public}d, seq=%{public}d, complete=%{public}d", topoMsgType, seq, complete);
531     if (topoMsgType != TOPO_MSG_TYPE_UPDATE || complete != TOPO_MSG_FLAG_COMPLETE) {
532         cJSON_Delete(json);
533         return;
534     }
535     if (SoftBusMutexLock(&g_topoTable.lock) != SOFTBUS_OK) {
536         LNN_LOGE(LNN_BUILDER, "lock topo table fail");
537         cJSON_Delete(json);
538         return;
539     }
540     ProcessTopoUpdateInfo(json, networkId, msg, len);
541     cJSON_Delete(json);
542     (void)SoftBusMutexUnlock(&g_topoTable.lock);
543 }
544 
OnLnnRelationChangedDelay(void * para)545 static void OnLnnRelationChangedDelay(void *para)
546 {
547     LnnRelationChangedMsg *msg = (LnnRelationChangedMsg *)para;
548     if (msg == NULL) {
549         return;
550     }
551     RouteLnnRelationEventHandler(msg);
552     SoftBusFree(msg);
553     return;
554 }
555 
OnLnnRelationChanged(const LnnEventBasicInfo * info)556 static void OnLnnRelationChanged(const LnnEventBasicInfo *info)
557 {
558     const LnnRelationChanedEventInfo *eventInfo = (const LnnRelationChanedEventInfo *)info;
559     LnnRelationChangedMsg *msg = NULL;
560 
561     if (info == NULL || info->event != LNN_EVENT_RELATION_CHANGED) {
562         return;
563     }
564     if (eventInfo->udid == NULL || eventInfo->type == CONNECTION_ADDR_MAX) {
565         LNN_LOGE(LNN_BUILDER, "invalid relation changed params");
566         return;
567     }
568     msg = (LnnRelationChangedMsg *)SoftBusMalloc(sizeof(LnnRelationChangedMsg));
569     if (msg == NULL) {
570         LNN_LOGE(LNN_BUILDER, "malloc relation changed msg fail");
571         return;
572     }
573     msg->type = eventInfo->type;
574     msg->relation = eventInfo->relation;
575     msg->isJoin = eventInfo->isJoin;
576     if (strcpy_s(msg->udid, UDID_BUF_LEN, eventInfo->udid) != EOK) {
577         LNN_LOGE(LNN_BUILDER, "copy udid to relation changed msg fail");
578         SoftBusFree(msg);
579         return;
580     }
581     if (LnnAsyncCallbackDelayHelper(GetLooper(LOOP_TYPE_DEFAULT), OnLnnRelationChangedDelay, (void *)msg,
582         RELATION_CHANGED_MSG_DELAY) != SOFTBUS_OK) {
583         LNN_LOGE(LNN_BUILDER, "async relation changed msg delay fail");
584         SoftBusFree(msg);
585     }
586 }
587 
FillAllRelation(LnnRelation * relation,uint32_t relationNum)588 static int32_t FillAllRelation(LnnRelation *relation, uint32_t relationNum)
589 {
590     TopoTableItem *item = NULL;
591     TopoTableItem *itemNext = NULL;
592     TopoInfo *info = NULL;
593     TopoInfo *infoNext = NULL;
594     uint32_t i, index;
595 
596     index = 0;
597     for (i = 0; i < TOPO_HASH_TABLE_SIZE; ++i) {
598         LIST_FOR_EACH_ENTRY_SAFE(item, itemNext, &g_topoTable.table[i], TopoTableItem, node) {
599             LIST_FOR_EACH_ENTRY_SAFE(info, infoNext, &item->joinList, TopoInfo, node) {
600                 if (strcpy_s(relation[index].udid, UDID_BUF_LEN, item->udid) != EOK) {
601                     return SOFTBUS_MEM_ERR;
602                 }
603                 if (strcpy_s(relation[index].peerUdid, UDID_BUF_LEN, info->peerUdid) != EOK) {
604                     return SOFTBUS_MEM_ERR;
605                 }
606                 if (memcpy_s(relation[index].relation, sizeof(relation[index].relation), info->relation,
607                     sizeof(info->relation)) != EOK) {
608                     return SOFTBUS_MEM_ERR;
609                 }
610                 index++;
611             }
612         }
613     }
614     if (index != relationNum) {
615         return SOFTBUS_ERR;
616     }
617     return SOFTBUS_OK;
618 }
619 
LnnInitTopoManager(void)620 int32_t LnnInitTopoManager(void)
621 {
622     int32_t i;
623 
624     if (SoftbusGetConfig(SOFTBUS_BOOL_SUPPORT_TOPO, (unsigned char *)&g_topoTable.isSupportTopo,
625         sizeof(g_topoTable.isSupportTopo)) != SOFTBUS_OK) {
626         LNN_LOGE(LNN_BUILDER, "Cannot get isSupportTopo from config file");
627         g_topoTable.isSupportTopo = true;
628     }
629     if (!g_topoTable.isSupportTopo) {
630         LNN_LOGE(LNN_BUILDER, "not Support Topo");
631         return SOFTBUS_ERR;
632     }
633     for (i = 0; i < TOPO_HASH_TABLE_SIZE; ++i) {
634         ListInit(&g_topoTable.table[i]);
635     }
636     g_topoTable.totalCount = 0;
637     SoftBusMutexInit(&g_topoTable.lock, NULL);
638     if (LnnRegisterEventHandler(LNN_EVENT_RELATION_CHANGED, OnLnnRelationChanged) != SOFTBUS_OK) {
639         LNN_LOGE(LNN_BUILDER, "reg discovery type changed event fail");
640         return SOFTBUS_ERR;
641     }
642     if (LnnRegSyncInfoHandler(LNN_INFO_TYPE_TOPO_UPDATE, OnReceiveTopoUpdateMsg) != SOFTBUS_OK) {
643         LNN_LOGE(LNN_BUILDER, "reg recv topo update msg fail");
644         return SOFTBUS_ERR;
645     }
646     return SOFTBUS_OK;
647 }
648 
LnnDeinitTopoManager(void)649 void LnnDeinitTopoManager(void)
650 {
651     if (!g_topoTable.isSupportTopo) {
652         LNN_LOGE(LNN_BUILDER, "not Support Topo");
653         return;
654     }
655     LnnUnregSyncInfoHandler(LNN_INFO_TYPE_TOPO_UPDATE, OnReceiveTopoUpdateMsg);
656     LnnUnregisterEventHandler(LNN_EVENT_RELATION_CHANGED, OnLnnRelationChanged);
657 
658     if (SoftBusMutexLock(&g_topoTable.lock) != SOFTBUS_OK) {
659         LNN_LOGE(LNN_BUILDER, "lock topo table fail");
660         return;
661     }
662     ClearTopoTable();
663     (void)SoftBusMutexUnlock(&g_topoTable.lock);
664     SoftBusMutexDestroy(&g_topoTable.lock);
665 }
666 
LnnGetAllRelation(LnnRelation ** relation,uint32_t * relationNum)667 int32_t LnnGetAllRelation(LnnRelation **relation, uint32_t *relationNum)
668 {
669     int32_t rc;
670     if (relation == NULL || relationNum == NULL) {
671         LNN_LOGE(LNN_BUILDER, "invalid params");
672         return SOFTBUS_INVALID_PARAM;
673     }
674     if (SoftBusMutexLock(&g_topoTable.lock) != SOFTBUS_OK) {
675         LNN_LOGE(LNN_BUILDER, "lock topo table fail");
676         return SOFTBUS_LOCK_ERR;
677     }
678     *relation = NULL;
679     *relationNum = g_topoTable.totalCount;
680     if (*relationNum == 0) {
681         (void)SoftBusMutexUnlock(&g_topoTable.lock);
682         return SOFTBUS_OK;
683     }
684     *relation = (LnnRelation *)SoftBusMalloc(*relationNum * sizeof(LnnRelation));
685     if (*relation == NULL) {
686         LNN_LOGE(LNN_BUILDER, "malloc LnnRelation error");
687         (void)SoftBusMutexUnlock(&g_topoTable.lock);
688         return SOFTBUS_MEM_ERR;
689     }
690     rc = FillAllRelation(*relation, *relationNum);
691     (void)SoftBusMutexUnlock(&g_topoTable.lock);
692     if (rc != SOFTBUS_OK) {
693         SoftBusFree(*relation);
694     }
695     return rc;
696 }
697 
LnnGetRelation(const char * udid,const char * peerUdid,uint8_t * relation,uint32_t len)698 int32_t LnnGetRelation(const char *udid, const char *peerUdid, uint8_t *relation, uint32_t len)
699 {
700     TopoTableItem *topoItem = NULL;
701     TopoInfo *topoInfo = NULL;
702     int32_t rc;
703     if (udid == NULL || peerUdid == NULL || relation == NULL || len != CONNECTION_ADDR_MAX) {
704         LNN_LOGE(LNN_BUILDER, "invalid params");
705         return SOFTBUS_INVALID_PARAM;
706     }
707     if (SoftBusMutexLock(&g_topoTable.lock) != SOFTBUS_OK) {
708         LNN_LOGE(LNN_BUILDER, "lock topo table fail");
709         return SOFTBUS_LOCK_ERR;
710     }
711     rc = FindTopoInfo(udid, peerUdid, &topoItem, &topoInfo);
712     if (rc != SOFTBUS_OK) {
713         LNN_LOGE(LNN_BUILDER, "FindTopoInfo error");
714         (void)SoftBusMutexUnlock(&g_topoTable.lock);
715         return rc;
716     }
717     if (memcpy_s(relation, len * sizeof(relation[0]), topoInfo->relation, sizeof(topoInfo->relation)) != EOK) {
718         rc = SOFTBUS_MEM_ERR;
719     }
720     (void)SoftBusMutexUnlock(&g_topoTable.lock);
721     return rc;
722 }