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 "wifi_direct_scheduler.h"
16 #include <thread>
17 #include "softbus_error_code.h"
18 #include "conn_log.h"
19 #include "command/connect_command.h"
20 #include "command/command_factory.h"
21 #include "command/disconnect_command.h"
22 #include "command/negotiate_command.h"
23
24 namespace OHOS::SoftBus {
ConnectDevice(const WifiDirectConnectInfo & info,const WifiDirectConnectCallback & callback,bool markRetried)25 int WifiDirectScheduler::ConnectDevice(const WifiDirectConnectInfo &info, const WifiDirectConnectCallback &callback,
26 bool markRetried)
27 {
28 CONN_LOGI(CONN_WIFI_DIRECT,
29 "requestId=%{public}d, pid=%{public}d, type=%{public}d, networkId=%{public}s, remoteUuid=%{public}s, "
30 "expectRole=0x%{public}x, bw=%{public}d, ipaddrType=%{public}d",
31 info.requestId, info.pid, info.connectType, WifiDirectAnonymizeDeviceId(info.remoteNetworkId).c_str(),
32 WifiDirectAnonymizeDeviceId(WifiDirectUtils::NetworkIdToUuid(info.remoteNetworkId)).c_str(),
33 info.expectApiRole, info.bandWidth, info.ipAddrType);
34 DumpNegotiateChannel(info.negoChannel);
35
36 auto command = CommandFactory::GetInstance().CreateConnectCommand(info, callback);
37 command->SetRetried(markRetried);
38 std::shared_ptr<WifiDirectExecutor> executor;
39 std::lock_guard executorLock(executorLock_);
40 auto ret = ScheduleActiveCommand(command, executor);
41 CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "schedule active command failed");
42 if (executor != nullptr) {
43 CONN_LOGI(CONN_WIFI_DIRECT, "commandId=%{public}u", command->GetId());
44 executor->SendEvent(command);
45 }
46 return ret;
47 }
48
CancelConnectDevice(const WifiDirectConnectInfo & info)49 int WifiDirectScheduler::CancelConnectDevice(const WifiDirectConnectInfo &info)
50 {
51 CONN_LOGI(CONN_WIFI_DIRECT, "requestId=%{public}d, pid=%{public}d", info.requestId, info.pid);
52
53 std::lock_guard commandLock(commandLock_);
54 for (auto itc = commandList_.begin(); itc != commandList_.end(); itc++) {
55 auto connectCommand = std::dynamic_pointer_cast<ConnectCommand>(*itc);
56 if (connectCommand != nullptr && connectCommand->IsSameCommand(info)) {
57 commandList_.erase(itc);
58 return SOFTBUS_OK;
59 }
60 }
61 return SOFTBUS_NOT_FIND;
62 }
63
ConnectDevice(const std::shared_ptr<ConnectCommand> & command,bool markRetried)64 int WifiDirectScheduler::ConnectDevice(const std::shared_ptr<ConnectCommand> &command, bool markRetried)
65 {
66 return ConnectDevice(command->GetConnectInfo().info_, command->GetConnectCallback(), markRetried);
67 }
68
DisconnectDevice(WifiDirectDisconnectInfo & info,WifiDirectDisconnectCallback & callback)69 int WifiDirectScheduler::DisconnectDevice(WifiDirectDisconnectInfo &info, WifiDirectDisconnectCallback &callback)
70 {
71 auto command = CommandFactory::GetInstance().CreateDisconnectCommand(info, callback);
72 CONN_LOGI(CONN_WIFI_DIRECT,
73 "requestId=%{public}d, pid=%{public}d, linkId=%{public}d, networkId=%{public}s, remoteUuid=%{public}s",
74 info.requestId, info.pid, info.linkId,
75 WifiDirectAnonymizeDeviceId(WifiDirectUtils::UuidToNetworkId(command->GetRemoteDeviceId())).c_str(),
76 WifiDirectAnonymizeDeviceId(command->GetRemoteDeviceId()).c_str());
77
78 std::shared_ptr<WifiDirectExecutor> executor;
79 std::lock_guard executorLock(executorLock_);
80 auto ret = ScheduleActiveCommand(command, executor);
81 CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "schedule active command failed");
82 if (executor != nullptr) {
83 CONN_LOGI(CONN_WIFI_DIRECT, "commandId=%{public}u", command->GetId());
84 executor->SendEvent(command);
85 }
86 return ret;
87 }
88
ForceDisconnectDevice(WifiDirectForceDisconnectInfo & info,WifiDirectDisconnectCallback & callback)89 int WifiDirectScheduler::ForceDisconnectDevice(
90 WifiDirectForceDisconnectInfo &info, WifiDirectDisconnectCallback &callback)
91 {
92 auto command = CommandFactory::GetInstance().CreateForceDisconnectCommand(info, callback);
93 CONN_LOGI(CONN_WIFI_DIRECT,
94 "requestId=%{public}d pid=%{public}d networkId=%{public}s remoteUuid=%{public}s linktype=%{public}d",
95 info.requestId, info.pid,
96 WifiDirectAnonymizeDeviceId(WifiDirectUtils::UuidToNetworkId(command->GetRemoteDeviceId())).c_str(),
97 WifiDirectAnonymizeDeviceId(command->GetRemoteDeviceId()).c_str(), info.linkType);
98 std::shared_ptr<WifiDirectExecutor> executor;
99 std::lock_guard executorLock(executorLock_);
100 auto ret = ScheduleActiveCommand(command, executor);
101 CONN_CHECK_AND_RETURN_RET_LOGE(
102 ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "schedule active command failed, ret=%{public}d", ret);
103 if (executor != nullptr) {
104 CONN_LOGI(CONN_WIFI_DIRECT, "commandId=%{public}u", command->GetId());
105 executor->SendEvent(command);
106 }
107 return ret;
108 }
109
ProcessNextCommand(WifiDirectExecutor * executor,std::shared_ptr<WifiDirectProcessor> & processor)110 bool WifiDirectScheduler::ProcessNextCommand(WifiDirectExecutor *executor,
111 std::shared_ptr<WifiDirectProcessor> &processor)
112 {
113 auto executorDeviceId = executor->GetRemoteDeviceId();
114 std::lock_guard executorLock(executorLock_);
115 auto ite = executors_.find(executorDeviceId);
116 if (ite == executors_.end()) {
117 CONN_LOGI(CONN_WIFI_DIRECT, "not find executor=%{public}s",
118 WifiDirectAnonymizeDeviceId(executorDeviceId).c_str());
119 return false;
120 }
121
122 auto executorCopy = ite->second;
123 executors_.erase(ite);
124 CONN_LOGI(CONN_WIFI_DIRECT, "remove executor=%{public}s", WifiDirectAnonymizeDeviceId(executorDeviceId).c_str());
125
126 std::lock_guard commandLock(commandLock_);
127 for (auto itc = commandList_.begin(); itc != commandList_.end(); itc++) {
128 auto command = *itc;
129 std::string commandDeviceId = command->GetRemoteDeviceId();
130 if (commandDeviceId == executorDeviceId || executors_.find(commandDeviceId) == executors_.end()) {
131 CONN_LOGI(CONN_WIFI_DIRECT, "commandDeviceId=%{public}s",
132 WifiDirectAnonymizeDeviceId(commandDeviceId).c_str());
133 commandList_.erase(itc);
134 processor = command->GetProcessor();
135 executors_.insert({commandDeviceId, executorCopy});
136 CONN_LOGI(CONN_WIFI_DIRECT, "add executor=%{public}s, commandId=%{public}u",
137 WifiDirectAnonymizeDeviceId(commandDeviceId).c_str(), command->GetId());
138 executor->SetRemoteDeviceId(commandDeviceId);
139 if (command->GetType() == CommandType::CONNECT_COMMAND) {
140 executor->SetActive(true);
141 executor->SendEvent(std::dynamic_pointer_cast<ConnectCommand>(command));
142 } else if (command->GetType() == CommandType::DISCONNECT_COMMAND) {
143 executor->SetActive(true);
144 executor->SendEvent(std::dynamic_pointer_cast<DisconnectCommand>(command));
145 } else if (command->GetType() == CommandType::NEGOTIATE_COMMAND) {
146 auto negotiateCommand = std::dynamic_pointer_cast<NegotiateCommand>(command);
147 CONN_LOGI(CONN_WIFI_DIRECT, "msgType=%{public}s",
148 negotiateCommand->GetNegotiateMessage().MessageTypeToString().c_str());
149 executor->SetActive(false);
150 executor->SendEvent(negotiateCommand);
151 }
152 return true;
153 }
154 }
155
156 return false;
157 }
158
ScheduleActiveCommand(const std::shared_ptr<WifiDirectCommand> & command,std::shared_ptr<WifiDirectExecutor> & executor)159 int WifiDirectScheduler::ScheduleActiveCommand(const std::shared_ptr<WifiDirectCommand> &command,
160 std::shared_ptr<WifiDirectExecutor> &executor)
161 {
162 auto remoteDeviceId = command->GetRemoteDeviceId();
163 if (remoteDeviceId.empty()) {
164 CONN_LOGE(CONN_WIFI_DIRECT, "remoteDeviceId emtpy");
165 return SOFTBUS_CONN_REMOTE_DEVICE_ID_EMPTY;
166 }
167
168 std::lock_guard executorLock(executorLock_);
169 auto it = executors_.find(remoteDeviceId);
170 if (it != executors_.end() || executors_.size() == MAX_EXECUTOR) {
171 CONN_LOGI(CONN_WIFI_DIRECT, "push command to list, commandId=%{public}u", command->GetId());
172 std::lock_guard commandLock(commandLock_);
173 commandList_.push_back(command);
174 return SOFTBUS_OK;
175 }
176
177 auto processor = command->GetProcessor();
178 if (processor == nullptr) {
179 CONN_LOGE(CONN_WIFI_DIRECT, "get processor failed");
180 return SOFTBUS_CONN_GET_PROCESSOR_FAILED;
181 }
182 CONN_LOGI(CONN_WIFI_DIRECT, "create executor=%{public}s", WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
183 executor = WifiDirectExecutorFactory::GetInstance().NewExecutor(remoteDeviceId, *this, processor, true);
184 if (executor == nullptr) {
185 return SOFTBUS_MALLOC_ERR;
186 }
187
188 executors_.insert({ remoteDeviceId, executor });
189 return SOFTBUS_OK;
190 }
191
DumpNegotiateChannel(const WifiDirectNegotiateChannel & channel)192 void WifiDirectScheduler::DumpNegotiateChannel(const WifiDirectNegotiateChannel &channel)
193 {
194 switch (channel.type) {
195 case NEGO_CHANNEL_NULL:
196 CONN_LOGI(CONN_WIFI_DIRECT, "NEGO_CHANNEL_NULL");
197 break;
198 case NEGO_CHANNEL_AUTH:
199 CONN_LOGI(CONN_WIFI_DIRECT, "NEGO_CHANNEL_AUTH, type=%{public}d, authId=%{public}" PRId64,
200 channel.handle.authHandle.type, channel.handle.authHandle.authId);
201 break;
202 case NEGO_CHANNEL_COC:
203 CONN_LOGI(CONN_WIFI_DIRECT, "NEGO_CHANNEL_COC");
204 break;
205 case NEGO_CHANNEL_ACTION:
206 CONN_LOGI(CONN_WIFI_DIRECT, "NEGO_CHANNEL_ACTION, actionAddr=%{public}d",
207 channel.handle.actionAddr);
208 break;
209 case NEGO_CHANNEL_SHARE:
210 CONN_LOGI(CONN_WIFI_DIRECT, "NEGO_CHANNEL_COC, channelId=%{public}d", channel.handle.channelId);
211 break;
212 default:
213 CONN_LOGW(CONN_WIFI_DIRECT, "not support type=%{public}d", channel.type);
214 }
215 }
216 }
217