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, AnonymizeWrapper(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 = (SocketResource *)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, false) !=
84         SOFTBUS_OK) {
85         TRANS_LOGE(TRANS_SDK, "get socketId failed, channelId=%{public}d", channel->channelId);
86         (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
87         SoftBusFree(newItem);
88         return;
89     }
90 
91     SocketResource *item = NULL;
92     LIST_FOR_EACH_ENTRY(item, &g_channelStatisticsList->list, SocketResource, node) {
93         if (item->socketId == newItem->socketId) {
94             TRANS_LOGE(TRANS_SDK, "socket id already in channel statistics list");
95             (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
96             SoftBusFree(newItem);
97             return;
98         }
99     }
100 
101     ListInit(&newItem->node);
102     CreateSocketResource(newItem, sessionName, channel);
103     ListAdd(&g_channelStatisticsList->list, &newItem->node);
104     g_channelStatisticsList->cnt++;
105     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
106 }
107 
UpdateChannelStatistics(int32_t socketId, int64_t len)108 void UpdateChannelStatistics(int32_t socketId, int64_t len)
109 {
110     if (socketId < 0 || len <= 0) {
111         TRANS_LOGE(TRANS_SDK, "invalid param");
112         return;
113     }
114     if (g_channelStatisticsList == NULL) {
115         TRANS_LOGE(TRANS_SDK, "channel statistices list init fail");
116         return;
117     }
118     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
119         TRANS_LOGE(TRANS_SDK, "channel statistics list lock fail");
120         return;
121     }
122     SocketResource *item = NULL;
123     LIST_FOR_EACH_ENTRY(item, &g_channelStatisticsList->list, SocketResource, node) {
124         if (item->socketId == socketId) {
125             item->traffic += len;
126             item->endTime = (int64_t)SoftBusGetSysTimeMs();
127             (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
128             return;
129         }
130     }
131     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
132 }
133 
PackStatistics(cJSON *json, SocketResource *resource)134 static int32_t PackStatistics(cJSON *json, SocketResource *resource)
135 {
136     if (json == NULL || resource == NULL) {
137         TRANS_LOGE(TRANS_SDK, "invalid param");
138         return SOFTBUS_INVALID_PARAM;
139     }
140     char laneId[MAX_LANE_ID_LEN] = { 0 };
141     if (sprintf_s(laneId, sizeof(laneId), "%" PRIu64"", resource->laneId) < 0) {
142         TRANS_LOGE(TRANS_SDK, "sprintf laneId fail");
143         return SOFTBUS_INVALID_PARAM;
144     }
145     if (!AddNumberToJsonObject(json, "channelId", resource->channelId) ||
146         !AddNumberToJsonObject(json, "channelType", resource->channelType) ||
147         !AddNumberToJsonObject(json, "socketId", resource->socketId) ||
148         !AddNumber64ToJsonObject(json, "traffic", resource->traffic) ||
149         !AddNumber64ToJsonObject(json, "startTime", resource->startTime) ||
150         !AddNumber64ToJsonObject(json, "endTime", resource->endTime)) {
151         TRANS_LOGE(TRANS_SDK, "add num to json fail");
152         return SOFTBUS_INVALID_PARAM;
153     }
154     if (!AddStringToJsonObject(json, "laneId", laneId) ||
155         !AddStringToJsonObject(json, "socketName", resource->socketName)) {
156         TRANS_LOGE(TRANS_SDK, "add string to json fail");
157         return SOFTBUS_INVALID_PARAM;
158     }
159     return SOFTBUS_OK;
160 }
161 
CloseChannelAndSendStatistics(SocketResource *resource)162 static void CloseChannelAndSendStatistics(SocketResource *resource)
163 {
164     if (resource == NULL) {
165         TRANS_LOGE(TRANS_SDK, "invalid param");
166         return;
167     }
168     cJSON *json = cJSON_CreateObject();
169     TRANS_CHECK_AND_RETURN_LOGE(json != NULL, TRANS_SDK, "cJSON_CreateObject failed");
170     int32_t ret = PackStatistics(json, resource);
171     if (ret != SOFTBUS_OK) {
172         TRANS_LOGE(TRANS_SDK, "pack statistics fail");
173         cJSON_Delete(json);
174         return;
175     }
176     char *str = cJSON_PrintUnformatted(json);
177     cJSON_Delete(json);
178     TRANS_CHECK_AND_RETURN_LOGE(str != NULL, TRANS_SDK, "cJSON_PrintUnformatted failed");
179     ServerIpcCloseChannelWithStatistics(resource->channelId, resource->channelType, resource->laneId, str, strlen(str));
180     cJSON_free(str);
181 }
182 
DeleteSocketResourceByChannelId(int32_t channelId, int32_t channelType)183 void DeleteSocketResourceByChannelId(int32_t channelId, int32_t channelType)
184 {
185     if (channelId < 0) {
186         TRANS_LOGE(TRANS_SDK, "invalid param");
187         return;
188     }
189     if (g_channelStatisticsList == NULL) {
190         TRANS_LOGE(TRANS_SDK, "channel statistices list init fail");
191         return;
192     }
193     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
194         TRANS_LOGE(TRANS_SDK, "channel statistics list lock fail");
195         return;
196     }
197     int32_t socketId;
198     if (ClientGetSessionIdByChannelId(channelId, channelType, &socketId, false) != SOFTBUS_OK) {
199         TRANS_LOGE(TRANS_SDK, "get socketId failed, channelId=%{public}d", channelId);
200         (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
201         return;
202     }
203     SocketResource *item = NULL;
204     SocketResource *next = NULL;
205     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_channelStatisticsList->list, SocketResource, node) {
206         if (item->socketId == socketId) {
207             CloseChannelAndSendStatistics(item);
208             ListDelete(&item->node);
209             g_channelStatisticsList->cnt--;
210             SoftBusFree(item);
211         }
212     }
213     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
214 }
215 
ClientTransStatisticsInit(void)216 int32_t ClientTransStatisticsInit(void)
217 {
218     if (g_channelStatisticsList != NULL) {
219         TRANS_LOGW(TRANS_SDK, "channel statistics list has init");
220         return SOFTBUS_OK;
221     }
222     g_channelStatisticsList = CreateSoftBusList();
223     if (g_channelStatisticsList == NULL) {
224         TRANS_LOGE(TRANS_SDK, "channel statistics list init fail");
225         return SOFTBUS_MALLOC_ERR;
226     }
227     TRANS_LOGI(TRANS_SDK, "ClientTransStatisticsInit");
228     return SOFTBUS_OK;
229 }
230 
ClientTransStatisticsDeinit(void)231 void ClientTransStatisticsDeinit(void)
232 {
233     if (g_channelStatisticsList == NULL) {
234         TRANS_LOGW(TRANS_SDK, "channel statistics list has deinit");
235         return;
236     }
237     if (SoftBusMutexLock(&g_channelStatisticsList->lock) != SOFTBUS_OK) {
238         TRANS_LOGE(TRANS_SDK, "channel statistics list lock failed");
239         return;
240     }
241     SocketResource *laneItem = NULL;
242     SocketResource *nextLaneItem = NULL;
243     LIST_FOR_EACH_ENTRY_SAFE(laneItem, nextLaneItem, &g_channelStatisticsList->list, SocketResource, node) {
244         ListDelete(&(laneItem->node));
245         SoftBusFree(laneItem);
246     }
247     g_channelStatisticsList->cnt = 0;
248     (void)SoftBusMutexUnlock(&g_channelStatisticsList->lock);
249     DestroySoftBusList(g_channelStatisticsList);
250     g_channelStatisticsList = NULL;
251     TRANS_LOGI(TRANS_SDK, "ClientTransStatisticsDeinit");
252 }
253