1 /*
2 * Copyright (c) 2024 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 "inner_link.h"
17
18 #include "securec.h"
19
20 #include "nlohmann/json.hpp"
21
22 #include "conn_log.h"
23 #include "softbus_adapter_timer.h"
24
25 #include "channel/auth_negotiate_channel.h"
26 #include "data/link_manager.h"
27 #include "utils/wifi_direct_anonymous.h"
28 #include "wifi_direct_ip_manager.h"
29
30 namespace OHOS::SoftBus {
InnerLink(const std::string & remoteMac)31 InnerLink::InnerLink(const std::string &remoteMac)
32 {
33 SetRemoteBaseMac(remoteMac);
34 }
35
InnerLink(LinkType type,const std::string & remoteDeviceId)36 InnerLink::InnerLink(LinkType type, const std::string &remoteDeviceId)
37 {
38 SetLinkType(type);
39 SetRemoteDeviceId(remoteDeviceId);
40 }
41
~InnerLink()42 InnerLink::~InnerLink()
43 {
44 auto listenerModuleId = GetListenerModule();
45 bool hasAnotherUsed = false;
46 LinkManager::GetInstance().ForEach([&hasAnotherUsed, this](InnerLink &innerLink) {
47 if (innerLink.GetLinkType() == InnerLink::LinkType::P2P && innerLink.GetLocalIpv4() == this->GetLocalIpv4() &&
48 innerLink.GetRemoteDeviceId() != this->GetRemoteDeviceId()) {
49 hasAnotherUsed = true;
50 }
51 return false;
52 });
53 CONN_LOGI(CONN_WIFI_DIRECT, "hasAnotherUsed=%{public}d", hasAnotherUsed);
54 if (listenerModuleId != UNUSE_BUTT) {
55 CONN_LOGI(CONN_WIFI_DIRECT, "stop auth listening");
56 if (GetLinkType() == LinkType::HML) {
57 AuthNegotiateChannel::StopListening(AUTH_LINK_TYPE_ENHANCED_P2P, listenerModuleId);
58 StopCustomListen(GetLocalCustomPort());
59 } else {
60 if (!hasAnotherUsed) {
61 AuthNegotiateChannel::StopListening(AUTH_LINK_TYPE_P2P, listenerModuleId);
62 }
63 }
64 }
65 if (!GetLocalIpv4().empty() && !GetRemoteIpv4().empty() && !GetRemoteBaseMac().empty() && !hasAnotherUsed &&
66 !GetLegacyReused()) {
67 CONN_LOGI(CONN_WIFI_DIRECT, "release ip");
68 WifiDirectIpManager::GetInstance().ReleaseIpv4(
69 GetLocalInterface(), Ipv4Info(GetLocalIpv4()), Ipv4Info(GetRemoteIpv4()), GetRemoteBaseMac());
70 }
71 }
72
GetLinkType() const73 InnerLink::LinkType InnerLink::GetLinkType() const
74 {
75 return Get(InnerLinKey::LINK_TYPE, LinkType::INVALID_TYPE);
76 }
77
SetLinkType(InnerLink::LinkType type)78 void InnerLink::SetLinkType(InnerLink::LinkType type)
79 {
80 Set(InnerLinKey::LINK_TYPE, type);
81 }
82
GetState() const83 InnerLink::LinkState InnerLink::GetState() const
84 {
85 return Get(InnerLinKey::STATE, LinkState::INVALID_STATE);
86 }
87
SetState(LinkState newState)88 void InnerLink::SetState(LinkState newState)
89 {
90 LinkState oldState = GetState();
91 if (oldState != newState) {
92 uint64_t changeTime = SoftBusGetSysTimeMs();
93 Set(InnerLinKey::STATE_CHANGE_TIME, changeTime);
94 Set(InnerLinKey::STATE, newState);
95 }
96 }
97
GetLocalInterface() const98 std::string InnerLink::GetLocalInterface() const
99 {
100 return Get(InnerLinKey::LOCAL_INTERFACE, std::string(""));
101 }
102
SetLocalInterface(const std::string & interface)103 void InnerLink::SetLocalInterface(const std::string &interface)
104 {
105 Set(InnerLinKey::LOCAL_INTERFACE, interface);
106 }
107
GetLocalBaseMac() const108 std::string InnerLink::GetLocalBaseMac() const
109 {
110 return Get(InnerLinKey::LOCAL_BASE_MAC, std::string(""));
111 }
112
SetLocalBaseMac(const std::string & mac)113 void InnerLink::SetLocalBaseMac(const std::string &mac)
114 {
115 Set(InnerLinKey::LOCAL_BASE_MAC, mac);
116 }
117
GetLocalDynamicMac() const118 std::string InnerLink::GetLocalDynamicMac() const
119 {
120 return Get(InnerLinKey::LOCAL_DYNAMIC_MAC, std::string(""));
121 }
122
SetLocalDynamicMac(const std::string & mac)123 void InnerLink::SetLocalDynamicMac(const std::string &mac)
124 {
125 Set(InnerLinKey::LOCAL_DYNAMIC_MAC, mac);
126 }
127
GetLocalIpv4() const128 std::string InnerLink::GetLocalIpv4() const
129 {
130 return Get(InnerLinKey::LOCAL_IPV4, std::string(""));
131 }
132
SetLocalIpv4(const std::string & ip)133 void InnerLink::SetLocalIpv4(const std::string &ip)
134 {
135 Set(InnerLinKey::LOCAL_IPV4, ip);
136 }
137
GetRemoteInterface() const138 std::string InnerLink::GetRemoteInterface() const
139 {
140 return Get(InnerLinKey::REMOTE_INTERFACE, std::string(""));
141 }
142
SetRemoteInterface(const std::string & interface)143 void InnerLink::SetRemoteInterface(const std::string &interface)
144 {
145 Set(InnerLinKey::REMOTE_INTERFACE, interface);
146 }
147
GetRemoteBaseMac() const148 std::string InnerLink::GetRemoteBaseMac() const
149 {
150 return Get(InnerLinKey::REMOTE_BASE_MAC, std::string(""));
151 }
152
SetRemoteBaseMac(const std::string & mac)153 void InnerLink::SetRemoteBaseMac(const std::string &mac)
154 {
155 Set(InnerLinKey::REMOTE_BASE_MAC, mac);
156 }
157
GetRemoteDynamicMac() const158 std::string InnerLink::GetRemoteDynamicMac() const
159 {
160 return Get(InnerLinKey::REMOTE_DYNAMIC_MAC, std::string(""));
161 }
162
SetRemoteDynamicMac(const std::string & mac)163 void InnerLink::SetRemoteDynamicMac(const std::string &mac)
164 {
165 Set(InnerLinKey::REMOTE_DYNAMIC_MAC, mac);
166 }
167
GetRemoteIpv4() const168 std::string InnerLink::GetRemoteIpv4() const
169 {
170 return Get(InnerLinKey::REMOTE_IPV4, std::string(""));
171 }
172
SetRemoteIpv4(const std::string & ip)173 void InnerLink::SetRemoteIpv4(const std::string &ip)
174 {
175 Set(InnerLinKey::REMOTE_IPV4, ip);
176 }
177
IsBeingUsedByLocal() const178 bool InnerLink::IsBeingUsedByLocal() const
179 {
180 return !linkIds_.empty();
181 }
182
IsBeingUsedByRemote() const183 bool InnerLink::IsBeingUsedByRemote() const
184 {
185 return Get(InnerLinKey::IS_BEING_USED_BY_REMOTE, false);
186 }
187
SetBeingUsedByRemote(bool value)188 void InnerLink::SetBeingUsedByRemote(bool value)
189 {
190 Set(InnerLinKey::IS_BEING_USED_BY_REMOTE, value);
191 }
192
GetFrequency() const193 int InnerLink::GetFrequency() const
194 {
195 return Get(InnerLinKey::FREQUENCY, -1);
196 }
197
SetFrequency(int frequency)198 void InnerLink::SetFrequency(int frequency)
199 {
200 Set(InnerLinKey::FREQUENCY, frequency);
201 }
202
GetRemoteDeviceId() const203 std::string InnerLink::GetRemoteDeviceId() const
204 {
205 return Get(InnerLinKey::REMOTE_DEVICE_ID, std::string(""));
206 }
207
SetRemoteDeviceId(const std::string & deviceId)208 void InnerLink::SetRemoteDeviceId(const std::string &deviceId)
209 {
210 Set(InnerLinKey::REMOTE_DEVICE_ID, deviceId);
211 }
212
GetNegotiateChannel() const213 std::shared_ptr<NegotiateChannel> InnerLink::GetNegotiateChannel() const
214 {
215 return channel_;
216 }
217
SetNegotiateChannel(const std::shared_ptr<NegotiateChannel> & channel)218 void InnerLink::SetNegotiateChannel(const std::shared_ptr<NegotiateChannel> &channel)
219 {
220 channel_ = channel;
221 }
222
GetLocalPort() const223 int InnerLink::GetLocalPort() const
224 {
225 return Get(InnerLinKey::LOCAL_PORT, -1);
226 }
227
SetLocalPort(int port)228 void InnerLink::SetLocalPort(int port)
229 {
230 Set(InnerLinKey::LOCAL_PORT, port);
231 }
232
GetListenerModule() const233 ListenerModule InnerLink::GetListenerModule() const
234 {
235 return Get(InnerLinKey::LISTENER_MODULE_ID, static_cast<ListenerModule>(UNUSE_BUTT));
236 }
237
SetListenerModule(ListenerModule module)238 void InnerLink::SetListenerModule(ListenerModule module)
239 {
240 Set(InnerLinKey::LISTENER_MODULE_ID, module);
241 }
242
GetLocalIpv6() const243 std::string InnerLink::GetLocalIpv6() const
244 {
245 return Get(InnerLinKey::LOCAL_IPV6, std::string());
246 }
247
SetLocalIpv6(const std::string & value)248 void InnerLink::SetLocalIpv6(const std::string &value)
249 {
250 Set(InnerLinKey::LOCAL_IPV6, value);
251 }
252
GetRemoteIpv6() const253 std::string InnerLink::GetRemoteIpv6() const
254 {
255 return Get(InnerLinKey::REMOTE_IPV6, std::string());
256 }
257
SetRemoteIpv6(const std::string & value)258 void InnerLink::SetRemoteIpv6(const std::string &value)
259 {
260 Set(InnerLinKey::REMOTE_IPV6, value);
261 }
262
HasPtk() const263 bool InnerLink::HasPtk() const
264 {
265 return Get(InnerLinKey::HAS_PTK, false);
266 }
267
SetPtk(bool value)268 void InnerLink::SetPtk(bool value)
269 {
270 Set(InnerLinKey::HAS_PTK, value);
271 }
272
GetLocalCustomPort() const273 int32_t InnerLink::GetLocalCustomPort() const
274 {
275 return Get(InnerLinKey::LOCAL_CUSTOM_PORT, 0);
276 }
277
SetLocalCustomPort(int32_t value)278 void InnerLink::SetLocalCustomPort(int32_t value)
279 {
280 Set(InnerLinKey::LOCAL_CUSTOM_PORT, value);
281 }
282
GetRemoteCustomPort() const283 int32_t InnerLink::GetRemoteCustomPort() const
284 {
285 return Get(InnerLinKey::REMOTE_CUSTOM_PORT, 0);
286 }
287
StopCustomListen(int32_t localCustomPort)288 void InnerLink::StopCustomListen(int32_t localCustomPort)
289 {
290 CONN_CHECK_AND_RETURN_LOGE(localCustomPort > 0, CONN_WIFI_DIRECT, "loacl custom port is zero");
291 bool hasMoreLocalCustomPort = false;
292 LinkManager::GetInstance().ForEach([&hasMoreLocalCustomPort] (InnerLink &link) {
293 if (link.GetLocalCustomPort() > 0) {
294 hasMoreLocalCustomPort = true;
295 return true;
296 }
297 return false;
298 });
299 if (!hasMoreLocalCustomPort) {
300 CONN_LOGI(CONN_WIFI_DIRECT, "localCustomPort=%{public}d, stop custom listening", localCustomPort);
301 AuthNegotiateChannel::StopCustomListening();
302 }
303 }
304
SetRemoteCustomPort(int32_t value)305 void InnerLink::SetRemoteCustomPort(int32_t value)
306 {
307 Set(InnerLinKey::REMOTE_CUSTOM_PORT, value);
308 }
309
GetNewPtkFrame() const310 bool InnerLink::GetNewPtkFrame() const
311 {
312 return Get(InnerLinKey::NEW_PTK_FRAME, false);
313 }
314
SetNewPtkFrame(bool value)315 void InnerLink::SetNewPtkFrame(bool value)
316 {
317 Set(InnerLinKey::NEW_PTK_FRAME, value);
318 }
319
GetLegacyReused() const320 bool InnerLink::GetLegacyReused() const
321 {
322 return Get(InnerLinKey::IS_LEGACY_REUSED, false);
323 }
324
SetLegacyReused(bool value)325 void InnerLink::SetLegacyReused(bool value)
326 {
327 CONN_LOGI(CONN_WIFI_DIRECT, "set legacy reused=%{public}d", value);
328 Set(InnerLinKey::IS_LEGACY_REUSED, value);
329 }
330
GenerateLink(uint32_t requestId,int pid,WifiDirectLink & link,bool ipv4)331 void InnerLink::GenerateLink(uint32_t requestId, int pid, WifiDirectLink &link, bool ipv4)
332 {
333 link.linkId = LinkManager::GetInstance().AllocateLinkId();
334 AddId(link.linkId, requestId, pid);
335 switch (GetLinkType()) {
336 case LinkType::HML:
337 link.linkType = WIFI_DIRECT_LINK_TYPE_HML;
338 break;
339 case LinkType::P2P:
340 link.linkType = WIFI_DIRECT_LINK_TYPE_P2P;
341 break;
342 default:
343 link.linkType = WIFI_DIRECT_LINK_TYPE_INVALID;
344 break;
345 }
346 std::string localIp;
347 std::string remoteIp;
348 if (ipv4 || GetLocalIpv6().empty()) {
349 localIp = GetLocalIpv4();
350 remoteIp = GetRemoteIpv4();
351 } else {
352 localIp = GetLocalIpv6();
353 remoteIp = GetRemoteIpv6();
354 }
355 if (strcpy_s(link.localIp, IP_STR_MAX_LEN, localIp.c_str()) != EOK) {
356 CONN_LOGI(CONN_WIFI_DIRECT, "local ip cpy failed, link id=%{public}d", link.linkId);
357 // fall-through
358 }
359 if (strcpy_s(link.remoteIp, IP_STR_MAX_LEN, remoteIp.c_str()) != EOK) {
360 CONN_LOGI(CONN_WIFI_DIRECT, "remote ip cpy failed, link id=%{public}d", link.linkId);
361 // fall-through
362 }
363 link.remotePort = GetRemoteCustomPort();
364 }
365
AddId(int linkId,uint32_t requestId,int pid)366 void InnerLink::AddId(int linkId, uint32_t requestId, int pid)
367 {
368 auto item = std::make_shared<LinkIdStruct>();
369 item->id = linkId;
370 item->requestId = requestId;
371 item->pid = pid;
372 linkIds_[linkId] = item;
373 }
374
RemoveId(int linkId)375 void InnerLink::RemoveId(int linkId)
376 {
377 if (linkIds_.find(linkId) == linkIds_.end()) {
378 return;
379 }
380 linkIds_.erase(linkId);
381 }
382
IsContainId(int linkId) const383 bool InnerLink::IsContainId(int linkId) const
384 {
385 return linkIds_.find(linkId) != linkIds_.end();
386 }
387
GetReference() const388 size_t InnerLink::GetReference() const
389 {
390 return linkIds_.size();
391 }
392
IsProtected() const393 bool InnerLink::IsProtected() const
394 {
395 LinkState state = Get(InnerLinKey::STATE, LinkState::INVALID_STATE);
396 if (state != LinkState::CONNECTED) {
397 CONN_LOGI(CONN_WIFI_DIRECT, "state=%{public}d", static_cast<int>(state));
398 return false;
399 }
400
401 uint64_t currentTime = SoftBusGetSysTimeMs();
402 uint64_t changeTime = Get(InnerLinKey::STATE_CHANGE_TIME, uint64_t(0));
403 if (currentTime && currentTime - PROTECT_DURATION_MS < changeTime) {
404 return true;
405 }
406 return false;
407 }
408
Dump() const409 void InnerLink::Dump() const
410 {
411 nlohmann::json object;
412 object["LINK_TYPE"] = GetLinkType();
413 object["STATE"] = GetState();
414 object["LOCAL_INTERFACE"] = GetLocalInterface();
415 object["LOCAL_BASE_MAC"] = WifiDirectAnonymizeMac(GetLocalBaseMac());
416 object["REMOTE_BASE_MAC"] = WifiDirectAnonymizeMac(GetRemoteBaseMac());
417 object["LOCAL_IPV4"] = WifiDirectAnonymizeIp(GetLocalIpv4());
418 object["REMOTE_IPV4"] = WifiDirectAnonymizeIp(GetRemoteIpv4());
419 object["LOCAL_IPV6"] = WifiDirectAnonymizeIp(GetLocalIpv6());
420 object["REMOTE_IPV6"] = WifiDirectAnonymizeIp(GetRemoteIpv6());
421 object["IS_BEING_USED_BY_LOCAL"] = IsBeingUsedByLocal();
422 object["IS_BEING_USED_BY_REMOTE"] = IsBeingUsedByRemote();
423 object["FREQUENCY"] = GetFrequency();
424 object["REMOTE_DEVICE_ID"] = WifiDirectAnonymizeDeviceId(GetRemoteDeviceId());
425 object["LOCAL_PORT"] = GetLocalPort();
426 object["LISTENER_MODULE_ID"] = GetListenerModule();
427 object["NEGOTIATION_CHANNEL"] = channel_ != nullptr;
428 object["LOCAL_CUSTOM_PORT"] = GetLocalCustomPort();
429 object["REMOTE_CUSTOM_PORT"] = GetRemoteCustomPort();
430
431 auto linkIdArrayObject = nlohmann::json::array();
432 for (const auto &[key, value] : linkIds_) {
433 nlohmann::json linkIdObject;
434 linkIdObject["LinkId"] = key;
435 linkIdObject["RequestId"] = value->requestId;
436 linkIdObject["Pid"] = value->pid;
437 linkIdArrayObject.push_back(linkIdObject);
438 }
439 object["LINKS"] = linkIdArrayObject;
440 CONN_LOGI(CONN_WIFI_DIRECT, "%{public}s", object.dump().c_str());
441 }
442 } // namespace OHOS::SoftBus
443