1 /*
2 * Copyright (C) 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 "pan_statemachine.h"
17 #include "pan_service.h"
18
19 namespace OHOS {
20 namespace bluetooth {
PanStateMachine(const std::string & address)21 PanStateMachine::PanStateMachine(const std::string &address)
22 : address_(address), panBnep_(address)
23 {}
24
Init()25 void PanStateMachine::Init()
26 {
27 connTimer_ = std::make_unique<utility::Timer>(
28 std::bind(&bluetooth::PanStateMachine::ConnectionTimeout, this));
29 disconnTimer_ = std::make_unique<utility::Timer>(
30 std::bind(&bluetooth::PanStateMachine::DisonnectionTimeout, this));
31
32 std::unique_ptr<utility::StateMachine::State> disconnectedState =
33 std::make_unique<PanDisconnectedState>(DISCONNECTED, *this);
34 std::unique_ptr<utility::StateMachine::State> connectingState =
35 std::make_unique<PanConnectingState>(CONNECTING, *this);
36 std::unique_ptr<utility::StateMachine::State> disconnectingState =
37 std::make_unique<PanDisconnectingState>(DISCONNECTING, *this);
38 std::unique_ptr<utility::StateMachine::State> connectedState =
39 std::make_unique<PanConnectedState>(CONNECTED, *this);
40
41 Move(disconnectedState);
42 Move(connectingState);
43 Move(disconnectingState);
44 Move(connectedState);
45
46 InitState(DISCONNECTED);
47 }
48
IsRemoving() const49 bool PanStateMachine::IsRemoving() const
50 {
51 return isRemoving_;
52 }
53
SetRemoving(bool isRemoving)54 void PanStateMachine::SetRemoving(bool isRemoving)
55 {
56 isRemoving_ = isRemoving;
57 }
58
GetDeviceLcid()59 uint16_t PanStateMachine::GetDeviceLcid()
60 {
61 return panBnep_.GetLcid();
62 }
63
ProcessL2capConnectionEvent(const PanMessage & event)64 void PanStateMachine::ProcessL2capConnectionEvent(
65 const PanMessage &event)
66 {
67 LOG_DEBUG("[PAN Machine]%{public}s():event[%{public}s]", __FUNCTION__,
68 PanStateMachine::GetEventName(event.what_).c_str());
69 panBnep_.ProcessEvent(event);
70 }
71
GetDeviceAdress()72 std::string PanStateMachine::GetDeviceAdress()
73 {
74 return address_;
75 }
76
Entry()77 void PanDisconnectedState::Entry()
78 {
79 stateMachine_.ProcessDeferredMessage();
80
81 if (isReentry_) {
82 stateMachine_.SetRemoving(true);
83 PanService *service = PanService::GetService();
84 if (service != nullptr) {
85 service->RemoveStateMachine(stateMachine_.GetDeviceAdress());
86 } else {
87 LOG_ERROR("[PAN Machine]%{public}s():PanService is nullptr!", __FUNCTION__);
88 }
89 stateMachine_.NotifyStateTransitions();
90 }
91 }
92
Exit()93 void PanDisconnectedState::Exit()
94 {
95 isReentry_ = true;
96 }
97
Dispatch(const utility::Message & msg)98 bool PanDisconnectedState::Dispatch(const utility::Message &msg)
99 {
100 PanMessage &event = (PanMessage &)msg;
101 LOG_DEBUG("[PAN Machine]%{public}s():[Disconnected][%{public}s]",
102 __FUNCTION__, PanStateMachine::GetEventName(event.what_).c_str());
103 switch (event.what_) {
104 case PAN_INT_OPEN_EVT:
105 stateMachine_.ProcessOpenEvent(event);
106 Transition(PanStateMachine::CONNECTING);
107 break;
108 case PAN_OPEN_CMPL_EVT:
109 Transition(PanStateMachine::CONNECTED);
110 break;
111 default:
112 break;
113 }
114 return true;
115 }
116
117
Entry()118 void PanConnectingState::Entry()
119 {
120 stateMachine_.NotifyStateTransitions();
121 stateMachine_.StartConnectionTimer();
122 }
Exit()123 void PanConnectingState::Exit()
124 {
125 stateMachine_.StopConnectionTimer();
126 }
127
Dispatch(const utility::Message & msg)128 bool PanConnectingState::Dispatch(const utility::Message &msg)
129 {
130 PanMessage &event = (PanMessage &)msg;
131 LOG_DEBUG("[PAN Machine]%{public}s():[Connecting][%{public}s]", __FUNCTION__,
132 PanStateMachine::GetEventName(event.what_).c_str());
133 switch (event.what_) {
134 case PAN_API_CLOSE_EVT:
135 stateMachine_.AddDeferredMessage(event);
136 break;
137 case PAN_INT_OPEN_EVT:
138 stateMachine_.ProcessOpenEvent(event);
139 Transition(PanStateMachine::CONNECTING);
140 break;
141 case PAN_INT_CLOSE_EVT:
142 stateMachine_.ProcessCloseEvent(event);
143 Transition(PanStateMachine::DISCONNECTED);
144 break;
145 case PAN_OPEN_CMPL_EVT:
146 stateMachine_.ProcessOpenComplete(event);
147 Transition(PanStateMachine::CONNECTED);
148 break;
149 default:
150 break;
151 }
152 return true;
153 }
154
Entry()155 void PanDisconnectingState::Entry()
156 {
157 stateMachine_.NotifyStateTransitions();
158 stateMachine_.StartDisconnectionTimer();
159 }
160
Exit()161 void PanDisconnectingState::Exit()
162 {
163 stateMachine_.StopDisconnectionTimer();
164 }
165
Dispatch(const utility::Message & msg)166 bool PanDisconnectingState::Dispatch(const utility::Message &msg)
167 {
168 PanMessage &event = (PanMessage &)msg;
169 LOG_DEBUG("[PAN Machine]%{public}s():[Disconnecting][%{public}s]", __FUNCTION__,
170 PanStateMachine::GetEventName(event.what_).c_str());
171 switch (event.what_) {
172 case PAN_INT_OPEN_EVT:
173 stateMachine_.ProcessOpenEvent(event);
174 Transition(PanStateMachine::CONNECTING);
175 break;
176 case PAN_INT_CLOSE_EVT:
177 stateMachine_.ProcessCloseEvent(event);
178 Transition(PanStateMachine::DISCONNECTED);
179 break;
180 case PAN_OPEN_CMPL_EVT:
181 Transition(PanStateMachine::CONNECTED);
182 break;
183 case PAN_DISCONNECTION_TIMEOUT_EVT:
184 Transition(PanStateMachine::CONNECTED);
185 break;
186 default:
187 break;
188 }
189 return true;
190 }
191
Entry()192 void PanConnectedState::Entry()
193 {
194 stateMachine_.ProcessDeferredMessage();
195 stateMachine_.NotifyStateTransitions();
196 }
197
Exit()198 void PanConnectedState::Exit()
199 {
200 }
201
Dispatch(const utility::Message & msg)202 bool PanConnectedState::Dispatch(const utility::Message &msg)
203 {
204 PanMessage &event = (PanMessage &)msg;
205 LOG_DEBUG("[PAN Machine]%{public}s():[Connected][%{public}s]", __FUNCTION__,
206 PanStateMachine::GetEventName(event.what_).c_str());
207 switch (event.what_) {
208 case PAN_API_CLOSE_EVT:
209 stateMachine_.ProcessCloseReqEvent(event);
210 Transition(PanStateMachine::DISCONNECTING);
211 break;
212 case PAN_INT_CLOSE_EVT:
213 stateMachine_.ProcessCloseEvent(event);
214 Transition(PanStateMachine::DISCONNECTED);
215 break;
216 case PAN_API_WRITE_DATA_EVT:
217 stateMachine_.ProcessSendData(event);
218 break;
219 case PAN_INT_DATA_EVT:
220 stateMachine_.ProcessReciveData(event);
221 break;
222 default:
223 break;
224 }
225 return true;
226 }
227
ProcessOpenEvent(const PanMessage & msg)228 void PanStateMachine::ProcessOpenEvent(const PanMessage &msg)
229 {
230 PanMessage event(PAN_OPEN_CMPL_EVT);
231 event.dev_ = address_;
232 PanService::GetService()->PostEvent(event);
233 }
234
ProcessCloseReqEvent(const PanMessage & msg)235 void PanStateMachine::ProcessCloseReqEvent(const PanMessage &msg)
236 {
237 panBnep_.Disconnect();
238 }
239
ProcessCloseEvent(const PanMessage & msg)240 void PanStateMachine::ProcessCloseEvent(const PanMessage &msg)
241 {
242 PanService::GetService()->CloseNetwork(address_);
243 }
244
ProcessReciveData(const PanMessage & msg)245 void PanStateMachine::ProcessReciveData(const PanMessage &msg)
246 {
247 uint8_t* data = nullptr;
248 int dataLength = 0;
249 if (msg.data_ != nullptr) {
250 data = msg.data_->get();
251 dataLength = msg.dataLength_;
252 }
253 PanService::GetService()->WriteNetworkData(address_, msg.ethernetHeader_, data, dataLength);
254 }
255
ProcessSendData(const PanMessage & msg)256 void PanStateMachine::ProcessSendData(const PanMessage &msg)
257 {
258 uint8_t* data = nullptr;
259 int dataLength = 0;
260 if (msg.data_ != nullptr) {
261 data = msg.data_->get();
262 dataLength = msg.dataLength_;
263 }
264 panBnep_.SendData(msg.ethernetHeader_, data, dataLength);
265 }
266
ProcessOpenComplete(const PanMessage & msg)267 void PanStateMachine::ProcessOpenComplete(const PanMessage &msg)
268 {
269 if (!PanService::GetService()->IsTetheringOn()) {
270 PanMessage event(PAN_API_CLOSE_EVT);
271 event.dev_ = address_;
272 PanService::GetService()->PostEvent(event);
273 return;
274 }
275 PanService::GetService()->OpenNetwork();
276 }
277
GetDeviceStateInt() const278 int PanStateMachine::GetDeviceStateInt() const
279 {
280 return static_cast<const PanState*>(GetState())->GetStateInt();
281 }
282
StartConnectionTimer() const283 void PanStateMachine::StartConnectionTimer() const
284 {
285 connTimer_->Start(CONNECTION_TIMEOUT_MS);
286 LOG_INFO("[PAN Machine]%{public}s():Start connection timer!", __FUNCTION__);
287 }
288
StopConnectionTimer() const289 void PanStateMachine::StopConnectionTimer() const
290 {
291 connTimer_->Stop();
292 LOG_INFO("[PAN Machine]%{public}s():Stop connection timer!", __FUNCTION__);
293 }
294
ConnectionTimeout() const295 void PanStateMachine::ConnectionTimeout() const
296 {
297 PanMessage event(PAN_CONNECTION_TIMEOUT_EVT);
298 event.dev_ = address_;
299 PanService::GetService()->PostEvent(event);
300 }
301
StartDisconnectionTimer() const302 void PanStateMachine::StartDisconnectionTimer() const
303 {
304 disconnTimer_->Start(DISCONNECTION_TIMEOUT_MS);
305 LOG_INFO("[PAN Machine]%{public}s():Start disconnection timer!", __FUNCTION__);
306 }
307
StopDisconnectionTimer() const308 void PanStateMachine::StopDisconnectionTimer() const
309 {
310 disconnTimer_->Stop();
311 LOG_INFO("[PAN Machine]%{public}s():Stop disconnection timer!", __FUNCTION__);
312 }
313
DisonnectionTimeout() const314 void PanStateMachine::DisonnectionTimeout() const
315 {
316 PanMessage event(PAN_DISCONNECTION_TIMEOUT_EVT);
317 event.dev_ = address_;
318 PanService::GetService()->PostEvent(event);
319 }
320
GetEventName(int what)321 std::string PanStateMachine::GetEventName(int what)
322 {
323 switch (what) {
324 case PAN_API_CLOSE_EVT:
325 return "PAN_API_CLOSE_EVENT";
326 case PAN_INT_OPEN_EVT:
327 return "PAN_INT_OPEN_EVENT";
328 case PAN_INT_CLOSE_EVT:
329 return "PAN_INT_CLOSE_EVENT";
330 case PAN_OPEN_CMPL_EVT:
331 return "PAN_OPEN_CMPL_EVENT";
332 case PAN_API_WRITE_DATA_EVT:
333 return "PAN_API_WRITE_DATA_EVENT";
334 case PAN_INT_DATA_EVT:
335 return "PAN_INT_DATA_EVENT";
336 case PAN_DISCONNECTION_TIMEOUT_EVT:
337 return "PAN_DISCONNECTION_TIMEOUT_EVT";
338 default:
339 return "Unknown";
340 }
341 }
342
NotifyStateTransitions()343 void PanStateMachine::NotifyStateTransitions()
344 {
345 PanService *service = PanService::GetService();
346 int toState = GetDeviceStateInt();
347 if (service != nullptr) {
348 RawAddress device(address_);
349 if ((preState_ != toState) && (preState_ <= PAN_STATE_CONNECTED)
350 && (toState <= PAN_STATE_CONNECTED)) {
351 service->NotifyStateChanged(device, toState);
352 }
353 }
354
355 preState_ = toState;
356 }
357
AddDeferredMessage(const PanMessage & msg)358 void PanStateMachine::AddDeferredMessage(const PanMessage &msg)
359 {
360 deferMsgs_.push_back(msg);
361 }
362
ProcessDeferredMessage()363 void PanStateMachine::ProcessDeferredMessage()
364 {
365 auto size = deferMsgs_.size();
366 while (size-- > 0 && !deferMsgs_.empty()) {
367 PanMessage event = deferMsgs_.front();
368 deferMsgs_.pop_front();
369 PanService::GetService()->PostEvent(event);
370 }
371 }
372 } // namespace bluetooth
373 } // namespace OHOS
374