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 }