update the header for Doxygen
[platform/framework/native/bluetooth.git] / src / FNetBt_BluetoothSppAcceptorImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 // @file    FNetBt_BluetoothSppAcceptorImpl.cpp
18 // @brief   This is the implementation file for the _BluetoothSppAcceptorImpl class.
19 //
20
21 #include <FBaseByteBuffer.h>
22 #include <FBaseUuId.h>
23 #include <FOspConfig.h>
24 #include <FNetBtBluetoothTypes.h>
25 #include <FNetBtBluetoothDevice.h>
26 #include <FNetBtIBluetoothSppAcceptorEventListener.h>
27 #include <FBaseSysLog.h>
28 #include "FNetBt_BluetoothSppAcceptorEvent.h"
29 #include "FNetBt_BluetoothSppAcceptorEventArg.h"
30 #include "FNetBt_BluetoothSppAcceptorImpl.h"
31 #include "FNetBt_BluetoothSppSystemAdapter.h"
32 #include "FNetBt_BluetoothGapSystemAdapter.h"
33
34 using namespace std;
35 using namespace Tizen::Base;
36 using namespace Tizen::Base::Runtime;
37
38 namespace Tizen { namespace Net { namespace Bluetooth
39 {
40
41 _BluetoothSppAcceptorImpl::_BluetoothSppAcceptorImpl(void)
42         : __pGapAdapter(null)
43         , __pSppAdapter(null)
44         , __pEvent(null)
45         , __stateMutex()
46         , __currentState(_BT_SPP_ACC_STATE_DISABLED)
47         , __parentSocketFd(_BT_INVALID_SOCKET_FD)
48         , __childSocketFd(_BT_INVALID_SOCKET_FD)
49 {
50 }
51
52 _BluetoothSppAcceptorImpl::~_BluetoothSppAcceptorImpl(void)
53 {
54         if (__pSppAdapter != null)
55         {
56                 if ((__currentState == _BT_SPP_ACC_STATE_ON_SERVICE) ||
57                         (__currentState == _BT_SPP_ACC_STATE_CONNECT_REQUESTED) ||
58                         (__currentState == _BT_SPP_ACC_STATE_CONNECTED))
59                 {
60                         (void) StopService();    // Ignores the result of this function.
61                 }
62         }
63
64         if (__pGapAdapter != null)
65         {
66                 __pGapAdapter->UnregisterManagerEventListener(*this);
67         }
68 }
69
70 result
71 _BluetoothSppAcceptorImpl::Construct(IBluetoothSppAcceptorEventListener& listener)
72 {
73         result r = E_SUCCESS;
74         std::unique_ptr<_BluetoothSppAcceptorEvent> pEvent;
75
76         r = __stateMutex.Create();
77         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create the state mutex.");
78
79         __pGapAdapter = _BluetoothGapSystemAdapter::GetInstance();
80         SysTryReturn(NID_NET_BT, __pGapAdapter != null, E_SYSTEM, E_SYSTEM,
81                                 "[E_SYSTEM] Failed to invoke _BluetoothGapSystemAdapter::GetInstance().");
82
83         __pSppAdapter = _BluetoothSppSystemAdapter::GetInstance();
84         SysTryReturn(NID_NET_BT, __pSppAdapter != null, E_SYSTEM, E_SYSTEM,
85                                 "[E_SYSTEM] Failed to invoke _BluetoothSppSystemAdapter::GetInstance().");
86
87         pEvent.reset(new (std::nothrow) _BluetoothSppAcceptorEvent());
88         SysTryReturn(NID_NET_BT, pEvent != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
89         r = pEvent->Construct();
90         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to construct the event.");
91         // add the IBluetoothSppAcceptorEventListener instance to a new created _BluetoothSppAcceptorEvent.
92         r = pEvent->AddListener(listener, true);
93         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM,
94                         "[%s] Propagating. Failed to add the application listener for SPP Acceptor", GetErrorMessage(r));
95
96         // registers this callback listener to the system adapter for activation/deactivation event
97         r = __pGapAdapter->RegisterManagerEventListener(*this, true);
98         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM,
99                            "[E_SYSTEM] Failed to register the callback listener to _BluetoothGapSystemAdapter.");
100
101         // check whether the Bluetooth is available
102         __stateMutex.Acquire();
103
104         if (__pGapAdapter->IsActivated() == true)
105         {
106                 __currentState = _BT_SPP_ACC_STATE_IDLE;
107         }
108
109         __stateMutex.Release();
110
111         __pEvent = move(pEvent);
112
113         return E_SUCCESS;
114 }
115
116 result
117 _BluetoothSppAcceptorImpl::AcceptConnection(void)
118 {
119         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
120
121         result r = E_SUCCESS;
122         int clientSocketFd = _BT_INVALID_SOCKET_FD;
123
124         __stateMutex.Acquire();
125
126         switch (__currentState)
127         {
128         case _BT_SPP_ACC_STATE_DISABLED:
129                 r = E_INVALID_STATE;
130                 break;
131
132         case _BT_SPP_ACC_STATE_IDLE:
133         case _BT_SPP_ACC_STATE_ON_SERVICE:
134         case _BT_SPP_ACC_STATE_CONNECTED:
135                 r = E_INVALID_OPERATION;
136                 break;
137
138         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
139                 r = __pSppAdapter->AcceptSocketRequest(__parentSocketFd, clientSocketFd);
140
141                 if (r == E_SUCCESS)
142                 {
143                         __currentState = _BT_SPP_ACC_STATE_CONNECTED;
144                         __childSocketFd = clientSocketFd;
145                 }
146                 else
147                 {
148                         __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
149                 }
150                 break;
151
152         default:
153                 r = E_FAILURE;
154                 break;
155         }
156
157         __stateMutex.Release();
158
159         if (r != E_SUCCESS)
160         {
161                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on accepting a connection request.", GetErrorMessage(r));
162         }
163
164         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
165
166         return r;
167 }
168
169 result
170 _BluetoothSppAcceptorImpl::RejectConnection()
171 {
172         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
173
174         result r = E_SUCCESS;
175
176         __stateMutex.Acquire();
177
178         switch (__currentState)
179         {
180         case _BT_SPP_ACC_STATE_DISABLED:
181                 r = E_INVALID_STATE;
182                 break;
183
184         case _BT_SPP_ACC_STATE_IDLE:
185         case _BT_SPP_ACC_STATE_ON_SERVICE:
186         case _BT_SPP_ACC_STATE_CONNECTED:
187                 r = E_INVALID_OPERATION;
188                 break;
189
190         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
191                 r = __pSppAdapter->RejectSocketRequest(__parentSocketFd);
192                 __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
193                 break;
194
195         default:
196                 r = E_FAILURE;
197                 break;
198         }
199
200         __stateMutex.Release();
201
202         if (r != E_SUCCESS)
203         {
204                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on rejecting a connection request.", GetErrorMessage(r));
205         }
206
207         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
208
209         return r;
210 }
211
212 result
213 _BluetoothSppAcceptorImpl::StartService(const Tizen::Base::UuId& serviceUuid)
214 {
215         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
216
217         result r = E_SUCCESS;
218         int serverSocketFd = _BT_INVALID_SOCKET_FD;
219
220         __stateMutex.Acquire();
221
222         switch (__currentState)
223         {
224         case _BT_SPP_ACC_STATE_DISABLED:
225                 r = E_INVALID_STATE;
226                 break;
227
228         case _BT_SPP_ACC_STATE_IDLE:
229                 r = __pSppAdapter->OpenServerSocket(serviceUuid, *this, serverSocketFd);
230                 if (r == E_SUCCESS)
231                 {
232                         __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
233                         __parentSocketFd = serverSocketFd;
234                 }
235                 break;
236
237         case _BT_SPP_ACC_STATE_ON_SERVICE:
238         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
239                 r = E_IN_PROGRESS;
240                 break;
241
242         case _BT_SPP_ACC_STATE_CONNECTED:
243                 r = E_ALREADY_CONNECTED;
244                 break;
245
246         default:
247                 r = E_FAILURE;
248                 break;
249         }
250
251         __stateMutex.Release();
252
253         if (r != E_SUCCESS)
254         {
255                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on starting SPP service.", GetErrorMessage(r));
256         }
257
258         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
259
260         return r;
261 }
262
263 result
264 _BluetoothSppAcceptorImpl::StopService(void)
265 {
266         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
267
268         result r = E_SUCCESS;
269         result resDisconnect = E_SUCCESS;
270
271         __stateMutex.Acquire();
272
273         switch (__currentState)
274         {
275         case _BT_SPP_ACC_STATE_DISABLED:
276                 r = E_INVALID_STATE;
277                 break;
278
279         case _BT_SPP_ACC_STATE_IDLE:
280                 r = E_INVALID_OPERATION;
281                 break;
282
283         case _BT_SPP_ACC_STATE_ON_SERVICE:
284                 r = __pSppAdapter->CloseServerSocket(__parentSocketFd);
285                 if (r == E_SUCCESS)
286                 {
287                         __currentState = _BT_SPP_ACC_STATE_IDLE;
288                         __parentSocketFd = _BT_INVALID_SOCKET_FD;
289                 }
290                 break;
291
292         // Stays in the current status, if StopSppServer() fails
293         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
294                 r = __pSppAdapter->RejectSocketRequest(__parentSocketFd);
295                 if (r == E_SUCCESS)
296                 {
297                         r = __pSppAdapter->CloseServerSocket(__parentSocketFd);
298                         if (r == E_SUCCESS)
299                         {
300                                 __currentState = _BT_SPP_ACC_STATE_IDLE;
301                                 __parentSocketFd = _BT_INVALID_SOCKET_FD;
302                         }
303                         else
304                         {
305                                 __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
306                         }
307                 }
308                 break;
309
310         case _BT_SPP_ACC_STATE_CONNECTED:
311                 resDisconnect = ProcessAsyncDisconnect();
312                 // stop server socket regardless whether disconnection is successful
313                 r = __pSppAdapter->CloseServerSocket(__parentSocketFd);
314                 if (r == E_SUCCESS)
315                 {
316                         __currentState = _BT_SPP_ACC_STATE_IDLE;
317                         __parentSocketFd = _BT_INVALID_SOCKET_FD;
318                 }
319                 else if (resDisconnect == E_SUCCESS)
320                 {
321                         __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
322                 }
323                 break;
324
325         default:
326                 r = E_FAILURE;
327                 break;
328         }
329
330         __stateMutex.Release();
331
332         if (r != E_SUCCESS)
333         {
334                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on stopping SPP service.", GetErrorMessage(r));
335         }
336
337         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
338
339         return r;
340 }
341
342 result
343 _BluetoothSppAcceptorImpl::SendData(const Tizen::Base::ByteBuffer& buffer)
344 {
345         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
346
347         result r = E_SUCCESS;
348
349         __stateMutex.Acquire();
350
351         switch (__currentState)
352         {
353         case _BT_SPP_ACC_STATE_DISABLED:
354                 r = E_INVALID_STATE;
355                 break;
356
357         case _BT_SPP_ACC_STATE_IDLE:
358         case _BT_SPP_ACC_STATE_ON_SERVICE:
359         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
360                 r = E_INVALID_OPERATION;
361                 break;
362
363         case _BT_SPP_ACC_STATE_CONNECTED:
364                 if (buffer.GetRemaining() > 0)
365                 {
366                         r = __pSppAdapter->SendSocketData(__childSocketFd, buffer);
367                 }
368                 else
369                 {
370                         r = E_INVALID_ARG;
371                 }
372                 break;
373
374         default:
375                 r = E_FAILURE;
376                 break;
377         }
378
379         __stateMutex.Release();
380
381         if (r != E_SUCCESS)
382         {
383                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on sending data.", GetErrorMessage(r));
384         }
385
386         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
387
388         return r;
389 }
390
391 result
392 _BluetoothSppAcceptorImpl::Disconnect()
393 {
394         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
395
396         result r = E_SUCCESS;
397
398         __stateMutex.Acquire();
399
400         switch (__currentState)
401         {
402         case _BT_SPP_ACC_STATE_DISABLED:
403                 r = E_INVALID_STATE;
404                 break;
405
406         case _BT_SPP_ACC_STATE_IDLE:
407         case _BT_SPP_ACC_STATE_ON_SERVICE:
408         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
409                 r = E_INVALID_OPERATION;
410                 break;
411
412         case _BT_SPP_ACC_STATE_CONNECTED:
413                 // send a disconnected event here if the disconnect method is successful
414                 // because the disconnect method of the underlying system is sync call. (transform sync into async)
415                 r = ProcessAsyncDisconnect();
416                 if (r == E_SUCCESS)
417                 {
418                         __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
419                 }
420                 break;
421
422         default:
423                 r = E_FAILURE;
424                 break;
425         }
426
427         __stateMutex.Release();
428
429         if (r != E_SUCCESS)
430         {
431                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on disconnecting the connection.", GetErrorMessage(r));
432         }
433
434         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
435
436         return r;
437 }
438
439 void
440 _BluetoothSppAcceptorImpl::OnBluetoothActivated(result r)
441 {
442         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
443
444         __stateMutex.Acquire();
445
446         if ((__currentState == _BT_SPP_ACC_STATE_DISABLED) && (r == E_SUCCESS))
447         {
448                 __currentState = _BT_SPP_ACC_STATE_IDLE;
449         }
450         __stateMutex.Release();
451
452         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s]", GetStringOfCurrentState());
453 }
454
455 void
456 _BluetoothSppAcceptorImpl::OnBluetoothDeactivated(result r)
457 {
458         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
459
460         __stateMutex.Acquire();
461
462         if (r == E_SUCCESS)
463         {
464                 __currentState = _BT_SPP_ACC_STATE_DISABLED;
465         }
466
467         __stateMutex.Release();
468
469         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s]", GetStringOfCurrentState());
470 }
471
472 void
473 _BluetoothSppAcceptorImpl::OnSocketConnectionRequested(const BluetoothDevice& device)
474 {
475         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
476
477         bool isFired = false;
478
479         __stateMutex.Acquire();
480
481         if (__currentState == _BT_SPP_ACC_STATE_ON_SERVICE)
482         {
483                 __currentState = _BT_SPP_ACC_STATE_CONNECT_REQUESTED;
484                 isFired = true;
485         }
486         else if ((__currentState == _BT_SPP_ACC_STATE_CONNECT_REQUESTED) ||
487                          (__currentState == _BT_SPP_ACC_STATE_CONNECTED))
488         {
489                 (void) __pSppAdapter->RejectSocketRequest(__parentSocketFd);
490         }
491         // ignore othre cases
492
493         __stateMutex.Release();
494
495         if (isFired)
496         {
497                 _BluetoothSppAcceptorEventArg* pArg = new (std::nothrow) _BluetoothSppAcceptorEventArg(device);
498                 if (pArg == null)
499                 {
500                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
501                         isFired = false;
502                 }
503                 else
504                 {
505                         __pEvent->FireAsync(*pArg);
506                 }
507         }
508
509         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [CONNECT_REQUESTED_Event:%s]",
510                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
511 }
512
513 void
514 _BluetoothSppAcceptorImpl::OnSocketDisconnected(result r)
515 {
516         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
517
518         bool isFired = false;
519
520         __stateMutex.Acquire();
521
522         if ((__currentState == _BT_SPP_ACC_STATE_CONNECT_REQUESTED) ||
523                 (__currentState == _BT_SPP_ACC_STATE_CONNECTED))
524         {
525                 if (r == E_SUCCESS)
526                 {
527                         __currentState = _BT_SPP_ACC_STATE_ON_SERVICE;
528                         __childSocketFd = _BT_INVALID_SOCKET_FD;
529
530                         isFired = true;
531                 }
532         }
533         // ignore other cases
534
535         __stateMutex.Release();
536
537         if (isFired)
538         {
539                 _BluetoothSppAcceptorEventArg* pArg = new (std::nothrow) _BluetoothSppAcceptorEventArg(r);
540                 if (pArg == null)
541                 {
542                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
543                         isFired = false;
544                 }
545                 else
546                 {
547                         __pEvent->FireAsync(*pArg);
548                         if (r != E_SUCCESS)
549                         {
550                                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on SPP-disconnect callback.", GetErrorMessage(r));
551                         }
552                 }
553         }
554
555         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [DISCONNECTED_Event:%s]",
556                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
557 }
558
559 void
560 _BluetoothSppAcceptorImpl::OnSocketDataReceived(Tizen::Base::ByteBuffer& buffer)
561 {
562         bool isFired = false;
563
564         if (__currentState == _BT_SPP_ACC_STATE_CONNECTED)
565         {
566                 _BluetoothSppAcceptorEventArg* pArg = new (std::nothrow) _BluetoothSppAcceptorEventArg(buffer);
567                 if (pArg == null)
568                 {
569                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
570                 }
571                 else
572                 {
573                         // use Fire() instead of FireAsync() to improve the transfer rate.
574                         __pEvent->Fire(*pArg);
575                         isFired = true;
576                 }
577         }
578
579         SysLog(NID_NET_BT, "[CurrentState:%s], [DATA_RECEIVED_Event:%s]",
580                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
581 }
582
583 result
584 _BluetoothSppAcceptorImpl::ProcessAsyncDisconnect(void)
585 {
586         result r = E_SUCCESS;
587
588         r = __pSppAdapter->DisconnectSocket(__childSocketFd);
589
590         // send a disconnected event here if the disconnect method is successful
591         // because the disconnect method of the underlying system is sync call. (transform sync into async)
592         if (r == E_SUCCESS)
593         {
594                 __childSocketFd = _BT_INVALID_SOCKET_FD;
595
596                 _BluetoothSppAcceptorEventArg* pArg = new (std::nothrow) _BluetoothSppAcceptorEventArg(r);
597                 if (pArg != null)
598                 {
599                         __pEvent->FireAsync(*pArg);
600                         SysLog(NID_NET_BT, "[DISCONNECTED_Event:Fired]");
601                 }
602         }
603
604         return r;
605 }
606
607 const char*
608 _BluetoothSppAcceptorImpl::GetStringOfCurrentState(void) const
609 {
610         const char* pStateString = null;
611
612         switch (__currentState)
613         {
614         case _BT_SPP_ACC_STATE_DISABLED:
615                 pStateString = "DISABLED";
616                 break;
617
618         case _BT_SPP_ACC_STATE_IDLE:
619                 pStateString = "IDLE";
620                 break;
621
622         case _BT_SPP_ACC_STATE_ON_SERVICE:
623                 pStateString = "ON_SERVICE";
624                 break;
625
626         case _BT_SPP_ACC_STATE_CONNECT_REQUESTED:
627                 pStateString = "CONNECT_REQUESTED";
628                 break;
629
630         case _BT_SPP_ACC_STATE_CONNECTED:
631                 pStateString = "CONNECTED";
632                 break;
633
634         default:
635                 pStateString = "Unknown";
636                 break;
637         }
638
639         return pStateString;
640 }
641
642 } } } // Tizen::Net::Bluetooth