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