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 }