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