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)198 void LinkManager::RemoveLinks(InnerLink::LinkType type)
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             if (it->first.first == type) {
207                 CONN_LOGI(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s",
208                           WifiDirectAnonymizeDeviceId(it->second->GetRemoteDeviceId()).c_str());
209                 links.push_back(it->second);
210                 it = links_.erase(it);
211             } else {
212                 it++;
213             }
214         }
215     }
216 
217     for (const auto &link : links) {
218         if (link->GetState() == InnerLink::LinkState::CONNECTED) {
219             GetWifiDirectManager()->notifyOffline(link->GetRemoteBaseMac().c_str(), link->GetRemoteIpv4().c_str(),
220                                                   link->GetRemoteDeviceId().c_str(), link->GetLocalIpv4().c_str());
221         }
222     }
223 }
224 
GetAllLinksBasicInfo(std::vector<InnerLinkBasicInfo> & infos)225 void LinkManager::GetAllLinksBasicInfo(std::vector<InnerLinkBasicInfo> &infos)
226 {
227     std::lock_guard lock(lock_);
228     for (const auto &[key, value] : links_) {
229         InnerLinkBasicInfo info = { 0 };
230         info.isBeingUsedByRemote = value->IsBeingUsedByRemote();
231         info.state = value->GetState();
232         info.linkType = value->GetLinkType();
233         info.freq = value->GetFrequency();
234         info.remoteDeviceId = value->GetRemoteDeviceId();
235         info.remoteIpv4 = value->GetRemoteIpv4();
236         info.remoteBaseMac = value->GetRemoteBaseMac();
237         infos.push_back(info);
238     }
239 }
240 
GetReuseLink(const std::string & remoteMac)241 std::shared_ptr<InnerLink> LinkManager::GetReuseLink(const std::string &remoteMac)
242 {
243     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
244     std::lock_guard lock(lock_);
245     for (const auto &[key, link] : links_) {
246         if (link->GetRemoteBaseMac() == remoteMac && link->GetState() == InnerLink::LinkState::CONNECTED) {
247             return link;
248         }
249     }
250     CONN_LOGE(CONN_WIFI_DIRECT, "not find remoteMac=%{public}s", WifiDirectAnonymizeMac(remoteMac).c_str());
251     return nullptr;
252 }
253 
GetReuseLink(WifiDirectConnectType connectType,const std::string & remoteDeviceId)254 std::shared_ptr<InnerLink> LinkManager::GetReuseLink(
255     WifiDirectConnectType connectType, const std::string &remoteDeviceId)
256 {
257     WifiDirectLinkType linkType = WIFI_DIRECT_LINK_TYPE_P2P;
258     if (connectType == WIFI_DIRECT_CONNECT_TYPE_AUTH_NEGO_HML ||
259         connectType == WIFI_DIRECT_CONNECT_TYPE_BLE_TRIGGER_HML ||
260         connectType == WIFI_DIRECT_CONNECT_TYPE_AUTH_TRIGGER_HML ||
261         connectType == WIFI_DIRECT_CONNECT_TYPE_ACTION_TRIGGER_HML) {
262         linkType = WIFI_DIRECT_LINK_TYPE_HML;
263     }
264 
265     return GetReuseLink(linkType, remoteDeviceId);
266 }
267 
GetReuseLink(WifiDirectLinkType wifiDirectLinkType,const std::string & remoteDeviceId)268 std::shared_ptr<InnerLink> LinkManager::GetReuseLink(
269     WifiDirectLinkType wifiDirectLinkType, const std::string &remoteDeviceId)
270 {
271     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
272     InnerLink::LinkType linkType { InnerLink::LinkType::INVALID_TYPE };
273     if (wifiDirectLinkType == WIFI_DIRECT_LINK_TYPE_HML) {
274         linkType = InnerLink::LinkType::HML;
275     }
276     if (wifiDirectLinkType == WIFI_DIRECT_LINK_TYPE_P2P) {
277         linkType = InnerLink::LinkType::P2P;
278     }
279     std::lock_guard lock(lock_);
280     auto iterator = links_.find({linkType, remoteDeviceId});
281     if (iterator == links_.end() || iterator->second->GetState() != InnerLink::LinkState::CONNECTED) {
282         CONN_LOGE(CONN_WIFI_DIRECT, "not find remoteDeviceId=%{public}s",
283                   WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
284         return nullptr;
285     }
286     return iterator->second;
287 }
288 
RefreshRelationShip(const std::string & remoteDeviceId,const std::string & remoteMac)289 void LinkManager::RefreshRelationShip(const std::string &remoteDeviceId, const std::string &remoteMac)
290 {
291     CONN_LOGI(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s, remoteMac=%{public}s",
292               WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str(), WifiDirectAnonymizeMac(remoteMac).c_str());
293     std::lock_guard lock(lock_);
294     auto it = links_.find({ InnerLink::LinkType::HML, remoteMac });
295     if (it == links_.end()) {
296         CONN_LOGE(CONN_WIFI_DIRECT, "not find %{public}s as device id", WifiDirectAnonymizeMac(remoteMac).c_str());
297         return;
298     }
299     auto link = it->second;
300     links_.erase(it);
301 
302     link->SetRemoteDeviceId(remoteDeviceId);
303     auto result = links_.insert({{ InnerLink::LinkType::HML, remoteDeviceId }, link });
304     if (!result.second) {
305         CONN_LOGE(CONN_WIFI_DIRECT, "insert by remoteDeviceId failed, use remoteMac");
306         links_.insert({{ InnerLink::LinkType::HML, remoteMac }, link });
307     }
308 }
309 
Dump() const310 void LinkManager::Dump() const
311 {
312     CONN_LOGD(CONN_WIFI_DIRECT, "enter");
313     std::lock_guard lock(lock_);
314     for (const auto &[key, value] : links_) {
315         value->Dump();
316     }
317     if (links_.empty()) {
318         CONN_LOGI(CONN_WIFI_DIRECT, "no inner link");
319     }
320 }
321 } // namespace OHOS::SoftBus
322