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