1 /*
2  * Copyright (c) 2023 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 "lnn_lane_reliability.h"
17 
18 #include <securec.h>
19 #include <string.h>
20 #include "bus_center_manager.h"
21 #include "lnn_lane_link.h"
22 #include "lnn_log.h"
23 #include "lnn_trans_lane.h"
24 #include "softbus_adapter_mem.h"
25 #include "softbus_base_listener.h"
26 #include "softbus_conn_interface.h"
27 #include "softbus_errcode.h"
28 #include "softbus_socket.h"
29 
30 #define WLAN_DETECT_TIMEOUT 3000
31 
32 typedef struct {
33     ListNode node;
34     LaneLinkInfo link;
35     uint32_t laneReqId;
36     LaneLinkCb cb;
37     union {
38         uint32_t wlanFd;
39     } connId;
40     uint32_t laneDetectId;
41 } LaneDetectInfo;
42 
43 static SoftBusList g_laneDetectList;
44 
GetSameLaneDetectInfo(LaneDetectInfo * infoItem)45 static int32_t GetSameLaneDetectInfo(LaneDetectInfo *infoItem)
46 {
47     if (SoftBusMutexLock(&g_laneDetectList.lock) != SOFTBUS_OK) {
48         return SOFTBUS_LOCK_ERR;
49     }
50     LaneDetectInfo *item = NULL;
51     LaneDetectInfo *next = NULL;
52     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_laneDetectList.list, LaneDetectInfo, node) {
53         switch (infoItem->link.type) {
54             case LANE_WLAN_2P4G:
55             case LANE_WLAN_5G:
56                 if ((strncmp(infoItem->link.linkInfo.wlan.connInfo.addr,
57                     item->link.linkInfo.wlan.connInfo.addr, MAX_SOCKET_ADDR_LEN) == 0) &&
58                     (infoItem->link.linkInfo.wlan.connInfo.port ==
59                     item->link.linkInfo.wlan.connInfo.port)) {
60                     infoItem->connId.wlanFd = item->connId.wlanFd;
61                     infoItem->laneDetectId = item->laneDetectId;
62                     ListTailInsert(&g_laneDetectList.list, &infoItem->node);
63                     SoftBusMutexUnlock(&g_laneDetectList.lock);
64                     return SOFTBUS_OK;
65                 }
66                 break;
67             default:
68                 break;
69         }
70     }
71     SoftBusMutexUnlock(&g_laneDetectList.lock);
72     return SOFTBUS_LANE_NOT_FOUND;
73 }
74 
ClientConnectTcp(LaneDetectInfo * infoItem)75 static int32_t ClientConnectTcp(LaneDetectInfo *infoItem)
76 {
77     ConnectOption option = {
78         .type = CONNECT_TCP,
79         .socketOption = {
80             .addr = "",
81             .port = infoItem->link.linkInfo.wlan.connInfo.port,
82             .moduleId = LANE,
83             .protocol = LNN_PROTOCOL_IP
84         }
85     };
86     if (strncpy_s(option.socketOption.addr, MAX_SOCKET_ADDR_LEN,
87         infoItem->link.linkInfo.wlan.connInfo.addr, MAX_SOCKET_ADDR_LEN) != EOK) {
88         return SOFTBUS_MEM_ERR;
89     }
90     char localIp[IP_LEN] = {0};
91     int32_t fd = SOFTBUS_INVALID_FD;
92     if (LnnGetLocalStrInfo(STRING_KEY_WLAN_IP, localIp, IP_LEN) != SOFTBUS_OK) {
93         LNN_LOGE(LNN_LANE, "get local ip fail");
94         fd = ConnOpenClientSocket(&option, BIND_ADDR_ALL, true);
95     } else {
96         fd = ConnOpenClientSocket(&option, localIp, true);
97     }
98     if (fd < 0) {
99         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
100     }
101     return fd;
102 }
103 
DelLaneDetectInfo(uint32_t detectId)104 static void DelLaneDetectInfo(uint32_t detectId)
105 {
106     if (SoftBusMutexLock(&g_laneDetectList.lock) != SOFTBUS_OK) {
107         return;
108     }
109     LaneDetectInfo *item = NULL;
110     LaneDetectInfo *next = NULL;
111     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_laneDetectList.list, LaneDetectInfo, node) {
112         if (item->laneDetectId == detectId) {
113             ListDelete(&item->node);
114             SoftBusFree(item);
115         }
116     }
117     SoftBusMutexUnlock(&g_laneDetectList.lock);
118 }
119 
GetLaneDetectInfoByWlanFd(uint32_t fd,LaneDetectInfo * infoItem)120 static int32_t GetLaneDetectInfoByWlanFd(uint32_t fd, LaneDetectInfo *infoItem)
121 {
122     if (SoftBusMutexLock(&g_laneDetectList.lock) != SOFTBUS_OK) {
123         return SOFTBUS_LOCK_ERR;
124     }
125     LaneDetectInfo *item = NULL;
126     LaneDetectInfo *next = NULL;
127     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_laneDetectList.list, LaneDetectInfo, node) {
128         if (item->connId.wlanFd == fd) {
129             if (memcpy_s(infoItem, sizeof(LaneDetectInfo), item,
130                 sizeof(LaneDetectInfo)) != EOK) {
131                 SoftBusMutexUnlock(&g_laneDetectList.lock);
132                 return SOFTBUS_MEM_ERR;
133             }
134             SoftBusMutexUnlock(&g_laneDetectList.lock);
135             return SOFTBUS_OK;
136         }
137     }
138     SoftBusMutexUnlock(&g_laneDetectList.lock);
139     return SOFTBUS_LANE_NOT_FOUND;
140 }
141 
AddLaneTriggerAndTimeOut(int32_t fd,uint32_t detectId)142 static int32_t AddLaneTriggerAndTimeOut(int32_t fd, uint32_t detectId)
143 {
144     int32_t ret = PostDetectTimeoutMessage(detectId, WLAN_DETECT_TIMEOUT);
145     if (ret != SOFTBUS_OK) {
146         LNN_LOGE(LNN_LANE, "wlan detect post timeout message fail, detectId=%{public}u", detectId);
147         return ret;
148     }
149     ret = AddTrigger(LANE, fd, WRITE_TRIGGER);
150     if (ret != SOFTBUS_OK) {
151         LNN_LOGE(LNN_LANE, "wlan detect add trigger fail, detectId=%{public}u, fd=%{public}d", detectId, fd);
152         RemoveDetectTimeoutMessage(detectId);
153         return ret;
154     }
155     return SOFTBUS_OK;
156 }
157 
158 static uint32_t g_ReqId = 0;
159 
GetLaneDetectIdWithoutLock()160 static uint32_t GetLaneDetectIdWithoutLock()
161 {
162 #define REQID_MAX 1000000
163     g_ReqId = g_ReqId % REQID_MAX + 1;
164     uint32_t reqId = g_ReqId;
165     return reqId;
166 }
167 
WlanDetectReliability(uint32_t laneReqId,const LaneLinkInfo * laneInfo,const LaneLinkCb * callback)168 static int32_t WlanDetectReliability(uint32_t laneReqId, const LaneLinkInfo *laneInfo, const LaneLinkCb *callback)
169 {
170     LaneDetectInfo *infoItem = (LaneDetectInfo *)SoftBusMalloc(sizeof(LaneDetectInfo));
171     if (infoItem == NULL) {
172         return SOFTBUS_MALLOC_ERR;
173     }
174     infoItem->laneReqId = laneReqId;
175     if (memcpy_s(&infoItem->cb, sizeof(LaneLinkCb), callback, sizeof(LaneLinkCb)) != EOK) {
176         SoftBusFree(infoItem);
177         return SOFTBUS_MEM_ERR;
178     }
179     if (memcpy_s(&(infoItem->link), sizeof(LaneLinkInfo), laneInfo, sizeof(LaneLinkInfo)) != EOK) {
180         SoftBusFree(infoItem);
181         return SOFTBUS_MEM_ERR;
182     }
183     if (GetSameLaneDetectInfo(infoItem) == SOFTBUS_OK) {
184         LNN_LOGI(LNN_LANE, "wlan reuse detectId=%{public}u, laneReqId=%{public}u", infoItem->laneDetectId,
185             infoItem->laneReqId);
186         return SOFTBUS_OK;
187     }
188     int32_t fd = ClientConnectTcp(infoItem);
189     if (fd < 0) {
190         LNN_LOGE(LNN_LANE, "wlan detect connect fail, port=%{public}d, laneReqId=%{public}u",
191             infoItem->link.linkInfo.wlan.connInfo.port, infoItem->laneReqId);
192         SoftBusFree(infoItem);
193         return fd;
194     }
195     infoItem->connId.wlanFd = (uint32_t)fd;
196     if (SoftBusMutexLock(&g_laneDetectList.lock) != SOFTBUS_OK) {
197         ConnShutdownSocket(fd);
198         SoftBusFree(infoItem);
199         return SOFTBUS_LOCK_ERR;
200     }
201     infoItem->laneDetectId = GetLaneDetectIdWithoutLock();
202     ListTailInsert(&g_laneDetectList.list, &infoItem->node);
203     SoftBusMutexUnlock(&g_laneDetectList.lock);
204     int32_t ret = AddLaneTriggerAndTimeOut(fd, infoItem->laneDetectId);
205     if (ret != SOFTBUS_OK) {
206         ConnShutdownSocket(fd);
207         DelLaneDetectInfo(infoItem->laneDetectId);
208         LNN_LOGI(LNN_LANE, "wlan add trigger and timrout msg fail, laneReqId=%{public}u", infoItem->laneDetectId);
209         return ret;
210     }
211     LNN_LOGI(LNN_LANE, "wlan first detectId=%{public}u, fd=%{public}d, laneReqId=%{public}u",
212         infoItem->laneDetectId, fd, infoItem->laneReqId);
213     return SOFTBUS_OK;
214 }
215 
LaneDetectFload(const LaneResource * resourceItem)216 int32_t LaneDetectFload(const LaneResource *resourceItem)
217 {
218     (void)resourceItem;
219     return SOFTBUS_OK;
220 }
221 
LaneDetectOnConnectEvent(ListenerModule module,int32_t cfd,const ConnectOption * clientAddr)222 static int32_t LaneDetectOnConnectEvent(ListenerModule module, int32_t cfd, const ConnectOption *clientAddr)
223 {
224     (void)module;
225     (void)cfd;
226     (void)clientAddr;
227     return SOFTBUS_OK;
228 }
229 
GetAllDetectInfoWithDetectId(uint32_t detectId,ListNode * detectInfoList)230 static int32_t GetAllDetectInfoWithDetectId(uint32_t detectId, ListNode *detectInfoList)
231 {
232     LNN_LOGI(LNN_LANE, "get all detect info, detectId=%{public}u", detectId);
233     if (SoftBusMutexLock(&g_laneDetectList.lock) != SOFTBUS_OK) {
234         return SOFTBUS_LOCK_ERR;
235     }
236     LaneDetectInfo *item = NULL;
237     LaneDetectInfo *next = NULL;
238     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_laneDetectList.list, LaneDetectInfo, node) {
239         if (item->laneDetectId == detectId) {
240             ListDelete(&item->node);
241             ListTailInsert(detectInfoList, &item->node);
242         }
243     }
244     SoftBusMutexUnlock(&g_laneDetectList.lock);
245     return SOFTBUS_OK;
246 }
247 
NotifyWlanDetectResult(LaneDetectInfo * requestItem,bool isSendSuc)248 static int32_t NotifyWlanDetectResult(LaneDetectInfo *requestItem, bool isSendSuc)
249 {
250     ListNode detectInfoList;
251     ListInit(&detectInfoList);
252     int32_t ret = GetAllDetectInfoWithDetectId(requestItem->laneDetectId, &detectInfoList);
253     if (ret != SOFTBUS_OK) {
254         LNN_LOGE(LNN_LANE, "get all detect info fail, detectId=%{public}u", requestItem->laneDetectId);
255         return ret;
256     }
257     LaneDetectInfo *item = NULL;
258     LaneDetectInfo *next = NULL;
259     LIST_FOR_EACH_ENTRY_SAFE(item, next, &detectInfoList, LaneDetectInfo, node) {
260         if (!isSendSuc) {
261             LNN_LOGI(LNN_LANE, "detect failed, wlan=%{public}d, laneReqId=%{public}u, detectId=%{public}u",
262                 item->link.type, item->laneReqId, requestItem->laneDetectId);
263             item->cb.onLaneLinkFail(item->laneReqId, SOFTBUS_CONN_FAIL, item->link.type);
264         } else {
265             LaneLinkInfo laneInfo;
266             (void)memset_s(&laneInfo, sizeof(LaneLinkInfo), 0, sizeof(LaneLinkInfo));
267             if (memcpy_s(&laneInfo, sizeof(LaneLinkInfo), &(item->link), sizeof(LaneLinkInfo)) != EOK) {
268                 LNN_LOGE(LNN_LANE, "memcpy linkinfo failed, laneReqId=%{public}u", item->laneReqId);
269                 ListDelete(&item->node);
270                 SoftBusFree(item);
271                 continue;
272             }
273             LNN_LOGI(LNN_LANE, "detect success, wlan=%{public}d, laneReqId=%{public}u, detectId=%{public}u",
274                 item->link.type, item->laneReqId, requestItem->laneDetectId);
275             item->cb.onLaneLinkSuccess(item->laneReqId, laneInfo.type, &laneInfo);
276         }
277         ListDelete(&item->node);
278         SoftBusFree(item);
279     }
280     return SOFTBUS_OK;
281 }
282 
LaneDetectOnDataEvent(ListenerModule module,int32_t events,int32_t fd)283 static int32_t LaneDetectOnDataEvent(ListenerModule module, int32_t events, int32_t fd)
284 {
285     if (module != LANE) {
286         return SOFTBUS_INVALID_PARAM;
287     }
288     if (events == SOFTBUS_SOCKET_OUT) {
289         LaneDetectInfo requestItem;
290         (void)memset_s(&requestItem, sizeof(LaneDetectInfo), 0, sizeof(LaneDetectInfo));
291         if (GetLaneDetectInfoByWlanFd(fd, &requestItem) != SOFTBUS_OK) {
292             LNN_LOGE(LNN_LANE, "wlan detect info not found by fd=%{public}d", fd);
293             (void)DelTrigger(LANE, fd, WRITE_TRIGGER);
294             ConnShutdownSocket(fd);
295             return SOFTBUS_LANE_NOT_FOUND;
296         }
297         LNN_LOGI(LNN_LANE, "wlan connect success, detectId=%{public}u, fd=%{public}d", requestItem.laneDetectId, fd);
298         (void)DelTrigger(LANE, fd, WRITE_TRIGGER);
299         char buf[] = "lanedetect";
300         ssize_t len = ConnSendSocketData(fd, buf, sizeof(buf), 0);
301         bool isSendSuc = (len == sizeof(buf)) ? true : false;
302         ConnShutdownSocket(fd);
303         RemoveDetectTimeoutMessage(requestItem.laneDetectId);
304         int32_t ret = NotifyWlanDetectResult(&requestItem, isSendSuc);
305         if (ret != SOFTBUS_OK) {
306             LNN_LOGE(LNN_LANE, "wlan notify detect result fail, detectId=%{public}u", requestItem.laneDetectId);
307             return ret;
308         }
309     } else if (events == SOFTBUS_SOCKET_EXCEPTION) {
310         LNN_LOGE(LNN_LANE, "wlan detect socket exception, fd=%{public}d", fd);
311         (void)DelTrigger(LANE, fd, WRITE_TRIGGER);
312         ConnShutdownSocket(fd);
313     }
314     return SOFTBUS_OK;
315 }
316 
LaneDetectReliability(uint32_t laneReqId,const LaneLinkInfo * linkInfo,const LaneLinkCb * callback)317 int32_t LaneDetectReliability(uint32_t laneReqId, const LaneLinkInfo *linkInfo, const LaneLinkCb *callback)
318 {
319     if (laneReqId == INVALID_LANE_REQ_ID || linkInfo == NULL || callback == NULL) {
320         LNN_LOGE(LNN_LANE, "invalid input parameter");
321         return SOFTBUS_INVALID_PARAM;
322     }
323     LNN_LOGI(LNN_LANE, "lane detect start, linktype=%{public}d, laneReqId=%{public}u", linkInfo->type, laneReqId);
324     int32_t result = SOFTBUS_LANE_DETECT_FAIL;
325     switch (linkInfo->type) {
326         case LANE_WLAN_2P4G:
327         case LANE_WLAN_5G:
328             result = WlanDetectReliability(laneReqId, linkInfo, callback);
329             break;
330         default:
331             break;
332     }
333     return result;
334 }
335 
NotifyDetectTimeout(uint32_t detectId)336 void NotifyDetectTimeout(uint32_t detectId)
337 {
338     ListNode detectInfoList;
339     ListInit(&detectInfoList);
340     if (GetAllDetectInfoWithDetectId(detectId, &detectInfoList) != SOFTBUS_OK) {
341         LNN_LOGE(LNN_LANE, "get all detect info fail, detectId=%{public}u", detectId);
342         return;
343     }
344     LaneDetectInfo *item = NULL;
345     LaneDetectInfo *next = NULL;
346     LIST_FOR_EACH_ENTRY_SAFE(item, next, &detectInfoList, LaneDetectInfo, node) {
347         LNN_LOGI(LNN_LANE, "detect timeout, link=%{public}d, laneReqId=%{public}u, detectId=%{public}u",
348             item->link.type, item->laneReqId, item->laneDetectId);
349         item->cb.onLaneLinkFail(item->laneReqId, SOFTBUS_LANE_DETECT_TIMEOUT, item->link.type);
350         ListDelete(&item->node);
351         SoftBusFree(item);
352     }
353 }
354 
InitLaneReliability(void)355 int32_t InitLaneReliability(void)
356 {
357     SoftbusBaseListener listener = {
358         .onConnectEvent = LaneDetectOnConnectEvent,
359         .onDataEvent = LaneDetectOnDataEvent,
360     };
361     int32_t ret = StartBaseClient(LANE, &listener);
362     if (ret != SOFTBUS_OK) {
363         LNN_LOGE(LNN_LANE, "listening fail, moudle=%{public}d ", LANE);
364         return ret;
365     }
366     if (SoftBusMutexInit(&g_laneDetectList.lock, NULL) != SOFTBUS_OK) {
367         return SOFTBUS_NO_INIT;
368     }
369     ListInit(&g_laneDetectList.list);
370     g_laneDetectList.cnt = 0;
371     return SOFTBUS_OK;
372 }
373 
DeinitLaneReliability(void)374 void DeinitLaneReliability(void)
375 {
376     if (SoftBusMutexLock(&g_laneDetectList.lock) != SOFTBUS_OK) {
377         return;
378     }
379     LaneDetectInfo *item = NULL;
380     LaneDetectInfo *next = NULL;
381     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_laneDetectList.list, LaneDetectInfo, node) {
382         ListDelete(&item->node);
383         SoftBusFree(item);
384     }
385     g_laneDetectList.cnt = 0;
386     SoftBusMutexUnlock(&g_laneDetectList.lock);
387     (void)SoftBusMutexDestroy(&g_laneDetectList.lock);
388 }