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