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 
16 #include "client_trans_statistics.h"
17 
18 #include <securec.h>
19 #include "cJSON.h"
20 
21 #include "anonymizer.h"
22 #include "client_trans_session_manager.h"
23 #include "client_trans_socket_manager.h"
24 #include "common_list.h"
25 #include "softbus_adapter_mem.h"
26 #include "softbus_conn_interface.h"
27 #include "softbus_errcode.h"
28 #include "softbus_json_utils.h"
29 #include "softbus_utils.h"
30 #include "trans_log.h"
31 #include "trans_server_proxy.h"
32 
33 static SoftBusList *g_channelStatisticsList = NULL;
34 
CreateSocketResource(SocketResource * item,const char * sessionName,const ChannelInfo * channel)35 static void CreateSocketResource(SocketResource *item, const char *sessionName, const ChannelInfo *channel)
36 {
37     if (item == NULL || sessionName == NULL || channel == NULL) {
38         TRANS_LOGE(TRANS_SDK, "invalid param");
39         return;
40     }
41     item->laneId = channel->laneId;
42     item->channelId = channel->channelId;
43     item->channelType = channel->channelType;
44     item->startTime = (int64_t)SoftBusGetSysTimeMs();
45 
46     char *tmpSessionName = NULL;
47     Anonymize(sessionName, &tmpSessionName);
48     if (strcpy_s(item->socketName, SESSION_NAME_SIZE_MAX, tmpSessionName) != EOK) {
49         TRANS_LOGE(TRANS_SDK, "strcpy failed");
50     }
51     AnonymizeFree(tmpSessionName);
52 }
53 
AddSocketResource(const char * sessionName,const ChannelInfo * channel)54 void AddSocketResource(const char *sessionName, const ChannelInfo *channel)
55 {
56     if (sessionName == NULL || channel == NULL || channel->isServer) {
57         TRANS_LOGE(TRANS_SDK, "invalid param");
58         return;
59     }
60     if (channel->connectType != CONNECT_BR && channel->connectType != CONNECT_BLE &&
61         channel->connectType != CONNECT_P2P && channel->connectType != CONNECT_HML) {
62         TRANS_LOGE(TRANS_SDK, "invalid param");
63         return;
64     }
65     if (g_channelStatisticsList == NULL) {
66         return;
67     }
68     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
69         TRANS_LOGE(TRANS_SDK, "channel statistics list lock fail");
70         return;
71     }
72     if ((int32_t)g_channelStatisticsList->cnt >= MAX_SOCKET_RESOURCE_NUM) {
73         TRANS_LOGE(TRANS_SDK, "channel statistics out of max num");
74         (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
75         return;
76     }
77     SocketResource *newItem = SoftBusCalloc(sizeof(SocketResource));
78     if (newItem == NULL) {
79         TRANS_LOGE(TRANS_SDK, "socket resource calloc fail");
80         (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
81         return;
82     }
83     if (ClientGetSessionIdByChannelId(channel->channelId, channel->channelType, &newItem->socketId) != SOFTBUS_OK) {
84         TRANS_LOGE(TRANS_SDK, "get socketId failed, channelId=%{public}d", channel->channelId);
85         (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
86         SoftBusFree(newItem);
87         return;
88     }
89 
90     SocketResource *item = NULL;
91     LIST_FOR_EACH_ENTRY(item, &g_channelStatisticsList->list, SocketResource, node) {
92         if (item->socketId == newItem->socketId) {
93             TRANS_LOGE(TRANS_SDK, "socket id already in channel statistics list");
94             (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
95             SoftBusFree(newItem);
96             return;
97         }
98     }
99 
100     ListInit(&newItem->node);
101     CreateSocketResource(newItem, sessionName, channel);
102     ListAdd(&g_channelStatisticsList->list, &newItem->node);
103     g_channelStatisticsList->cnt++;
104     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
105 }
106 
UpdateChannelStatistics(int32_t socketId,int64_t len)107 void UpdateChannelStatistics(int32_t socketId, int64_t len)
108 {
109     if (socketId < 0 || len <= 0) {
110         TRANS_LOGE(TRANS_SDK, "invalid param");
111         return;
112     }
113     if (g_channelStatisticsList == NULL) {
114         TRANS_LOGE(TRANS_SDK, "channel statistices list init fail");
115         return;
116     }
117     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
118         TRANS_LOGE(TRANS_SDK, "channel statistics list lock fail");
119         return;
120     }
121     SocketResource *item = NULL;
122     LIST_FOR_EACH_ENTRY(item, &g_channelStatisticsList->list, SocketResource, node) {
123         if (item->socketId == socketId) {
124             item->traffic += len;
125             item->endTime = (int64_t)SoftBusGetSysTimeMs();
126             (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
127             return;
128         }
129     }
130     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
131 }
132 
PackStatistics(cJSON * json,SocketResource * resource)133 static int32_t PackStatistics(cJSON *json, SocketResource *resource)
134 {
135     if (json == NULL || resource == NULL) {
136         TRANS_LOGE(TRANS_SDK, "invalid param");
137         return SOFTBUS_INVALID_PARAM;
138     }
139     char laneId[MAX_LANE_ID_LEN] = { 0 };
140     if (sprintf_s(laneId, sizeof(laneId), "%"PRIu64"", resource->laneId) < 0) {
141         TRANS_LOGE(TRANS_SDK, "sprintf laneId fail");
142         return SOFTBUS_INVALID_PARAM;
143     }
144     if (!AddNumberToJsonObject(json, "channelId", resource->channelId) ||
145         !AddNumberToJsonObject(json, "channelType", resource->channelType) ||
146         !AddNumberToJsonObject(json, "socketId", resource->socketId) ||
147         !AddNumber64ToJsonObject(json, "traffic", resource->traffic) ||
148         !AddNumber64ToJsonObject(json, "startTime", resource->startTime) ||
149         !AddNumber64ToJsonObject(json, "endTime", resource->endTime)) {
150         TRANS_LOGE(TRANS_SDK, "add num to json fail");
151         return SOFTBUS_INVALID_PARAM;
152     }
153     if (!AddStringToJsonObject(json, "laneId", laneId) ||
154         !AddStringToJsonObject(json, "socketName", resource->socketName)) {
155         TRANS_LOGE(TRANS_SDK, "add string to json fail");
156         return SOFTBUS_INVALID_PARAM;
157     }
158     return SOFTBUS_OK;
159 }
160 
CloseChannelAndSendStatistics(SocketResource * resource)161 static void CloseChannelAndSendStatistics(SocketResource *resource)
162 {
163     if (resource == NULL) {
164         TRANS_LOGE(TRANS_SDK, "invalid param");
165         return;
166     }
167     cJSON *json = cJSON_CreateObject();
168     TRANS_CHECK_AND_RETURN_LOGE(json != NULL, TRANS_SDK, "cJSON_CreateObject failed");
169     int32_t ret = PackStatistics(json, resource);
170     if (ret != SOFTBUS_OK) {
171         TRANS_LOGE(TRANS_SDK, "pack statistics fail");
172         cJSON_Delete(json);
173         return;
174     }
175     char *str = cJSON_PrintUnformatted(json);
176     cJSON_Delete(json);
177     TRANS_CHECK_AND_RETURN_LOGE(str != NULL, TRANS_SDK, "cJSON_PrintUnformatted failed");
178     ServerIpcCloseChannelWithStatistics(resource->channelId, resource->channelType, resource->laneId, str, strlen(str));
179     cJSON_free(str);
180 }
181 
DeleteSocketResourceByChannelId(int32_t channelId,int32_t channelType)182 void DeleteSocketResourceByChannelId(int32_t channelId, int32_t channelType)
183 {
184     if (channelId < 0) {
185         TRANS_LOGE(TRANS_SDK, "invalid param");
186         return;
187     }
188     if (g_channelStatisticsList == NULL) {
189         TRANS_LOGE(TRANS_SDK, "channel statistices list init fail");
190         return;
191     }
192     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
193         TRANS_LOGE(TRANS_SDK, "channel statistics list lock fail");
194         return;
195     }
196     int32_t socketId;
197     if (ClientGetSessionIdByChannelId(channelId, channelType, &socketId) != SOFTBUS_OK) {
198         TRANS_LOGE(TRANS_SDK, "get socketId failed, channelId=%{public}d", channelId);
199         (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
200         return;
201     }
202     SocketResource *item = NULL;
203     SocketResource *next = NULL;
204     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_channelStatisticsList->list, SocketResource, node) {
205         if (item->socketId == socketId) {
206             CloseChannelAndSendStatistics(item);
207             ListDelete(&item->node);
208             g_channelStatisticsList->cnt--;
209             SoftBusFree(item);
210         }
211     }
212     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
213 }
214 
ClientTransStatisticsInit(void)215 int32_t ClientTransStatisticsInit(void)
216 {
217     if (g_channelStatisticsList != NULL) {
218         TRANS_LOGE(TRANS_SDK, "channel statistics list has init");
219         return SOFTBUS_OK;
220     }
221     g_channelStatisticsList = CreateSoftBusList();
222     if (g_channelStatisticsList == NULL) {
223         TRANS_LOGE(TRANS_SDK, "channel statistics list init fail");
224         return SOFTBUS_MALLOC_ERR;
225     }
226     TRANS_LOGI(TRANS_SDK, "ClientTransStatisticsInit");
227     return SOFTBUS_OK;
228 }
229 
ClientTransStatisticsDeinit(void)230 void ClientTransStatisticsDeinit(void)
231 {
232     if (g_channelStatisticsList == NULL) {
233         TRANS_LOGE(TRANS_SDK, "channel statistics list has deinit");
234         return;
235     }
236     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
237         TRANS_LOGE(TRANS_SDK, "channel statistics list lock failed");
238         return;
239     }
240     SocketResource *laneItem = NULL;
241     SocketResource *nextLaneItem = NULL;
242     LIST_FOR_EACH_ENTRY_SAFE(laneItem, nextLaneItem, &g_channelStatisticsList->list, SocketResource, node) {
243         ListDelete(&(laneItem->node));
244         SoftBusFree(laneItem);
245     }
246     g_channelStatisticsList->cnt = 0;
247     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
248     DestroySoftBusList(g_channelStatisticsList);
249     g_channelStatisticsList = NULL;
250     TRANS_LOGI(TRANS_SDK, "ClientTransStatisticsDeinit");
251 }
252