1 /*
2  * Copyright (C) 2021-2022 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 "p2p_group_operating_state.h"
17 #include <dlfcn.h>
18 #include "wifi_p2p_hal_interface.h"
19 #include "p2p_state_machine.h"
20 #include "wifi_logger.h"
21 #include "if_config.h"
22 #include "wifi_config_center.h"
23 #include "wifi_hisysevent.h"
24 #include "wifi_net_agent.h"
25 
26 DEFINE_WIFILOG_P2P_LABEL("P2pGroupOperatingState");
27 
28 #define P2P_ENHANCE_MASK 0x08000000
29 #define BAND_MASK 5
30 #define P2P_IP_ADDR_PREFIX_LEN 24
31 
32 namespace OHOS {
33 namespace Wifi {
P2pGroupOperatingState(P2pStateMachine & stateMachine,WifiP2pGroupManager & groupMgr,WifiP2pDeviceManager & deviceMgr)34 P2pGroupOperatingState::P2pGroupOperatingState(P2pStateMachine &stateMachine, WifiP2pGroupManager &groupMgr,
35     WifiP2pDeviceManager &deviceMgr)
36     : State("P2pGroupOperatingState"),
37       mProcessFunMap(),
38       p2pStateMachine(stateMachine),
39       groupManager(groupMgr),
40       deviceManager(deviceMgr)
41 {}
42 
GoInState()43 void P2pGroupOperatingState::GoInState()
44 {
45     WIFI_LOGI("             GoInState");
46     WifiConfigCenter::GetInstance().SetExplicitGroup(false);
47     Init();
48 }
49 
GoOutState()50 void P2pGroupOperatingState::GoOutState()
51 {
52     WIFI_LOGI("             GoOutState");
53     WifiConfigCenter::GetInstance().SetExplicitGroup(false);
54 }
55 
Init()56 void P2pGroupOperatingState::Init()
57 {
58     mProcessFunMap.insert(
59         std::make_pair(P2P_STATE_MACHINE_CMD::CMD_FORM_GROUP, &P2pGroupOperatingState::ProcessCmdCreateGroup));
60     mProcessFunMap.insert(std::make_pair(
61         P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_STARTED, &P2pGroupOperatingState::ProcessGroupStartedEvt));
62     mProcessFunMap.insert(std::make_pair(
63         P2P_STATE_MACHINE_CMD::CREATE_GROUP_TIMED_OUT, &P2pGroupOperatingState::ProcessCreateGroupTimeOut));
64     mProcessFunMap.insert(std::make_pair(
65         P2P_STATE_MACHINE_CMD::P2P_EVENT_GROUP_REMOVED, &P2pGroupOperatingState::ProcessGroupRemovedEvt));
66     mProcessFunMap.insert(
67         std::make_pair(P2P_STATE_MACHINE_CMD::CMD_P2P_DISABLE, &P2pGroupOperatingState::ProcessCmdDisable));
68     mProcessFunMap.insert(
69         std::make_pair(P2P_STATE_MACHINE_CMD::CMD_REMOVE_GROUP, &P2pGroupOperatingState::ProcessCmdRemoveGroup));
70     mProcessFunMap.insert(
71         std::make_pair(P2P_STATE_MACHINE_CMD::CMD_DELETE_GROUP, &P2pGroupOperatingState::ProcessCmdDeleteGroup));
72     mProcessFunMap.insert(std::make_pair(P2P_STATE_MACHINE_CMD::CMD_HID2D_CREATE_GROUP,
73         &P2pGroupOperatingState::ProcessCmdHid2dCreateGroup));
74 }
75 
ProcessCmdCreateGroup(const InternalMessagePtr msg) const76 bool P2pGroupOperatingState::ProcessCmdCreateGroup(const InternalMessagePtr msg) const
77 {
78     WifiErrorNo ret = WIFI_HAL_OPT_FAILED;
79     const int minValidNetworkid = 0;
80     WifiP2pConfigInternal config;
81     SharedLinkManager::SetGroupUid(msg->GetParam1());
82     msg->GetMessageObj(config);
83     int freq = p2pStateMachine.GetAvailableFreqByBand(config.GetGoBand());
84     int netId = config.GetNetId();
85     if (netId >= minValidNetworkid) {
86         // Restart the group using an existing network ID.
87         WIFI_LOGE("Restart the group using an existing network ID.");
88         if ((!config.GetPassphrase().empty() && config.GetPassphrase().length() >= MIN_PSK_LEN &&
89             config.GetPassphrase().length() <= MAX_PSK_LEN) ||
90             config.GetPassphrase().empty()) {
91             if (!p2pStateMachine.SetGroupConfig(config, false)) {
92                 WIFI_LOGW("Some configuration settings failed!");
93             }
94             ret = WifiP2PHalInterface::GetInstance().GroupAdd(true, netId, freq);
95             p2pStateMachine.UpdateGroupManager();
96             p2pStateMachine.UpdatePersistentGroups();
97         }
98     } else if (netId == PERSISTENT_NET_ID || netId == TEMPORARY_NET_ID) {
99         // Create a new persistence group.
100         WIFI_LOGE("Create a new %{public}s group.", (netId == PERSISTENT_NET_ID) ? "persistence" : "temporary");
101         if (config.GetPassphrase().empty() && config.GetGroupName().empty()) {
102             WifiConfigCenter::GetInstance().SetExplicitGroup(true);
103             ret = WifiP2PHalInterface::GetInstance().GroupAdd((netId == PERSISTENT_NET_ID) ? true : false, netId, freq);
104             p2pStateMachine.UpdateGroupManager();
105             p2pStateMachine.UpdatePersistentGroups();
106         } else if (!config.GetPassphrase().empty() && !config.GetGroupName().empty() &&
107                    config.GetPassphrase().length() >= MIN_PSK_LEN && config.GetPassphrase().length() <= MAX_PSK_LEN) {
108             WifiConfigCenter::GetInstance().SetExplicitGroup(true);
109             if (p2pStateMachine.DealCreateNewGroupWithConfig(config, freq)) {
110                 ret = WIFI_HAL_OPT_OK;
111             }
112         }
113     } else {
114         WIFI_LOGE("Invalid parameter.");
115     }
116     if (WifiErrorNo::WIFI_HAL_OPT_FAILED == ret) {
117         WIFI_LOGE("p2p configure to CreateGroup failed.");
118         p2pStateMachine.BroadcastActionResult(P2pActionCallback::CreateGroup, WIFI_OPT_FAILED);
119         p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
120     } else {
121         const int cgTimedOut = 5000;
122         WIFI_LOGI("p2p configure to CreateGroup successful.");
123         p2pStateMachine.MessageExecutedLater(
124             static_cast<int>(P2P_STATE_MACHINE_CMD::CREATE_GROUP_TIMED_OUT), cgTimedOut);
125         p2pStateMachine.BroadcastActionResult(P2pActionCallback::CreateGroup, WIFI_OPT_SUCCESS);
126     }
127     return EXECUTED;
128 }
129 
ProcessGroupStartedEvt(const InternalMessagePtr msg) const130 bool P2pGroupOperatingState::ProcessGroupStartedEvt(const InternalMessagePtr msg) const
131 {
132     p2pStateMachine.StopTimer(static_cast<int>(P2P_STATE_MACHINE_CMD::CREATE_GROUP_TIMED_OUT));
133     WifiP2pGroupInfo group;
134     msg->GetMessageObj(group);
135     WIFI_LOGI("P2P_EVENT_GROUP_STARTED create group interface name : %{private}s, network name : %{private}s, owner "
136               "address : %{private}s",
137         group.GetInterface().c_str(), group.GetGroupName().c_str(), group.GetOwner().GetDeviceAddress().c_str());
138     if (group.IsPersistent()) {
139         /**
140          * Update groups.
141          */
142         p2pStateMachine.UpdateGroupManager();
143         group.SetNetworkId(groupManager.GetGroupNetworkId(group.GetOwner(), group.GetGroupName()));
144         WIFI_LOGI("the group network id is %{public}d set id is %{public}d",
145             group.GetNetworkId(), groupManager.GetGroupNetworkId(group.GetOwner(), group.GetGroupName()));
146         p2pStateMachine.UpdatePersistentGroups();
147     } else {
148         group.SetNetworkId(TEMPORARY_NET_ID);
149         WIFI_LOGI("This is a temporary group.");
150     }
151 
152     std::string goAddr = group.GetOwner().GetDeviceAddress();
153     if (group.IsGroupOwner()) { /* append setting the device name if this is GO */
154         WifiP2pDevice thisDevice = deviceManager.GetThisDevice();
155         thisDevice.SetP2pDeviceStatus(P2pDeviceStatus::PDS_CONNECTED);
156         thisDevice.SetDeviceAddress(goAddr);
157         group.SetOwner(thisDevice);
158         group.SetExplicitGroup(WifiConfigCenter::GetInstance().IsExplicitGroup());
159     } else {
160         WifiP2pDevice dev = deviceManager.GetDevices(goAddr);
161         dev.SetP2pDeviceStatus(P2pDeviceStatus::PDS_CONNECTED);
162         if (dev.IsValid()) {
163             group.SetOwner(dev);
164         }
165     }
166     group.SetCreatorUid(WifiConfigCenter::GetInstance().GetP2pCreatorUid());
167     WifiConfigCenter::GetInstance().SaveP2pCreatorUid(-1);
168     group.SetP2pGroupStatus(P2pGroupStatus::GS_STARTED);
169     p2pStateMachine.groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, group);
170 
171     if (groupManager.GetCurrentGroup().IsGroupOwner()) {
172         if (!p2pStateMachine.StartDhcpServer()) {
173             WIFI_LOGE("failed to startup Dhcp server.");
174             p2pStateMachine.SendMessage(static_cast<int>(P2P_STATE_MACHINE_CMD::CMD_REMOVE_GROUP));
175         }
176     } else {
177         p2pStateMachine.StartDhcpClientInterface();
178     }
179     SharedLinkManager::IncreaseSharedLink();
180     p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_CONNECTED);
181     if (WifiP2PHalInterface::GetInstance().SetP2pPowerSave(group.GetInterface(), true) != WIFI_HAL_OPT_OK) {
182         WIFI_LOGE("SetP2pPowerSave() failed!");
183     }
184     p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupFormedState);
185     return EXECUTED;
186 }
187 
ProcessCreateGroupTimeOut(const InternalMessagePtr msg) const188 bool P2pGroupOperatingState::ProcessCreateGroupTimeOut(const InternalMessagePtr msg) const
189 {
190     WIFI_LOGI("recv event: %{public}d", msg->GetMessageName());
191     p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
192     return EXECUTED;
193 }
194 
ProcessGroupRemovedEvt(const InternalMessagePtr msg) const195 bool P2pGroupOperatingState::ProcessGroupRemovedEvt(const InternalMessagePtr msg) const
196 {
197     WIFI_LOGI("recv group remove event: %{public}d", msg->GetMessageName());
198     if (groupManager.GetCurrentGroup().IsPersistent()) {
199         groupManager.StashGroups();
200         WifiP2pGroupInfo copy = groupManager.GetCurrentGroup();
201         copy.SetP2pGroupStatus(P2pGroupStatus::GS_CREATED);
202         copy.SetGoIpAddress(std::string(""));
203         groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, copy);
204         groupManager.StashGroups();
205     }
206     if (groupManager.GetCurrentGroup().GetInterface() == p2pStateMachine.p2pDevIface) {
207         p2pStateMachine.p2pDevIface = "";
208     }
209     SharedLinkManager::ClearSharedLinkCount();
210     p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_DISCONNECTED);
211     IpPool::ReleaseIpPool();
212     IfConfig::GetInstance().FlushIpAddr(groupManager.GetCurrentGroup().GetInterface(), IpType::IPTYPE_IPV4);
213     if (groupManager.GetCurrentGroup().IsGroupOwner()) {
214         if (!p2pStateMachine.StopDhcpServer()) {
215             WIFI_LOGW("failed to stop Dhcp server.");
216         }
217     } else {
218         p2pStateMachine.StopP2pDhcpClient();
219         WriteWifiP2pStateHiSysEvent(groupManager.GetCurrentGroup().GetInterface(), P2P_GC, P2P_OFF);
220     }
221     WifiErrorNo ret = WifiP2PHalInterface::GetInstance().P2pFlush();
222     if (ret != WifiErrorNo::WIFI_HAL_OPT_OK) {
223         WIFI_LOGE("call P2pFlush() failed, ErrCode: %{public}d", static_cast<int>(ret));
224     }
225     WifiP2pGroupInfo invalidGroup;
226     groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, invalidGroup);
227     p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
228     return EXECUTED;
229 }
230 
ProcessCmdDisable(const InternalMessagePtr msg) const231 bool P2pGroupOperatingState::ProcessCmdDisable(const InternalMessagePtr msg) const
232 {
233     /**
234      * Before disabling P2P, you need to remove the group.
235      */
236     p2pStateMachine.DelayMessage(msg);
237     return ProcessCmdRemoveGroup(msg);
238 }
239 
ProcessCmdRemoveGroup(const InternalMessagePtr msg) const240 bool P2pGroupOperatingState::ProcessCmdRemoveGroup(const InternalMessagePtr msg) const
241 {
242     /**
243      * Removes a current setup group.
244      */
245     WIFI_LOGI("recv CMD: %{public}d", msg->GetMessageName());
246     WifiP2pGroupInfo group = groupManager.GetCurrentGroup();
247     auto dhcpFunc = [=]() {
248         if (!groupManager.GetCurrentGroup().IsGroupOwner()) {
249             p2pStateMachine.StopP2pDhcpClient();
250         } else {
251             if (!p2pStateMachine.StopDhcpServer()) {
252                 WIFI_LOGW("failed to stop Dhcp server.");
253             }
254         }
255     };
256     if (group.GetP2pGroupStatus() == P2pGroupStatus::GS_STARTED) {
257         /**
258          * Only started groups can be removed.
259          */
260         WIFI_LOGI("now remove : %{private}s.", group.GetInterface().c_str());
261         if (p2pStateMachine.p2pDevIface == group.GetInterface()) {
262             p2pStateMachine.p2pDevIface = "";
263         }
264         WifiNetAgent::GetInstance().DelInterfaceAddress(group.GetInterface(),
265             group.IsGroupOwner() ? group.GetGoIpAddress() : group.GetGcIpAddress(), P2P_IP_ADDR_PREFIX_LEN);
266         if (WifiP2PHalInterface::GetInstance().GroupRemove(group.GetInterface())) {
267             WIFI_LOGE("P2P group removal failed.");
268             dhcpFunc();
269             WifiP2pGroupInfo invalidGroup;
270             groupManager.SetCurrentGroup(WifiMacAddrInfoType::P2P_CURRENT_GROUP_MACADDR_INFO, invalidGroup);
271             p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_DISCONNECTED);
272             p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
273             p2pStateMachine.BroadcastActionResult(P2pActionCallback::RemoveGroup, WIFI_OPT_FAILED);
274             WriteP2pAbDisConnectHiSysEvent(static_cast<int>(P2P_ERROR_CODE::P2P_GROUP_REMOVE_ERROR),
275                 static_cast<int>(P2P_ERROR_RES::P2P_GROUP_REMOVE_FAILURE));
276         } else {
277             p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_DISCONNECTED);
278             WIFI_LOGI("The P2P group is successfully removed.");
279             p2pStateMachine.BroadcastActionResult(P2pActionCallback::RemoveGroup, WIFI_OPT_SUCCESS);
280             WifiErrorNo ret = WifiP2PHalInterface::GetInstance().P2pFlush();
281             if (ret != WifiErrorNo::WIFI_HAL_OPT_OK) {
282                 WIFI_LOGE("call P2pFlush() failed, ErrCode: %{public}d", static_cast<int>(ret));
283             }
284             p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupRemoveState);
285         }
286     } else {
287         WIFI_LOGE("Error:No group can be removed.");
288         p2pStateMachine.ChangeConnectedStatus(P2pConnectedState::P2P_DISCONNECTED);
289         p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
290     }
291     return EXECUTED;
292 }
293 
ProcessCmdDeleteGroup(const InternalMessagePtr msg) const294 bool P2pGroupOperatingState::ProcessCmdDeleteGroup(const InternalMessagePtr msg) const
295 {
296     /**
297      * Delete a group from the group list.
298      */
299     WIFI_LOGI("Delete a group from the group list.");
300     WifiErrorNo ret;
301     WifiP2pGroupInfo group;
302     WifiP2pGroupInfo currentGroup = groupManager.GetCurrentGroup();
303     msg->GetMessageObj(group);
304     int networkId = group.GetNetworkId();
305     /**
306      * If the current group is to be deleted, remove the current group first.
307      */
308     if (currentGroup.GetP2pGroupStatus() == P2pGroupStatus::GS_STARTED) {
309         if (group.GetNetworkId() == currentGroup.GetNetworkId() || group.GetNetworkId() == -1) {
310             ProcessCmdRemoveGroup(msg);
311         } else {
312             p2pStateMachine.SwitchState(&p2pStateMachine.p2pGroupFormedState);
313         }
314     } else {
315         p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
316     }
317 
318     ret = WifiP2PHalInterface::GetInstance().RemoveNetwork(networkId);
319     groupManager.RemoveGroup(group);
320     if (ret) {
321         WIFI_LOGE("P2P group deletion failed.");
322         p2pStateMachine.BroadcastActionResult(P2pActionCallback::DeleteGroup, WIFI_OPT_FAILED);
323     } else {
324         WIFI_LOGI("The P2P group is deleted successfully.");
325         p2pStateMachine.UpdateGroupManager();
326         p2pStateMachine.UpdatePersistentGroups();
327         p2pStateMachine.BroadcastActionResult(P2pActionCallback::DeleteGroup, WIFI_OPT_SUCCESS);
328     }
329     return EXECUTED;
330 }
331 
ProcessCmdHid2dCreateGroup(const InternalMessagePtr msg) const332 bool P2pGroupOperatingState::ProcessCmdHid2dCreateGroup(const InternalMessagePtr msg) const
333 {
334     WifiErrorNo ret = WIFI_HAL_OPT_FAILED;
335     int freq = 0;
336     int freqEnhance = 0;
337     bool isFreqEnhance = false;
338     std::pair<int, FreqType> info;
339     msg->GetMessageObj(info);
340     freq = info.first;
341     isFreqEnhance = (info.second == FreqType::FREQUENCY_160M);
342     WIFI_LOGI("Create a hid2d group, frequency: %{public}d, isFreqEnhance: %{public}d.", freq, isFreqEnhance);
343     do {
344         if (enhanceService_ == nullptr) {
345             WIFI_LOGE("p2p enhanceService_ is nullptr");
346             break;
347         }
348         freqEnhance = enhanceService_->FreqEnhance(freq, isFreqEnhance);
349         if (!(static_cast<unsigned int>(freqEnhance) & (static_cast<unsigned int>(P2P_ENHANCE_MASK))) &&
350             (static_cast<unsigned int>(freqEnhance) % static_cast<unsigned int>(BAND_MASK != 0))) {
351             WIFI_LOGE("FreqEnhance Error :freq = %d, freqEnhance = %d.", freq, freqEnhance);
352         } else {
353             freq = freqEnhance;
354         }
355     } while (0);
356     ret = WifiP2PHalInterface::GetInstance().GroupAdd(true, PERSISTENT_NET_ID, freq);
357     if (WifiErrorNo::WIFI_HAL_OPT_FAILED == ret) {
358         WIFI_LOGE("p2p configure to CreateGroup failed.");
359         p2pStateMachine.BroadcastActionResult(P2pActionCallback::CreateHid2dGroup, WIFI_OPT_FAILED);
360         p2pStateMachine.SwitchState(&p2pStateMachine.p2pIdleState);
361     } else {
362         SharedLinkManager::SetGroupUid(msg->GetParam1());
363         const int cgTimedOut = 5000;
364         WIFI_LOGI("p2p configure hid2d group successful.");
365         p2pStateMachine.MessageExecutedLater(
366             static_cast<int>(P2P_STATE_MACHINE_CMD::CREATE_GROUP_TIMED_OUT), cgTimedOut);
367         p2pStateMachine.BroadcastActionResult(P2pActionCallback::CreateHid2dGroup, WIFI_OPT_SUCCESS);
368     }
369     return EXECUTED;
370 }
371 
ExecuteStateMsg(InternalMessagePtr msg)372 bool P2pGroupOperatingState::ExecuteStateMsg(InternalMessagePtr msg)
373 {
374     if (msg == nullptr) {
375         WIFI_LOGE("fatal error!");
376         return NOT_EXECUTED;
377     }
378     int msgName = msg->GetMessageName();
379     auto iter = mProcessFunMap.find(static_cast<P2P_STATE_MACHINE_CMD>(msgName));
380     if (iter == mProcessFunMap.end()) {
381         return NOT_EXECUTED;
382     }
383     if ((this->*(iter->second))(msg)) {
384         return EXECUTED;
385     } else {
386         return NOT_EXECUTED;
387     }
388 }
389 
SetEnhanceService(IEnhanceService * enhanceService)390 void P2pGroupOperatingState::SetEnhanceService(IEnhanceService* enhanceService)
391 {
392     enhanceService_ = enhanceService;
393 }
394 
395 }  // namespace Wifi
396 }  // namespace OHOS
397