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