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