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