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 #ifndef WIFI_DIRECT_SCHEDULER_H
16 #define WIFI_DIRECT_SCHEDULER_H
17 
18 #include <list>
19 #include <map>
20 #include <mutex>
21 #include <memory>
22 #include <string>
23 #include <thread>
24 #include "wifi_direct_types.h"
25 #include "wifi_direct_executor.h"
26 #include "command/wifi_direct_command.h"
27 #include "command/connect_command.h"
28 #include "event/wifi_direct_event_wrapper.h"
29 #include "utils/wifi_direct_anonymous.h"
30 #include "utils/wifi_direct_utils.h"
31 #include "wifi_direct_executor_factory.h"
32 
33 namespace OHOS::SoftBus {
34 class WifiDirectSchedulerFactory;
35 class WifiDirectScheduler {
36 public:
37     virtual ~WifiDirectScheduler() = default;
38 
39     int ConnectDevice(const WifiDirectConnectInfo &info, const WifiDirectConnectCallback &callback,
40                       bool markRetried = false);
41     int ConnectDevice(const std::shared_ptr<ConnectCommand> &command, bool markRetried = false);
42     int CancelConnectDevice(const WifiDirectConnectInfo &info);
43     int DisconnectDevice(WifiDirectDisconnectInfo &info, WifiDirectDisconnectCallback &callback);
44     int ForceDisconnectDevice(WifiDirectForceDisconnectInfo &info, WifiDirectDisconnectCallback &callback);
45 
46     template<typename Command>
ProcessNegotiateData(const std::string & remoteDeviceId,Command & command)47     void ProcessNegotiateData(const std::string &remoteDeviceId, Command &command)
48     {
49         auto aDeviceId = WifiDirectAnonymizeDeviceId(remoteDeviceId);
50         CONN_LOGD(CONN_WIFI_DIRECT, "remoteDeviceId=%{public}s", aDeviceId.c_str());
51         std::lock_guard executorLock(executorLock_);
52         auto it = executors_.find(remoteDeviceId);
53         if (it != executors_.end()) {
54             if (it->second->CanAcceptNegotiateData(command)) {
55                 CONN_LOGI(CONN_WIFI_DIRECT, "send command to executor=%{public}s, commandId=%{public}d",
56                           aDeviceId.c_str(), command.GetId());
57                 it->second->SendEvent(std::make_shared<Command>(command));
58                 return;
59             }
60             std::lock_guard commandLock(commandLock_);
61             CONN_LOGI(CONN_WIFI_DIRECT, "push command to list, commandId=%{public}u", command.GetId());
62             commandList_.push_back(std::make_shared<Command>(command));
63             return;
64         }
65 
66         if (executors_.size() == MAX_EXECUTOR) {
67             CONN_LOGI(CONN_WIFI_DIRECT, "push command to list, commandId=%{public}u", command.GetId());
68             std::lock_guard commandLock(commandLock_);
69             commandList_.push_back(std::make_shared<Command>(command));
70             return;
71         }
72 
73         auto processor = command.GetProcessor();
74         if (processor == nullptr) {
75             CONN_LOGE(CONN_WIFI_DIRECT, "get processor failed");
76             return;
77         }
78         auto executor =  WifiDirectExecutorFactory::GetInstance().NewExecutor(remoteDeviceId, *this, processor, false);
79         if (executor == nullptr) {
80             return;
81         }
82         executors_.insert({ remoteDeviceId, executor });
83         CONN_LOGI(CONN_WIFI_DIRECT, "send command to executor=%{public}s, commandId=%{public}d",
84                   aDeviceId.c_str(), command.GetId());
85         executor->SendEvent(std::make_shared<Command>(command));
86     }
87 
88     template<typename Event>
ProcessEvent(const std::string & remoteDeviceId,const Event & event)89     void ProcessEvent(const std::string &remoteDeviceId, const Event &event)
90     {
91         std::lock_guard lock(executorLock_);
92         auto it = executors_.find(remoteDeviceId);
93         if (it == executors_.end()) {
94             CONN_LOGE(CONN_WIFI_DIRECT, "executor not exist, remoteDeviceId=%{public}s",
95                       WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
96             return;
97         }
98 
99         CONN_LOGI(CONN_WIFI_DIRECT, "send event to executor=%{public}s",
100                   WifiDirectAnonymizeDeviceId(remoteDeviceId).c_str());
101         auto content = std::make_shared<Event>(event);
102         it->second->SendEvent(content);
103     }
104 
105     template<typename Command>
QueueCommandFront(Command & command)106     void QueueCommandFront(Command &command)
107     {
108         std::lock_guard commandLock(commandLock_);
109         CONN_LOGI(CONN_WIFI_DIRECT, "push data to list front");
110         commandList_.push_front(std::make_shared<Command>(command));
111     }
112 
113     template<typename Command>
QueueCommandBack(Command & command)114     void QueueCommandBack(Command &command)
115     {
116         std::lock_guard commandLock(commandLock_);
117         CONN_LOGI(CONN_WIFI_DIRECT, "push data to list back");
118         commandList_.push_back(std::make_shared<Command>(command));
119     }
120 
121     template<typename Command>
FetchAndDispatchCommand(const std::string & remoteDeviceId)122     void FetchAndDispatchCommand(const std::string &remoteDeviceId)
123     {
124         std::lock_guard executorLock(executorLock_);
125         auto eit = executors_.find(remoteDeviceId);
126         if (eit == executors_.end()) {
127             return;
128         }
129 
130         std::lock_guard commandLock(commandLock_);
131         for (auto cit = commandList_.begin(); cit != commandList_.end(); cit++) {
132             auto &command = *cit;
133             if (command->GetRemoteDeviceId() != remoteDeviceId) {
134                 continue;
135             }
136             auto cmd = std::dynamic_pointer_cast<Command>(command);
137             if (cmd != nullptr) {
138                 CONN_LOGI(CONN_WIFI_DIRECT, "type=%{public}d, commandId=%{public}u",
139                           static_cast<int>(command->GetType()), command->GetId());
140                 eit->second->SendEvent(cmd);
141                 commandList_.erase(cit);
142                 return;
143             }
144         }
145     }
146 
RejectNegotiateData(WifiDirectProcessor & processor)147     void RejectNegotiateData(WifiDirectProcessor &processor)
148     {
149         std::lock_guard executorLock(executorLock_);
150         processor.SetRejectNegotiateData();
151     }
152 
153     virtual bool ProcessNextCommand(WifiDirectExecutor *executor, std::shared_ptr<WifiDirectProcessor> &processor);
154 
CheckExecutorRunning(const std::string & remoteDeviceId)155     bool CheckExecutorRunning(const std::string &remoteDeviceId)
156     {
157         std::lock_guard executorLock(executorLock_);
158         auto iterator = executors_.find(remoteDeviceId);
159         return iterator != executors_.end();
160     }
161 
162 protected:
163     int ScheduleActiveCommand(const std::shared_ptr<WifiDirectCommand> &command,
164                               std::shared_ptr<WifiDirectExecutor> &executor);
165     static void DumpNegotiateChannel(const WifiDirectNegotiateChannel &channel);
166 
167     static constexpr int MAX_EXECUTOR = 8;
168     std::recursive_mutex executorLock_;
169     std::map<std::string, std::shared_ptr<WifiDirectExecutor>> executors_;
170     std::recursive_mutex commandLock_;
171     std::list<std::shared_ptr<WifiDirectCommand>> commandList_;
172 
173 private:
174     friend WifiDirectSchedulerFactory;
GetInstance()175     static WifiDirectScheduler& GetInstance()
176     {
177         static WifiDirectScheduler instance;
178         return instance;
179     }
180 };
181 }
182 #endif
183