2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 // @file FNetBt_BluetoothSppSystemAdapter.cpp
18 // @brief This is the implementation file for the _BluetoothSppSystemAdapter class.
22 #include <FBaseByteBuffer.h>
23 #include <FBaseString.h>
24 #include <FBaseUuId.h>
25 #include <FBaseColArrayList.h>
26 #include <FBaseColHashMapT.h>
27 #include <FBaseColIComparerT.h>
28 #include <FBaseColIHashCodeProviderT.h>
29 #include <FBaseUtilStringUtil.h>
30 #include <FNetBtBluetoothTypes.h>
31 #include <FNetBtBluetoothDevice.h>
32 #include <FBaseSysLog.h>
33 #include <FBase_StringConverter.h>
34 #include "FNetBt_BluetoothSppSystemAdapter.h"
35 #include "FNetBt_BluetoothGapSystemAdapter.h"
36 #include "FNetBt_BluetoothDeviceImpl.h"
37 #include "FNetBt_IBluetoothSocketListener.h"
40 using namespace Tizen::Base;
41 using namespace Tizen::Base::Collection;
42 using namespace Tizen::Base::Utility;
44 namespace Tizen { namespace Net { namespace Bluetooth
47 struct _SocketFdDeleter
49 void operator()(int* serverSocketFd)
51 (void) bt_socket_destroy_rfcomm(*serverSocketFd);
56 * @class _BluetoothAddressComparer
57 * @brief The _BluetoothAddressComparer class provides the comparer about two specified String
58 * which consists of Bluetooth address and service UUID.
60 class _BluetoothAddressComparer
61 : public Tizen::Base::Collection::IComparerT <Tizen::Base::String>
62 , public Tizen::Base::Object
65 _BluetoothAddressComparer(void){}
66 virtual ~_BluetoothAddressComparer(void){}
68 virtual result Compare(const Tizen::Base::String& obj1, const Tizen::Base::String& obj2, int& cmp) const
70 cmp = obj1.CompareTo(obj2);
75 _BluetoothAddressComparer(const _BluetoothAddressComparer& value);
76 _BluetoothAddressComparer& operator =(const _BluetoothAddressComparer& value);
78 }; //_BluetoothAddressComparer
81 * @class _BluetoothAddressHashCodeProviderT
82 * @brief The _BluetoothAddressHashCodeProviderT class provides the hash code of a specified String
83 * which consists of Bluetooth address and service UUID.
85 class _BluetoothAddressHashCodeProvider
86 : public Tizen::Base::Collection::IHashCodeProviderT <Tizen::Base::String>
89 _BluetoothAddressHashCodeProvider(void) {}
90 virtual ~_BluetoothAddressHashCodeProvider(void) {}
91 virtual int GetHashCode(const Tizen::Base::String& obj) const
93 return obj.GetHashCode();
97 _BluetoothAddressHashCodeProvider(const _BluetoothAddressHashCodeProvider& value);
98 _BluetoothAddressHashCodeProvider& operator =(const _BluetoothAddressHashCodeProvider& value);
100 }; //_BluetoothAddressHashCodeProvider
103 static _BluetoothAddressComparer _btAddressComparer;
104 static _BluetoothAddressHashCodeProvider _btAddressHashCodeProvider;
106 _BluetoothSppSystemAdapter* _BluetoothSppSystemAdapter::__pInstance = null;
108 _BluetoothSppSystemAdapter::_BluetoothSppSystemAdapter(void)
109 : __pServerSocketMap(null)
111 , __pClientSocketMap(null)
115 _BluetoothSppSystemAdapter::~_BluetoothSppSystemAdapter(void)
117 // unregister the callback methods from the underlying layer
118 (void) bt_socket_unset_connection_state_changed_cb();
119 (void) bt_socket_unset_data_received_cb();
120 (void) bt_socket_unset_connection_requested_cb();
124 _BluetoothSppSystemAdapter::InitSingleton(void)
127 static _BluetoothSppSystemAdapter inst;
129 r = inst.Construct();
130 SysTryReturnVoidResult(NID_NET_BT, r == true, E_SYSTEM, "[E_SYSTEM] Propagating.");
135 _BluetoothSppSystemAdapter*
136 _BluetoothSppSystemAdapter::GetInstance(void)
138 static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
140 if (__pInstance == null)
143 pthread_once(&onceBlock, InitSingleton);
144 result r = GetLastResult();
147 onceBlock = PTHREAD_ONCE_INIT;
155 _BluetoothSppSystemAdapter::Construct(void)
157 result r = E_SUCCESS;
158 int err = BT_ERROR_NONE;
159 unique_ptr< Tizen::Base::Collection::HashMapT<int, _IBluetoothSocketListener*> > pServerSocketMap;
160 unique_ptr< Tizen::Base::Collection::HashMapT<int, _IBluetoothSocketListener*> > pSocketMap;
161 unique_ptr< Tizen::Base::Collection::HashMapT<Tizen::Base::String, _IBluetoothSocketListener*> > pClientSocketMap;
163 pServerSocketMap.reset(new (std::nothrow) HashMapT<int, _IBluetoothSocketListener*>);
164 SysTryReturn(NID_NET_BT, pServerSocketMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
165 r = pServerSocketMap->Construct();
166 SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
168 pSocketMap.reset(new (std::nothrow) HashMapT<int, _IBluetoothSocketListener*>);
169 SysTryReturn(NID_NET_BT, pSocketMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
170 r = pSocketMap->Construct();
171 SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
173 pClientSocketMap.reset(new (std::nothrow) HashMapT<String, _IBluetoothSocketListener*>);
174 SysTryReturn(NID_NET_BT, pClientSocketMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
175 //construct map with default capacity(16) and loadFactor(0.75f) value.
176 r = pClientSocketMap->Construct(16, 0.75f, _btAddressHashCodeProvider, _btAddressComparer);
177 SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
179 err = bt_socket_set_connection_state_changed_cb(&OnSocketConnectionStateChanged, null);
180 SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
182 err = bt_socket_set_data_received_cb(&OnSocketDataReceived, null);
183 if (err != BT_ERROR_NONE)
185 (void) bt_socket_unset_connection_state_changed_cb();
187 SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
189 err = bt_socket_set_connection_requested_cb(&OnSocketConnectionRequested, null);
190 if (err != BT_ERROR_NONE)
192 (void) bt_socket_unset_connection_state_changed_cb();
193 (void) bt_socket_unset_data_received_cb();
195 SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
197 __pServerSocketMap = move(pServerSocketMap);
198 __pSocketMap = move(pSocketMap);
199 __pClientSocketMap = move(pClientSocketMap);
205 _BluetoothSppSystemAdapter::OpenServerSocket(const UuId& serviceUuid, _IBluetoothSocketListener& listener, int& serverSocketFd)
207 int err = BT_ERROR_NONE;
208 result r = E_FAILURE;
209 unique_ptr<char[]> pUuidStr;
210 unique_ptr<int, _SocketFdDeleter> pSocketFd(&serverSocketFd);
213 pUuidStr.reset(_StringConverter::CopyToCharArrayN(serviceUuid.ToString()));
214 SysTryReturnResult(NID_NET_BT, pUuidStr != null, E_INVALID_ARG, "The service UUID is invalid.");
216 err = bt_adapter_is_service_used(pUuidStr.get(), &isUsed);
217 SysTryReturnResult(NID_NET_BT, (err == BT_ERROR_NONE) && !isUsed, E_SERVICE_UNAVAILABLE,
218 "Server socket with the specified service UUID is not available.");
220 err = bt_socket_create_rfcomm(pUuidStr.get(), &serverSocketFd);
221 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_FAILURE, "Creating a server socket has failed.");
223 err = bt_socket_listen(serverSocketFd, 1);
224 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_FAILURE, "Listen of the server socket has failed.");
226 SysLog(NID_NET_BT, "A rfcomm server socket (FD: %d) is created.", serverSocketFd);
228 // add the _IBluetoothSocketListener pointer to the server socket map.
229 r = __pServerSocketMap->Add(serverSocketFd, &listener);
230 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_FAILURE, "Propagating.");
238 _BluetoothSppSystemAdapter::CloseServerSocket(const int serverSocketFd)
240 int err = BT_ERROR_NONE;
241 result r = E_SUCCESS;
243 err = bt_socket_destroy_rfcomm(serverSocketFd);
244 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_FAILURE, "Closing the server socket has failed.");
245 SysLog(NID_NET_BT, "The server socket (FD: %d) is closed.", serverSocketFd);
247 // remove the _IBluetoothSocketListener pointer related to the specified socket FD from the server socket map.
248 r = __pServerSocketMap->Remove(serverSocketFd);
251 SysLog(NID_NET_BT, "But the server socket could not be removed from the server socket map.");
252 // 'r', the error result generated after destroying the socket successfully, is NOT propagated
259 _BluetoothSppSystemAdapter::AcceptSocketRequest(int serverSocketFd, int& socketFd)
261 int err = BT_ERROR_NONE;
262 result r = E_SUCCESS;
263 _IBluetoothSocketListener* pListener = null;
265 // find the appropriate _IBluetoothSocketListener pointer with the server socket FD.
266 r = __pServerSocketMap->GetValue(serverSocketFd, pListener);
267 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_FAILURE, "The server socket number is unknown.");
269 err = bt_socket_accept(serverSocketFd, &socketFd);
270 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_FAILURE, "Accepting the connection request has failed.");
272 SysLog(NID_NET_BT, "The connection request to the server socket (FD: %d) is accepted. (child socket FD: %d)",
273 serverSocketFd, socketFd);
275 // add the _IBluetoothSocketListener pointer to the socket map.
276 // In case for server socket event, _IBluetoothSocketListener pointer is copied from __pServerSocketMap to __pSocketMap
277 r = __pSocketMap->Add(socketFd, pListener);
280 (void) bt_socket_disconnect_rfcomm(socketFd);
282 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_FAILURE, "Propagating.");
288 _BluetoothSppSystemAdapter::RejectSocketRequest(int serverSocketFd)
290 result r = E_FAILURE;
292 if (bt_socket_reject(serverSocketFd) == BT_ERROR_NONE)
297 SysLog(NID_NET_BT, "Rejecting the connection request to the server socket (FD: %d) ", serverSocketFd,
298 r == E_SUCCESS ? "is successful." : "has failed.");
304 _BluetoothSppSystemAdapter::ConnectSocket(const ByteBuffer& serverAddress, const UuId& serviceUuid,
305 _IBluetoothSocketListener& listener)
307 result r = E_SUCCESS;
308 unique_ptr<char[]> pAddressStr;
309 unique_ptr<char[]> pUuidStr;
310 int err = BT_ERROR_NONE;
315 SysTryReturnResult(NID_NET_BT, serverAddress.GetRemaining() == _BT_ADDRESS_LENGTH, E_INVALID_ARG,
316 "The address of the remote device is incorrect.");
318 uuid = serviceUuid.ToString();
319 pUuidStr.reset(_StringConverter::CopyToCharArrayN(uuid));
320 SysTryReturnResult(NID_NET_BT, pUuidStr != null, E_INVALID_ARG, "The service UUID is invalid.");
322 address = _BluetoothDeviceImpl::GetAddressString(serverAddress);
323 pAddressStr.reset(_StringConverter::CopyToCharArrayN(address));
324 SysTryReturnResult(NID_NET_BT, pAddressStr != null, E_INVALID_ARG, "The service UUID is invalid.");
326 err = bt_socket_connect_rfcomm(pAddressStr.get(), pUuidStr.get());
327 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_FAILURE, "Connecting to the server has failed.");
329 SysLog(NID_NET_BT, "Sending a connection request to [%s] is successful.", pAddressStr.get());
331 // add the _IBluetoothSocketListener pointer to the client socket map.
332 key = address + String(L"+") + uuid;
333 r = __pClientSocketMap->Add(key, &listener);
336 // TODO: check the feature that cancels the connection request.
337 (void) bt_socket_disconnect_rfcomm(_BT_INVALID_SOCKET_FD);
339 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_FAILURE, "Propagating.");
345 _BluetoothSppSystemAdapter::DisconnectSocket(int socketFd)
347 result r = E_SUCCESS;
348 int err = BT_ERROR_NONE;
350 // TODO: more detailed error resolution is needed
351 err = bt_socket_disconnect_rfcomm(socketFd);
352 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_FAILURE, "Disconnecting the rfcomm socket has failed.");
354 SysLog(NID_NET_BT, "Disconnecting the rfcomm socket (FD: %d) is successful.", socketFd);
356 r = __pSocketMap->Remove(socketFd);
359 SysLog(NID_NET_BT, "But, The socket (FD: %d) could not be removed from the socket map.", socketFd);
360 // 'r', the error result generated after destroying the socket successfully, is NOT propagated
367 _BluetoothSppSystemAdapter::SendSocketData(int socketFd, const Tizen::Base::ByteBuffer& data)
369 result r = E_SUCCESS;
370 const byte* pSendData = null;
373 pSendData = data.GetPointer();
374 pSendData += data.GetPosition();
375 dataLength = data.GetRemaining();
377 if (bt_socket_send_data(socketFd, (char*) pSendData, dataLength) == BT_ERROR_NONE)
386 SysLog(NID_NET_BT, "Sending data (%d bytes) through the rfcomm socket (FD: %d) %s", dataLength, socketFd,
387 r == E_SUCCESS ?"is successful." : "has failed.");
393 _BluetoothSppSystemAdapter::OnSocketConnectionRequested(int serverSocketFd, const char* pRemoteAddress, void* pUserData)
395 result r = E_SUCCESS;
396 ByteBuffer deviceAddress;
397 BluetoothDevice requester;
398 String deviceAddressStr(pRemoteAddress);
399 _IBluetoothSocketListener* pListener = null;
400 _BluetoothSppSystemAdapter* pSppAdapter = _BluetoothSppSystemAdapter::GetInstance();
402 // find the appropriate _IBluetoothSocketListener pointer with the server socket FD.
403 // the server socket FD is used for distinguishing the recipient from the registered server sockets.
404 r = pSppAdapter->__pServerSocketMap->GetValue(serverSocketFd, pListener);
405 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] The socket number is unknown.");
407 deviceAddress.Construct(_BT_ADDRESS_LENGTH);
408 (void) _BluetoothDeviceImpl::GetAddressByteBuffer(deviceAddressStr, L":", deviceAddress);
410 r = _BluetoothGapSystemAdapter::GetPairedDevice(deviceAddress, requester);
411 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] Getting information of the request has failed.");
413 pListener->OnSocketConnectionRequested(requester);
417 _BluetoothSppSystemAdapter::OnSocketConnectionStateChanged(int status, bt_socket_connection_state_e connectionState,
418 bt_socket_connection_s* pConnectionInfo, void* pUserData)
420 result r = E_SUCCESS;
421 _IBluetoothSocketListener* pListener = null;
422 _BluetoothSppSystemAdapter* pSppAdapter = _BluetoothSppSystemAdapter::GetInstance();
424 switch (connectionState)
426 case BT_SOCKET_CONNECTED:
427 if (pConnectionInfo->local_role == BT_SOCKET_CLIENT)
429 SysLog(NID_NET_BT, "Connected event from [address: %s, uuid: %s] is received.",
430 pConnectionInfo->remote_address, pConnectionInfo->service_uuid);
432 String address(pConnectionInfo->remote_address);
433 String uuid(pConnectionInfo->service_uuid);
434 String key = address + String(L"+") + uuid;
436 // find the appropriate _IBluetoothSocketListener pointer with the server address and the service UUID.
437 r = pSppAdapter->__pClientSocketMap->GetValue(key, pListener);
438 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] The server address or the service UUID is unknown.");
440 // TODO: more detailed error resolution is needed
441 if (status == BT_ERROR_NONE)
443 // add the _IBluetoothSocketListener pointer to the socket map.
444 // In case for client socket event, the _IBluetoothSocketListener ponter is moved
445 // from __pClientSocketMap to __pSocketMap
446 r = pSppAdapter->__pSocketMap->Add(pConnectionInfo->socket_fd, pListener);
449 SysLogException(NID_NET_BT, E_SYSTEM, "[%s] Propagating. the socket could not be added to the socket map.",
456 SysLog(NID_NET_BT, "[E_SYSTEM] Connection request failure is reported by the subsystem.");
460 pListener->OnSocketConnectionResponded(pConnectionInfo->socket_fd, r);
462 // remove the _IBluetoothSocketListener pointer related to the specified server address and UUID
463 // from the client socket map.
464 r = pSppAdapter->__pClientSocketMap->Remove(key);
467 SysLog(NID_NET_BT, "But the socket could not be removed from the client socket map.");
468 // 'r', the error result is ignored.
472 // this event is ignored in case of SERVER ROLE.
476 case BT_SOCKET_DISCONNECTED:
477 SysLog(NID_NET_BT, "Disconnected event with [socket fd: %d] is received.", pConnectionInfo->socket_fd);
479 // find the appropriate _IBluetoothSocketListener pointer with the socket FD
480 r = pSppAdapter->__pSocketMap->GetValue(pConnectionInfo->socket_fd, pListener);
481 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] The socket number is unknown.");
483 // TODO: more detailed error resolution is needed
484 r = ((status == BT_ERROR_NONE) ? E_SUCCESS : E_SYSTEM);
486 pListener->OnSocketDisconnected(r);
488 // remove the _IBluetoothSocketListener pointer related to the specified socket FD from the socket map.
489 r = pSppAdapter->__pSocketMap->Remove(pConnectionInfo->socket_fd);
492 SysLog(NID_NET_BT, "But the socket (FD: %d) could not be removed from the socket map.",
493 pConnectionInfo->socket_fd);
494 // 'r', the error result is ignored.
500 // ignore other cases
501 SysLog(NID_NET_BT, "The connection state is invalid.");
507 _BluetoothSppSystemAdapter::OnSocketDataReceived(bt_socket_received_data_s* pData, void* pUserData)
509 result r = E_SUCCESS;
510 ByteBuffer dataBuffer;
511 _IBluetoothSocketListener* pListener = null;
512 _BluetoothSppSystemAdapter* pSppAdapter = _BluetoothSppSystemAdapter::GetInstance();
514 SysLog(NID_NET_BT, "Data (%d bytes) through the socket (FD: %d) is received.", pData->data_size, pData->socket_fd);
516 // find the appropriate _IBluetoothSocketListener pointer with the socket FD
517 r = pSppAdapter->__pSocketMap->GetValue(pData->socket_fd, pListener);
518 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] The socket number is unknown.");
520 // TODO: The deep copy should be modified to a shallow copy for better performance
521 dataBuffer.Construct(pData->data_size);
522 dataBuffer.SetArray((byte*) pData->data, 0, pData->data_size);
523 dataBuffer.SetPosition(0);
525 pListener->OnSocketDataReceived(dataBuffer);
528 } } } // Tizen::Net::Bluetooth