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 &param, 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