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