1 /*
2 * Copyright (c) 2021-2025 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 "trans_tcp_direct_manager.h"
17
18 #include <securec.h>
19
20 #include "bus_center_manager.h"
21 #include "softbus_adapter_mem.h"
22 #include "softbus_def.h"
23 #include "softbus_error_code.h"
24 #include "legacy/softbus_hisysevt_transreporter.h"
25 #include "softbus_socket.h"
26 #include "trans_channel_common.h"
27 #include "trans_event.h"
28 #include "trans_log.h"
29 #include "trans_tcp_direct_callback.h"
30 #include "trans_tcp_direct_listener.h"
31 #include "trans_tcp_direct_message.h"
32 #include "trans_tcp_direct_p2p.h"
33 #include "trans_tcp_direct_sessionconn.h"
34 #include "trans_tcp_direct_wifi.h"
35 #include "wifi_direct_manager.h"
36
37 #define HANDSHAKE_TIMEOUT 19
38
OnSessionOpenFailProc(const SessionConn * node,int32_t errCode)39 static void OnSessionOpenFailProc(const SessionConn *node, int32_t errCode)
40 {
41 TRANS_LOGW(TRANS_CTRL, "OnSesssionOpenFailProc: channelId=%{public}d, side=%{public}d, status=%{public}d",
42 node->channelId, node->serverSide, node->status);
43 int64_t timeStart = node->appInfo.timeStart;
44 int64_t timeDiff = GetSoftbusRecordTimeMillis() - timeStart;
45 char localUdid[UDID_BUF_LEN] = { 0 };
46 (void)LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, sizeof(localUdid));
47 TransEventExtra extra = {
48 .calleePkg = NULL,
49 .callerPkg = node->appInfo.myData.pkgName,
50 .channelId = node->channelId,
51 .peerChannelId = node->appInfo.peerData.channelId,
52 .peerNetworkId = node->appInfo.peerNetWorkId,
53 .socketName = node->appInfo.myData.sessionName,
54 .linkType = node->appInfo.connectType,
55 .costTime = (int32_t)timeDiff,
56 .errcode = errCode,
57 .osType = (node->appInfo.osType < 0) ? UNKNOW_OS_TYPE : node->appInfo.osType,
58 .localUdid = localUdid,
59 .peerUdid = node->appInfo.peerUdid,
60 .peerDevVer = node->appInfo.peerVersion,
61 .result = EVENT_STAGE_RESULT_FAILED
62 };
63 extra.deviceState = TransGetDeviceState(node->appInfo.peerNetWorkId);
64 if (!node->serverSide) {
65 TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL, EVENT_STAGE_OPEN_CHANNEL_END, extra);
66 } else {
67 TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL_SERVER, EVENT_STAGE_OPEN_CHANNEL_END, extra);
68 }
69 if (node->serverSide == false) {
70 if (TransTdcOnChannelOpenFailed(node->appInfo.myData.pkgName, node->appInfo.myData.pid,
71 node->channelId, errCode) != SOFTBUS_OK) {
72 TRANS_LOGW(TRANS_CTRL, "notify channel open fail err");
73 }
74 }
75
76 int32_t fd = node->appInfo.fd;
77 if (fd >= 0) {
78 TRANS_LOGW(TRANS_CTRL, "session is shutdown. fd=%{public}d", fd);
79 DelTrigger(node->listenMod, fd, RW_TRIGGER);
80 TransTdcSocketReleaseFd(node->listenMod, fd);
81 }
82 }
83
NotifyTdcChannelTimeOut(ListNode * tdcChannelList)84 static void NotifyTdcChannelTimeOut(ListNode *tdcChannelList)
85 {
86 if (tdcChannelList == NULL) {
87 TRANS_LOGE(TRANS_CTRL, "param invalid");
88 return;
89 }
90
91 SessionConn *item = NULL;
92 SessionConn *nextItem = NULL;
93 LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, tdcChannelList, SessionConn, node) {
94 OnSessionOpenFailProc(item, SOFTBUS_TRANS_HANDSHAKE_TIMEOUT);
95 TransSrvDelDataBufNode(item->channelId);
96 SoftBusFree(item);
97 }
98 }
99
TransTdcTimerProc(void)100 static void TransTdcTimerProc(void)
101 {
102 SessionConn *item = NULL;
103 SessionConn *nextItem = NULL;
104 SoftBusList *sessionList = GetSessionConnList();
105 if (sessionList == NULL) {
106 TRANS_LOGE(TRANS_CTRL, "get session conn list failed");
107 return;
108 }
109 if (GetSessionConnLock() != SOFTBUS_OK) {
110 TRANS_LOGE(TRANS_CTRL, "get session conn lock failed");
111 return;
112 }
113
114 ListNode tempTdcChannelList;
115 ListInit(&tempTdcChannelList);
116
117 LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &sessionList->list, SessionConn, node) {
118 item->timeout++;
119 if (item->status < TCP_DIRECT_CHANNEL_STATUS_CONNECTED) {
120 if (item->timeout >= HANDSHAKE_TIMEOUT) {
121 ListDelete(&item->node);
122 sessionList->cnt--;
123
124 ListAdd(&tempTdcChannelList, &item->node);
125 }
126 }
127 }
128 ReleaseSessionConnLock();
129
130 NotifyTdcChannelTimeOut(&tempTdcChannelList);
131 }
132
NotifyTdcChannelStopProc(ListNode * tdcChannelList)133 static void NotifyTdcChannelStopProc(ListNode *tdcChannelList)
134 {
135 if (tdcChannelList == NULL) {
136 TRANS_LOGE(TRANS_INIT, "param invalid");
137 return;
138 }
139
140 SessionConn *item = NULL;
141 SessionConn *nextItem = NULL;
142
143 LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, tdcChannelList, SessionConn, node) {
144 OnSessionOpenFailProc(item, SOFTBUS_TRANS_NET_STATE_CHANGED);
145 TransSrvDelDataBufNode(item->channelId);
146 SoftBusFree(item);
147 }
148 }
149
150
TransTdcStopSessionProc(ListenerModule listenMod)151 void TransTdcStopSessionProc(ListenerModule listenMod)
152 {
153 TRANS_LOGD(TRANS_CTRL, "enter.");
154
155 SessionConn *item = NULL;
156 SessionConn *nextItem = NULL;
157
158 SoftBusList *sessionList = GetSessionConnList();
159 if (sessionList == NULL) {
160 TRANS_LOGE(TRANS_INIT, "get session conn list failed");
161 return;
162 }
163 if (GetSessionConnLock() != SOFTBUS_OK) {
164 TRANS_LOGE(TRANS_INIT, "get session conn lock failed");
165 return;
166 }
167
168 ListNode tempTdcChannelList;
169 ListInit(&tempTdcChannelList);
170 LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &sessionList->list, SessionConn, node) {
171 if (listenMod != item->listenMod) {
172 continue;
173 }
174 ListDelete(&item->node);
175 sessionList->cnt--;
176
177 ListAdd(&tempTdcChannelList, &item->node);
178 }
179 ReleaseSessionConnLock();
180 NotifyTdcChannelStopProc(&tempTdcChannelList);
181 TRANS_LOGD(TRANS_CTRL, "ok");
182 }
183
TransTcpDirectInit(const IServerChannelCallBack * cb)184 int32_t TransTcpDirectInit(const IServerChannelCallBack *cb)
185 {
186 TRANS_CHECK_AND_RETURN_RET_LOGE(cb != NULL, SOFTBUS_INVALID_PARAM, TRANS_CTRL, "param invalid");
187 int32_t ret = P2pDirectChannelInit();
188 if (ret != SOFTBUS_OK) {
189 if (ret != SOFTBUS_FUNC_NOT_SUPPORT) {
190 TRANS_LOGE(TRANS_INIT, "init p2p direct channel failed");
191 return ret;
192 }
193 TRANS_LOGW(TRANS_INIT, "p2p direct channel not support.");
194 }
195
196 ret = TransSrvDataListInit();
197 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret,
198 TRANS_INIT, "init srv trans tcp direct databuf list failed");
199
200 ret = TransTdcSetCallBack(cb);
201 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_INIT, "set srv trans tcp dierct call failed");
202
203 ret = RegisterTimeoutCallback(SOFTBUS_TCP_DIRECTCHANNEL_TIMER_FUN, TransTdcTimerProc);
204 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_INIT, "RegisterTimeoutCallback failed");
205
206 ret = CreatSessionConnList();
207 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_INIT, "CreatSessionConnList failed");
208
209 ret = CreateTcpChannelInfoList();
210 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_INIT, "CreateTcpChannelInfoList failed");
211
212 return SOFTBUS_OK;
213 }
214
TransTcpDirectDeinit(void)215 void TransTcpDirectDeinit(void)
216 {
217 (void)RegisterTimeoutCallback(SOFTBUS_TCP_DIRECTCHANNEL_TIMER_FUN, NULL);
218 TransSrvDataListDeinit();
219 }
220
TransTdcDeathCallback(const char * pkgName,int32_t pid)221 void TransTdcDeathCallback(const char *pkgName, int32_t pid)
222 {
223 if (pkgName == NULL) {
224 TRANS_LOGE(TRANS_CTRL, "param invalid");
225 return;
226 }
227
228 SessionConn *item = NULL;
229 SessionConn *nextItem = NULL;
230 if (GetSessionConnLock() != SOFTBUS_OK) {
231 TRANS_LOGE(TRANS_CTRL, "get session conn lock failed");
232 return;
233 }
234 SoftBusList *sessionList = GetSessionConnList();
235 if (sessionList == NULL) {
236 TRANS_LOGE(TRANS_CTRL, "get session conn list failed");
237 ReleaseSessionConnLock();
238 return;
239 }
240 LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &sessionList->list, SessionConn, node) {
241 if ((strcmp(item->appInfo.myData.pkgName, pkgName) == 0) && (item->appInfo.myData.pid == pid)) {
242 ListDelete(&item->node);
243 char *anonymizePkgName = NULL;
244 Anonymize(pkgName, &anonymizePkgName);
245 TRANS_LOGI(TRANS_CTRL, "delete pkgName=%{public}s, pid=%{public}d", anonymizePkgName, pid);
246 AnonymizeFree(anonymizePkgName);
247 sessionList->cnt--;
248 DelTrigger(item->listenMod, item->appInfo.fd, RW_TRIGGER);
249 TransTdcSocketReleaseFd(item->listenMod, item->appInfo.fd);
250 SoftBusFree(item);
251 continue;
252 }
253 }
254 ReleaseSessionConnLock();
255 }
256
TransUpdateAppInfo(AppInfo * appInfo,const ConnectOption * connInfo)257 static int32_t TransUpdateAppInfo(AppInfo *appInfo, const ConnectOption *connInfo)
258 {
259 appInfo->peerData.port = connInfo->socketOption.port;
260 if (strcpy_s(appInfo->peerData.addr, sizeof(appInfo->peerData.addr), connInfo->socketOption.addr) != EOK) {
261 TRANS_LOGE(TRANS_CTRL, "strcpy_s remote ip fail.");
262 return SOFTBUS_STRCPY_ERR;
263 }
264 appInfo->routeType = connInfo->type == CONNECT_TCP ? WIFI_STA : WIFI_P2P;
265 appInfo->protocol = connInfo->socketOption.protocol;
266 if (connInfo->socketOption.protocol == LNN_PROTOCOL_NIP) {
267 if (LnnGetLocalStrInfo(STRING_KEY_NODE_ADDR, appInfo->myData.addr, sizeof(appInfo->myData.addr)) !=
268 SOFTBUS_OK) {
269 TRANS_LOGE(TRANS_CTRL, "Lnn: get local ip fail.");
270 return SOFTBUS_TRANS_GET_LOCAL_IP_FAILED;
271 }
272 } else {
273 if (connInfo->type == CONNECT_TCP) {
274 if (LnnGetLocalStrInfo(STRING_KEY_WLAN_IP, appInfo->myData.addr, sizeof(appInfo->myData.addr)) !=
275 SOFTBUS_OK) {
276 TRANS_LOGE(TRANS_CTRL, "Lnn: get local ip fail.");
277 return SOFTBUS_TRANS_GET_LOCAL_IP_FAILED;
278 }
279 }
280 }
281 return SOFTBUS_OK;
282 }
283
TransOpenDirectChannel(AppInfo * appInfo,const ConnectOption * connInfo,int32_t * channelId)284 int32_t TransOpenDirectChannel(AppInfo *appInfo, const ConnectOption *connInfo, int32_t *channelId)
285 {
286 TRANS_LOGD(TRANS_CTRL, "enter.");
287 if (appInfo == NULL || connInfo == NULL || channelId == NULL) {
288 return SOFTBUS_INVALID_PARAM;
289 }
290 int32_t ret = TransUpdateAppInfo(appInfo, connInfo);
291 if (ret != SOFTBUS_OK) {
292 TRANS_LOGE(TRANS_CTRL, "udp app fail");
293 return ret;
294 }
295 if (connInfo->type == CONNECT_P2P || connInfo->type == CONNECT_HML) {
296 appInfo->routeType = WIFI_P2P;
297 ret = OpenP2pDirectChannel(appInfo, connInfo, channelId);
298 } else if (connInfo->type == CONNECT_P2P_REUSE) {
299 appInfo->routeType = WIFI_P2P_REUSE;
300 ret = OpenTcpDirectChannel(appInfo, connInfo, channelId);
301 } else {
302 appInfo->routeType = WIFI_STA;
303 ret = OpenTcpDirectChannel(appInfo, connInfo, channelId);
304 }
305
306 ConnectType connType = connInfo->type;
307 if (connType == CONNECT_P2P_REUSE) {
308 connType = (IsHmlIpAddr(appInfo->myData.addr)) ? CONNECT_HML : CONNECT_P2P;
309 }
310 TransEventExtra extra = {
311 .peerNetworkId = NULL,
312 .calleePkg = NULL,
313 .callerPkg = NULL,
314 .linkType = connType,
315 .channelType = CHANNEL_TYPE_TCP_DIRECT,
316 .channelId = *channelId,
317 .errcode = ret,
318 .socketName = appInfo->myData.sessionName,
319 .result = (ret == SOFTBUS_OK) ? EVENT_STAGE_RESULT_OK : EVENT_STAGE_RESULT_FAILED
320 };
321 SessionConn conn;
322 if (GetSessionConnById(*channelId, &conn) == SOFTBUS_OK) {
323 extra.authId = conn.authHandle.authId;
324 extra.socketFd = conn.appInfo.fd;
325 extra.requestId = (int32_t)conn.requestId;
326 };
327 (void)memset_s(conn.appInfo.sessionKey, sizeof(conn.appInfo.sessionKey), 0, sizeof(conn.appInfo.sessionKey));
328 TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL, EVENT_STAGE_START_CONNECT, extra);
329 return ret;
330 }
331