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_query.h"
17
18 #include <securec.h>
19 #include "bus_center_info_key.h"
20 #include "bus_center_manager.h"
21 #include "lnn_distributed_net_ledger.h"
22 #include "lnn_feature_capability.h"
23 #include "lnn_lane_communication_capability.h"
24 #include "lnn_local_net_ledger.h"
25 #include "lnn_log.h"
26 #include "lnn_lane_link.h"
27 #include "softbus_bus_center.h"
28 #include "softbus_error_code.h"
29 #include "softbus_wifi_api_adapter.h"
30 #include "wifi_direct_manager.h"
31
32 #define QOS_MIN_BANDWIDTH (384 * 1024)
33 #define QOS_P2P_ONLY_BANDWIDTH (160 * 1024 * 1024)
34
35 typedef struct {
36 bool available;
37 int32_t (*QueryLink)(const char *networkId);
38 } LinkState;
39
GetFileLaneLink(LaneLinkType * linkList,uint32_t * listNum,bool isHighBand)40 static void GetFileLaneLink(LaneLinkType *linkList, uint32_t *listNum, bool isHighBand)
41 {
42 linkList[(*listNum)++] = LANE_HML;
43 linkList[(*listNum)++] = LANE_WLAN_5G;
44 linkList[(*listNum)++] = LANE_WLAN_2P4G;
45 linkList[(*listNum)++] = LANE_P2P;
46 if (!isHighBand) {
47 linkList[(*listNum)++] = LANE_BR;
48 }
49 }
50
GetStreamLaneLink(LaneLinkType * linkList,uint32_t * listNum,bool isHighBand)51 static void GetStreamLaneLink(LaneLinkType *linkList, uint32_t *listNum, bool isHighBand)
52 {
53 linkList[(*listNum)++] = LANE_HML;
54 linkList[(*listNum)++] = LANE_WLAN_5G;
55 linkList[(*listNum)++] = LANE_WLAN_2P4G;
56 linkList[(*listNum)++] = LANE_P2P;
57 }
58
GetMsgLaneLink(LaneLinkType * linkList,uint32_t * listNum,bool isHighBand)59 static void GetMsgLaneLink(LaneLinkType *linkList, uint32_t *listNum, bool isHighBand)
60 {
61 linkList[(*listNum)++] = LANE_HML;
62 linkList[(*listNum)++] = LANE_WLAN_5G;
63 linkList[(*listNum)++] = LANE_WLAN_2P4G;
64 linkList[(*listNum)++] = LANE_P2P;
65 if (!isHighBand) {
66 linkList[(*listNum)++] = LANE_BLE;
67 linkList[(*listNum)++] = LANE_BR;
68 }
69 }
70
GetBytesLaneLink(LaneLinkType * linkList,uint32_t * listNum,bool isHighBand)71 static void GetBytesLaneLink(LaneLinkType *linkList, uint32_t *listNum, bool isHighBand)
72 {
73 linkList[(*listNum)++] = LANE_HML;
74 linkList[(*listNum)++] = LANE_WLAN_5G;
75 linkList[(*listNum)++] = LANE_WLAN_2P4G;
76 linkList[(*listNum)++] = LANE_P2P;
77 if (!isHighBand) {
78 linkList[(*listNum)++] = LANE_BLE;
79 linkList[(*listNum)++] = LANE_BR;
80 }
81 }
82
GetLaneResource(LaneTransType transType,LaneLinkType * optLink,uint32_t * linkNum,bool isHighBand)83 static int32_t GetLaneResource(LaneTransType transType, LaneLinkType *optLink, uint32_t *linkNum,
84 bool isHighBand)
85 {
86 LaneLinkType defaultLink[LANE_LINK_TYPE_BUTT];
87 (void)memset_s(defaultLink, sizeof(defaultLink), -1, sizeof(defaultLink));
88 uint32_t optLinkMaxNum = *linkNum;
89 uint32_t index = 0;
90 switch (transType) {
91 case LANE_T_MSG:
92 GetMsgLaneLink(defaultLink, &index, isHighBand);
93 break;
94 case LANE_T_BYTE:
95 GetBytesLaneLink(defaultLink, &index, isHighBand);
96 break;
97 case LANE_T_FILE:
98 GetFileLaneLink(defaultLink, &index, isHighBand);
99 break;
100 case LANE_T_RAW_STREAM:
101 case LANE_T_COMMON_VIDEO:
102 case LANE_T_COMMON_VOICE:
103 GetStreamLaneLink(defaultLink, &index, isHighBand);
104 break;
105 default:
106 LNN_LOGE(LNN_LANE, "lane type is not supported, transType=%{public}d", transType);
107 return SOFTBUS_INVALID_PARAM;
108 }
109 *linkNum = 0;
110 if (memcpy_s(optLink, optLinkMaxNum * sizeof(LaneLinkType), defaultLink, sizeof(defaultLink)) != EOK) {
111 LNN_LOGE(LNN_LANE, "memcpy default linkList to optinal fail");
112 return SOFTBUS_MEM_ERR;
113 }
114 *linkNum = index;
115 return SOFTBUS_OK;
116 }
117
GetNetCap(const char * networkId,uint32_t * local,uint32_t * remote)118 static bool GetNetCap(const char *networkId, uint32_t *local, uint32_t *remote)
119 {
120 int32_t ret = LnnGetLocalNumU32Info(NUM_KEY_NET_CAP, local);
121 if (ret != SOFTBUS_OK) {
122 LNN_LOGE(LNN_LANE, "LnnGetLocalNumInfo err, ret=%{public}d", ret);
123 return false;
124 }
125 ret = LnnGetRemoteNumU32Info(networkId, NUM_KEY_NET_CAP, remote);
126 if (ret != SOFTBUS_OK) {
127 LNN_LOGE(LNN_LANE, "LnnGetRemoteNumInfo err, ret=%{public}d", ret);
128 return false;
129 }
130 return true;
131 }
132
BrLinkState(const char * networkId)133 static int32_t BrLinkState(const char *networkId)
134 {
135 uint32_t local = 0;
136 uint32_t remote = 0;
137 if (!GetNetCap(networkId, &local, &remote)) {
138 LNN_LOGE(LNN_LANE, "GetNetCap error");
139 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
140 }
141 if (!(local & (1 << BIT_BR))) {
142 LNN_LOGE(LNN_LANE, "local bluetooth close, local=%{public}u", local);
143 return SOFTBUS_BLUETOOTH_OFF;
144 }
145 if (!(remote & (1 << BIT_BR))) {
146 LNN_LOGE(LNN_LANE, "remote bluetooth close, remote=%{public}u", remote);
147 return SOFTBUS_BLUETOOTH_OFF;
148 }
149 LNN_LOGI(LNN_LANE, "br link ok, local=%{public}u, remote=%{public}u", local, remote);
150 return SOFTBUS_OK;
151 }
152
BleLinkState(const char * networkId)153 static int32_t BleLinkState(const char *networkId)
154 {
155 uint32_t local = 0;
156 uint32_t remote = 0;
157 if (!GetNetCap(networkId, &local, &remote)) {
158 LNN_LOGE(LNN_LANE, "GetNetCap error");
159 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
160 }
161 if (!(local & (1 << BIT_BLE))) {
162 LNN_LOGE(LNN_LANE, "local bluetooth close, local=%{public}u", local);
163 return SOFTBUS_BLUETOOTH_OFF;
164 }
165 if (!(remote & (1 << BIT_BLE))) {
166 LNN_LOGE(LNN_LANE, "remote bluetooth close, remote=%{public}u", remote);
167 return SOFTBUS_BLUETOOTH_OFF;
168 }
169 LNN_LOGI(LNN_LANE, "ble link ok, local=%{public}u, remote=%{public}u", local, remote);
170 return SOFTBUS_OK;
171 }
172
WlanLinkState(const char * networkId)173 static int32_t WlanLinkState(const char *networkId)
174 {
175 if (!SoftBusIsWifiActive()) {
176 return SOFTBUS_WIFI_OFF;
177 }
178 NodeInfo node;
179 (void)memset_s(&node, sizeof(NodeInfo), 0, sizeof(NodeInfo));
180 if (LnnGetRemoteNodeInfoById(networkId, CATEGORY_NETWORK_ID, &node) != SOFTBUS_OK) {
181 LNN_LOGE(LNN_LANE, "get remote node info fail");
182 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
183 }
184 if (!LnnHasDiscoveryType(&node, DISCOVERY_TYPE_WIFI) && !LnnHasDiscoveryType(&node, DISCOVERY_TYPE_LSA)) {
185 LNN_LOGE(LNN_LANE, "peer node not wifi online");
186 return SOFTBUS_NETWORK_NODE_OFFLINE;
187 }
188 uint32_t local = 0;
189 uint32_t remote = 0;
190 if (!GetNetCap(networkId, &local, &remote)) {
191 LNN_LOGE(LNN_LANE, "GetNetCap error");
192 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
193 }
194 if (!(local & (1 << BIT_WIFI))) {
195 LNN_LOGE(LNN_LANE, "local wifi close, local=%{public}u", local);
196 return SOFTBUS_WIFI_DISCONNECT;
197 }
198 if (!(remote & (1 << BIT_WIFI))) {
199 LNN_LOGE(LNN_LANE, "remote wifi close, remote=%{public}u", remote);
200 return SOFTBUS_WIFI_DISCONNECT;
201 }
202 LNN_LOGI(LNN_LANE, "wifi link ok, local=%{public}u, remote=%{public}u", local, remote);
203 return SOFTBUS_OK;
204 }
205
P2pLinkState(const char * networkId)206 static int32_t P2pLinkState(const char *networkId)
207 {
208 struct WifiDirectManager *pManager = GetWifiDirectManager();
209 if (pManager == NULL) {
210 LNN_LOGE(LNN_LANE, "not support wifi direct");
211 return SOFTBUS_P2P_NOT_SUPPORT;
212 }
213 SoftBusWifiDetailState wifiState = SoftBusGetWifiState();
214 if (wifiState == SOFTBUS_WIFI_STATE_INACTIVE || wifiState == SOFTBUS_WIFI_STATE_DEACTIVATING) {
215 return SOFTBUS_WIFI_OFF;
216 }
217 uint32_t local = 0;
218 uint32_t remote = 0;
219 if (!GetNetCap(networkId, &local, &remote)) {
220 LNN_LOGE(LNN_LANE, "GetNetCap error");
221 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
222 }
223 if (((local & (1 << BIT_WIFI_P2P)) == 0) || ((remote & (1 << BIT_WIFI_P2P)) == 0)) {
224 LNN_LOGE(LNN_LANE, "p2p capa disable, local=%{public}u, remote=%{public}u", local, remote);
225 return SOFTBUS_P2P_NOT_SUPPORT;
226 }
227 int32_t ret = pManager->prejudgeAvailability(networkId, WIFI_DIRECT_LINK_TYPE_P2P);
228 if (ret == V1_ERROR_GC_CONNECTED_TO_ANOTHER_DEVICE) {
229 return SOFTBUS_P2P_ROLE_CONFLICT;
230 }
231 return ret;
232 }
233
HmlLinkState(const char * networkId)234 static int32_t HmlLinkState(const char *networkId)
235 {
236 struct WifiDirectManager *pManager = GetWifiDirectManager();
237 if (pManager == NULL) {
238 LNN_LOGE(LNN_LANE, "not support wifi direct");
239 return SOFTBUS_HML_NOT_SUPPORT;
240 }
241 SoftBusWifiDetailState wifiState = SoftBusGetWifiState();
242 if (wifiState == SOFTBUS_WIFI_STATE_INACTIVE || wifiState == SOFTBUS_WIFI_STATE_DEACTIVATING) {
243 return SOFTBUS_WIFI_OFF;
244 }
245 uint64_t feature = LnnGetFeatureCapabilty();
246 if (!IsFeatureSupport(feature, BIT_WIFI_DIRECT_TLV_NEGOTIATION)) {
247 LNN_LOGE(LNN_LANE, "local feature not supported");
248 return SOFTBUS_HML_NOT_SUPPORT;
249 }
250 bool result = false;
251 if (LnnGetRemoteBoolInfo(networkId, BOOL_KEY_TLV_NEGOTIATION, &result) != SOFTBUS_OK) {
252 LNN_LOGE(LNN_LANE, "get remote feature failed");
253 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
254 }
255 if (!result) {
256 LNN_LOGE(LNN_LANE, "remote feature not supported");
257 return SOFTBUS_HML_NOT_SUPPORT;
258 }
259 int32_t ret = pManager->prejudgeAvailability(networkId, WIFI_DIRECT_LINK_TYPE_HML);
260 if (ret == ERROR_LOCAL_THREE_VAP_CONFLICT) {
261 return SOFTBUS_HML_THREE_VAP_CONFLIC;
262 }
263 return ret;
264 }
265
UsbLinkState(const char * networkId)266 static int32_t UsbLinkState(const char *networkId)
267 {
268 NodeInfo node;
269 (void)memset_s(&node, sizeof(NodeInfo), 0, sizeof(NodeInfo));
270 if (LnnGetRemoteNodeInfoById(networkId, CATEGORY_NETWORK_ID, &node) != SOFTBUS_OK) {
271 LNN_LOGE(LNN_LANE, "get remote node info fail");
272 return SOFTBUS_LANE_GET_LEDGER_INFO_ERR;
273 }
274 if (!LnnHasDiscoveryType(&node, DISCOVERY_TYPE_USB)) {
275 LNN_LOGE(LNN_LANE, "peer node not USB online");
276 return SOFTBUS_NETWORK_NODE_OFFLINE;
277 }
278
279 int32_t ret = CheckStaticNetCap(networkId, LANE_USB);
280 if (ret != SOFTBUS_OK) {
281 LNN_LOGE(LNN_LANE, "check static capability fail, errorCode: %{public}d", ret);
282 return ret;
283 }
284
285 ret = CheckDynamicNetCap(networkId, LANE_USB);
286 if (ret != SOFTBUS_OK) {
287 LNN_LOGE(LNN_LANE, "check dynamic capability fail, errorCode: %{public}d", ret);
288 return ret;
289 }
290 LNN_LOGI(LNN_LANE, "usb link ok");
291 return SOFTBUS_OK;
292 }
293
294 static LinkState g_linkState[LANE_LINK_TYPE_BUTT] = {
295 [LANE_BR] = {true, BrLinkState},
296 [LANE_BLE] = { true, BleLinkState},
297 [LANE_WLAN_2P4G] = { true, WlanLinkState},
298 [LANE_WLAN_5G] = { true, WlanLinkState},
299 [LANE_P2P] = { true, P2pLinkState},
300 [LANE_HML] = { true, HmlLinkState},
301 [LANE_USB] = { true, UsbLinkState},
302 };
303
IsValidLaneLink(const char * networkId,LaneLinkType linkType)304 static int32_t IsValidLaneLink(const char *networkId, LaneLinkType linkType)
305 {
306 if ((linkType < 0) || (linkType >= LANE_LINK_TYPE_BUTT)) {
307 LNN_LOGE(LNN_LANE, "invalid linkType=%{public}d", linkType);
308 return SOFTBUS_INVALID_PARAM;
309 }
310 if (!g_linkState[linkType].available) {
311 LNN_LOGE(LNN_LANE, "invalid QueryLink, linkType=%{public}d", linkType);
312 return SOFTBUS_INVALID_PARAM;
313 }
314 if (g_linkState[linkType].QueryLink == NULL) {
315 LNN_LOGE(LNN_LANE, "invalid QueryLink, linkType=%{public}d", linkType);
316 return SOFTBUS_INVALID_PARAM;
317 }
318 return g_linkState[linkType].QueryLink(networkId);
319 }
320
isHighRequire(const QosInfo * qosInfo,bool * isHighBand)321 static bool isHighRequire(const QosInfo *qosInfo, bool *isHighBand)
322 {
323 if (qosInfo->minBW > QOS_MIN_BANDWIDTH) {
324 *isHighBand = true;
325 return true;
326 } else {
327 *isHighBand = false;
328 return true;
329 }
330 return false;
331 }
332
QueryByRequireLink(const LaneQueryInfo * queryInfo,const QosInfo * qosInfo)333 static int32_t QueryByRequireLink(const LaneQueryInfo *queryInfo, const QosInfo *qosInfo)
334 {
335 if (qosInfo->minBW == QOS_P2P_ONLY_BANDWIDTH) {
336 return IsValidLaneLink(queryInfo->networkId, LANE_P2P);
337 }
338 bool isHighBand = false;
339 if (!isHighRequire(qosInfo, &isHighBand)) {
340 LNN_LOGE(LNN_LANE, "set param failed");
341 return SOFTBUS_INVALID_PARAM;
342 }
343 LaneLinkType optLink[LANE_LINK_TYPE_BUTT];
344 (void)memset_s(optLink, sizeof(optLink), 0, sizeof(optLink));
345 uint32_t linkNum = LANE_LINK_TYPE_BUTT;
346 int32_t ret = GetLaneResource(queryInfo->transType, optLink, &linkNum, isHighBand);
347 if (ret != SOFTBUS_OK) {
348 LNN_LOGE(LNN_LANE, "get defaultLinkList fail");
349 return ret;
350 }
351 for (uint32_t i = 0; i < linkNum; i++) {
352 ret = IsValidLaneLink(queryInfo->networkId, optLink[i]);
353 if (ret == SOFTBUS_OK) {
354 LNN_LOGI(LNN_LANE, "high require get enable Link, linktype=%{public}d", optLink[i]);
355 return ret;
356 }
357 }
358 return ret;
359 }
360
QueryByDefaultLink(const LaneQueryInfo * queryInfo)361 static int32_t QueryByDefaultLink(const LaneQueryInfo *queryInfo)
362 {
363 LaneLinkType optLink[LANE_LINK_TYPE_BUTT];
364 (void)memset_s(optLink, sizeof(optLink), 0, sizeof(optLink));
365 uint32_t linkNum = LANE_LINK_TYPE_BUTT;
366 int32_t ret = GetLaneResource(queryInfo->transType, optLink, &linkNum, false);
367 if (ret != SOFTBUS_OK) {
368 LNN_LOGE(LNN_LANE, "get defaultLinkList fail");
369 return ret;
370 }
371 for (uint32_t i = 0; i < linkNum; i++) {
372 ret = IsValidLaneLink(queryInfo->networkId, optLink[i]);
373 if (ret == SOFTBUS_OK) {
374 LNN_LOGI(LNN_LANE, "default get enable Link, linktype=%{public}d", optLink[i]);
375 return ret;
376 }
377 }
378 return ret;
379 }
380
QueryLaneResource(const LaneQueryInfo * queryInfo,const QosInfo * qosInfo)381 int32_t QueryLaneResource(const LaneQueryInfo *queryInfo, const QosInfo *qosInfo)
382 {
383 if (queryInfo == NULL || qosInfo == NULL) {
384 LNN_LOGE(LNN_LANE, "invalid param");
385 return SOFTBUS_INVALID_PARAM;
386 }
387 if (qosInfo->minBW > 0) {
388 LNN_LOGI(LNN_LANE, "Query lane by prefer linklist, transType=%{public}d, minBW=%{public}d",
389 queryInfo->transType, qosInfo->minBW);
390 return QueryByRequireLink(queryInfo, qosInfo);
391 } else {
392 LNN_LOGI(LNN_LANE, "Query lane by default linklist, transType=%{public}d", queryInfo->transType);
393 return QueryByDefaultLink(queryInfo);
394 }
395 }