1 /*
2  * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifdef DFINDER_SAVE_DEVICE_LIST
17 #include "nstackx_device_remote.h"
18 #include <securec.h>
19 #include "nstackx_device.h"
20 #include "nstackx_dfinder_log.h"
21 #include "nstackx_error.h"
22 #include "nstackx_dfinder_hidump.h"
23 #include "nstackx_list.h"
24 #include "nstackx_timer.h"
25 #include "nstackx_util.h"
26 #include "nstackx_statistics.h"
27 #ifdef ONE_RECORD_OF_DEVICE_FROM_ONE_LOCAL_NIF
28 #define RX_IFACE_REMOTE_NODE_COUNT 1
29 #else
30 #define RX_IFACE_REMOTE_NODE_COUNT 4
31 #endif
32 
33 #define TAG "REMOTEDEVICE"
34 #define REPORT_INTERVAL 1000 /* 1 SECOND */
35 struct RxIface_;
36 struct RemoteDevice_;
37 typedef struct RemoteNode_ {
38     List node;
39     List orderedNode;
40     DeviceInfo deviceInfo;
41     struct in_addr remoteIp;
42     struct RxIface_ *rxIface;
43     UpdateState updateState;
44     struct timespec updateTs;
45 } RemoteNode;
46 
47 typedef struct RxIface_ {
48     List node;
49     NSTACKX_InterfaceInfo localIfInfo;
50     List remoteNodeList;
51     uint32_t remoteNodeCnt;
52     struct RemoteDevice_ *device;
53     struct timespec updateTime;
54 } RxIface;
55 
56 typedef struct RemoteDevice_ {
57     List node;
58     char deviceId[NSTACKX_MAX_DEVICE_ID_LEN];
59     List rxIfaceList;
60 } RemoteDevice;
61 
62 static List *g_remoteDeviceList;
63 static List *g_remoteDeviceListBackup;
64 static List *g_remoteDeviceOrderedList;
65 static uint32_t g_remoteNodeCount;
66 static uint32_t g_agingTime;
67 static struct timespec g_lastReportedTime;
RemoteDeviceListInit(void)68 int32_t RemoteDeviceListInit(void)
69 {
70     g_remoteDeviceList = (List *)malloc(sizeof(List));
71     if (g_remoteDeviceList == NULL) {
72         DFINDER_LOGE(TAG, "malloc remote device list failed");
73         goto FAIL;
74     }
75     g_remoteDeviceListBackup = (List *)malloc(sizeof(List));
76     if (g_remoteDeviceListBackup == NULL) {
77         DFINDER_LOGE(TAG, "malloc remote device backup list failed");
78         goto FAIL;
79     }
80     g_remoteDeviceOrderedList = (List *)malloc(sizeof(List));
81     if (g_remoteDeviceOrderedList == NULL) {
82         DFINDER_LOGE(TAG, "malloc remote device ordered list failed");
83         goto FAIL;
84     }
85     ListInitHead(g_remoteDeviceList);
86     ListInitHead(g_remoteDeviceListBackup);
87     ListInitHead(g_remoteDeviceOrderedList);
88     g_remoteNodeCount = 0;
89     return NSTACKX_EOK;
90 
91 FAIL:
92     free(g_remoteDeviceList);
93     g_remoteDeviceList = NULL;
94 
95     free(g_remoteDeviceListBackup);
96     g_remoteDeviceListBackup = NULL;
97 
98     return NSTACKX_EFAILED;
99 }
100 
DestroyRemoteNode(RxIface * rxIface,RemoteNode * node)101 static void DestroyRemoteNode(RxIface *rxIface, RemoteNode *node)
102 {
103     ListRemoveNode(&node->node);
104     ListRemoveNode(&node->orderedNode);
105     if (g_remoteNodeCount > 0) {
106         g_remoteNodeCount--;
107     }
108     if (rxIface->remoteNodeCnt > 0) {
109         rxIface->remoteNodeCnt--;
110     }
111     free(node);
112     DFINDER_LOGD(TAG, "iface %s remove a node, node count: %u, total node count: %u",
113         rxIface->localIfInfo.networkName, rxIface->remoteNodeCnt, g_remoteNodeCount);
114 }
115 
DestroyRxIface(RxIface * rxIface)116 void DestroyRxIface(RxIface *rxIface)
117 {
118     List *pos = NULL;
119     List *tmp = NULL;
120     LIST_FOR_EACH_SAFE(pos, tmp, &rxIface->remoteNodeList) {
121         DestroyRemoteNode(rxIface, (RemoteNode *)pos);
122     }
123     ListRemoveNode(&rxIface->node);
124     free(rxIface);
125 }
126 
DestroyRemoteDevice(RemoteDevice * device)127 void DestroyRemoteDevice(RemoteDevice *device)
128 {
129     List *pos = NULL;
130     List *tmp = NULL;
131     RxIface *rxIface = NULL;
132     LIST_FOR_EACH_SAFE(pos, tmp, &device->rxIfaceList) {
133         rxIface = (RxIface *)pos;
134         DestroyRxIface(rxIface);
135     }
136     ListRemoveNode(&device->node);
137     free(device);
138 }
139 
ClearRemoteDeviceList(List * list)140 static void ClearRemoteDeviceList(List *list)
141 {
142     if (list == NULL) {
143         return;
144     }
145     List *pos = NULL;
146     List *tmp = NULL;
147     RemoteDevice *device = NULL;
148     LIST_FOR_EACH_SAFE(pos, tmp, list) {
149         device = (RemoteDevice *)pos;
150         DestroyRemoteDevice(device);
151     }
152 }
153 
RemoteDeviceListDeinit(void)154 void RemoteDeviceListDeinit(void)
155 {
156     ClearRemoteDeviceList(g_remoteDeviceList);
157     free(g_remoteDeviceList);
158     g_remoteDeviceList = NULL;
159     ClearRemoteDeviceList(g_remoteDeviceListBackup);
160     free(g_remoteDeviceListBackup);
161     g_remoteDeviceListBackup = NULL;
162     free(g_remoteDeviceOrderedList);
163     g_remoteDeviceOrderedList = NULL;
164     g_remoteNodeCount = 0;
165 }
166 
ClearRemoteDeviceListBackup(void)167 void ClearRemoteDeviceListBackup(void)
168 {
169     ClearRemoteDeviceList(g_remoteDeviceListBackup);
170 }
171 
BackupRemoteDeviceList(void)172 void BackupRemoteDeviceList(void)
173 {
174     ClearRemoteDeviceList(g_remoteDeviceListBackup);
175     List *tmp = g_remoteDeviceListBackup;
176     g_remoteDeviceListBackup = g_remoteDeviceList;
177     g_remoteDeviceList = tmp;
178     g_remoteNodeCount = 0;
179 }
180 
FindRemoteDevice(List * list,const char * deviceId)181 static RemoteDevice *FindRemoteDevice(List *list, const char *deviceId)
182 {
183     List *pos = NULL;
184     RemoteDevice *device = NULL;
185     LIST_FOR_EACH(pos, list) {
186         device = (RemoteDevice *)pos;
187         if (strcmp(device->deviceId, deviceId) == 0) {
188             return device;
189         }
190     }
191     return NULL;
192 }
193 
FindRxIface(const RemoteDevice * device,const NSTACKX_InterfaceInfo * interfaceInfo)194 static RxIface *FindRxIface(const RemoteDevice* device, const NSTACKX_InterfaceInfo *interfaceInfo)
195 {
196     List *pos = NULL;
197     RxIface *rxIface = NULL;
198     LIST_FOR_EACH(pos, &device->rxIfaceList) {
199         rxIface = (RxIface *)pos;
200         if ((strcmp(interfaceInfo->networkIpAddr, rxIface->localIfInfo.networkIpAddr) == 0) &&
201             (strcmp(interfaceInfo->networkName, rxIface->localIfInfo.networkName) == 0)) {
202             return rxIface;
203         }
204     }
205     return NULL;
206 }
207 
FindRemoteNodeByRemoteIp(const RxIface * rxIface,const struct in_addr * remoteIp)208 static RemoteNode *FindRemoteNodeByRemoteIp(const RxIface* rxIface, const struct in_addr *remoteIp)
209 {
210     List *pos = NULL;
211     RemoteNode *remoteNode = NULL;
212     LIST_FOR_EACH(pos, &rxIface->remoteNodeList) {
213         remoteNode = (RemoteNode *)pos;
214         if (remoteNode->remoteIp.s_addr == remoteIp->s_addr) {
215             return remoteNode;
216         }
217     }
218     return NULL;
219 }
220 
CreateRemoteDevice(const char * deviceId)221 static RemoteDevice *CreateRemoteDevice(const char *deviceId)
222 {
223     RemoteDevice *device = (RemoteDevice *)calloc(1, sizeof(RemoteDevice));
224     if (device == NULL) {
225         DFINDER_LOGE(TAG, "malloc RemoteDevice failed");
226         return NULL;
227     }
228     if (strcpy_s(device->deviceId, sizeof(device->deviceId), deviceId) != EOK) {
229         DFINDER_LOGE(TAG, "strcpy Remote device deviceId failed");
230         free(device);
231         return NULL;
232     }
233     ListInitHead(&(device->rxIfaceList));
234     return device;
235 }
236 
CreateRxIface(RemoteDevice * device,const NSTACKX_InterfaceInfo * interfaceInfo)237 static RxIface *CreateRxIface(RemoteDevice *device, const NSTACKX_InterfaceInfo *interfaceInfo)
238 {
239     RxIface *rxIface = (RxIface *)calloc(1, sizeof(RxIface));
240     if (rxIface == NULL) {
241         DFINDER_LOGE(TAG, "malloc RxIface failed");
242         return NULL;
243     }
244     (void)memcpy_s(&rxIface->localIfInfo, sizeof(NSTACKX_InterfaceInfo), interfaceInfo,
245         sizeof(NSTACKX_InterfaceInfo));
246     rxIface->device = device;
247     ListInitHead(&(rxIface->remoteNodeList));
248     return rxIface;
249 }
250 
CheckAndUpdateBusinessAll(BusinessDataAll * curInfo,const BusinessDataAll * newInfo,int8_t * updated)251 static uint32_t CheckAndUpdateBusinessAll(BusinessDataAll *curInfo, const BusinessDataAll *newInfo, int8_t *updated)
252 {
253     if (newInfo->isBroadcast == NSTACKX_TRUE) {
254         if (strcmp(curInfo->businessDataBroadcast, newInfo->businessDataBroadcast) != 0) {
255             if (strcpy_s(curInfo->businessDataBroadcast, NSTACKX_MAX_BUSINESS_DATA_LEN,
256                 newInfo->businessDataBroadcast) != EOK) {
257                 return NSTACKX_EFAILED;
258             }
259             *updated = NSTACKX_TRUE;
260         }
261     } else {
262         if (strcmp(curInfo->businessDataUnicast, newInfo->businessDataUnicast) != 0) {
263             if (strcpy_s(curInfo->businessDataUnicast, NSTACKX_MAX_BUSINESS_DATA_LEN,
264                 newInfo->businessDataUnicast) != EOK) {
265                 return NSTACKX_EFAILED;
266             }
267             *updated = NSTACKX_TRUE;
268         }
269     }
270     curInfo->isBroadcast = newInfo->isBroadcast;
271     return NSTACKX_EOK;
272 }
273 
CreateRemoteNode(RxIface * rxIface,const struct in_addr * remoteIp,const DeviceInfo * deviceInfo)274 static RemoteNode *CreateRemoteNode(RxIface *rxIface, const struct in_addr *remoteIp, const DeviceInfo *deviceInfo)
275 {
276     RemoteNode *remoteNode = (RemoteNode *)calloc(1, sizeof(RemoteNode));
277     if (remoteNode == NULL) {
278         DFINDER_LOGE(TAG, "malloc RemoteNode failed");
279         return NULL;
280     }
281 
282     remoteNode->rxIface = rxIface;
283     remoteNode->remoteIp = *remoteIp;
284     remoteNode->updateState = DFINDER_UPDATE_STATE_NULL;
285     (void)memcpy_s(&remoteNode->deviceInfo, sizeof(DeviceInfo), deviceInfo, sizeof(DeviceInfo));
286 
287     if (strcpy_s(remoteNode->deviceInfo.networkName, NSTACKX_MAX_INTERFACE_NAME_LEN,
288         rxIface->localIfInfo.networkName) != EOK) {
289         DFINDER_LOGE(TAG, "copy local report nif name failed");
290         free(remoteNode);
291         return NULL;
292     }
293     remoteNode->deviceInfo.update = NSTACKX_TRUE;
294     return remoteNode;
295 }
296 
UpdateDeviceInfoBusinessData(DeviceInfo * curInfo,const DeviceInfo * newInfo,int8_t * updated)297 static int32_t UpdateDeviceInfoBusinessData(DeviceInfo *curInfo, const DeviceInfo *newInfo, int8_t *updated)
298 {
299     return CheckAndUpdateBusinessAll(&curInfo->businessData, &newInfo->businessData, updated);
300 }
301 
UpdateCapabilityBitmap(DeviceInfo * curInfo,const DeviceInfo * newInfo,int8_t * updated)302 static int32_t UpdateCapabilityBitmap(DeviceInfo *curInfo, const DeviceInfo *newInfo,
303     int8_t *updated)
304 {
305     /* judge capabilityBitmap is or not different with new deviceInfo */
306     if ((curInfo->capabilityBitmapNum != newInfo->capabilityBitmapNum) ||
307         (newInfo->capabilityBitmapNum &&
308         memcmp(curInfo->capabilityBitmap, newInfo->capabilityBitmap,
309                newInfo->capabilityBitmapNum * sizeof(uint32_t)))) {
310         *updated = NSTACKX_TRUE;
311     }
312 
313     curInfo->capabilityBitmapNum = newInfo->capabilityBitmapNum;
314 
315     (void)memset_s(curInfo->capabilityBitmap, sizeof(curInfo->capabilityBitmap), 0,
316         sizeof(curInfo->capabilityBitmap));
317     if (newInfo->capabilityBitmapNum) {
318         if (memcpy_s(curInfo->capabilityBitmap, sizeof(curInfo->capabilityBitmap),
319             newInfo->capabilityBitmap, newInfo->capabilityBitmapNum * sizeof(uint32_t)) != EOK) {
320             DFINDER_LOGE(TAG, "UpdateCapabilityBitmap, capabilityBitmap copy error");
321             return NSTACKX_EFAILED;
322         }
323     }
324     return NSTACKX_EOK;
325 }
326 
UpdateDeviceInfoInner(DeviceInfo * curInfo,const DeviceInfo * newInfo,int8_t * updated)327 static int32_t UpdateDeviceInfoInner(DeviceInfo *curInfo, const DeviceInfo *newInfo, int8_t *updated)
328 {
329     if (curInfo->deviceType != newInfo->deviceType) {
330         DFINDER_LOGE(TAG, "deviceType is different");
331         return NSTACKX_EFAILED;
332     }
333 
334     if (strcmp(curInfo->deviceName, newInfo->deviceName) != 0) {
335         if (strcpy_s(curInfo->deviceName, sizeof(curInfo->deviceName), newInfo->deviceName) != EOK) {
336             DFINDER_LOGE(TAG, "deviceName copy error");
337             return NSTACKX_EFAILED;
338         }
339         *updated = NSTACKX_TRUE;
340     }
341 
342     if (strlen(newInfo->version) > 0 && strcmp(curInfo->version, newInfo->version) != 0) {
343         if (strcpy_s(curInfo->version, sizeof(curInfo->version), newInfo->version) != EOK) {
344             DFINDER_LOGE(TAG, "hicom version copy error");
345             return NSTACKX_EFAILED;
346         }
347         *updated = NSTACKX_TRUE;
348     }
349 
350     if (UpdateCapabilityBitmap(curInfo, newInfo, updated) != NSTACKX_EOK) {
351         DFINDER_LOGE(TAG, "UpdateCapabilityBitmap fails");
352         return NSTACKX_EFAILED;
353     }
354 
355     if (curInfo->mode != newInfo->mode) {
356         curInfo->mode = newInfo->mode;
357         *updated = NSTACKX_TRUE;
358     }
359 
360     if (curInfo->businessType != newInfo->businessType) {
361         curInfo->businessType = newInfo->businessType;
362         *updated = NSTACKX_TRUE;
363     }
364     return NSTACKX_EOK;
365 }
366 
UpdateDeviceInfo(DeviceInfo * curInfo,const RxIface * rxIface,const DeviceInfo * newInfo,int8_t * updatedPtr)367 static int32_t UpdateDeviceInfo(DeviceInfo *curInfo, const RxIface *rxIface, const DeviceInfo *newInfo,
368     int8_t *updatedPtr)
369 {
370     int8_t updated = NSTACKX_FALSE;
371     if (UpdateDeviceInfoInner(curInfo, newInfo, &updated) != NSTACKX_EOK) {
372         DFINDER_LOGE(TAG, "UpdateDeviceInfoInner error");
373         return NSTACKX_EFAILED;
374     }
375 
376     if (strcmp(curInfo->deviceHash, newInfo->deviceHash) != 0) {
377         if (strcpy_s(curInfo->deviceHash, sizeof(curInfo->deviceHash), newInfo->deviceHash) != EOK) {
378             DFINDER_LOGE(TAG, "deviceHash copy error");
379             return NSTACKX_EFAILED;
380         }
381         updated = NSTACKX_TRUE;
382     }
383 
384     if (strcmp(curInfo->serviceData, newInfo->serviceData) != 0) {
385         if (strcpy_s(curInfo->serviceData, NSTACKX_MAX_SERVICE_DATA_LEN, newInfo->serviceData) != EOK) {
386             DFINDER_LOGE(TAG, "serviceData copy error");
387             return NSTACKX_EFAILED;
388         }
389         updated = NSTACKX_TRUE;
390     }
391     updated = (newInfo->seq.dealBcast) ?
392         (curInfo->seq.seqBcast != newInfo->seq.seqBcast) : (curInfo->seq.seqUcast != newInfo->seq.seqUcast);
393     if (newInfo->seq.dealBcast) {
394         curInfo->seq.seqBcast = newInfo->seq.seqBcast;
395     } else {
396         curInfo->seq.seqUcast = newInfo->seq.seqUcast;
397     }
398 #ifndef DFINDER_USE_MINI_NSTACKX
399     if (strcmp(curInfo->extendServiceData, newInfo->extendServiceData) != 0) {
400         if (strcpy_s(curInfo->extendServiceData, NSTACKX_MAX_EXTEND_SERVICE_DATA_LEN,
401             newInfo->extendServiceData) != EOK) {
402             DFINDER_LOGE(TAG, "extendServiceData copy error");
403             return NSTACKX_EFAILED;
404         }
405         updated = NSTACKX_TRUE;
406     }
407 #endif
408 
409     if (UpdateDeviceInfoBusinessData(curInfo, newInfo, &updated) != NSTACKX_EOK) {
410         DFINDER_LOGE(TAG, "businessData copy error");
411         return NSTACKX_EFAILED;
412     }
413 
414     if (strcpy_s(curInfo->networkName, NSTACKX_MAX_INTERFACE_NAME_LEN,
415         rxIface->localIfInfo.networkName) != EOK) {
416         DFINDER_LOGE(TAG, "copy local report nif name failed");
417         return NSTACKX_EFAILED;
418     }
419     curInfo->discoveryType = newInfo->discoveryType;
420     *updatedPtr |= updated;
421     return NSTACKX_EOK;
422 }
423 
UpdatedByTimeout(RxIface * rxIface,int8_t * updated)424 static void UpdatedByTimeout(RxIface *rxIface, int8_t *updated)
425 {
426     struct timespec cur;
427     ClockGetTime(CLOCK_MONOTONIC, &cur);
428     uint32_t diffMs = GetTimeDiffMs(&cur, &(rxIface->updateTime));
429     if (diffMs > GetNotifyTimeoutMs()) {
430         *updated = NSTACKX_TRUE;
431     }
432     rxIface->updateTime = cur;
433 }
434 
UpdateRemoteNode(RemoteNode * remoteNode,RxIface * rxIface,const DeviceInfo * deviceInfo,int8_t * updated)435 static int32_t UpdateRemoteNode(RemoteNode *remoteNode, RxIface *rxIface, const DeviceInfo *deviceInfo,
436     int8_t *updated)
437 {
438     int32_t ret = UpdateDeviceInfo(&remoteNode->deviceInfo, rxIface, deviceInfo, updated);
439     if (ret == NSTACKX_EOK && (*updated == NSTACKX_FALSE)) {
440         UpdatedByTimeout(rxIface, updated);
441     }
442     return ret;
443 }
444 
445 #ifdef DFINDER_DISTINGUISH_ACTIVE_PASSIVE_DISCOVERY
UpdateRemoteNodeChangeStateActive(UpdateState * curState,int8_t * updated)446 static void UpdateRemoteNodeChangeStateActive(UpdateState *curState, int8_t *updated)
447 {
448     switch (*curState) {
449         case DFINDER_UPDATE_STATE_NULL:
450             *curState = DFINDER_UPDATE_STATE_UNICAST;
451             *updated = NSTACKX_TRUE;
452             break;
453         case DFINDER_UPDATE_STATE_BROADCAST:
454             if (*updated == NSTACKX_TRUE) {
455                 *curState = DFINDER_UPDATE_STATE_UNICAST;
456             } else {
457                 *curState = DFINDER_UPDATE_STATE_ALL;
458                 *updated = NSTACKX_TRUE;
459             }
460             break;
461         case DFINDER_UPDATE_STATE_UNICAST:
462             break;
463         case DFINDER_UPDATE_STATE_ALL:
464             if (*updated == NSTACKX_TRUE) {
465                 *curState = DFINDER_UPDATE_STATE_UNICAST;
466             }
467             break;
468         default:
469             break;
470     }
471 }
472 
UpdateRemoteNodeChangeStatePassive(UpdateState * curState,int8_t * updated)473 static void UpdateRemoteNodeChangeStatePassive(UpdateState *curState, int8_t *updated)
474 {
475     switch (*curState) {
476         case DFINDER_UPDATE_STATE_NULL:
477             *curState = DFINDER_UPDATE_STATE_BROADCAST;
478             *updated = NSTACKX_TRUE;
479             break;
480         case DFINDER_UPDATE_STATE_BROADCAST:
481             break;
482         case DFINDER_UPDATE_STATE_UNICAST:
483             if (*updated == NSTACKX_TRUE) {
484                 *curState = DFINDER_UPDATE_STATE_BROADCAST;
485             } else {
486                 *curState = DFINDER_UPDATE_STATE_ALL;
487                 *updated = NSTACKX_TRUE;
488             }
489             break;
490         case DFINDER_UPDATE_STATE_ALL:
491             if (*updated == NSTACKX_TRUE) {
492                 *curState = DFINDER_UPDATE_STATE_BROADCAST;
493             }
494             break;
495         default:
496             break;
497     }
498 }
499 
CheckAndUpdateRemoteNodeChangeState(RemoteNode * remoteNode,const DeviceInfo * deviceInfo,int8_t * updated)500 static void CheckAndUpdateRemoteNodeChangeState(RemoteNode *remoteNode,
501     const DeviceInfo *deviceInfo, int8_t *updated)
502 {
503     UpdateState *curState = &(remoteNode->updateState);
504     if (deviceInfo->discoveryType == NSTACKX_DISCOVERY_TYPE_PASSIVE) {
505         UpdateRemoteNodeChangeStatePassive(curState, updated);
506     } else {
507         UpdateRemoteNodeChangeStateActive(curState, updated);
508     }
509 }
510 #endif /* END OF DFINDER_DISTINGUISH_ACTIVE_PASSIVE_DISCOVERY */
511 
DestroyOldestRemoteNode(RxIface * rxIface)512 static void DestroyOldestRemoteNode(RxIface *rxIface)
513 {
514     DFINDER_LOGD(TAG, "rx iface %s release the oldest remote node",
515         rxIface->localIfInfo.networkName);
516     List *pos = NULL;
517     List *tmp = NULL;
518     RemoteNode *oldestNode = NULL;
519     LIST_FOR_EACH_SAFE(pos, tmp, &rxIface->remoteNodeList) {
520         RemoteNode *tmpNode = (RemoteNode *)pos;
521         if (oldestNode == NULL || GetTimeDiffMs(&tmpNode->updateTs, &oldestNode->updateTs) == 0) {
522             oldestNode = tmpNode;
523         }
524     }
525 
526     if (oldestNode != NULL) {
527         DestroyRemoteNode(rxIface, oldestNode);
528     }
529 }
530 
AddRemoteNodeToList(RxIface * rxIface,RemoteNode * remoteNode)531 static void AddRemoteNodeToList(RxIface *rxIface, RemoteNode *remoteNode)
532 {
533     ListInsertTail(&rxIface->remoteNodeList, &remoteNode->node);
534     rxIface->remoteNodeCnt++;
535     g_remoteNodeCount++;
536     DFINDER_LOGD(TAG, "iface %s add a node, iface node count: %u, total node count: %u",
537         rxIface->localIfInfo.networkName, rxIface->remoteNodeCnt, g_remoteNodeCount);
538 }
539 
SetDeviceListAgingTime(uint32_t agingTime)540 void SetDeviceListAgingTime(uint32_t agingTime)
541 {
542     if (agingTime < NSTACKX_MIN_AGING_TIME || agingTime > NSTACKX_MAX_AGING_TIME) {
543         DFINDER_LOGE(TAG, "illegal agingTime passed in, set agingTime default value");
544         g_agingTime = NSTACKX_DEFAULT_AGING_TIME;
545         return;
546     }
547     g_agingTime = agingTime;
548     DFINDER_LOGD(TAG, "the agingTime is set to: %u seconds", g_agingTime);
549 }
550 
IsAllowToBeRemoved(RemoteNode * remoteNode)551 static bool IsAllowToBeRemoved(RemoteNode *remoteNode)
552 {
553     struct timespec now;
554     ClockGetTime(CLOCK_MONOTONIC, &now);
555     uint32_t diffTime = GetTimeDiffMs(&now, &remoteNode->updateTs);
556     return diffTime >= g_agingTime * NSTACKX_MILLI_TICKS;
557 }
558 
OrderedNodeEntry(List * node)559 static __inline RemoteNode *OrderedNodeEntry(List *node)
560 {
561     return (RemoteNode *)((char *)(node) - (uintptr_t)(&(((RemoteNode *)0)->orderedNode)));
562 }
563 
CheckAndRemoveAgingNode(void)564 static int32_t CheckAndRemoveAgingNode(void)
565 {
566     RemoteNode *oldestNode = OrderedNodeEntry(ListGetFront(g_remoteDeviceOrderedList));
567     if (!IsAllowToBeRemoved(oldestNode)) {
568         DFINDER_LOGD(TAG, "remote node count %u reach the max device num, please reset the max value",
569             g_remoteNodeCount);
570         struct timespec now;
571         ClockGetTime(CLOCK_MONOTONIC, &now);
572         uint32_t measureElapse = GetTimeDiffMs(&now, &g_lastReportedTime);
573         if (measureElapse > REPORT_INTERVAL) {
574             NotifyDFinderMsgRecver(DFINDER_ON_TOO_MANY_DEVICE);
575             g_lastReportedTime = now;
576         }
577         return NSTACKX_EFAILED;
578     }
579     RxIface *rxIface = (RxIface *)oldestNode->rxIface;
580     DestroyRemoteNode(rxIface, oldestNode);
581     return NSTACKX_EOK;
582 }
583 
RemoveOldestNodesWithCount(uint32_t diffNum)584 void RemoveOldestNodesWithCount(uint32_t diffNum)
585 {
586     RemoteNode *oldestNode = NULL;
587     RxIface *rxIface = NULL;
588     for (uint32_t i = 0; i < diffNum; i++) {
589         oldestNode = OrderedNodeEntry(ListGetFront(g_remoteDeviceOrderedList));
590         rxIface = (RxIface *)oldestNode->rxIface;
591         DestroyRemoteNode(rxIface, oldestNode);
592     }
593 }
594 
GetRemoteNodeCount(void)595 uint32_t GetRemoteNodeCount(void)
596 {
597     return g_remoteNodeCount;
598 }
599 
CheckAndCreateRemoteNode(RxIface * rxIface,const struct in_addr * remoteIp,const DeviceInfo * deviceInfo)600 static RemoteNode *CheckAndCreateRemoteNode(RxIface *rxIface,
601     const struct in_addr *remoteIp, const DeviceInfo *deviceInfo)
602 {
603     if (rxIface->remoteNodeCnt >= RX_IFACE_REMOTE_NODE_COUNT) {
604         DestroyOldestRemoteNode(rxIface);
605     }
606 
607     if (g_remoteNodeCount == GetMaxDeviceNum() && CheckAndRemoveAgingNode() != NSTACKX_EOK) {
608         DFINDER_LOGE(TAG, "remote node count %u reach the max device num", g_remoteNodeCount);
609         IncStatistics(STATS_OVER_DEVICE_LIMIT);
610         return NULL;
611     }
612 
613     RemoteNode *remoteNode = CreateRemoteNode(rxIface, remoteIp, deviceInfo);
614     if (remoteNode == NULL) {
615         return NULL;
616     }
617     AddRemoteNodeToList(rxIface, remoteNode);
618     ListInsertTail(g_remoteDeviceOrderedList, &remoteNode->orderedNode);
619 
620     return remoteNode;
621 }
622 
UpdateRemoteNodeByDeviceInfo(const char * deviceId,const NSTACKX_InterfaceInfo * interfaceInfo,const struct in_addr * remoteIp,const DeviceInfo * deviceInfo,int8_t * updated)623 int32_t UpdateRemoteNodeByDeviceInfo(const char *deviceId, const NSTACKX_InterfaceInfo *interfaceInfo,
624     const struct in_addr *remoteIp, const DeviceInfo *deviceInfo, int8_t *updated)
625 {
626     RemoteDevice *device = FindRemoteDevice(g_remoteDeviceList, deviceId);
627     if (device == NULL) {
628         device = CreateRemoteDevice(deviceId);
629         if (device == NULL) {
630             return NSTACKX_EFAILED;
631         }
632         ListInsertTail(g_remoteDeviceList, &(device->node));
633     }
634 
635     RxIface *rxIface = FindRxIface(device, interfaceInfo);
636     if (rxIface == NULL) {
637         rxIface = CreateRxIface(device, interfaceInfo);
638         if (rxIface == NULL) {
639             goto FAIL_AND_FREE;
640         }
641         ClockGetTime(CLOCK_MONOTONIC, &(rxIface->updateTime));
642         ListInsertTail(&(device->rxIfaceList), &(rxIface->node));
643     }
644 
645     RemoteNode *remoteNode = FindRemoteNodeByRemoteIp(rxIface, remoteIp);
646     if (remoteNode == NULL) {
647         remoteNode = CheckAndCreateRemoteNode(rxIface, remoteIp, deviceInfo);
648         if (remoteNode == NULL) {
649             goto FAIL_AND_FREE;
650         }
651         ClockGetTime(CLOCK_MONOTONIC, &(rxIface->updateTime));
652         *updated = NSTACKX_TRUE;
653     } else {
654         if (UpdateRemoteNode(remoteNode, rxIface, deviceInfo, updated) != NSTACKX_EOK) {
655             return NSTACKX_EFAILED;
656         }
657         ListRemoveNode(&remoteNode->orderedNode);
658         ListInsertTail(g_remoteDeviceOrderedList, &remoteNode->orderedNode);
659     }
660 #ifdef DFINDER_DISTINGUISH_ACTIVE_PASSIVE_DISCOVERY
661     CheckAndUpdateRemoteNodeChangeState(remoteNode, deviceInfo, updated);
662 #endif
663     remoteNode->deviceInfo.update = *updated;
664     ClockGetTime(CLOCK_MONOTONIC, &remoteNode->updateTs);
665     return NSTACKX_EOK;
666 
667 FAIL_AND_FREE:
668     if (rxIface != NULL && ListIsEmpty(&rxIface->remoteNodeList)) {
669         ListRemoveNode(&rxIface->node);
670         free(rxIface);
671     }
672 
673     if (ListIsEmpty(&device->rxIfaceList)) {
674         ListRemoveNode(&device->node);
675         free(device);
676     }
677     return NSTACKX_EFAILED;
678 }
679 
CopyRemoteNodeToDeviceInfo(DeviceInfo * deviceInfo,NSTACKX_DeviceInfo * deviceList,uint32_t * count,bool doFilter)680 static int32_t CopyRemoteNodeToDeviceInfo(DeviceInfo *deviceInfo, NSTACKX_DeviceInfo *deviceList,
681     uint32_t *count, bool doFilter)
682 {
683     if (doFilter && !MatchDeviceFilter(deviceInfo)) {
684         DFINDER_LOGI(TAG, "Filter device");
685         return NSTACKX_EOK;
686     }
687 
688     if (GetIsNotifyPerDevice() == true && deviceInfo->update != NSTACKX_TRUE) {
689         return NSTACKX_EOK;
690     }
691 
692     if (GetNotifyDeviceInfo(&deviceList[*count], deviceInfo) != NSTACKX_EOK) {
693         DFINDER_LOGE(TAG, "GetNotifyDeviceInfo failed");
694         return NSTACKX_EFAILED;
695     }
696 
697     deviceList[*count].update = deviceInfo->update;
698     deviceInfo->update = NSTACKX_FALSE;
699     ++(*count);
700     return NSTACKX_EOK;
701 }
702 
CopyRemoteNodeListToDeviceInfo(List * rxIfaceList,NSTACKX_DeviceInfo * deviceList,uint32_t maxDeviceNum,uint32_t * deviceCountPtr,bool doFilter)703 static int32_t CopyRemoteNodeListToDeviceInfo(List *rxIfaceList, NSTACKX_DeviceInfo *deviceList,
704     uint32_t maxDeviceNum, uint32_t *deviceCountPtr, bool doFilter)
705 {
706     List *pos = NULL;
707     RemoteNode *remoteNode = NULL;
708     int32_t ret;
709     LIST_FOR_EACH(pos, rxIfaceList) {
710         if (*deviceCountPtr >= maxDeviceNum) {
711             break;
712         }
713         remoteNode = (RemoteNode *)pos;
714         ret = CopyRemoteNodeToDeviceInfo(&(remoteNode->deviceInfo), deviceList, deviceCountPtr, doFilter);
715         if (ret != NSTACKX_EOK) {
716             DFINDER_LOGE(TAG, "copy remote node to deviceinfo failed");
717             return NSTACKX_EFAILED;
718         }
719     }
720     return NSTACKX_EOK;
721 }
722 
CopyRxIfaceListToDeviceInfo(List * rxIfaceList,NSTACKX_DeviceInfo * deviceList,uint32_t maxDeviceNum,uint32_t * deviceCountPtr,bool doFilter)723 static int32_t CopyRxIfaceListToDeviceInfo(List *rxIfaceList, NSTACKX_DeviceInfo *deviceList,
724     uint32_t maxDeviceNum, uint32_t *deviceCountPtr, bool doFilter)
725 {
726     List *pos = NULL;
727     RxIface *rxIface = NULL;
728     LIST_FOR_EACH(pos, rxIfaceList) {
729         rxIface = (RxIface *)pos;
730         if (CopyRemoteNodeListToDeviceInfo(&rxIface->remoteNodeList, deviceList, maxDeviceNum,
731             deviceCountPtr, doFilter) != NSTACKX_EOK) {
732             DFINDER_LOGE(TAG, "copy remote node list to deviceinfo failed");
733             return NSTACKX_EFAILED;
734         }
735     }
736     return NSTACKX_EOK;
737 }
738 
CopyRemoteDeviceListToDeviceInfo(NSTACKX_DeviceInfo * deviceList,uint32_t maxDeviceNum,uint32_t * deviceCountPtr,bool doFilter)739 static int32_t CopyRemoteDeviceListToDeviceInfo(NSTACKX_DeviceInfo *deviceList, uint32_t maxDeviceNum,
740     uint32_t *deviceCountPtr, bool doFilter)
741 {
742     List *pos = NULL;
743     RemoteDevice *device = NULL;
744     LIST_FOR_EACH(pos, g_remoteDeviceList) {
745         device = (RemoteDevice *)pos;
746         if (CopyRxIfaceListToDeviceInfo(&device->rxIfaceList, deviceList, maxDeviceNum,
747             deviceCountPtr, doFilter) != NSTACKX_EOK) {
748             DFINDER_LOGE(TAG, "copy rxIface list to deviceinfo failed");
749             return NSTACKX_EFAILED;
750         }
751     }
752     return NSTACKX_EOK;
753 }
754 
DestroyRxIfaceByIfnameInner(RemoteDevice * device,const char * ifName)755 static void DestroyRxIfaceByIfnameInner(RemoteDevice *device, const char *ifName)
756 {
757     List *pos = NULL;
758     List *tmp = NULL;
759     RxIface *rxIface = NULL;
760     LIST_FOR_EACH_SAFE(pos, tmp, &device->rxIfaceList) {
761         rxIface = (RxIface *)pos;
762         if (strcmp(rxIface->localIfInfo.networkName, ifName) == 0) {
763             DFINDER_LOGD(TAG, "destroy rxIface: %s", ifName);
764             DestroyRxIface(rxIface);
765         }
766     }
767 }
768 
DestroyRxIfaceByIfname(const char * ifName)769 void DestroyRxIfaceByIfname(const char *ifName)
770 {
771     if (g_remoteDeviceList == NULL) {
772         return;
773     }
774     List *pos = NULL;
775     List *tmp = NULL;
776     RemoteDevice *device = NULL;
777     LIST_FOR_EACH_SAFE(pos, tmp, g_remoteDeviceList) {
778         device = (RemoteDevice *)pos;
779         DestroyRxIfaceByIfnameInner(device, ifName);
780     }
781 }
782 
GetRxIfaceFirstRemoteNode(RxIface * rxIface)783 static RemoteNode *GetRxIfaceFirstRemoteNode(RxIface *rxIface)
784 {
785     List *pos = NULL;
786     RemoteNode *remoteNode = NULL;
787     LIST_FOR_EACH(pos, &rxIface->remoteNodeList) {
788         remoteNode = (RemoteNode *)pos;
789         if (remoteNode->remoteIp.s_addr != 0) {
790             return remoteNode;
791         }
792     }
793     return NULL;
794 }
795 
GetRemoteDevcieFirstRxIface(RemoteDevice * device)796 static RxIface *GetRemoteDevcieFirstRxIface(RemoteDevice *device)
797 {
798     List *pos = NULL;
799     RxIface *rxIface = NULL;
800     LIST_FOR_EACH(pos, &device->rxIfaceList) {
801         rxIface = (RxIface *)pos;
802         if (!ListIsEmpty(&rxIface->remoteNodeList)) {
803             return rxIface;
804         }
805     }
806     return NULL;
807 }
808 
GetRemoteDeviceIpInner(List * list,const char * deviceId)809 const struct in_addr *GetRemoteDeviceIpInner(List *list, const char *deviceId)
810 {
811     RemoteDevice *device = FindRemoteDevice(list, deviceId);
812     if (device == NULL || ListIsEmpty(&device->rxIfaceList)) {
813         return NULL;
814     }
815 
816     RxIface *rxIface = GetRemoteDevcieFirstRxIface(device);
817     if (rxIface == NULL) {
818         return NULL;
819     }
820 
821     RemoteNode *remoteNode = GetRxIfaceFirstRemoteNode(rxIface);
822     if (remoteNode == NULL) {
823         return NULL;
824     }
825 
826     return &remoteNode->remoteIp;
827 }
828 
GetRemoteDeviceIp(const char * deviceId)829 const struct in_addr *GetRemoteDeviceIp(const char *deviceId)
830 {
831     const struct in_addr *remoteIp;
832     remoteIp = GetRemoteDeviceIpInner(g_remoteDeviceList, deviceId);
833     if (remoteIp != NULL) {
834         return remoteIp;
835     }
836     return GetRemoteDeviceIpInner(g_remoteDeviceListBackup, deviceId);
837 }
838 
839 #ifdef NSTACKX_DFINDER_HIDUMP
DumpRemoteNode(const RemoteDevice * dev,char * buf,size_t len)840 static int DumpRemoteNode(const RemoteDevice *dev, char *buf, size_t len)
841 {
842     List *pos = NULL;
843     size_t index = 0;
844     LIST_FOR_EACH(pos, &dev->rxIfaceList) {
845         RxIface *rxIface = (RxIface *)pos;
846         List *tmp = NULL;
847         LIST_FOR_EACH(tmp, &rxIface->remoteNodeList) {
848             RemoteNode *node = (RemoteNode *)tmp;
849             int ret = DumpDeviceInfo(&node->deviceInfo, buf + index, len - index, NSTACKX_TRUE);
850             if (ret < 0 || (size_t)ret > len - index) {
851                 DFINDER_LOGE(TAG, "dump remote node failed");
852                 return NSTACKX_EFAILED;
853             }
854 
855             index += (size_t)ret;
856         }
857     }
858 
859     return index;
860 }
861 
DumpRemoteDevice(char * buf,size_t len)862 int DumpRemoteDevice(char *buf, size_t len)
863 {
864     List *pos = NULL;
865     size_t index = 0;
866     LIST_FOR_EACH(pos, g_remoteDeviceList) {
867         RemoteDevice *device = (RemoteDevice *)pos;
868         int ret = DumpRemoteNode(device, buf + index, len - index);
869         if (ret < 0 || (size_t)ret > len - index) {
870             DFINDER_LOGE(TAG, "dump remote device failed");
871             return NSTACKX_EFAILED;
872         }
873 
874         index += (size_t)ret;
875     }
876 
877     return index;
878 }
879 #endif
880 
GetDeviceList(NSTACKX_DeviceInfo * deviceList,uint32_t * deviceListLen,bool doFilter)881 void GetDeviceList(NSTACKX_DeviceInfo *deviceList, uint32_t *deviceListLen, bool doFilter)
882 {
883     if (deviceList == NULL) {
884         DFINDER_LOGE(TAG, "device list is null");
885         return;
886     }
887 
888     uint32_t maxDeviceNum = *deviceListLen;
889     uint32_t count = 0;
890     (void)CopyRemoteDeviceListToDeviceInfo(deviceList, maxDeviceNum, &count, doFilter);
891     *deviceListLen = count;
892 }
893 #endif /* END OF DFINDER_SAVE_DEVICE_LIST */
894