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