• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "trans_network_statistics.h"
16 
17 #include <securec.h>
18 #include "cJSON.h"
19 
20 #include "comm_log.h"
21 #include "softbus_adapter_mem.h"
22 #include "softbus_error_code.h"
23 #include "softbus_json_utils.h"
24 #include "softbus_utils.h"
25 #include "trans_event.h"
26 
27 typedef struct {
28     ListNode node;
29     int32_t channelId;
30     int32_t channelType;
31 } ChannelDfxInfo;
32 
33 typedef struct {
34     ListNode node;
35     int32_t channelId;
36     char *channelInfo;
37     uint32_t len;
38 } ChannelStatisticsInfo;
39 
40 typedef struct {
41     ListNode node;
42     NetworkResource resource;
43     int64_t startTime;
44     int64_t endTime;
45     ListNode channels;
46 } NetworkStatisticsInfo;
47 
48 static SoftBusList *g_networkResourceList = NULL;
49 
50 static SoftBusList *g_channelDfxInfoList = NULL;
51 
AddChannelStatisticsInfo(int32_t channelId,int32_t channelType)52 void AddChannelStatisticsInfo(int32_t channelId, int32_t channelType)
53 {
54     if (channelId < 0) {
55         COMM_LOGE(COMM_DFX, "invalid param");
56         return;
57     }
58     if (g_channelDfxInfoList == NULL) {
59         COMM_LOGE(COMM_DFX, "channel info list init failed, channelId=%{public}d", channelId);
60         return;
61     }
62     if (SoftBusMutexLock(&g_channelDfxInfoList->lock) != SOFTBUS_OK) {
63         COMM_LOGE(COMM_DFX, "channel info list lock failed, channelId=%{public}d", channelId);
64         return;
65     }
66     if ((int32_t)g_channelDfxInfoList->cnt >= MAX_CHANNEL_INFO_NUM) {
67         COMM_LOGE(COMM_DFX, "channel info list out of max num, channelId=%{public}d", channelId);
68         (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
69         return;
70     }
71 
72     ChannelDfxInfo *temp = NULL;
73     LIST_FOR_EACH_ENTRY(temp, &g_channelDfxInfoList->list, ChannelDfxInfo, node) {
74         if (temp->channelId == channelId && temp->channelType == channelType) {
75             COMM_LOGE(COMM_DFX, "channel info already in channel info list, channelId=%{public}d", channelId);
76             (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
77             return;
78         }
79     }
80     ChannelDfxInfo *channelInfo = (ChannelDfxInfo *)SoftBusCalloc(sizeof(ChannelDfxInfo));
81     if (channelInfo == NULL) {
82         COMM_LOGE(COMM_DFX, "channel info calloc failed, channelId=%{public}d", channelId);
83         (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
84         return;
85     }
86     channelInfo->channelId = channelId;
87     channelInfo->channelType = channelType;
88     ListAdd(&g_channelDfxInfoList->list, &channelInfo->node);
89     g_channelDfxInfoList->cnt++;
90     (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
91 }
92 
AddNetworkResource(NetworkResource * networkResource)93 void AddNetworkResource(NetworkResource *networkResource)
94 {
95     if (networkResource == NULL) {
96         COMM_LOGE(COMM_DFX, "invalid param");
97         return;
98     }
99     if (g_networkResourceList == NULL) {
100         COMM_LOGE(COMM_DFX, "g_networkResourceList init fail");
101         return;
102     }
103     if (SoftBusMutexLock(&g_networkResourceList->lock) != SOFTBUS_OK) {
104         COMM_LOGE(COMM_DFX, "lock failed");
105         return;
106     }
107     if ((int32_t)g_networkResourceList->cnt >= MAX_NETWORK_RESOURCE_NUM) {
108         COMM_LOGE(COMM_DFX, "network Resource out of max num");
109         (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
110         return;
111     }
112 
113     NetworkStatisticsInfo *temp = NULL;
114     LIST_FOR_EACH_ENTRY(temp, &g_networkResourceList->list, NetworkStatisticsInfo, node) {
115         if (temp->resource.laneId == networkResource->laneId) {
116             COMM_LOGE(COMM_DFX, "laneId already in g_networkResourceList");
117             (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
118             return;
119         }
120     }
121     NetworkStatisticsInfo *info = (NetworkStatisticsInfo *)SoftBusCalloc(sizeof(NetworkStatisticsInfo));
122     if (info == NULL) {
123         COMM_LOGE(COMM_DFX, "network resource info SoftBusCalloc fail");
124         (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
125         return;
126     }
127     if (memcpy_s(&info->resource, sizeof(NetworkResource), networkResource, sizeof(NetworkResource)) != EOK) {
128         COMM_LOGE(COMM_DFX, "network resource memcpy fail");
129         (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
130         SoftBusFree(info);
131         return;
132     }
133     ListInit(&info->node);
134     ListInit(&info->channels);
135     info->startTime = SoftBusGetSysTimeMs();
136     ListAdd(&g_networkResourceList->list, &info->node);
137     g_networkResourceList->cnt++;
138     (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
139 }
140 
IsChannelDfxInfoValid(int32_t channelId,int32_t channelType)141 static bool IsChannelDfxInfoValid(int32_t channelId, int32_t channelType)
142 {
143     if (channelId < 0) {
144         COMM_LOGE(COMM_DFX, "invalid param");
145         return false;
146     }
147     if (g_channelDfxInfoList == NULL) {
148         COMM_LOGE(COMM_DFX, "channel info list init failed, channelId=%{public}d", channelId);
149         return false;
150     }
151     if (SoftBusMutexLock(&g_channelDfxInfoList->lock) != SOFTBUS_OK) {
152         COMM_LOGE(COMM_DFX, "channel info list lock failed, channelId=%{public}d", channelId);
153         return false;
154     }
155 
156     bool ret = false;
157     ChannelDfxInfo *temp = NULL;
158     LIST_FOR_EACH_ENTRY(temp, &g_channelDfxInfoList->list, ChannelDfxInfo, node) {
159         if (temp->channelId == channelId && temp->channelType == channelType) {
160             ret = true;
161             break;
162         }
163     }
164     (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
165     return ret;
166 }
167 
RemoveChannelDfxInfo(int32_t channelId,int32_t channelType)168 static void RemoveChannelDfxInfo(int32_t channelId, int32_t channelType)
169 {
170     if (channelId < 0) {
171         COMM_LOGE(COMM_DFX, "invalid param");
172         return;
173     }
174     if (g_channelDfxInfoList == NULL) {
175         COMM_LOGE(COMM_DFX, "channel info list init failed, channelId=%{public}d", channelId);
176         return;
177     }
178     if (SoftBusMutexLock(&g_channelDfxInfoList->lock) != SOFTBUS_OK) {
179         COMM_LOGE(COMM_DFX, "channel info list lock failed, channelId=%{public}d", channelId);
180         return;
181     }
182 
183     ChannelDfxInfo *temp = NULL;
184     ChannelDfxInfo *next = NULL;
185     LIST_FOR_EACH_ENTRY_SAFE(temp, next, &(g_channelDfxInfoList->list), ChannelDfxInfo, node) {
186         if (temp->channelId == channelId && temp->channelType == channelType) {
187             ListDelete(&temp->node);
188             g_channelDfxInfoList->cnt--;
189             SoftBusFree(temp);
190         }
191     }
192     (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
193 }
194 
ChannelStatisticsInfoInit(ChannelStatisticsInfo * info,int32_t channelId,const void * dataInfo,uint32_t len)195 static int32_t ChannelStatisticsInfoInit(ChannelStatisticsInfo *info, int32_t channelId, const void *dataInfo,
196     uint32_t len)
197 {
198     if (info == NULL || dataInfo == NULL || len > MAX_SOCKET_RESOURCE_LEN) {
199         COMM_LOGE(COMM_DFX, "invalid param, channelId=%{public}d", channelId);
200         return SOFTBUS_INVALID_PARAM;
201     }
202 
203     info->channelInfo = (char *)SoftBusCalloc(len + 1);
204     if (info->channelInfo == NULL) {
205         COMM_LOGE(COMM_DFX, "channel info mallloc fail, channelId=%{public}d", channelId);
206         return SOFTBUS_MALLOC_ERR;
207     }
208     if (memcpy_s(info->channelInfo, len + 1, (char *)dataInfo, len) != EOK) {
209         COMM_LOGE(COMM_DFX, "channel info memcpy fail, channelId=%{public}d", channelId);
210         SoftBusFree(info->channelInfo);
211         return SOFTBUS_MEM_ERR;
212     }
213     info->channelId = channelId;
214     info->len = len;
215     return SOFTBUS_OK;
216 }
217 
UpdateNetworkResourceByLaneId(int32_t channelId,int32_t channelType,uint64_t laneId,const void * dataInfo,uint32_t len)218 void UpdateNetworkResourceByLaneId(int32_t channelId, int32_t channelType, uint64_t laneId,
219     const void *dataInfo, uint32_t len)
220 {
221     if (dataInfo == NULL || len > MAX_SOCKET_RESOURCE_LEN || !IsChannelDfxInfoValid(channelId, channelType)) {
222         COMM_LOGE(COMM_DFX, "invalid param, channelId=%{public}d", channelId);
223         return;
224     }
225     RemoveChannelDfxInfo(channelId, channelType);
226     if (g_networkResourceList == NULL) {
227         COMM_LOGE(COMM_DFX, "network resource list init fail, channelId=%{public}d", channelId);
228         return;
229     }
230     if (SoftBusMutexLock(&g_networkResourceList->lock) != SOFTBUS_OK) {
231         COMM_LOGE(COMM_DFX, "lock failed, channelId=%{public}d", channelId);
232         return;
233     }
234 
235     NetworkStatisticsInfo *temp = NULL;
236     LIST_FOR_EACH_ENTRY(temp, &g_networkResourceList->list, NetworkStatisticsInfo, node) {
237         if (temp->resource.laneId != laneId) {
238             continue;
239         }
240         ChannelStatisticsInfo *item = NULL;
241         LIST_FOR_EACH_ENTRY(item, &temp->channels, ChannelStatisticsInfo, node) {
242             if (item->channelId == channelId) {
243                 COMM_LOGE(COMM_DFX, "channelId already in channels, channelId=%{public}d", channelId);
244                 (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
245                 return;
246             }
247         }
248         ChannelStatisticsInfo *info = (ChannelStatisticsInfo *)SoftBusCalloc(sizeof(ChannelStatisticsInfo));
249         if (info == NULL) {
250             COMM_LOGE(COMM_DFX, "channel statistics info SoftBusCalloc fail, channelId=%{public}d", channelId);
251             (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
252             return;
253         }
254         if (ChannelStatisticsInfoInit(info, channelId, dataInfo, len) != SOFTBUS_OK) {
255             COMM_LOGE(COMM_DFX, "channel statistics info set fail, channelId=%{public}d", channelId);
256             (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
257             SoftBusFree(info);
258             return;
259         }
260         ListInit(&info->node);
261         ListAdd(&temp->channels, &info->node);
262         (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
263         return;
264     }
265     (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
266 }
267 
PackNetworkStatistics(cJSON * json,NetworkStatisticsInfo * info)268 static int32_t PackNetworkStatistics(cJSON *json, NetworkStatisticsInfo *info)
269 {
270     if (json == NULL || info == NULL) {
271         COMM_LOGE(COMM_DFX, "invalid param");
272         return SOFTBUS_INVALID_PARAM;
273     }
274 
275     char laneId[MAX_LANE_ID_LEN] = { 0 };
276     if (sprintf_s(laneId, sizeof(laneId), "%" PRIu64, info->resource.laneId) < 0) {
277         COMM_LOGE(COMM_DFX, "sprintf lane id fail");
278         return SOFTBUS_MEM_ERR;
279     }
280     if (!AddStringToJsonObject(json, "laneId", laneId) ||
281         !AddStringToJsonObject(json, "localUdid", info->resource.localUdid) ||
282         !AddStringToJsonObject(json, "peerUdid", info->resource.peerUdid)) {
283         return SOFTBUS_PARSE_JSON_ERR;
284     }
285     if (!AddNumberToJsonObject(json, "lineLinkType", info->resource.laneLinkType) ||
286         !AddNumber64ToJsonObject(json, "startTime", info->startTime) ||
287         !AddNumber64ToJsonObject(json, "endTime", info->endTime)) {
288         return SOFTBUS_PARSE_JSON_ERR;
289     }
290 
291     cJSON *channelStatsObj = cJSON_AddArrayToObject(json, "channelStats");
292     if (channelStatsObj == NULL) {
293         return SOFTBUS_PARSE_JSON_ERR;
294     }
295     ChannelStatisticsInfo *temp = NULL;
296     LIST_FOR_EACH_ENTRY(temp, &info->channels, ChannelStatisticsInfo, node) {
297         if (temp->channelInfo == NULL) {
298             continue;
299         }
300         cJSON *channelInfoJson = cJSON_ParseWithLength(temp->channelInfo, temp->len);
301         if (channelInfoJson == NULL) {
302             COMM_LOGE(COMM_DFX, "parse channel info json fail, channelId=%{public}d", temp->channelId);
303             continue;
304         }
305         cJSON_AddItemToArray(channelStatsObj, channelInfoJson);
306     }
307     return SOFTBUS_OK;
308 }
309 
DfxRecordTransChannelStatistics(NetworkStatisticsInfo * networkStatisticsInfo)310 static void DfxRecordTransChannelStatistics(NetworkStatisticsInfo *networkStatisticsInfo)
311 {
312     if (networkStatisticsInfo == NULL) {
313         COMM_LOGE(COMM_DFX, "invalid param");
314         return;
315     }
316     if (IsListEmpty(&networkStatisticsInfo->channels)) {
317         return;
318     }
319     cJSON *json = cJSON_CreateObject();
320     COMM_CHECK_AND_RETURN_LOGW(json != NULL, COMM_DFX, "cJSON_CreateObject fail");
321 
322     if (PackNetworkStatistics(json, networkStatisticsInfo) != SOFTBUS_OK) {
323         cJSON_Delete(json);
324         return;
325     }
326     char *trafficStats = cJSON_PrintUnformatted(json);
327     cJSON_Delete(json);
328     COMM_CHECK_AND_RETURN_LOGW(trafficStats != NULL, COMM_DFX, "cJSON_PrintUnformatted fail");
329     TransEventExtra extra = {
330         .result = EVENT_STAGE_RESULT_OK,
331         .trafficStats = trafficStats
332     };
333     TRANS_EVENT(EVENT_SCENE_TRANS_CHANNEL_STATISTICS, EVENT_STAGE_TRANS_COMMON_ONE, extra);
334     cJSON_free(trafficStats);
335 }
336 
DeleteNetworkResourceByLaneId(uint64_t laneId)337 void DeleteNetworkResourceByLaneId(uint64_t laneId)
338 {
339     if (g_networkResourceList == NULL) {
340         COMM_LOGE(COMM_DFX, "network resource list init fail");
341         return;
342     }
343     if (SoftBusMutexLock(&g_networkResourceList->lock) != SOFTBUS_OK) {
344         COMM_LOGE(COMM_DFX, "lock failed");
345         return;
346     }
347 
348     NetworkStatisticsInfo *item = NULL;
349     NetworkStatisticsInfo *next = NULL;
350     LIST_FOR_EACH_ENTRY_SAFE(item, next, &(g_networkResourceList->list), NetworkStatisticsInfo, node) {
351         if (item->resource.laneId == laneId) {
352             item->endTime = SoftBusGetSysTimeMs();
353             DfxRecordTransChannelStatistics(item);
354             ChannelStatisticsInfo *channelItem = NULL;
355             ChannelStatisticsInfo *channelNext = NULL;
356             LIST_FOR_EACH_ENTRY_SAFE(channelItem, channelNext, &item->channels, ChannelStatisticsInfo, node) {
357                 ListDelete(&channelItem->node);
358                 SoftBusFree(channelItem->channelInfo);
359                 SoftBusFree(channelItem);
360             }
361             ListDelete(&item->node);
362             g_networkResourceList->cnt--;
363             SoftBusFree(item);
364         }
365     }
366     (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
367 }
368 
TransNetworkStatisticsInit(void)369 int32_t TransNetworkStatisticsInit(void)
370 {
371     if (g_networkResourceList != NULL) {
372         COMM_LOGW(COMM_DFX, "network statistics has init");
373     } else {
374         g_networkResourceList = CreateSoftBusList();
375         if (g_networkResourceList == NULL) {
376             COMM_LOGE(COMM_DFX, "network statistics init fail");
377             return SOFTBUS_MALLOC_ERR;
378         }
379     }
380 
381     if (g_channelDfxInfoList != NULL) {
382         COMM_LOGW(COMM_DFX, "channel statistics has init");
383     } else {
384         g_channelDfxInfoList = CreateSoftBusList();
385         if (g_channelDfxInfoList == NULL) {
386             COMM_LOGE(COMM_DFX, "channel statistics init fail");
387             return SOFTBUS_MALLOC_ERR;
388         }
389     }
390     return SOFTBUS_OK;
391 }
392 
TransNetworkResourceDeinit(void)393 static void TransNetworkResourceDeinit(void)
394 {
395     if (g_networkResourceList == NULL) {
396         COMM_LOGW(COMM_DFX, "network statistics has deinit");
397         return;
398     }
399 
400     if (SoftBusMutexLock(&g_networkResourceList->lock) != SOFTBUS_OK) {
401         COMM_LOGE(COMM_DFX, "lock failed");
402         return;
403     }
404     NetworkStatisticsInfo *item = NULL;
405     NetworkStatisticsInfo *next = NULL;
406     LIST_FOR_EACH_ENTRY_SAFE(item, next, &(g_networkResourceList->list), NetworkStatisticsInfo, node) {
407         if (!IsListEmpty(&item->channels)) {
408             ChannelStatisticsInfo *channelItem = NULL;
409             ChannelStatisticsInfo *channelNext = NULL;
410             LIST_FOR_EACH_ENTRY_SAFE(channelItem, channelNext, &item->channels, ChannelStatisticsInfo, node) {
411                 ListDelete(&channelItem->node);
412                 SoftBusFree(channelItem->channelInfo);
413                 SoftBusFree(channelItem);
414             }
415         }
416         ListDelete(&item->node);
417         SoftBusFree(item);
418     }
419     g_networkResourceList->cnt = 0;
420     (void)SoftBusMutexUnlock(&g_networkResourceList->lock);
421     DestroySoftBusList(g_networkResourceList);
422     g_networkResourceList = NULL;
423 }
424 
TransChannelStatisticsDeinit(void)425 static void TransChannelStatisticsDeinit(void)
426 {
427     if (g_channelDfxInfoList == NULL) {
428         COMM_LOGW(COMM_DFX, "channel statistics has deinit");
429         return;
430     }
431 
432     if (SoftBusMutexLock(&g_channelDfxInfoList->lock) != SOFTBUS_OK) {
433         COMM_LOGE(COMM_DFX, "channel statistics lock failed");
434         return;
435     }
436     ChannelDfxInfo *item = NULL;
437     ChannelDfxInfo *next = NULL;
438     LIST_FOR_EACH_ENTRY_SAFE(item, next, &(g_channelDfxInfoList->list), ChannelDfxInfo, node) {
439         ListDelete(&item->node);
440         SoftBusFree(item);
441     }
442     g_channelDfxInfoList->cnt = 0;
443     (void)SoftBusMutexUnlock(&g_channelDfxInfoList->lock);
444     DestroySoftBusList(g_channelDfxInfoList);
445     g_channelDfxInfoList = NULL;
446 }
447 
TransNetworkStatisticsDeinit(void)448 void TransNetworkStatisticsDeinit(void)
449 {
450     TransNetworkResourceDeinit();
451     TransChannelStatisticsDeinit();
452 }