1 /*
2  * Copyright (c) 2021-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_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_base_listener.h"
24 #include "softbus_def.h"
25 #include "softbus_errcode.h"
26 #include "softbus_socket.h"
27 #include "softbus_utils.h"
28 #include "trans_log.h"
29 #include "trans_pending_pkt.h"
30 #include "trans_server_proxy.h"
31 
32 #define HEART_TIME 300
33 #define TCP_KEEPALIVE_INTERVAL 4
34 #define TCP_KEEPALIVE_COUNT 5
35 #define USER_TIME_OUT (320 * 1000)
36 
37 static SoftBusList *g_tcpDirectChannelInfoList = NULL;
38 
CheckInfoAndMutexLock(TcpDirectChannelInfo * info)39 static bool CheckInfoAndMutexLock(TcpDirectChannelInfo *info)
40 {
41     if (info == NULL) {
42         TRANS_LOGE(TRANS_SDK, "param invalid.");
43         return false;
44     }
45     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
46         TRANS_LOGE(TRANS_SDK, "lock failed");
47         return false;
48     }
49     return true;
50 }
51 
TransTdcGetInfoById(int32_t channelId,TcpDirectChannelInfo * info)52 TcpDirectChannelInfo *TransTdcGetInfoById(int32_t channelId, TcpDirectChannelInfo *info)
53 {
54     if (!CheckInfoAndMutexLock(info)) {
55         return NULL;
56     }
57 
58     TcpDirectChannelInfo *item = NULL;
59     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
60         if (item->channelId == channelId) {
61             (void)memcpy_s(info, sizeof(TcpDirectChannelInfo), item, sizeof(TcpDirectChannelInfo));
62             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
63             return item;
64         }
65     }
66 
67     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
68     return NULL;
69 }
70 
TransTdcSetListenerStateById(int32_t channelId,bool needStopListener)71 int32_t TransTdcSetListenerStateById(int32_t channelId, bool needStopListener)
72 {
73     if (g_tcpDirectChannelInfoList == NULL) {
74         TRANS_LOGE(TRANS_SDK, "g_tcpDirectChannelInfoList is NULL, channelId=%{public}d", channelId);
75         return SOFTBUS_INVALID_PARAM;
76     }
77     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
78         TRANS_LOGE(TRANS_SDK, "lock failed, channelId=%{public}d", channelId);
79         return SOFTBUS_LOCK_ERR;
80     }
81 
82     TcpDirectChannelInfo *item = NULL;
83     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
84         if (item->channelId == channelId) {
85             item->detail.needStopListener = needStopListener;
86             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
87             TRANS_LOGI(TRANS_SDK, "succ, channelId=%{public}d, needStopListener=%{public}d", channelId,
88                 needStopListener);
89             return SOFTBUS_OK;
90         }
91     }
92 
93     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
94     TRANS_LOGE(TRANS_SDK, "channel not found, channelId=%{public}d", channelId);
95     return SOFTBUS_NOT_FIND;
96 }
97 
TransTdcGetInfoByIdWithIncSeq(int32_t channelId,TcpDirectChannelInfo * info)98 TcpDirectChannelInfo *TransTdcGetInfoByIdWithIncSeq(int32_t channelId, TcpDirectChannelInfo *info)
99 {
100     if (!CheckInfoAndMutexLock(info)) {
101         return NULL;
102     }
103 
104     TcpDirectChannelInfo *item = NULL;
105     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
106         if (item->channelId == channelId) {
107             (void)memcpy_s(info, sizeof(TcpDirectChannelInfo), item, sizeof(TcpDirectChannelInfo));
108             item->detail.sequence++;
109             item->detail.fdRefCnt++;
110             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
111             return item;
112         }
113     }
114 
115     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
116     return NULL;
117 }
118 
TransTdcGetInfoByFd(int32_t fd,TcpDirectChannelInfo * info)119 TcpDirectChannelInfo *TransTdcGetInfoByFd(int32_t fd, TcpDirectChannelInfo *info)
120 {
121     if (!CheckInfoAndMutexLock(info)) {
122         return NULL;
123     }
124 
125     TcpDirectChannelInfo *item = NULL;
126     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
127         if (item->detail.fd == fd) {
128             (void)memcpy_s(info, sizeof(TcpDirectChannelInfo), item, sizeof(TcpDirectChannelInfo));
129             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
130             return item;
131         }
132     }
133 
134     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
135     return NULL;
136 }
137 
TransTdcCloseChannel(int32_t channelId)138 void TransTdcCloseChannel(int32_t channelId)
139 {
140     TRANS_LOGI(TRANS_SDK, "Close tdc Channel, channelId=%{public}d.", channelId);
141     if (ServerIpcCloseChannel(NULL, channelId, CHANNEL_TYPE_TCP_DIRECT) != SOFTBUS_OK) {
142         TRANS_LOGE(TRANS_SDK, "close server tdc channelId=%{public}d err.", channelId);
143     }
144 
145     TcpDirectChannelInfo *item = NULL;
146     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
147         TRANS_LOGE(TRANS_SDK, "lock failed");
148         return;
149     }
150 
151     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
152         if (item->channelId != channelId) {
153             continue;
154         }
155         TransTdcReleaseFd(item->detail.fd);
156         item->detail.needRelease = true;
157         if (item->detail.fdRefCnt <= 0) {
158             SoftBusMutexDestroy(&(item->detail.fdLock));
159             ListDelete(&item->node);
160             SoftBusFree(item);
161             item = NULL;
162         }
163         (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
164         DelPendingPacket(channelId, PENDING_TYPE_DIRECT);
165         TRANS_LOGI(TRANS_SDK, "Delete tdc item success. channelId=%{public}d", channelId);
166         return;
167     }
168 
169     TRANS_LOGE(TRANS_SDK, "Target item not exist. channelId=%{public}d", channelId);
170     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
171 }
172 
TransGetNewTcpChannel(const ChannelInfo * channel)173 static TcpDirectChannelInfo *TransGetNewTcpChannel(const ChannelInfo *channel)
174 {
175     if (channel == NULL) {
176         TRANS_LOGE(TRANS_SDK, "param invalid");
177         return NULL;
178     }
179     TcpDirectChannelInfo *item = (TcpDirectChannelInfo *)SoftBusCalloc(sizeof(TcpDirectChannelInfo));
180     if (item == NULL) {
181         TRANS_LOGE(TRANS_SDK, "calloc failed");
182         return NULL;
183     }
184     item->channelId = channel->channelId;
185     item->detail.fd = channel->fd;
186     item->detail.channelType = channel->channelType;
187     if (SoftBusMutexInit(&(item->detail.fdLock), NULL) != SOFTBUS_OK) {
188         SoftBusFree(item);
189         TRANS_LOGE(TRANS_SDK, "init fd lock failed");
190         return NULL;
191     }
192     if (memcpy_s(item->detail.sessionKey, SESSION_KEY_LENGTH, channel->sessionKey, SESSION_KEY_LENGTH) != EOK) {
193         SoftBusFree(item);
194         TRANS_LOGE(TRANS_SDK, "sessionKey copy failed");
195         return NULL;
196     }
197     if (strcpy_s(item->detail.myIp, IP_LEN, channel->myIp) != EOK) {
198         SoftBusFree(item);
199         TRANS_LOGE(TRANS_SDK, "myIp copy failed");
200         return NULL;
201     }
202     return item;
203 }
204 
ClientTransCheckTdcChannelExist(int32_t channelId)205 static int32_t ClientTransCheckTdcChannelExist(int32_t channelId)
206 {
207     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
208         TRANS_LOGE(TRANS_SDK, "lock failed.");
209         return SOFTBUS_LOCK_ERR;
210     }
211     TcpDirectChannelInfo *item = NULL;
212     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
213         if (item->channelId == channelId) {
214             TRANS_LOGE(TRANS_SDK, "tcp direct already exist. channelId=%{public}d", channelId);
215             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
216             return SOFTBUS_TRANS_TDC_CHANNEL_ALREADY_EXIST;
217         }
218     }
219     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
220     return SOFTBUS_OK;
221 }
222 
TransTdcDelChannelInfo(int32_t channelId,int32_t errCode)223 static void TransTdcDelChannelInfo(int32_t channelId, int32_t errCode)
224 {
225     TRANS_LOGI(TRANS_SDK, "Delete tdc channelId=%{public}d.", channelId);
226 
227     TcpDirectChannelInfo *item = NULL;
228     TcpDirectChannelInfo *nextNode = NULL;
229     if (g_tcpDirectChannelInfoList == NULL) {
230         return;
231     }
232     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
233         TRANS_LOGE(TRANS_SDK, "lock failed");
234         return;
235     }
236 
237     LIST_FOR_EACH_ENTRY_SAFE(item, nextNode, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
238         if (item->channelId == channelId) {
239             if (errCode == SOFTBUS_TRANS_NEGOTIATE_REJECTED) {
240                 TransTdcCloseFd(item->detail.fd);
241                 TRANS_LOGI(
242                     TRANS_SDK, "Server reject conn, channelId=%{public}d, fd=%{public}d", channelId, item->detail.fd);
243             } else {
244                 TransTdcReleaseFd(item->detail.fd);
245             }
246             ListDelete(&item->node);
247             SoftBusMutexDestroy(&(item->detail.fdLock));
248             SoftBusFree(item);
249             item = NULL;
250             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
251             TRANS_LOGI(TRANS_SDK, "Delete tdc item success. channelId=%{public}d", channelId);
252             return;
253         }
254     }
255 
256     TRANS_LOGE(TRANS_SDK, "Target item not exist. channelId=%{public}d", channelId);
257     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
258 }
259 
ClientTransTdcHandleListener(const char * sessionName,const ChannelInfo * channel)260 static int32_t ClientTransTdcHandleListener(const char *sessionName, const ChannelInfo *channel)
261 {
262     bool isSocket = false;
263     int32_t ret = ClientTransTdcIfChannelForSocket(sessionName, &isSocket);
264     if (ret != SOFTBUS_OK) {
265         TRANS_LOGE(TRANS_SDK, "get channel socket fail, channelId=%{public}d", channel->channelId);
266         return ret;
267     }
268 
269     if (channel->isServer && isSocket) {
270         TRANS_LOGI(TRANS_SDK, "no need listen here, channelId=%{public}d", channel->channelId);
271         return SOFTBUS_OK;
272     }
273 
274     ret = TransTdcCreateListenerWithoutAddTrigger(channel->fd);
275     if (ret != SOFTBUS_OK) {
276         TRANS_LOGE(TRANS_SDK, "create listener fail, channelId=%{public}d", channel->channelId);
277         return ret;
278     }
279     if (g_tcpDirectChannelInfoList == NULL) {
280         TRANS_LOGE(TRANS_SDK, "g_tcpDirectChannelInfoList is NULL, channelId=%{public}d", channel->channelId);
281         return SOFTBUS_INVALID_PARAM;
282     }
283     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
284         TRANS_LOGE(TRANS_SDK, "lock failed, channelId=%{public}d", channel->channelId);
285         return SOFTBUS_LOCK_ERR;
286     }
287 
288     TcpDirectChannelInfo info;
289     (void)memset_s(&info, sizeof(TcpDirectChannelInfo), 0, sizeof(TcpDirectChannelInfo));
290     TcpDirectChannelInfo *res = TransTdcGetInfoById(channel->channelId, &info);
291     if (res == NULL) {
292         DelTrigger(DIRECT_CHANNEL_CLIENT, channel->fd, READ_TRIGGER);
293         TRANS_LOGE(TRANS_SDK, "TransTdcGetInfoById failed, channelId=%{public}d", channel->channelId);
294         (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
295         return SOFTBUS_NOT_FIND;
296     }
297 
298     if (!info.detail.needStopListener) {
299         TRANS_LOGI(TRANS_SDK, "info.detail.needStopListener false, channelId=%{public}d", channel->channelId);
300         AddTrigger(DIRECT_CHANNEL_CLIENT, channel->fd, READ_TRIGGER);
301     }
302     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
303     return SOFTBUS_OK;
304 }
305 
ClientTransSetTcpOption(int32_t fd)306 static int32_t ClientTransSetTcpOption(int32_t fd)
307 {
308     int32_t ret = ConnSetTcpKeepalive(fd, HEART_TIME, TCP_KEEPALIVE_INTERVAL, TCP_KEEPALIVE_COUNT);
309     if (ret != SOFTBUS_OK) {
310         TRANS_LOGE(TRANS_SDK, "ConnSetTcpKeepalive failed, fd=%{public}d.", fd);
311         return ret;
312     }
313     ret = ConnSetTcpUserTimeOut(fd, USER_TIME_OUT);
314     if (ret != SOFTBUS_OK) {
315         TRANS_LOGE(TRANS_SDK, "ConnSetTcpUserTimeOut failed, fd=%{public}d.", fd);
316         return ret;
317     }
318     return SOFTBUS_OK;
319 }
320 
ClientTransTdcOnChannelOpened(const char * sessionName,const ChannelInfo * channel)321 int32_t ClientTransTdcOnChannelOpened(const char *sessionName, const ChannelInfo *channel)
322 {
323     TRANS_CHECK_AND_RETURN_RET_LOGE(sessionName != NULL && channel != NULL,
324         SOFTBUS_INVALID_PARAM, TRANS_SDK, "param invalid");
325 
326     int32_t ret = ClientTransCheckTdcChannelExist(channel->channelId);
327     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "check tdc channel fail!");
328 
329     TcpDirectChannelInfo *item = TransGetNewTcpChannel(channel);
330     TRANS_CHECK_AND_RETURN_RET_LOGE(item != NULL, SOFTBUS_MEM_ERR,
331         TRANS_SDK, "get new tcp channel err. channelId=%{public}d", channel->channelId);
332     ret = TransAddDataBufNode(channel->channelId, channel->fd);
333     if (ret != SOFTBUS_OK) {
334         TRANS_LOGE(TRANS_SDK, "add node fail. channelId=%{public}d, fd=%{public}d", channel->channelId, channel->fd);
335         SoftBusFree(item);
336         return ret;
337     }
338 
339     ret = ClientTransSetTcpOption(channel->fd);
340     if (ret != SOFTBUS_OK) {
341         goto EXIT_ERR;
342     }
343     ret = SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock);
344     if (ret != SOFTBUS_OK) {
345         TRANS_LOGE(TRANS_SDK, "lock failed.");
346         goto EXIT_ERR;
347     }
348     ListAdd(&g_tcpDirectChannelInfoList->list, &item->node);
349     TRANS_LOGI(TRANS_SDK, "add channelId=%{public}d, fd=%{public}d", item->channelId, channel->fd);
350     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
351 
352     ret = ClientTransTdcOnSessionOpened(sessionName, channel);
353     if (ret != SOFTBUS_OK) {
354         TransDelDataBufNode(channel->channelId);
355         TransTdcDelChannelInfo(channel->channelId, ret);
356         TRANS_LOGE(TRANS_SDK, "notify on session opened err.");
357         return ret;
358     }
359 
360     ret = ClientTransTdcHandleListener(sessionName, channel);
361     if (ret != SOFTBUS_OK) {
362         ClientTransTdcOnSessionClosed(channel->channelId, SHUTDOWN_REASON_LOCAL);
363         TransDelDataBufNode(channel->channelId);
364         TransTdcDelChannelInfo(channel->channelId, ret);
365         return ret;
366     }
367 
368     return SOFTBUS_OK;
369 EXIT_ERR:
370     TransDelDataBufNode(channel->channelId);
371     SoftBusFree(item);
372     return ret;
373 }
374 
TransTdcManagerInit(const IClientSessionCallBack * callback)375 int32_t TransTdcManagerInit(const IClientSessionCallBack *callback)
376 {
377     g_tcpDirectChannelInfoList = CreateSoftBusList();
378     if (g_tcpDirectChannelInfoList == NULL || TransDataListInit() != SOFTBUS_OK) {
379         TRANS_LOGE(TRANS_INIT, "init tcp direct channel fail.");
380         return SOFTBUS_NO_INIT;
381     }
382     int32_t ret = ClientTransTdcSetCallBack(callback);
383     if (ret != SOFTBUS_OK) {
384         TRANS_LOGE(TRANS_INIT, "ClientTransTdcSetCallBack fail, ret=%{public}d", ret);
385         return ret;
386     }
387     ret = PendingInit(PENDING_TYPE_DIRECT);
388     if (ret != SOFTBUS_OK) {
389         TRANS_LOGE(TRANS_INIT, "trans direct pending init failed, ret=%{public}d", ret);
390         return SOFTBUS_NO_INIT;
391     }
392     TRANS_LOGE(TRANS_INIT, "init tcp direct channel success.");
393     return SOFTBUS_OK;
394 }
395 
TransTdcManagerDeinit(void)396 void TransTdcManagerDeinit(void)
397 {
398     if (g_tcpDirectChannelInfoList == NULL) {
399         return;
400     }
401 
402     TransDataListDeinit();
403     DestroySoftBusList(g_tcpDirectChannelInfoList);
404     g_tcpDirectChannelInfoList = NULL;
405     PendingDeinit(PENDING_TYPE_DIRECT);
406 }
407 
ClientTransTdcOnChannelOpenFailed(int32_t channelId,int32_t errCode)408 int32_t ClientTransTdcOnChannelOpenFailed(int32_t channelId, int32_t errCode)
409 {
410     return ClientTransTdcOnSessionOpenFailed(channelId, errCode);
411 }
412 
TransTdcGetSessionKey(int32_t channelId,char * key,unsigned int len)413 int32_t TransTdcGetSessionKey(int32_t channelId, char *key, unsigned int len)
414 {
415     if (key == NULL) {
416         TRANS_LOGW(TRANS_SDK, "invalid param.");
417         return SOFTBUS_INVALID_PARAM;
418     }
419     TcpDirectChannelInfo channel;
420     if (TransTdcGetInfoById(channelId, &channel) == NULL) {
421         TRANS_LOGE(TRANS_SDK, "get tdc info failed. channelId=%{public}d", channelId);
422         return SOFTBUS_TRANS_TDC_CHANNEL_NOT_FOUND;
423     }
424     if (memcpy_s(key, len, channel.detail.sessionKey, SESSION_KEY_LENGTH) != EOK) {
425         TRANS_LOGE(TRANS_SDK, "copy session key failed.");
426         return SOFTBUS_MEM_ERR;
427     }
428     return SOFTBUS_OK;
429 }
430 
TransTdcGetHandle(int32_t channelId,int * handle)431 int32_t TransTdcGetHandle(int32_t channelId, int *handle)
432 {
433     if (handle == NULL) {
434         TRANS_LOGW(TRANS_SDK, "invalid param.");
435         return SOFTBUS_INVALID_PARAM;
436     }
437     TcpDirectChannelInfo channel;
438     if (TransTdcGetInfoById(channelId, &channel) == NULL) {
439         TRANS_LOGE(TRANS_SDK, "get tdc info failed. channelId=%{public}d", channelId);
440         return SOFTBUS_TRANS_TDC_CHANNEL_NOT_FOUND;
441     }
442     *handle = channel.detail.fd;
443     return SOFTBUS_OK;
444 }
445 
TransDisableSessionListener(int32_t channelId)446 int32_t TransDisableSessionListener(int32_t channelId)
447 {
448     TcpDirectChannelInfo channel;
449     if (TransTdcGetInfoById(channelId, &channel) == NULL) {
450         TRANS_LOGE(TRANS_SDK, "get tdc info failed. channelId=%{public}d", channelId);
451         return SOFTBUS_TRANS_TDC_CHANNEL_NOT_FOUND;
452     }
453     if (channel.detail.fd < 0) {
454         TRANS_LOGE(TRANS_SDK, "invalid handle.");
455         return SOFTBUS_INVALID_FD;
456     }
457     if (g_tcpDirectChannelInfoList == NULL) {
458         TRANS_LOGE(TRANS_SDK, "g_tcpDirectChannelInfoList is NULL, channelId=%{public}d", channelId);
459         return SOFTBUS_NO_INIT;
460     }
461     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
462         TRANS_LOGE(TRANS_SDK, "lock failed, channelId=%{public}d", channelId);
463         return SOFTBUS_LOCK_ERR;
464     }
465 
466     (void)TransTdcSetListenerStateById(channelId, true);
467     int32_t ret = TransTdcStopRead(channel.detail.fd);
468     if (ret != SOFTBUS_OK) {
469         TRANS_LOGW(TRANS_SDK, "stop read failed. channelId=%{public}d, ret=%{public}d", channelId, ret);
470     }
471     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
472     return SOFTBUS_OK;
473 }
474 
TransUpdateFdState(int32_t channelId)475 void TransUpdateFdState(int32_t channelId)
476 {
477     if (g_tcpDirectChannelInfoList == NULL) {
478         TRANS_LOGE(TRANS_SDK, "g_tcpDirectChannelInfoList is NULL, channelId=%{public}d", channelId);
479         return;
480     }
481     if (SoftBusMutexLock(&g_tcpDirectChannelInfoList->lock) != SOFTBUS_OK) {
482         TRANS_LOGE(TRANS_SDK, "lock failed, channelId=%{public}d", channelId);
483         return;
484     }
485 
486     TcpDirectChannelInfo *item = NULL;
487     LIST_FOR_EACH_ENTRY(item, &(g_tcpDirectChannelInfoList->list), TcpDirectChannelInfo, node) {
488         if (item->channelId == channelId) {
489             item->detail.fdRefCnt--;
490             if (item->detail.needRelease && item->detail.fdRefCnt <= 0) {
491                 SoftBusMutexDestroy(&(item->detail.fdLock));
492                 ListDelete(&item->node);
493                 SoftBusFree(item);
494                 item = NULL;
495                 TRANS_LOGI(TRANS_SDK, "Delete tdc item success. channelId=%{public}d", channelId);
496             }
497             (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
498             return;
499         }
500     }
501 
502     (void)SoftBusMutexUnlock(&g_tcpDirectChannelInfoList->lock);
503     TRANS_LOGE(TRANS_SDK, "channel not found, channelId=%{public}d", channelId);
504     return;
505 }
506