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 }