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 "auth_negotiate_channel.h"
17 #include "securec.h"
18 #include "common_timer_errors.h"
19
20 #include "conn_log.h"
21 #include "lnn_distributed_net_ledger.h"
22 #include "softbus_error_code.h"
23
24 #include "wifi_direct_scheduler.h"
25 #include "wifi_direct_scheduler_factory.h"
26 #include "command/negotiate_command.h"
27 #include "data/link_manager.h"
28 #include "entity/entity_factory.h"
29 #include "protocol/wifi_direct_protocol_factory.h"
30 #include "utils/wifi_direct_anonymous.h"
31 #include "utils/wifi_direct_utils.h"
32
33 namespace OHOS::SoftBus {
34 static constexpr int TIMER_TIMEOUT = 50;
35 static constexpr int WAIT_DETECT_RESPONSE_TIMEOUT_MS = 1000;
36 Utils::Timer AuthNegotiateChannel::timer_("DetectLink", TIMER_TIMEOUT);
37
AuthNegotiateChannel(const AuthHandle & handle)38 AuthNegotiateChannel::AuthNegotiateChannel(const AuthHandle &handle)
39 : handle_(handle), timerId_(Utils::TIMER_ERR_INVALID_VALUE), close_(false)
40 {
41 char remoteUuid[UUID_BUF_LEN] {};
42 auto ret = AuthGetDeviceUuid(handle_.authId, remoteUuid, UUID_BUF_LEN);
43 CONN_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, CONN_WIFI_DIRECT, "auth get device id failed");
44 remoteDeviceId_ = remoteUuid;
45 CONN_LOGI(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s", WifiDirectAnonymizeDeviceId(remoteDeviceId_).c_str());
46 }
47
~AuthNegotiateChannel()48 AuthNegotiateChannel::~AuthNegotiateChannel()
49 {
50 if (close_) {
51 CONN_LOGI(CONN_WIFI_DIRECT, "close auth");
52 AuthCloseConn(handle_);
53 }
54 }
55
operator ==(const AuthNegotiateChannel & other) const56 bool AuthNegotiateChannel::operator==(const AuthNegotiateChannel &other) const
57 {
58 return handle_.authId == other.handle_.authId && handle_.type == other.handle_.type;
59 }
60
IsMeta() const61 bool AuthNegotiateChannel::IsMeta() const
62 {
63 bool isMeta = false;
64 int32_t ret = AuthGetMetaType(handle_.authId, &isMeta);
65 CONN_CHECK_AND_RETURN_RET_LOGW(ret == SOFTBUS_OK, false, CONN_WIFI_DIRECT, "get meta type failed");
66 return isMeta;
67 }
68
SetClose()69 void AuthNegotiateChannel::SetClose()
70 {
71 close_ = true;
72 }
73
GetRemoteDeviceId() const74 std::string AuthNegotiateChannel::GetRemoteDeviceId() const
75 {
76 return remoteDeviceId_;
77 }
78
GenerateSequence()79 static int64_t GenerateSequence()
80 {
81 static int64_t wifiDirectTransferSequence = 0;
82
83 if (wifiDirectTransferSequence < 0) {
84 wifiDirectTransferSequence = 0;
85 }
86 return wifiDirectTransferSequence++;
87 }
88
SendMessage(const NegotiateMessage & msg) const89 int AuthNegotiateChannel::SendMessage(const NegotiateMessage &msg) const
90 {
91 CONN_LOGI(CONN_WIFI_DIRECT, "msgType=%{public}s", msg.MessageTypeToString().c_str());
92 ProtocolType type { ProtocolType::TLV };
93 if (!remoteDeviceId_.empty() && (!WifiDirectUtils::IsLocalSupportTlv() ||
94 !WifiDirectUtils::IsRemoteSupportTlv(remoteDeviceId_))) {
95 type = ProtocolType::JSON;
96 }
97 auto protocol = WifiDirectProtocolFactory::CreateProtocol(type);
98 CONN_CHECK_AND_RETURN_RET_LOGE(
99 protocol != nullptr, SOFTBUS_INVALID_PARAM, CONN_WIFI_DIRECT, "create protocol failed");
100 std::vector<uint8_t> output;
101 msg.Marshalling(*protocol, output);
102
103 AuthTransData dataInfo = {
104 .module = MODULE_P2P_LINK,
105 .seq = GenerateSequence(),
106 .len = static_cast<uint32_t>(output.size()),
107 .data = output.data(),
108 };
109
110 CONN_CHECK_AND_RETURN_RET_LOGE(
111 AuthPostTransData(handle_, &dataInfo) == SOFTBUS_OK, SOFTBUS_CONN_AUTH_POST_DATA_FAILED,
112 CONN_WIFI_DIRECT, "post data failed");
113 return SOFTBUS_OK;
114 }
115
OnWaitDetectResponseTimeout()116 void AuthNegotiateChannel::OnWaitDetectResponseTimeout()
117 {
118 CONN_LOGI(CONN_WIFI_DIRECT, "timeout");
119 {
120 std::lock_guard lock(channelLock_);
121 authIdToChannelMap_.erase(handle_.authId);
122 if (authIdToChannelMap_.empty()) {
123 CONN_LOGI(CONN_WIFI_DIRECT, "shutdown timer");
124 timer_.Shutdown(true);
125 }
126 }
127
128 NegotiateMessage response(NegotiateMessageType::CMD_DETECT_LINK_RSP);
129 response.SetResultCode(SOFTBUS_TIMOUT);
130 promise_->set_value(response);
131 }
132
SendMessageAndWaitResponse(const NegotiateMessage & msg)133 NegotiateMessage AuthNegotiateChannel::SendMessageAndWaitResponse(const NegotiateMessage &msg)
134 {
135 auto ret = SendMessage(msg);
136 if (ret != SOFTBUS_OK) {
137 NegotiateMessage response(NegotiateMessageType::CMD_DETECT_LINK_RSP);
138 response.SetResultCode(ret);
139 return response;
140 }
141
142 CONN_LOGI(CONN_WIFI_DIRECT, "send detect link request success");
143 {
144 std::lock_guard lock(channelLock_);
145 promise_ = std::make_shared<std::promise<NegotiateMessage>>();
146 if (authIdToChannelMap_.empty()) {
147 CONN_LOGI(CONN_WIFI_DIRECT, "setup timer");
148 timer_.Setup();
149 }
150 timerId_ = timer_.Register([this] () {
151 std::thread(&AuthNegotiateChannel::OnWaitDetectResponseTimeout, this).detach();
152 }, WAIT_DETECT_RESPONSE_TIMEOUT_MS, true);
153 authIdToChannelMap_[handle_.authId] = shared_from_this();
154 }
155
156 return promise_->get_future().get();
157 }
158
ProcessDetectLinkRequest(const std::shared_ptr<AuthNegotiateChannel> & channel)159 void AuthNegotiateChannel::ProcessDetectLinkRequest(const std::shared_ptr<AuthNegotiateChannel> &channel)
160 {
161 CONN_LOGI(CONN_WIFI_DIRECT, "send detect link response");
162 NegotiateMessage response(NegotiateMessageType::CMD_DETECT_LINK_RSP);
163 response.SetResultCode(SOFTBUS_OK);
164 channel->SendMessage(response);
165 }
166
ProcessDetectLinkResponse(AuthHandle handle,const NegotiateMessage & response)167 void AuthNegotiateChannel::ProcessDetectLinkResponse(AuthHandle handle, const NegotiateMessage &response)
168 {
169 std::lock_guard lock(channelLock_);
170 auto it = authIdToChannelMap_.find(handle.authId);
171 if (it == authIdToChannelMap_.end()) {
172 CONN_LOGE(CONN_WIFI_DIRECT, "not find channel by authId=%{public}" PRId64, handle.authId);
173 return;
174 }
175
176 auto channel = it->second;
177 timer_.Unregister(channel->timerId_);
178 authIdToChannelMap_.erase(it);
179 if (authIdToChannelMap_.empty()) {
180 CONN_LOGI(CONN_WIFI_DIRECT, "shutdown timer");
181 timer_.Shutdown(true);
182 }
183 channel->promise_->set_value(response);
184 }
185
CheckSameAccount(const NegotiateMessage & msg)186 static bool CheckSameAccount(const NegotiateMessage &msg)
187 {
188 bool ret = true;
189 switch (msg.GetMessageType()) {
190 case NegotiateMessageType::CMD_V3_REQ:
191 case NegotiateMessageType::CMD_V3_RSP:
192 case NegotiateMessageType::CMD_V3_CUSTOM_PORT_REQ:
193 case NegotiateMessageType::CMD_V3_CUSTOM_PORT_RSP:
194 case NegotiateMessageType::CMD_AUTH_HAND_SHAKE:
195 case NegotiateMessageType::CMD_AUTH_HAND_SHAKE_RSP:
196 case NegotiateMessageType::CMD_CONN_V2_REQ_3:
197 case NegotiateMessageType::CMD_CONN_V2_RESP_3:
198 ret = msg.GetExtraData().empty() || msg.GetExtraData().front();
199 break;
200 default:
201 ret = true;
202 break;
203 }
204 return ret;
205 }
206
OnAuthDataReceived(AuthHandle handle,const AuthTransData * data)207 static void OnAuthDataReceived(AuthHandle handle, const AuthTransData *data)
208 {
209 ProtocolType type { ProtocolType::TLV };
210 auto channel = std::make_shared<AuthNegotiateChannel>(handle);
211 auto remoteDeviceId = channel->GetRemoteDeviceId();
212 if (!remoteDeviceId.empty() && (!WifiDirectUtils::IsLocalSupportTlv() ||
213 !WifiDirectUtils::IsRemoteSupportTlv(remoteDeviceId))) {
214 type = ProtocolType::JSON;
215 }
216 auto protocol = WifiDirectProtocolFactory::CreateProtocol(type);
217 std::vector<uint8_t> input;
218 input.insert(input.end(), data->data, data->data + data->len);
219 NegotiateMessage msg;
220 msg.Unmarshalling(*protocol, input);
221 bool sameAccount = CheckSameAccount(msg);
222 CONN_LOGI(CONN_WIFI_DIRECT, "sameAccount=%{public}d", sameAccount);
223 if (!sameAccount) {
224 CONN_LOGI(CONN_WIFI_DIRECT, "diff account, use remote mac as device id");
225 remoteDeviceId = msg.GetLinkInfo().GetRemoteBaseMac();
226 }
227
228 CONN_LOGI(CONN_WIFI_DIRECT, "msgType=%{public}s", msg.MessageTypeToString().c_str());
229 if (msg.GetMessageType() == NegotiateMessageType::CMD_DETECT_LINK_REQ) {
230 std::thread(AuthNegotiateChannel::ProcessDetectLinkRequest, channel).detach();
231 return;
232 } else if (msg.GetMessageType() == NegotiateMessageType::CMD_DETECT_LINK_RSP) {
233 std::thread(AuthNegotiateChannel::ProcessDetectLinkResponse, handle, msg).detach();
234 return;
235 } else if (static_cast<int>(msg.GetMessageType()) ==
236 static_cast<int>(LegacyCommandType::CMD_GC_WIFI_CONFIG_CHANGED) ||
237 msg.GetLegacyP2pCommandType() == LegacyCommandType::CMD_GC_WIFI_CONFIG_CHANGED) {
238 CONN_LOGI(CONN_WIFI_DIRECT, "do not process %{public}d", static_cast<int>(msg.GetMessageType()));
239 return;
240 }
241
242 msg.SetRemoteDeviceId(remoteDeviceId);
243 NegotiateCommand command(msg, channel);
244 WifiDirectSchedulerFactory::GetInstance().GetScheduler().ProcessNegotiateData(remoteDeviceId, command);
245 }
246
OnAuthDisconnected(AuthHandle authHandle)247 static void OnAuthDisconnected(AuthHandle authHandle)
248 {
249 CONN_LOGI(CONN_WIFI_DIRECT, "type=%{public}d authId=%{public}" PRId64, authHandle.type, authHandle.authId);
250 AuthNegotiateChannel disconnectChannel(authHandle);
251 InnerLink::LinkType type = InnerLink::LinkType::INVALID_TYPE;
252 std::string remoteDeviceId;
253 std::string remoteMac;
254 bool isLegacyReused = false;
255 LinkManager::GetInstance().ForEach(
256 [&disconnectChannel, &type, &remoteDeviceId, &remoteMac, &isLegacyReused] (const InnerLink &innerLink) {
257 auto channel = std::dynamic_pointer_cast<AuthNegotiateChannel>(innerLink.GetNegotiateChannel());
258 if (channel != nullptr && disconnectChannel == *channel) {
259 type = innerLink.GetLinkType();
260 remoteDeviceId= innerLink.GetRemoteDeviceId();
261 remoteMac = innerLink.GetRemoteBaseMac();
262 isLegacyReused = innerLink.GetLegacyReused();
263 return true;
264 }
265 return false;
266 });
267
268 CONN_LOGI(CONN_WIFI_DIRECT, "disconnect type=%{public}d, remoteUuid=%{public}s, remoteMac=%{public}s",
269 static_cast<int>(type), WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str(),
270 WifiDirectAnonymizeMac(remoteMac).c_str());
271 if (type != InnerLink::LinkType::INVALID_TYPE) {
272 LinkManager::GetInstance().RemoveLink(type, remoteDeviceId);
273 if (!isLegacyReused) {
274 auto &entity = EntityFactory::GetInstance().GetEntity(type);
275 entity.DisconnectLink(remoteMac);
276 entity.DestroyGroupIfNeeded();
277 }
278 }
279 }
280
OnAuthException(AuthHandle authHandle,int32_t error)281 static void OnAuthException(AuthHandle authHandle, int32_t error)
282 {
283 auto channel = std::make_shared<AuthNegotiateChannel>(authHandle);
284 auto remoteDeviceId = channel->GetRemoteDeviceId();
285 CONN_LOGI(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s auth exception error=%{public}d",
286 WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str(), error);
287 AuthExceptionEvent event { error, authHandle };
288 WifiDirectSchedulerFactory::GetInstance().GetScheduler().ProcessEvent(remoteDeviceId, event);
289 }
290
Init()291 void AuthNegotiateChannel::Init()
292 {
293 CONN_LOGI(CONN_INIT, "enter");
294 AuthTransListener authListener = {
295 .onDataReceived = OnAuthDataReceived,
296 .onDisconnected = OnAuthDisconnected,
297 .onException = OnAuthException,
298 };
299
300 int32_t ret = RegAuthTransListener(MODULE_P2P_LINK, &authListener);
301 CONN_CHECK_AND_RETURN_LOGW(ret == SOFTBUS_OK, CONN_INIT, "register auth transfer listener failed");
302 }
303
StartListening(AuthLinkType type,const std::string & localIp,int port)304 std::pair<int, ListenerModule> AuthNegotiateChannel::StartListening(
305 AuthLinkType type, const std::string &localIp, int port)
306 {
307 CONN_LOGI(CONN_WIFI_DIRECT, "type=%{public}d, localIp=%{public}s, port=%{public}d", type,
308 WifiDirectAnonymizeIp(localIp).c_str(), port);
309 ListenerModule module;
310 auto resultPort = AuthStartListeningForWifiDirect(type, localIp.c_str(), port, &module);
311 CONN_LOGI(CONN_WIFI_DIRECT, "resultPort=%{public}d, module=%{public}d", resultPort, module);
312 return { resultPort, module };
313 }
314
StopListening(AuthLinkType type,ListenerModule module)315 void AuthNegotiateChannel::StopListening(AuthLinkType type, ListenerModule module)
316 {
317 CONN_LOGI(CONN_WIFI_DIRECT, "type=%{public}d, moduleId=%{public}d", type, module);
318 AuthStopListeningForWifiDirect(type, module);
319 }
320
OnConnOpened(uint32_t requestId,AuthHandle authHandle)321 void AuthNegotiateChannel::OnConnOpened(uint32_t requestId, AuthHandle authHandle)
322 {
323 std::string remoteDeviceId;
324 {
325 std::lock_guard lock(lock_);
326 remoteDeviceId = requestIdToDeviceIdMap_[requestId];
327 requestIdToDeviceIdMap_.erase(requestId);
328 }
329
330 CONN_LOGI(CONN_WIFI_DIRECT, "requestId=%{public}u remoteDeviceId=%{public}s", requestId,
331 WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
332 AuthOpenEvent event { SOFTBUS_OK, authHandle };
333 WifiDirectSchedulerFactory::GetInstance().GetScheduler().ProcessEvent(remoteDeviceId, event);
334 }
335
OnConnOpenFailed(uint32_t requestId,int32_t reason)336 void AuthNegotiateChannel::OnConnOpenFailed(uint32_t requestId, int32_t reason)
337 {
338 std::string remoteDeviceId;
339 {
340 std::lock_guard lock(lock_);
341 remoteDeviceId = requestIdToDeviceIdMap_[requestId];
342 requestIdToDeviceIdMap_.erase(requestId);
343 }
344
345 CONN_LOGE(CONN_WIFI_DIRECT, "requestId=%{public}u remoteDeviceId=%{public}s reason=%{public}d", requestId,
346 WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str(), reason);
347 AuthOpenEvent event { reason };
348 WifiDirectSchedulerFactory::GetInstance().GetScheduler().ProcessEvent(remoteDeviceId, event);
349 }
350
OpenConnection(const OpenParam & param,const std::shared_ptr<AuthNegotiateChannel> & channel)351 int AuthNegotiateChannel::OpenConnection(const OpenParam ¶m, const std::shared_ptr<AuthNegotiateChannel> &channel)
352 {
353 bool isMeta = false;
354 bool needUdid = true;
355 if (channel != nullptr) {
356 isMeta = channel->IsMeta();
357 }
358 if (param.remoteUuid.length() < UUID_BUF_LEN - 1) {
359 isMeta = true;
360 needUdid = false;
361 }
362
363 CONN_LOGI(CONN_WIFI_DIRECT, "remoteUuid=%{public}s, remoteIp=%{public}s, remotePort=%{public}d, isMeta=%{public}d",
364 WifiDirectAnonymizeDeviceId(param.remoteUuid).c_str(), WifiDirectAnonymizeIp(param.remoteIp).c_str(),
365 param.remotePort, isMeta);
366
367 AuthConnInfo authConnInfo {};
368 authConnInfo.type = param.type;
369 authConnInfo.info.ipInfo.port = param.remotePort;
370 authConnInfo.info.ipInfo.moduleId = param.module;
371 if (isMeta && needUdid) {
372 authConnInfo.info.ipInfo.authId = channel->handle_.authId;
373 }
374 auto ret = strcpy_s(authConnInfo.info.ipInfo.ip, IP_LEN, param.remoteIp.c_str());
375 CONN_CHECK_AND_RETURN_RET_LOGW(
376 ret == EOK, SOFTBUS_CONN_OPEN_CONNECTION_COPY_IP_FAILED, CONN_WIFI_DIRECT, "copy ip failed");
377 if (needUdid) {
378 const char *remoteUdid = LnnConvertDLidToUdid(param.remoteUuid.c_str(), CATEGORY_UUID);
379 CONN_CHECK_AND_RETURN_RET_LOGE(remoteUdid != nullptr && strlen(remoteUdid) != 0,
380 SOFTBUS_CONN_OPEN_CONNECTION_GET_REMOTE_UUID_FAILED, CONN_WIFI_DIRECT, "get remote udid failed");
381 ret = strcpy_s(authConnInfo.info.ipInfo.udid, UDID_BUF_LEN, remoteUdid);
382 CONN_CHECK_AND_RETURN_RET_LOGE(
383 ret == EOK, SOFTBUS_CONN_OPEN_CONNECTION_COPY_UUID_FAILED, CONN_WIFI_DIRECT, "copy udid failed");
384 }
385
386 AuthConnCallback authConnCallback = {
387 .onConnOpened = AuthNegotiateChannel::OnConnOpened,
388 .onConnOpenFailed = AuthNegotiateChannel::OnConnOpenFailed,
389 };
390
391 auto requestId = AuthGenRequestId();
392 {
393 std::lock_guard lock(lock_);
394 requestIdToDeviceIdMap_[requestId] = param.remoteUuid;
395 }
396
397 ret = AuthOpenConn(&authConnInfo, requestId, &authConnCallback, isMeta);
398 if (ret != SOFTBUS_OK) {
399 CONN_LOGE(CONN_WIFI_DIRECT, "auth open connect failed, error=%{public}d", ret);
400 std::lock_guard lock(lock_);
401 requestIdToDeviceIdMap_.erase(requestId);
402 }
403 return ret;
404 }
405
StopCustomListening()406 void AuthNegotiateChannel::StopCustomListening()
407 {
408 AuthStopListening(AUTH_LINK_TYPE_RAW_ENHANCED_P2P);
409 }
410 } // namespace OHOS::SoftBus
411