• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "link_manager.h"
16 
17 #include "conn_log.h"
18 
19 #include "utils/wifi_direct_anonymous.h"
20 #include "wifi_direct_manager.h"
21 
22 namespace OHOS::SoftBus {
AllocateLinkId()23 int LinkManager::AllocateLinkId()
24 {
25     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
26     std::lock_guard lock(lock_);
27     if (currentLinkId_ < 0) {
28         currentLinkId_ = 0;
29     }
30     auto newId = currentLinkId_++;
31     while (GetLinkById(newId) != nullptr) {
32         newId = currentLinkId_++;
33     }
34     return newId;
35 }
36 
GetLinkById(int linkId)37 std::shared_ptr<InnerLink> LinkManager::GetLinkById(int linkId)
38 {
39     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
40     std::lock_guard lock(lock_);
41     for (const auto &link : links_) {
42         if (link.second->IsContainId(linkId)) {
43             return link.second;
44         }
45     }
46     return nullptr;
47 }
48 
ForEach(const Checker & checker)49 void LinkManager::ForEach(const Checker &checker)
50 {
51     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
52     std::lock_guard lock(lock_);
53     for (auto &[key, link] : links_) {
54         if (checker(*link)) {
55             break;
56         }
57     }
58 }
59 
ProcessIfPresent(InnerLink::LinkType type,const std::string & remoteDeviceId,const Handler & handler)60 bool LinkManager::ProcessIfPresent(InnerLink::LinkType type, const std::string &remoteDeviceId, const Handler &handler)
61 {
62     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
63     std::lock_guard lock(lock_);
64     auto iterator = links_.find({ type, remoteDeviceId });
65     if (iterator == links_.end()) {
66         CONN_LOGE(CONN_WIFI_DIRECT, "type=%{public}d remoteDeviceId=%{public}s not found", static_cast<int>(type),
67             WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
68         return false;
69     }
70 
71     handler(*iterator->second);
72     return true;
73 }
74 
ProcessIfAbsent(InnerLink::LinkType type,const std::string & remoteDeviceId,const Handler & handler)75 bool LinkManager::ProcessIfAbsent(InnerLink::LinkType type, const std::string &remoteDeviceId, const Handler &handler)
76 {
77     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
78     std::lock_guard lock(lock_);
79     auto iterator = links_.find({ type, remoteDeviceId });
80     if (iterator != links_.end()) {
81         CONN_LOGE(CONN_WIFI_DIRECT, "type=%{public}d remoteDeviceId=%{public}s already exist", static_cast<int>(type),
82             WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
83         return false;
84     }
85 
86     auto link = std::make_shared<InnerLink>(type, remoteDeviceId);
87     links_.insert({
88         { type, remoteDeviceId },
89         link
90     });
91     handler(*link);
92     return true;
93 }
94 
ProcessIfPresent(const std::string & remoteMac,const Handler & handler)95 bool LinkManager::ProcessIfPresent(const std::string &remoteMac, const Handler &handler)
96 {
97     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
98     std::lock_guard lock(lock_);
99     auto iterator = std::find_if(links_.begin(), links_.end(), [&remoteMac](const auto &link) {
100         return link.second->GetRemoteBaseMac() == remoteMac;
101     });
102     if (iterator == links_.end()) {
103         CONN_LOGE(CONN_WIFI_DIRECT, "remoteMac=%{public}s not found", WifiDirectAnonymizeMac(remoteMac).c_str());
104         return false;
105     }
106 
107     handler(*iterator->second);
108     return true;
109 }
110 
ProcessIfAbsent(const std::string & remoteMac,const Handler & handler)111 bool LinkManager::ProcessIfAbsent(const std::string &remoteMac, const Handler &handler)
112 {
113     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
114     std::lock_guard lock(lock_);
115     auto iterator = std::find_if(links_.begin(), links_.end(), [&remoteMac](const auto &link) {
116         return link.second->GetRemoteBaseMac() == remoteMac;
117     });
118     if (iterator != links_.end()) {
119         CONN_LOGE(CONN_WIFI_DIRECT, "remoteMac=%{public}s already exist", WifiDirectAnonymizeMac(remoteMac).c_str());
120         return false;
121     }
122 
123     auto link = std::make_shared<InnerLink>(remoteMac);
124     handler(*link);
125     auto type = link->GetLinkType();
126     auto remoteDeviceId = link->GetRemoteDeviceId();
127     links_.insert({
128         { type, remoteDeviceId },
129         link
130     });
131     return true;
132 }
133 
ProcessIfPresent(int linkId,const Handler & handler)134 bool LinkManager::ProcessIfPresent(int linkId, const Handler &handler)
135 {
136     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
137     std::lock_guard lock(lock_);
138     auto iterator = std::find_if(links_.begin(), links_.end(), [&linkId](const auto &link) {
139         return link.second->IsContainId(linkId);
140     });
141     if (iterator == links_.end()) {
142         CONN_LOGE(CONN_WIFI_DIRECT, "link id=%{public}d not found", linkId);
143         return false;
144     }
145 
146     handler(*iterator->second);
147     return true;
148 }
149 
RemoveLink(InnerLink::LinkType type,const std::string & remoteDeviceId)150 void LinkManager::RemoveLink(InnerLink::LinkType type, const std::string &remoteDeviceId)
151 {
152     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
153     std::shared_ptr<InnerLink> link;
154     {
155         std::lock_guard lock(lock_);
156         auto it = links_.find({type, remoteDeviceId});
157         if (it == links_.end()) {
158             CONN_LOGE(CONN_WIFI_DIRECT, "not find remoteDeviceId=%{public}s",
159                       WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
160             return;
161         }
162         link = it->second;
163         links_.erase(it);
164     }
165 
166     CONN_LOGI(CONN_WIFI_DIRECT, "find remoteDeviceId=%{public}s", WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
167     if (link != nullptr && link->GetState() == InnerLink::LinkState::CONNECTED) {
168         GetWifiDirectManager()->notifyOffline(link->GetRemoteBaseMac().c_str(), link->GetRemoteIpv4().c_str(),
169                                               link->GetRemoteDeviceId().c_str(), link->GetLocalIpv4().c_str());
170     }
171 }
172 
RemoveLink(const std::string & remoteMac)173 void LinkManager::RemoveLink(const std::string &remoteMac)
174 {
175     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
176     std::shared_ptr<InnerLink> link;
177     {
178         std::lock_guard lock(lock_);
179         for (const auto &[key, value] : links_) {
180             if (!remoteMac.empty() && remoteMac == value->GetRemoteBaseMac()) {
181                 CONN_LOGI(CONN_WIFI_DIRECT, "find remoteMac=%{public}s", WifiDirectAnonymizeMac(remoteMac).c_str());
182                 link = value;
183                 links_.erase(key);
184                 break;
185             }
186         }
187     }
188     if (link == nullptr) {
189         CONN_LOGE(CONN_WIFI_DIRECT, "not find remoteMac=%{public}s", WifiDirectAnonymizeMac(remoteMac).c_str());
190         return;
191     }
192     if (link->GetState() == InnerLink::LinkState::CONNECTED) {
193         GetWifiDirectManager()->notifyOffline(link->GetRemoteBaseMac().c_str(), link->GetRemoteIpv4().c_str(),
194                                               link->GetRemoteDeviceId().c_str(), link->GetLocalIpv4().c_str());
195     }
196 }
197 
RemoveLinks(InnerLink::LinkType type,bool onlyRemoveConnected)198 void LinkManager::RemoveLinks(InnerLink::LinkType type, bool onlyRemoveConnected)
199 {
200     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
201     std::vector<std::shared_ptr<InnerLink>> links;
202     {
203         std::lock_guard lock(lock_);
204         auto it = links_.begin();
205         while (it != links_.end()) {
206             auto condition = onlyRemoveConnected ?
207                 (it->first.first == type && it->second->GetState() == InnerLink::LinkState::CONNECTED) :
208                 it->first.first == type;
209             if (condition) {
210                 CONN_LOGI(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s",
211                           WifiDirectAnonymizeDeviceId(it->second->GetRemoteDeviceId()).c_str());
212                 links.push_back(it->second);
213                 it = links_.erase(it);
214             } else {
215                 it++;
216             }
217         }
218     }
219 
220     for (const auto &link : links) {
221         if (link->GetState() == InnerLink::LinkState::CONNECTED) {
222             GetWifiDirectManager()->notifyOffline(link->GetRemoteBaseMac().c_str(), link->GetRemoteIpv4().c_str(),
223                                                   link->GetRemoteDeviceId().c_str(), link->GetLocalIpv4().c_str());
224         }
225     }
226 }
227 
GetAllLinksBasicInfo(std::vector<InnerLinkBasicInfo> & infos)228 void LinkManager::GetAllLinksBasicInfo(std::vector<InnerLinkBasicInfo> &infos)
229 {
230     std::lock_guard lock(lock_);
231     for (const auto &[key, value] : links_) {
232         InnerLinkBasicInfo info = { 0 };
233         info.isBeingUsedByRemote = value->IsBeingUsedByRemote();
234         info.state = value->GetState();
235         info.linkType = value->GetLinkType();
236         info.freq = value->GetFrequency();
237         info.remoteDeviceId = value->GetRemoteDeviceId();
238         info.remoteIpv4 = value->GetRemoteIpv4();
239         info.remoteBaseMac = value->GetRemoteBaseMac();
240         infos.push_back(info);
241     }
242 }
243 
GetReuseLink(const std::string & remoteMac)244 std::shared_ptr<InnerLink> LinkManager::GetReuseLink(const std::string &remoteMac)
245 {
246     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
247     std::lock_guard lock(lock_);
248     for (const auto &[key, link] : links_) {
249         if (link->GetRemoteBaseMac() == remoteMac && link->GetState() == InnerLink::LinkState::CONNECTED) {
250             return link;
251         }
252     }
253     CONN_LOGE(CONN_WIFI_DIRECT, "not find remoteMac=%{public}s", WifiDirectAnonymizeMac(remoteMac).c_str());
254     return nullptr;
255 }
256 
GetReuseLink(WifiDirectConnectType connectType,const std::string & remoteDeviceId)257 std::shared_ptr<InnerLink> LinkManager::GetReuseLink(
258     WifiDirectConnectType connectType, const std::string &remoteDeviceId)
259 {
260     WifiDirectLinkType linkType = WIFI_DIRECT_LINK_TYPE_P2P;
261     if (connectType == WIFI_DIRECT_CONNECT_TYPE_AUTH_NEGO_HML ||
262         connectType == WIFI_DIRECT_CONNECT_TYPE_BLE_TRIGGER_HML ||
263         connectType == WIFI_DIRECT_CONNECT_TYPE_AUTH_TRIGGER_HML ||
264         connectType == WIFI_DIRECT_CONNECT_TYPE_ACTION_TRIGGER_HML) {
265         linkType = WIFI_DIRECT_LINK_TYPE_HML;
266     }
267 
268     return GetReuseLink(linkType, remoteDeviceId);
269 }
270 
GetReuseLink(WifiDirectLinkType wifiDirectLinkType,const std::string & remoteDeviceId)271 std::shared_ptr<InnerLink> LinkManager::GetReuseLink(
272     WifiDirectLinkType wifiDirectLinkType, const std::string &remoteDeviceId)
273 {
274     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
275     InnerLink::LinkType linkType { InnerLink::LinkType::INVALID_TYPE };
276     if (wifiDirectLinkType == WIFI_DIRECT_LINK_TYPE_HML) {
277         linkType = InnerLink::LinkType::HML;
278     }
279     if (wifiDirectLinkType == WIFI_DIRECT_LINK_TYPE_P2P) {
280         linkType = InnerLink::LinkType::P2P;
281     }
282     std::lock_guard lock(lock_);
283     auto iterator = links_.find({linkType, remoteDeviceId});
284     if (iterator == links_.end() || iterator->second->GetState() != InnerLink::LinkState::CONNECTED) {
285         CONN_LOGE(CONN_WIFI_DIRECT, "not find remoteDeviceId=%{public}s",
286                   WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
287         return nullptr;
288     }
289     return iterator->second;
290 }
291 
RefreshRelationShip(const std::string & remoteDeviceId,const std::string & remoteMac)292 void LinkManager::RefreshRelationShip(const std::string &remoteDeviceId, const std::string &remoteMac)
293 {
294     CONN_LOGI(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s, remoteMac=%{public}s",
295               WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str(), WifiDirectAnonymizeMac(remoteMac).c_str());
296     std::lock_guard lock(lock_);
297     auto it = links_.find({ InnerLink::LinkType::HML, remoteMac });
298     if (it == links_.end()) {
299         CONN_LOGE(CONN_WIFI_DIRECT, "not find %{public}s as device id", WifiDirectAnonymizeMac(remoteMac).c_str());
300         return;
301     }
302     auto link = it->second;
303     links_.erase(it);
304 
305     link->SetRemoteDeviceId(remoteDeviceId);
306     auto result = links_.insert({{ InnerLink::LinkType::HML, remoteDeviceId }, link });
307     if (!result.second) {
308         CONN_LOGE(CONN_WIFI_DIRECT, "insert by remoteDeviceId failed, use remoteMac");
309         links_.insert({{ InnerLink::LinkType::HML, remoteMac }, link });
310     }
311 }
312 
Dump() const313 void LinkManager::Dump() const
314 {
315     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
316     std::lock_guard lock(lock_);
317     for (const auto &[key, value] : links_) {
318         value->Dump();
319     }
320     if (links_.empty()) {
321         CONN_LOGI(CONN_WIFI_DIRECT, "no inner link");
322     }
323 }
324 } // namespace OHOS::SoftBus
325