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 "rfcomm_defs.h"
17 
18 typedef int (*SessionActionFunc)(RfcommSessionInfo *session, const void *data);
19 typedef struct {
20     RfcommSessionEvent eventId;
21     SessionActionFunc fn;
22 } RfcommSessionEvtAction;
23 
24 static int RfcommOpenSession(RfcommSessionInfo *session, const void *data);
25 static int RfcommCloseSession(RfcommSessionInfo *session, const void *data);
26 static int RfcommRecvSessionSecurityRslt(RfcommSessionInfo *session, const void *data);
27 static int RfcommRecvConnectReq(RfcommSessionInfo *session, const void *data);
28 static int RfcommRecvReqConnectRslt(RfcommSessionInfo *session, const void *data);
29 static int RfcommRecvConnectRsp(RfcommSessionInfo *session, const void *data);
30 static int RfcommRecvConfigReq(RfcommSessionInfo *session, const void *data);
31 static int RfcommRecvConfigRsp(RfcommSessionInfo *session, const void *data);
32 static int RfcommRecvDisconnectReq(RfcommSessionInfo *session, const void *data);
33 static int RfcommRecvSabm0(RfcommSessionInfo *session, const void *data);
34 static int RfcommRecvDisc0(RfcommSessionInfo *session, const void *data);
35 static int RfcommRecvUa0(RfcommSessionInfo *session, const void *data);
36 static int RfcommRecvDm0(RfcommSessionInfo *session, const void *data);
37 static int RfcommRecvFconReq(RfcommSessionInfo *session, const void *data);
38 static int RfcommRecvFconRsp(RfcommSessionInfo *session, const void *data);
39 static int RfcommRecvFcoffReq(RfcommSessionInfo *session, const void *data);
40 static int RfcommRecvFcoffRsp(RfcommSessionInfo *session, const void *data);
41 static int RfcommRecvTestReq(RfcommSessionInfo *session, const void *data);
42 static int RfcommRecvTestRsp(RfcommSessionInfo *session, const void *data);
43 static int RfcommRecvNsc(RfcommSessionInfo *session, const void *data);
44 static int RfcommRecvLinkLoss(RfcommSessionInfo *session, const void *data);
45 static int RfcommRecvTimeOut(RfcommSessionInfo *session, const void *data);
46 static int RfcommRestartSession(RfcommSessionInfo *session);
47 static int RfcommAcceptPeerConnectReq(RfcommSessionInfo *session);
48 
49 static RfcommSessionEvtAction g_sessionEvtActTbl[EV_SESSION_EV_MAX] = {
50     {EV_SESSION_SEND_OPEN_REQ, RfcommOpenSession},
51     {EV_SESSION_SEND_CLOSE_REQ, RfcommCloseSession},
52     {EV_SESSION_RECV_SECURITY_RESULT, RfcommRecvSessionSecurityRslt},
53     {EV_SESSION_RECV_REQ_CONNECT_RESULT, RfcommRecvReqConnectRslt},
54     {EV_SESSION_RECV_CONNECT_REQ, RfcommRecvConnectReq},
55     {EV_SESSION_RECV_CONNECT_RSP, RfcommRecvConnectRsp},
56     {EV_SESSION_RECV_CONFIG_REQ, RfcommRecvConfigReq},
57     {EV_SESSION_RECV_CONFIG_RSP, RfcommRecvConfigRsp},
58     {EV_SESSION_RECV_DISCONNECT_REQ, RfcommRecvDisconnectReq},
59     {EV_SESSION_RECV_SABM0, RfcommRecvSabm0},
60     {EV_SESSION_RECV_DISC0, RfcommRecvDisc0},
61     {EV_SESSION_RECV_UA0, RfcommRecvUa0},
62     {EV_SESSION_RECV_DM0, RfcommRecvDm0},
63     {EV_SESSION_RECV_FCON_REQ, RfcommRecvFconReq},
64     {EV_SESSION_RECV_FCON_RSP, RfcommRecvFconRsp},
65     {EV_SESSION_RECV_FCOFF_REQ, RfcommRecvFcoffReq},
66     {EV_SESSION_RECV_FCOFF_RSP, RfcommRecvFcoffRsp},
67     {EV_SESSION_RECV_TEST_REQ, RfcommRecvTestReq},
68     {EV_SESSION_RECV_TEST_RSP, RfcommRecvTestRsp},
69     {EV_SESSION_RECV_NSC, RfcommRecvNsc},
70     {EV_SESSION_RECV_LINK_LOSS, RfcommRecvLinkLoss},
71     {EV_SESSION_TIMEOUT, RfcommRecvTimeOut}
72 };
73 
74 /**
75  * @brief State machine for handling events related to session.
76  *
77  * @param session The pointer of the session in the session list.
78  * @param event   The event id.
79  * @param data    Data related to the event.
80  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
81  */
RfcommSessionEvtFsm(RfcommSessionInfo * session,RfcommSessionEvent event,const void * data)82 int RfcommSessionEvtFsm(RfcommSessionInfo *session, RfcommSessionEvent event, const void *data)
83 {
84     LOG_INFO("%{public}s", __func__);
85 
86     int ret = 0;
87 
88     for (int cnt = 0; cnt < EV_SESSION_EV_MAX; cnt++) {
89         if (g_sessionEvtActTbl[cnt].eventId == event) {
90             ret = g_sessionEvtActTbl[cnt].fn(session, data);
91             break;
92         }
93     }
94 
95     return ret;
96 }
97 
98 /**
99  * @brief Processing after receiving connect session request.
100  *
101  * @param session The pointer of the session in the session list.
102  * @param data    Data related to the event.
103  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
104  */
RfcommOpenSession(RfcommSessionInfo * session,const void * data)105 int RfcommOpenSession(RfcommSessionInfo *session, const void *data)
106 {
107     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
108 
109     if (data == NULL) {
110         return RFCOMM_ERR_PARAM;
111     }
112 
113     int ret = 0;
114     uint8_t scn = *(uint8_t *)data;
115 
116     switch (session->sessionState) {
117         case ST_SESSION_CLOSED:
118             session->sessionState = ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT;
119             ret = RfcommCheckSessionSecurity(session, scn, false);
120             break;
121         case ST_SESSION_DISC0_REQ_WAIT_UA0:
122             // fall-through
123         case ST_SESSION_CLOSING:
124             // If a connection request is received during the closing process,
125             // the status is set to ST_SESSION_WAIT_RESTART, and after the UA response is received,
126             // the reconnection process is performed.
127             session->sessionState = ST_SESSION_WAIT_RESTART;
128             break;
129         default:
130             break;
131     }
132 
133     return ret;
134 }
135 
RfcommRecvReqConnectRslt(RfcommSessionInfo * session,const void * data)136 int RfcommRecvReqConnectRslt(RfcommSessionInfo *session, const void *data)
137 {
138     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
139 
140     if (data == NULL) {
141         return RFCOMM_ERR_PARAM;
142     }
143 
144     RfcommReqConnectRslt connectRslt;
145     (void)memcpy_s(&connectRslt, sizeof(RfcommReqConnectRslt), data, sizeof(RfcommReqConnectRslt));
146 
147     if (session->sessionState != ST_SESSION_WAIT_CONNECT_REQ_RESULT) {
148         return RFCOMM_SUCCESS;
149     }
150 
151     LOG_INFO("%{public}s pendingL2capId :%hu.", __func__, session->pendingL2capId);
152     if (session->pendingL2capId != 0) {
153         RfcommStopSessionTimer(session);
154         if ((connectRslt.result == RFCOMM_SUCCESS) && (connectRslt.lcid != 0)) {
155             RfcommSendDisconnectReq(connectRslt.lcid);
156         }
157         // Accept peer's connection request.
158         return RfcommAcceptPeerConnectReq(session);
159     }
160 
161     if ((connectRslt.result != RFCOMM_SUCCESS) || (connectRslt.lcid == 0)) {
162         // Notify all channels on the session that connection failed.
163         RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
164         // Remove all channels on session.
165         RfcommRemoveAllChannelOnSession(session);
166         // Destroy session from session list.
167         RfcommRemoveSession(session);
168     } else {
169         session->l2capId = connectRslt.lcid;
170         session->sessionState = ST_SESSION_WAIT_CONNECT_RSP;
171     }
172 
173     return RFCOMM_SUCCESS;
174 }
175 
176 /**
177  * @brief Processing after receiving connect response from L2CAP.
178  *
179  * @param session The pointer of the session in the session list.
180  * @param data    Data related to the event.
181  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
182  */
RfcommRecvConnectRsp(RfcommSessionInfo * session,const void * data)183 int RfcommRecvConnectRsp(RfcommSessionInfo *session, const void *data)
184 {
185     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
186 
187     if (data == NULL) {
188         return RFCOMM_ERR_PARAM;
189     }
190 
191     uint16_t result = *(uint16_t *)data;
192     L2capConfigInfo config;
193     (void)memset_s(&config, sizeof(config), 0, sizeof(config));
194 
195     if (session->sessionState != ST_SESSION_WAIT_CONNECT_RSP) {
196         LOG_DEBUG("%{public}s:Session state is not WAIT_CONNECT_RSP.", __func__);
197         return RFCOMM_FAILED;
198     }
199 
200     LOG_INFO("%{public}s pendingL2capId:%hu.", __func__, session->pendingL2capId);
201     if (result != L2CAP_CONNECTION_SUCCESSFUL) {
202         if (session->pendingL2capId != 0) {
203             RfcommStopSessionTimer(session);
204             // Accept peer's connection request.
205             return RfcommAcceptPeerConnectReq(session);
206         }
207         // Notify all channels on the session that connection failed.
208         RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
209         // Remove all channels on session.
210         RfcommRemoveAllChannelOnSession(session);
211         // Destroy session.
212         RfcommRemoveSession(session);
213 
214         return RFCOMM_SUCCESS;
215     }
216 
217     if (session->pendingL2capId != 0) {
218         RfcommStopSessionTimer(session);
219         RfcommSendConnectRsp(session->pendingL2capId, session->pendingId, L2CAP_NO_RESOURCES_AVAILABLE, 0);
220         session->pendingL2capId = 0;
221         session->pendingId = 0;
222     }
223 
224     config.rfc.mode = 0;  // Basic mode
225     config.flushTimeout = 0xFFFF;
226     config.mtu = session->l2capLocalMtu;
227     config.fcs = 0x01;
228 
229     session->sessionState = ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP;
230 
231     return RfcommSendConfigReq(session->l2capId, &config);
232 }
233 
234 /**
235  * @brief Processing after receiving config response from L2CAP.
236  *
237  * @param session The pointer of the session in the session list.
238  * @param data    Data related to the event.
239  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
240  */
RfcommRecvConfigRsp(RfcommSessionInfo * session,const void * data)241 int RfcommRecvConfigRsp(RfcommSessionInfo *session, const void *data)
242 {
243     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
244 
245     if (data == NULL) {
246         return RFCOMM_ERR_PARAM;
247     }
248 
249     int ret = 0;
250     RfcommConfigRspInfo *configResult = (RfcommConfigRspInfo *)data;
251 
252     if (configResult->result != L2CAP_SUCCESS) {
253         RfcommSendDisconnectReq(session->l2capId);
254         // Notify all channels on the session that connection failed.
255         RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
256         // Remove all channels on session.
257         RfcommRemoveAllChannelOnSession(session);
258         // Destroy session.
259         RfcommRemoveSession(session);
260 
261         return RFCOMM_SUCCESS;
262     }
263 
264     switch (session->sessionState) {
265         case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP:
266             session->sessionState = ST_SESSION_INITIATOR_WAIT_CONFIG_REQ;
267             break;
268         case ST_SESSION_INITIATOR_WAIT_CONFIG_RSP:
269             ret = RfcommSendSabm(session, CONTROL_DLCI);
270             session->sessionState = ST_SESSION_SABM0_REQ_WAIT_UA0;
271             RfcommStartSessionTimer(session, T1_SABM_DISC);
272             break;
273         case ST_SESSION_RESPONDER_WAIT_CONFIG_REQ_AND_RSP:
274             session->sessionState = ST_SESSION_RESPONDER_WAIT_CONFIG_REQ;
275             break;
276         case ST_SESSION_RESPONDER_WAIT_CONFIG_RSP:
277             session->sessionState = ST_SESSION_WAIT_SABM0;
278             break;
279         default:
280             break;
281     }
282 
283     return ret;
284 }
285 
286 /**
287  * @brief Processing after receiving config request from L2CAP.
288  *
289  * @param session The pointer of the session in the session list.
290  * @param data    Data related to the event.
291  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
292  */
RfcommRecvConfigReq(RfcommSessionInfo * session,const void * data)293 int RfcommRecvConfigReq(RfcommSessionInfo *session, const void *data)
294 {
295     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
296 
297     if (data == NULL) {
298         return RFCOMM_ERR_PARAM;
299     }
300 
301     RfcommConfigReqInfo reqInfo;
302     (void)memcpy_s(&reqInfo, sizeof(RfcommConfigReqInfo), (RfcommConfigReqInfo *)data, sizeof(RfcommConfigReqInfo));
303 
304     session->l2capPeerMtu = reqInfo.cfg.mtu;
305 
306     if (reqInfo.cfg.rfc.mode != 0) {
307         LOG_DEBUG("%{public}s mode is not basic mode, reconfig.", __func__);
308 
309         (void)memset_s(&reqInfo.cfg, sizeof(L2capConfigInfo), 0x00, sizeof(L2capConfigInfo));
310         reqInfo.cfg.rfc.mode = 0;
311         reqInfo.cfg.flushTimeout = 0xFFFF;
312         reqInfo.cfg.fcs = 0x01;
313         reqInfo.cfg.mtu = session->l2capPeerMtu;
314 
315         return RfcommSendConfigRsp(session->l2capId, reqInfo.id, &reqInfo.cfg, L2CAP_UNACCEPTABLE_PARAMETERS);
316     }
317 
318     int ret = RfcommSendConfigRsp(session->l2capId, reqInfo.id, &reqInfo.cfg, 0);
319 
320     switch (session->sessionState) {
321         case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP:
322             session->sessionState = ST_SESSION_INITIATOR_WAIT_CONFIG_RSP;
323             break;
324         case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ:
325             ret = RfcommSendSabm(session, CONTROL_DLCI);
326             session->sessionState = ST_SESSION_SABM0_REQ_WAIT_UA0;
327             RfcommStartSessionTimer(session, T1_SABM_DISC);
328             break;
329         case ST_SESSION_RESPONDER_WAIT_CONFIG_REQ_AND_RSP:
330             session->sessionState = ST_SESSION_RESPONDER_WAIT_CONFIG_RSP;
331             break;
332         case ST_SESSION_RESPONDER_WAIT_CONFIG_REQ:
333             session->sessionState = ST_SESSION_WAIT_SABM0;
334             break;
335         default:
336             break;
337     }
338     return ret;
339 }
340 
341 /**
342  * @brief Processing after receiving UA(DLCI0) response from peer.
343  *
344  * @param session The pointer of the session in the session list.
345  * @param data    Data related to the event.
346  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
347  */
RfcommRecvUa0(RfcommSessionInfo * session,const void * data)348 int RfcommRecvUa0(RfcommSessionInfo *session, const void *data)
349 {
350     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
351 
352     (void)data;
353     int ret = 0;
354 
355     switch (session->sessionState) {
356         case ST_SESSION_SABM0_REQ_WAIT_UA0:
357             session->sessionState = ST_SESSION_CONNECTED;
358             // Stop timer.
359             RfcommStopSessionTimer(session);
360             // After the session is successfully connected,
361             // connect all links under the session.
362             RfcommOpenAllChannelOnSession(session);
363             break;
364         case ST_SESSION_DISC0_REQ_WAIT_UA0:
365             // Stop timer.
366             RfcommStopSessionTimer(session);
367             // L2CAP disconnect.
368             ret = RfcommSendDisconnectReq(session->l2capId);
369             // Remove all channels on session.
370             RfcommRemoveAllChannelOnSession(session);
371             // Destroy session.
372             RfcommRemoveSession(session);
373             break;
374         case ST_SESSION_WAIT_RESTART:
375             // Stop timer.
376             RfcommStopSessionTimer(session);
377             // L2CAP disconnect.
378             RfcommSendDisconnectReq(session->l2capId);
379             // Restart the session, init the session information first.
380             ret = RfcommRestartSession(session);
381             break;
382         default:
383             break;
384     }
385     return ret;
386 }
387 
388 /**
389  * @brief Processing after receiving connect request from L2CAP.
390  *
391  * @param session The pointer of the session in the session list.
392  * @param data    Data related to the event.
393  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
394  */
RfcommRecvConnectReq(RfcommSessionInfo * session,const void * data)395 int RfcommRecvConnectReq(RfcommSessionInfo *session, const void *data)
396 {
397     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
398 
399     if (data == NULL) {
400         return RFCOMM_ERR_PARAM;
401     }
402 
403     int ret = 0;
404     RfcommRecvConnectedInfo connectedInfo;
405     (void)memcpy_s(&connectedInfo, sizeof(RfcommRecvConnectedInfo), data, sizeof(RfcommRecvConnectedInfo));
406 
407     switch (session->sessionState) {
408         case ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT:
409             session->id = connectedInfo.id;
410             session->l2capId = connectedInfo.lcid;
411             session->isInitiator = false;
412             RfcommUpdateChannelDirectionBit(session, false);
413             // fall-through
414         case ST_SESSION_CLOSED:
415             session->sessionState = ST_SESSION_RESPONDER_WAIT_SECURITY_RESULT;
416             ret = RfcommCheckSessionSecurity(session, 0, true);
417             break;
418         case ST_SESSION_WAIT_CONNECT_REQ_RESULT:
419             // fall-through
420         case ST_SESSION_WAIT_CONNECT_RSP:
421             session->pendingL2capId = connectedInfo.lcid;
422             session->pendingId = connectedInfo.id;
423             uint32_t randomNum = RandomGenerate();
424             uint8_t timer = randomNum % RFCOMM_NUM_TEN;
425             RfcommStartSessionTimer(session, timer);
426             break;
427         default:
428             ret = RfcommSendConnectRsp(session->l2capId, session->id, L2CAP_NO_RESOURCES_AVAILABLE, 0);
429             break;
430     }
431 
432     return ret;
433 }
434 
435 /**
436  * @brief Processing after receiving SABM(DLCI0) request from peer.
437  *
438  * @param session The pointer of the session in the session list.
439  * @param data    Data related to the event.
440  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
441  */
RfcommRecvSabm0(RfcommSessionInfo * session,const void * data)442 int RfcommRecvSabm0(RfcommSessionInfo *session, const void *data)
443 {
444     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
445 
446     (void)data;
447 
448     if (session->sessionState != ST_SESSION_WAIT_SABM0) {
449         LOG_DEBUG("%{public}s:Session state is not WAIT_SABM0.", __func__);
450         return RFCOMM_FAILED;
451     }
452 
453     int ret = RfcommSendUa(session, CONTROL_DLCI);
454     session->sessionState = ST_SESSION_CONNECTED;
455     // After the session is successfully connected,
456     // connect all links under the session.
457     RfcommOpenAllChannelOnSession(session);
458     return ret;
459 }
460 
461 /**
462  * @brief Processing after receiving DISC(DLCI0) request from peer.
463  *
464  * @param session The pointer of the session in the session list.
465  * @param data    Data related to the event.
466  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
467  */
RfcommRecvDisc0(RfcommSessionInfo * session,const void * data)468 int RfcommRecvDisc0(RfcommSessionInfo *session, const void *data)
469 {
470     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
471 
472     (void)data;
473     int ret;
474     bool sessionValid = false;
475 
476     switch (session->sessionState) {
477         case ST_SESSION_SABM0_REQ_WAIT_UA0:
478             session->sessionState = ST_SESSION_CLOSING;
479             ret = RfcommSendUa(session, CONTROL_DLCI);
480             // Notify all channels on the session that connection failed.
481             RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
482             // Remove all channels on session.
483             RfcommRemoveAllChannelOnSession(session);
484             break;
485         case ST_SESSION_DISC0_REQ_WAIT_UA0:
486             ret = RfcommSendUa(session, CONTROL_DLCI);
487             break;
488         case ST_SESSION_CONNECTED:
489             session->sessionState = ST_SESSION_CLOSING;
490             ret = RfcommSendUa(session, CONTROL_DLCI);
491             // Delete all channels on the session(except the channel to be connected).
492             RfcommRemoveInvalidChannelOnSession(session);
493             // Check if the session is valid.
494             sessionValid = RfcommCheckSessionValid(session);
495             if (sessionValid) {
496                 // If there are channels to be connected, set RESTART of session's state.
497                 session->sessionState = ST_SESSION_WAIT_RESTART;
498                 RfcommResetAllChannelOnSession(session);
499             }
500             break;
501         default:
502             ret = RfcommSendDm(session, CONTROL_DLCI, true);
503             break;
504     }
505 
506     return ret;
507 }
508 
509 /**
510  * @brief Processing after receiving link loss notification from L2CAP.
511  *
512  * @param session The pointer of the session in the session list.
513  * @param data    Data related to the event.
514  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
515  */
RfcommRecvLinkLoss(RfcommSessionInfo * session,const void * data)516 int RfcommRecvLinkLoss(RfcommSessionInfo *session, const void *data)
517 {
518     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
519 
520     if (data == NULL) {
521         return RFCOMM_ERR_PARAM;
522     }
523 
524     uint8_t reason = *(uint8_t *)data;
525 
526     if (reason == L2CAP_STATE_COLLISION) {
527         LOG_DEBUG("%{public}s Connect request error.Retry!", __func__);
528         return RfcommRestartSession(session);
529     }
530 
531     switch (session->sessionState) {
532         case ST_SESSION_CONNECTED:
533             // Notify all channels on the session that disconnection.
534             RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_DISCONNECTED);
535             break;
536         default:
537             // Stop timer.
538             RfcommStopSessionTimer(session);
539             // Notify all channels on the session that connection failed.
540             RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
541             break;
542     }
543     // Remove all channels on session.
544     RfcommRemoveAllChannelOnSession(session);
545     // Destroy session.
546     RfcommRemoveSession(session);
547 
548     return RFCOMM_SUCCESS;
549 }
550 
551 /**
552  * @brief Processing after receiving the request to disconnect session from L2CAP.
553  *
554  * @param session The pointer of the session in the session list.
555  * @param data    Data related to the event.
556  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
557  */
RfcommRecvDisconnectReq(RfcommSessionInfo * session,const void * data)558 int RfcommRecvDisconnectReq(RfcommSessionInfo *session, const void *data)
559 {
560     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
561 
562     (void)data;
563 
564     if (session->sessionState == ST_SESSION_WAIT_RESTART) {
565         // Restart the session, init the session information first.
566         return RfcommRestartSession(session);
567     }
568 
569     // Notify all channels on the session that disconnection.
570     RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_DISCONNECTED);
571     // Remove all channels on session.
572     RfcommRemoveAllChannelOnSession(session);
573     // Destroy session.
574     RfcommRemoveSession(session);
575 
576     return RFCOMM_SUCCESS;
577 }
578 
579 /**
580  * @brief The processing after receiving the request to close the session.
581  *        When all channels on the session are disconnected, perform this process.
582  *
583  * @param session The pointer of the session in the session list.
584  * @param data    Data related to the event.
585  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
586  */
RfcommCloseSession(RfcommSessionInfo * session,const void * data)587 int RfcommCloseSession(RfcommSessionInfo *session, const void *data)
588 {
589     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
590 
591     (void)data;
592     int ret = 0;
593 
594     switch (session->sessionState) {
595         case ST_SESSION_WAIT_CONNECT_RSP:
596         // fall-through
597         case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP:
598         // fall-through
599         case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ:
600         // fall-through
601         case ST_SESSION_INITIATOR_WAIT_CONFIG_RSP:
602         // fall-through
603         case ST_SESSION_SABM0_REQ_WAIT_UA0:
604             // Stop timer.
605             RfcommStopSessionTimer(session);
606             ret = RfcommSendDisconnectReq(session->l2capId);
607             // Remove all channels on session.
608             RfcommRemoveAllChannelOnSession(session);
609             // Destroy session.
610             RfcommRemoveSession(session);
611             break;
612         case ST_SESSION_CONNECTED:
613             ret = RfcommSendDisc(session, CONTROL_DLCI);
614             session->sessionState = ST_SESSION_DISC0_REQ_WAIT_UA0;
615             RfcommStartSessionTimer(session, T1_SABM_DISC);
616             break;
617         default:
618             break;
619     }
620     return ret;
621 }
622 
623 /**
624  * @brief The processing after receiving the DM(DLCI0) response from peer.
625  *
626  * @param session The pointer of the session in the session list.
627  * @param data    Data related to the event.
628  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
629  */
RfcommRecvDm0(RfcommSessionInfo * session,const void * data)630 int RfcommRecvDm0(RfcommSessionInfo *session, const void *data)
631 {
632     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
633 
634     (void)data;
635     int ret = 0;
636 
637     switch (session->sessionState) {
638         case ST_SESSION_SABM0_REQ_WAIT_UA0:
639             // Stop timer.
640             RfcommStopSessionTimer(session);
641             ret = RfcommSendDisconnectReq(session->l2capId);
642             // Notify all channels on the session that connection failed.
643             RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
644             break;
645         case ST_SESSION_DISC0_REQ_WAIT_UA0:
646             // Stop timer.
647             RfcommStopSessionTimer(session);
648             ret = RfcommSendDisconnectReq(session->l2capId);
649             break;
650         case ST_SESSION_WAIT_RESTART:
651             // Stop timer.
652             RfcommStopSessionTimer(session);
653             // L2CAP disconnect.
654             RfcommSendDisconnectReq(session->l2capId);
655             // Restart the session, init the session information first.
656             return RfcommRestartSession(session);
657         default:
658             break;
659     }
660 
661     // Remove all channels on session.
662     RfcommRemoveAllChannelOnSession(session);
663     // Destroy session.
664     RfcommRemoveSession(session);
665 
666     return ret;
667 }
668 
669 /**
670  * @brief The processing after receiving timeout notification.
671  *
672  * @param session The pointer of the session in the session list.
673  * @param data    Data related to the event.
674  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
675  */
RfcommRecvTimeOut(RfcommSessionInfo * session,const void * data)676 int RfcommRecvTimeOut(RfcommSessionInfo *session, const void *data)
677 {
678     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
679 
680     (void)data;
681     int ret = 0;
682 
683     switch (session->sessionState) {
684         case ST_SESSION_SABM0_REQ_WAIT_UA0:
685             ret = RfcommSendDisconnectReq(session->l2capId);
686             // Notify all channels on the session that connection failed.
687             RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
688             // Remove all channels on session.
689             RfcommRemoveAllChannelOnSession(session);
690             // Destroy session.
691             RfcommRemoveSession(session);
692             break;
693         case ST_SESSION_WAIT_SABM0:
694             break;
695         case ST_SESSION_DISC0_REQ_WAIT_UA0:
696             ret = RfcommSendDisconnectReq(session->l2capId);
697             // Remove all channels on session.
698             RfcommRemoveAllChannelOnSession(session);
699             // Destroy session.
700             RfcommRemoveSession(session);
701             break;
702         case ST_SESSION_WAIT_RESTART:
703             // L2CAP disconnect.
704             RfcommSendDisconnectReq(session->l2capId);
705             // Restart the session, init the session information first.
706             ret = RfcommRestartSession(session);
707             break;
708         case ST_SESSION_CONNECTED:
709             // Notify all channels that DLC is disconnected.
710             RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_DISCONNECTED);
711             // Remove all channels on session.
712             RfcommRemoveAllChannelOnSession(session);
713             // The default action performed on timeouts is to close down the multiplexer session.
714             ret = RfcommSendDisc(session, CONTROL_DLCI);
715             session->sessionState = ST_SESSION_DISC0_REQ_WAIT_UA0;
716             RfcommStartSessionTimer(session, T1_SABM_DISC);
717             break;
718         case ST_SESSION_WAIT_CONNECT_RSP:
719             if (session->pendingL2capId != 0) {
720                 // L2CAP disconnect.
721                 RfcommSendDisconnectReq(session->l2capId);
722                 // Accept peer's connection request.
723                 ret = RfcommAcceptPeerConnectReq(session);
724             }
725             break;
726         default:
727             break;
728     }
729 
730     return ret;
731 }
732 
733 /**
734  * @brief The processing after receiving FCON request from peer.
735  *
736  * @param session The pointer of the session in the session list.
737  * @param data    Data related to the event.
738  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
739  */
RfcommRecvFconReq(RfcommSessionInfo * session,const void * data)740 int RfcommRecvFconReq(RfcommSessionInfo *session, const void *data)
741 {
742     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
743 
744     (void)data;
745 
746     if (session->sessionState != ST_SESSION_CONNECTED) {
747         LOG_DEBUG("%{public}s:Session state is not connected.", __func__);
748         return RfcommSendDm(session, CONTROL_DLCI, false);
749     }
750     // Send FCon response.
751     int ret = RfcommSendUihFcon(session, false);
752 
753     // When credit based flow control is being used on a session,
754     // the FCon and FCoff multiplexer control commands shall not be used.
755     if (session->fcType == FC_TYPE_CREDIT) {
756         LOG_DEBUG("%{public}s:Credit based fc is used, ignore FC-bit.", __func__);
757         return ret;
758     }
759     // Set the flow control status, and send buffered data on all channels.
760     if (session->peerSessionFc) {
761         session->peerSessionFc = false;
762         RfcommSendAllCachePktOnSession(session);
763     }
764 
765     return ret;
766 }
767 
768 /**
769  * @brief The processing after receiving FCON response from peer.
770  *
771  * @param session The pointer of the session in the session list.
772  * @param data    Data related to the event.
773  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
774  */
RfcommRecvFconRsp(RfcommSessionInfo * session,const void * data)775 int RfcommRecvFconRsp(RfcommSessionInfo *session, const void *data)
776 {
777     LOG_INFO("%{public}s", __func__);
778 
779     (void)session;
780     (void)data;
781 
782     return RFCOMM_SUCCESS;
783 }
784 
785 /**
786  * @brief The processing after receiving FCOFF request from peer.
787  *
788  * @param session The pointer of the session in the session list.
789  * @param data    Data related to the event.
790  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
791  */
RfcommRecvFcoffReq(RfcommSessionInfo * session,const void * data)792 int RfcommRecvFcoffReq(RfcommSessionInfo *session, const void *data)
793 {
794     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
795 
796     (void)data;
797 
798     if (session->sessionState != ST_SESSION_CONNECTED) {
799         LOG_DEBUG("%{public}s:Session state is not connected.", __func__);
800         return RfcommSendDm(session, CONTROL_DLCI, false);
801     }
802 
803     // Send FCon response.
804     int ret = RfcommSendUihFcoff(session, false);
805 
806     // When credit based flow control is being used on a session,
807     // the FCon and FCoff multiplexer control commands shall not be used.
808     if (session->fcType == FC_TYPE_CREDIT) {
809         LOG_DEBUG("%{public}s:Credit based fc is used, ignore FC-bit.", __func__);
810         return ret;
811     }
812     // Set the flow control status.
813     session->peerSessionFc = true;
814 
815     return ret;
816 }
817 
818 /**
819  * @brief The processing after receiving FCOFF response from peer.
820  *
821  * @param session The pointer of the session in the session list.
822  * @param data    Data related to the event.
823  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
824  */
RfcommRecvFcoffRsp(RfcommSessionInfo * session,const void * data)825 int RfcommRecvFcoffRsp(RfcommSessionInfo *session, const void *data)
826 {
827     LOG_INFO("%{public}s", __func__);
828 
829     (void)session;
830     (void)data;
831 
832     return RFCOMM_SUCCESS;
833 }
834 
835 /**
836  * @brief The processing after receiving test request from peer.
837  *
838  * @param session The pointer of the session in the session list.
839  * @param data    Data related to the event.
840  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
841  */
RfcommRecvTestReq(RfcommSessionInfo * session,const void * data)842 int RfcommRecvTestReq(RfcommSessionInfo *session, const void *data)
843 {
844     LOG_INFO("%{public}s", __func__);
845 
846     if (data == NULL) {
847         return RFCOMM_ERR_PARAM;
848     }
849 
850     RfcommUihInfo info;
851     (void)memcpy_s(&info, sizeof(RfcommUihInfo), data, sizeof(RfcommUihInfo));
852 
853     return RfcommSendUihTest(session, false, info.test.pkt);
854 }
855 
856 /**
857  * @brief The processing after receiving test response from peer.
858  *
859  * @param session The pointer of the session in the session list.
860  * @param data    Data related to the event.
861  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
862  */
RfcommRecvTestRsp(RfcommSessionInfo * session,const void * data)863 int RfcommRecvTestRsp(RfcommSessionInfo *session, const void *data)
864 {
865     LOG_INFO("%{public}s", __func__);
866 
867     (void)session;
868     (void)data;
869 
870     return RFCOMM_SUCCESS;
871 }
872 
873 /**
874  * @brief The processing after receiving NSC response from peer.
875  *
876  * @param session The pointer of the session in the session list.
877  * @param data    Data related to the event.
878  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
879  */
RfcommRecvNsc(RfcommSessionInfo * session,const void * data)880 int RfcommRecvNsc(RfcommSessionInfo *session, const void *data)
881 {
882     LOG_INFO("%{public}s", __func__);
883 
884     if (data == NULL) {
885         return RFCOMM_ERR_PARAM;
886     }
887 
888     RfcommUihInfo info;
889     (void)memcpy_s(&info, sizeof(RfcommUihInfo), data, sizeof(RfcommUihInfo));
890 
891     LOG_DEBUG("%{public}s:ea is %hhu.", __func__, info.nsc.ea);
892     LOG_DEBUG("%{public}s:cr is %hhu.", __func__, info.nsc.cr);
893     LOG_DEBUG("%{public}s:type is %hhu.", __func__, info.nsc.type);
894 
895     return RFCOMM_SUCCESS;
896 }
897 
898 /**
899  * @brief The processing after receiving the result of session's security.
900  *
901  * @param session The pointer of the session in the session list.
902  * @param data    Data related to the event.
903  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
904  */
RfcommRecvSessionSecurityRslt(RfcommSessionInfo * session,const void * data)905 int RfcommRecvSessionSecurityRslt(RfcommSessionInfo *session, const void *data)
906 {
907     LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
908 
909     if (data == NULL) {
910         return RFCOMM_ERR_PARAM;
911     }
912 
913     int ret = 0;
914     RfcommSessionSecurityRslt securityRslt;
915     L2capConfigInfo config;
916     (void)memset_s(&config, sizeof(config), 0, sizeof(config));
917     (void)memcpy_s(&securityRslt, sizeof(RfcommSessionSecurityRslt), data, sizeof(RfcommSessionSecurityRslt));
918 
919     switch (session->sessionState) {
920         case ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT:
921             if (securityRslt.direction != OUTGOING) {
922                 LOG_ERROR("%{public}s Direction is error:%{public}d.", __func__, securityRslt.direction);
923                 break;
924             }
925             if (securityRslt.result != GAP_SUCCESS) {
926                 // Notify all channels on the session that connection failed.
927                 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
928                 // Remove all channels on session.
929                 RfcommRemoveAllChannelOnSession(session);
930                 // Destroy session from session list.
931                 RfcommRemoveSession(session);
932                 break;
933             }
934             session->sessionState = ST_SESSION_WAIT_CONNECT_REQ_RESULT;
935             ret = RfcommSendConnectReq(&(session->btAddr));
936             break;
937         case ST_SESSION_RESPONDER_WAIT_SECURITY_RESULT:
938             if (securityRslt.direction != INCOMING) {
939                 LOG_ERROR("%{public}s Direction is error:%{public}d.", __func__, securityRslt.direction);
940                 break;
941             }
942             if (securityRslt.result != GAP_SUCCESS) {
943                 RfcommSendConnectRsp(session->l2capId, session->id, L2CAP_NO_RESOURCES_AVAILABLE, 0);
944                 // Notify all channels on the session that connection failed.
945                 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
946                 // Remove all channels on session.
947                 RfcommRemoveAllChannelOnSession(session);
948                 // Destroy session.
949                 RfcommRemoveSession(session);
950                 break;
951             }
952             RfcommSendConnectRsp(session->l2capId, session->id, 0, 0);
953 
954             config.rfc.mode = 0;  // Basic mode
955             config.flushTimeout = 0xFFFF;
956             config.mtu = session->l2capLocalMtu;
957             config.fcs = 0x01;
958 
959             session->sessionState = ST_SESSION_RESPONDER_WAIT_CONFIG_REQ_AND_RSP;
960             ret = RfcommSendConfigReq(session->l2capId, &config);
961             break;
962         default:
963             break;
964     }
965     return ret;
966 }
967 
968 /**
969  * @brief Restart the session.When a connection request is received during the disconnection process,
970  *        the connection is recreated after disconnection.
971  *
972  * @param session The pointer of the session in the session list.
973  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
974  */
RfcommRestartSession(RfcommSessionInfo * session)975 int RfcommRestartSession(RfcommSessionInfo *session)
976 {
977     LOG_INFO("%{public}s", __func__);
978 
979     RfcommResetSessionInfo(session);
980     session->isInitiator = true;
981     RfcommUpdateChannelDirectionBit(session, true);
982     // Start to reopen the session.
983     session->sessionState = ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT;
984     RfcommChannelInfo *channel = RfcommGetFirstChannelOnSession(session);
985     if (channel == NULL) {
986         LOG_ERROR("%{public}s No channel on the session.", __func__);
987         return RFCOMM_SUCCESS;
988     }
989 
990     return RfcommCheckSessionSecurity(session, channel->scn, false);
991 }
992 
993 /**
994  * @brief Accept the connection request from the peer device.
995  *
996  * @param session The pointer of the session in the session list.
997  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
998  */
RfcommAcceptPeerConnectReq(RfcommSessionInfo * session)999 int RfcommAcceptPeerConnectReq(RfcommSessionInfo *session)
1000 {
1001     LOG_INFO("%{public}s", __func__);
1002 
1003     session->l2capId = session->pendingL2capId;
1004     session->id = session->pendingId;
1005     session->isInitiator = false;
1006     RfcommUpdateChannelDirectionBit(session, false);
1007     session->pendingL2capId = 0;
1008     session->pendingId = 0;
1009 
1010     session->sessionState = ST_SESSION_RESPONDER_WAIT_SECURITY_RESULT;
1011     return RfcommCheckSessionSecurity(session, 0, true);
1012 }