1 /*
2 * Copyright (c) 2021 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_tcp_direct_manager.h"
17
18 #include <securec.h>
19
20 #include "client_trans_tcp_direct_callback.h"
21 #include "client_trans_tcp_direct_listener.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_def.h"
24 #include "softbus_errcode.h"
25 #include "softbus_socket.h"
26 #include "softbus_utils.h"
27 #include "trans_log.h"
28 #include "trans_pending_pkt.h"
29 #include "trans_server_proxy.h"
30
31 #define HEART_TIME 300
32 #define USER_TIME_OUT (30 * 1000)
33
34 static SoftBusList *g_tcpDirectChannelInfoList = NULL;
35
CheckInfoAndMutexLock(TcpDirectChannelInfo * info)36 static bool CheckInfoAndMutexLock(TcpDirectChannelInfo *info)
37 {
38 if (info == NULL) {
39 TRANS_LOGE(TRANS_SDK, "param invalid.");
40 return false;
41 }
42 if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
43 TRANS_LOGE(TRANS_SDK, "lock failed");
44 return false;
45 }
46 return true;
47 }
48
TransTdcGetInfoById(int32_t channelId,TcpDirectChannelInfo * info)49 TcpDirectChannelInfo *TransTdcGetInfoById(int32_t channelId, TcpDirectChannelInfo *info)
50 {
51 if (!CheckInfoAndMutexLock(info)) {
52 return NULL;
53 }
54
55 TcpDirectChannelInfo *item = NULL;
56 LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
57 if (item->channelId == channelId) {
58 (void)memcpy_s(info, sizeof(TcpDirectChannelInfo), item, sizeof(TcpDirectChannelInfo));
59 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
60 return item;
61 }
62 }
63
64 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
65 return NULL;
66 }
67
TransTdcGetInfoByIdWithIncSeq(int32_t channelId,TcpDirectChannelInfo * info)68 TcpDirectChannelInfo *TransTdcGetInfoByIdWithIncSeq(int32_t channelId, TcpDirectChannelInfo *info)
69 {
70 if (!CheckInfoAndMutexLock(info)) {
71 return NULL;
72 }
73
74 TcpDirectChannelInfo *item = NULL;
75 LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
76 if (item->channelId == channelId) {
77 (void)memcpy_s(info, sizeof(TcpDirectChannelInfo), item, sizeof(TcpDirectChannelInfo));
78 item->detail.sequence++;
79 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
80 return item;
81 }
82 }
83
84 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
85 return NULL;
86 }
87
TransTdcGetInfoByFd(int32_t fd,TcpDirectChannelInfo * info)88 TcpDirectChannelInfo *TransTdcGetInfoByFd(int32_t fd, TcpDirectChannelInfo *info)
89 {
90 if (!CheckInfoAndMutexLock(info)) {
91 return NULL;
92 }
93
94 TcpDirectChannelInfo *item = NULL;
95 LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
96 if (item->detail.fd == fd) {
97 (void)memcpy_s(info, sizeof(TcpDirectChannelInfo), item, sizeof(TcpDirectChannelInfo));
98 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
99 return item;
100 }
101 }
102
103 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
104 return NULL;
105 }
106
TransTdcCloseChannel(int32_t channelId)107 void TransTdcCloseChannel(int32_t channelId)
108 {
109 TRANS_LOGI(TRANS_SDK, "Close tdc Channel, channelId=%{public}d.", channelId);
110 if (ServerIpcCloseChannel(channelId, CHANNEL_TYPE_TCP_DIRECT) != SOFTBUS_OK) {
111 TRANS_LOGE(TRANS_SDK, "close server tdc channelId=%{public}d err.", channelId);
112 }
113
114 TcpDirectChannelInfo *item = NULL;
115 if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
116 TRANS_LOGE(TRANS_SDK, "lock failed");
117 return;
118 }
119
120 LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
121 if (item->channelId == channelId) {
122 TransTdcReleaseFd(item->detail.fd);
123 ListDelete(&item->node);
124 SoftBusFree(item);
125 item = NULL;
126 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
127 DelPendingPacket(channelId, PENDING_TYPE_DIRECT);
128 TRANS_LOGI(TRANS_SDK, "Delete tdc item success. channelId=%{public}d", channelId);
129 return;
130 }
131 }
132
133 TRANS_LOGE(TRANS_SDK, "Target item not exist. channelId=%{public}d", channelId);
134 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
135 }
136
TransGetNewTcpChannel(const ChannelInfo * channel)137 static TcpDirectChannelInfo *TransGetNewTcpChannel(const ChannelInfo *channel)
138 {
139 if (channel == NULL) {
140 TRANS_LOGE(TRANS_SDK, "param invalid");
141 return NULL;
142 }
143 TcpDirectChannelInfo *item = (TcpDirectChannelInfo *)SoftBusCalloc(sizeof(TcpDirectChannelInfo));
144 if (item == NULL) {
145 TRANS_LOGE(TRANS_SDK, "calloc failed");
146 return NULL;
147 }
148 item->channelId = channel->channelId;
149 item->detail.fd = channel->fd;
150 item->detail.channelType = channel->channelType;
151 if (memcpy_s(item->detail.sessionKey, SESSION_KEY_LENGTH, channel->sessionKey, SESSION_KEY_LENGTH) != EOK) {
152 SoftBusFree(item);
153 TRANS_LOGE(TRANS_SDK, "sessionKey copy failed");
154 return NULL;
155 }
156 return item;
157 }
158
ClientTransCheckTdcChannelExist(int32_t channelId)159 static int32_t ClientTransCheckTdcChannelExist(int32_t channelId)
160 {
161 if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
162 TRANS_LOGE(TRANS_SDK, "lock failed.");
163 return SOFTBUS_ERR;
164 }
165 TcpDirectChannelInfo *item = NULL;
166 LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
167 if (item->channelId == channelId) {
168 TRANS_LOGE(TRANS_SDK, "tcp direct already exist. channelId=%{public}d", channelId);
169 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
170 return SOFTBUS_ERR;
171 }
172 }
173 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
174 return SOFTBUS_OK;
175 }
176
TransTdcDelChannelInfo(int32_t channelId)177 static void TransTdcDelChannelInfo(int32_t channelId)
178 {
179 TRANS_LOGI(TRANS_SDK, "Delete tdc channelId=%{public}d.", channelId);
180
181 TcpDirectChannelInfo *item = NULL;
182 TcpDirectChannelInfo *nextNode = NULL;
183 if (g_tcpDirectChannelInfoList == NULL) {
184 return;
185 }
186 if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
187 TRANS_LOGE(TRANS_SDK, "lock failed");
188 return;
189 }
190
191 LIST_FOR_EACH_ENTRY_SAFE(item, nextNode, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
192 if (item->channelId == channelId) {
193 TransTdcReleaseFd(item->detail.fd);
194 ListDelete(&item->node);
195 SoftBusFree(item);
196 item = NULL;
197 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
198 TRANS_LOGI(TRANS_SDK, "Delete tdc item success. channelId=%{public}d", channelId);
199 return;
200 }
201 }
202
203 TRANS_LOGE(TRANS_SDK, "Target item not exist. channelId=%{public}d", channelId);
204 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
205 }
206
ClientTransTdcOnChannelOpened(const char * sessionName,const ChannelInfo * channel)207 int32_t ClientTransTdcOnChannelOpened(const char *sessionName, const ChannelInfo *channel)
208 {
209 if (sessionName == NULL || channel == NULL) {
210 TRANS_LOGE(TRANS_SDK, "param invalid");
211 return SOFTBUS_ERR;
212 }
213 if (ClientTransCheckTdcChannelExist(channel->channelId) != SOFTBUS_OK) {
214 return SOFTBUS_ERR;
215 }
216 TcpDirectChannelInfo *item = TransGetNewTcpChannel(channel);
217 if (item == NULL) {
218 TRANS_LOGE(TRANS_SDK, "get new tcp channel err. channelId=%{public}d", channel->channelId);
219 return SOFTBUS_ERR;
220 }
221 if (TransAddDataBufNode(channel->channelId, channel->fd) != SOFTBUS_OK) {
222 TRANS_LOGE(TRANS_SDK,
223 "add data buf node fail. channelId=%{public}d, fd=%{public}d", channel->channelId, channel->fd);
224 SoftBusFree(item);
225 return SOFTBUS_ERR;
226 }
227 if (TransTdcCreateListener(channel->fd) != SOFTBUS_OK) {
228 TRANS_LOGE(TRANS_SDK, "trans tdc create listener failed. fd=%{public}d", channel->fd);
229 goto EXIT_ERR;
230 }
231 if (ConnSetTcpKeepAlive(channel->fd, HEART_TIME) != SOFTBUS_OK) {
232 TRANS_LOGE(TRANS_SDK, "ConnSetTcpKeepAlive failed, fd=%{public}d.", channel->fd);
233 goto EXIT_ERR;
234 }
235 if (ConnSetTcpUserTimeOut(channel->fd, USER_TIME_OUT) != SOFTBUS_OK) {
236 TRANS_LOGE(TRANS_SDK, "ConnSetTcpUserTimeOut failed, fd=%{public}d.", channel->fd);
237 goto EXIT_ERR;
238 }
239 if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
240 TRANS_LOGE(TRANS_SDK, "lock failed.");
241 goto EXIT_ERR;
242 }
243 ListAdd(&g_tcpDirectChannelInfoList->list, &item->node);
244 TRANS_LOGI(TRANS_SDK, "add channelId=%{public}d", item->channelId);
245 (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
246
247 if (ClientTransTdcOnSessionOpened(sessionName, channel) != SOFTBUS_OK) {
248 TransDelDataBufNode(channel->channelId);
249 TransTdcDelChannelInfo(channel->channelId);
250 TRANS_LOGE(TRANS_SDK, "notify on session opened err.");
251 return SOFTBUS_ERR;
252 }
253 return SOFTBUS_OK;
254 EXIT_ERR:
255 TransDelDataBufNode(channel->channelId);
256 SoftBusFree(item);
257 return SOFTBUS_ERR;
258 }
259
TransTdcManagerInit(const IClientSessionCallBack * callback)260 int32_t TransTdcManagerInit(const IClientSessionCallBack *callback)
261 {
262 g_tcpDirectChannelInfoList = CreateSoftBusList();
263 if (g_tcpDirectChannelInfoList == NULL || TransDataListInit() != SOFTBUS_OK) {
264 TRANS_LOGE(TRANS_INIT, "init tcp direct channel fail.");
265 return SOFTBUS_ERR;
266 }
267 if (ClientTransTdcSetCallBack(callback) != SOFTBUS_OK) {
268 TRANS_LOGE(TRANS_INIT, "ClientTransTdcSetCallBack fail.");
269 return SOFTBUS_ERR;
270 }
271 if (PendingInit(PENDING_TYPE_DIRECT) == SOFTBUS_ERR) {
272 TRANS_LOGE(TRANS_INIT, "trans direct pending init failed.");
273 return SOFTBUS_ERR;
274 }
275 TRANS_LOGE(TRANS_INIT, "init tcp direct channel success.");
276 return SOFTBUS_OK;
277 }
278
TransTdcManagerDeinit(void)279 void TransTdcManagerDeinit(void)
280 {
281 if (g_tcpDirectChannelInfoList == NULL) {
282 return;
283 }
284
285 TransDataListDeinit();
286 DestroySoftBusList(g_tcpDirectChannelInfoList);
287 g_tcpDirectChannelInfoList = NULL;
288 PendingDeinit(PENDING_TYPE_DIRECT);
289 }
290
ClientTransTdcOnChannelOpenFailed(int32_t channelId,int32_t errCode)291 int32_t ClientTransTdcOnChannelOpenFailed(int32_t channelId, int32_t errCode)
292 {
293 return ClientTransTdcOnSessionOpenFailed(channelId, errCode);
294 }
295
TransTdcGetSessionKey(int32_t channelId,char * key,unsigned int len)296 int32_t TransTdcGetSessionKey(int32_t channelId, char *key, unsigned int len)
297 {
298 if (key == NULL) {
299 TRANS_LOGW(TRANS_SDK, "invalid param.");
300 return SOFTBUS_INVALID_PARAM;
301 }
302 TcpDirectChannelInfo channel;
303 if (TransTdcGetInfoById(channelId, &channel) == NULL) {
304 TRANS_LOGE(TRANS_SDK, "get tdc info failed. channelId=%{public}d", channelId);
305 return SOFTBUS_ERR;
306 }
307 if (memcpy_s(key, len, channel.detail.sessionKey, SESSION_KEY_LENGTH) != EOK) {
308 TRANS_LOGE(TRANS_SDK, "copy session key failed.");
309 return SOFTBUS_MEM_ERR;
310 }
311 return SOFTBUS_OK;
312 }
313
TransTdcGetHandle(int32_t channelId,int * handle)314 int32_t TransTdcGetHandle(int32_t channelId, int *handle)
315 {
316 if (handle == NULL) {
317 TRANS_LOGW(TRANS_SDK, "invalid param.");
318 return SOFTBUS_INVALID_PARAM;
319 }
320 TcpDirectChannelInfo channel;
321 if (TransTdcGetInfoById(channelId, &channel) == NULL) {
322 TRANS_LOGE(TRANS_SDK, "get tdc info failed. channelId=%{public}d", channelId);
323 return SOFTBUS_ERR;
324 }
325 *handle = channel.detail.fd;
326 return SOFTBUS_OK;
327 }
328
TransDisableSessionListener(int32_t channelId)329 int32_t TransDisableSessionListener(int32_t channelId)
330 {
331 TcpDirectChannelInfo channel;
332 if (TransTdcGetInfoById(channelId, &channel) == NULL) {
333 TRANS_LOGE(TRANS_SDK, "get tdc info failed. channelId=%{public}d", channelId);
334 return SOFTBUS_ERR;
335 }
336 if (channel.detail.fd < 0) {
337 TRANS_LOGE(TRANS_SDK, "invalid handle.");
338 return SOFTBUS_ERR;
339 }
340 return TransTdcStopRead(channel.detail.fd);
341 }
342