X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_le_adapter%2Fcaleadapter.c;h=9a46051a927b53de38b64afcb5f1b1f37ab93cef;hb=9d5949060f992881916284e39ccb44437aa44fc1;hp=1f201721c16a59f1d9b321e10ce6900d294eb2f8;hpb=af20dae23be24c201b33f8f8287b2ddd59bff3d9;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c index 1f20172..9a46051 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c @@ -1,4 +1,4 @@ -/****************************************************************** +/* **************************************************************** * * Copyright 2014 Samsung Electronics All Rights Reserved. * @@ -26,1524 +26,2035 @@ #include "cacommon.h" #include "camutex.h" #include "caadapterutils.h" +#ifndef SINGLE_THREAD #include "caqueueingthread.h" -#include "camsgparser.h" +#endif +#include "cafragmentation.h" #include "oic_malloc.h" +#include "oic_string.h" +#include "caremotehandler.h" /** - * @var CALEADAPTER_TAG - * @brief Logging tag for module name. + * Logging tag for module name. */ -#define CALEADAPTER_TAG "CA_BLE_ADAPTER" +#define CALEADAPTER_TAG "LAD" + + +/** + * Stores the information of the Data to be sent from the queues. + * + * This structure will be pushed to the sender/receiver queue for + * processing. + */ +typedef struct +{ + /// Remote endpoint contains the information of remote device. + CAEndpoint_t *remoteEndpoint; + + /// Data to be transmitted over LE transport. + uint8_t *data; + + /// Length of the data being transmitted. + uint32_t dataLen; +} CALEData_t; /** - * @var g_networkCallback - * @brief Callback to provide the status of the network change to CA layer. + * Stores information of all the senders. + * + * This structure will be used to track and defragment all incoming + * data packet. + */ +typedef struct +{ + uint32_t recvDataLen; + uint32_t totalDataLen; + uint8_t *defragData; + CAEndpoint_t *remoteEndpoint; + } CABLESenderInfo_t; + +/** + * Callback to provide the status of the network change to CA layer. */ static CANetworkChangeCallback g_networkCallback = NULL; /** - * @var g_localBLEAddress - * @brief bleAddress of the local adapter. Value will be initialized to zero, and will be updated later. + * bleAddress of the local adapter. Value will be initialized to zero, + * and will be updated later. */ -static char g_localBLEAddress[16] = { 0, }; +static char g_localBLEAddress[18] = { 0 }; /** - * @var g_isServer - * @brief Variable to differentiate btw GattServer and GattClient. + * Variable to differentiate btw GattServer and GattClient. */ static bool g_isServer = false; /** - * @var g_bleIsServerMutex - * @brief Mutex to synchronize the task to be executed on the GattServer function calls. + * Mutex to synchronize the task to be executed on the GattServer + * function calls. */ static ca_mutex g_bleIsServerMutex = NULL; /** - * @var g_bleNetworkCbMutex - * @brief Mutex to synchronize the callback to be called for the network changes. + * Mutex to synchronize the callback to be called for the network + * changes. */ static ca_mutex g_bleNetworkCbMutex = NULL; /** - * @var g_bleLocalAddressMutex - * @brief Mutex to synchronize the updation of the local LE address of the adapter. + * Mutex to synchronize the updates of the local LE address of the + * adapter. */ static ca_mutex g_bleLocalAddressMutex = NULL; /** - * @var gBleClientThreadPool - * @brief reference to threadpool + * Reference to thread pool. */ -static u_thread_pool_t g_bleAdapterThreadPool = NULL; +static ca_thread_pool_t g_bleAdapterThreadPool = NULL; /** - * @var g_bleAdapterThreadPoolMutex - * @brief Mutex to synchronize the task to be pushed to thread pool. + * Mutex to synchronize the task to be pushed to thread pool. */ static ca_mutex g_bleAdapterThreadPoolMutex = NULL; /** - * @var g_bLEClientSendQueueHandle - * @brief Queue to process the outgoing packets from GATTClient. + * Mutex to synchronize the queing of the data from SenderQueue. */ -static CAQueueingThread_t *g_bLEClientSendQueueHandle = NULL; +static ca_mutex g_bleClientSendDataMutex = NULL; /** - * @var g_bleClientReceiverQueue - * @brief Queue to process the incoming packets to GATT Client. + * Mutex to synchronize the queing of the data from ReceiverQueue. */ -static CAQueueingThread_t *g_bleClientReceiverQueue = NULL; +static ca_mutex g_bleReceiveDataMutex = NULL; + /** - * @var g_bleClientSendDataMutex - * @brief Mutex to synchronize the queing of the data from SenderQueue. + * Mutex to synchronize the queing of the data from SenderQueue. */ -static ca_mutex g_bleClientSendDataMutex = NULL; +static ca_mutex g_bleServerSendDataMutex = NULL; +/** + * Mutex to synchronize the callback to be called for the + * adapterReqResponse. + */ +static ca_mutex g_bleAdapterReqRespCbMutex = NULL; /** - * @var g_bleClientReceiveDataMutex - * @brief Mutex to synchronize the queing of the data from ReceiverQueue. + * Callback to be called when network packet received from either + * GattServer or GattClient. */ -static ca_mutex g_bleClientReceiveDataMutex = NULL; +static CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL; /** - * @var g_dataReceiverHandlerState - * @brief Stop condition of redvhandler. + * Callback to notify error from the BLE adapter. */ -static bool g_dataReceiverHandlerState = false; +static CAErrorHandleCallback g_errorHandler = NULL; /** - * @var g_sendQueueHandle - * @brief Queue to process the outgoing packets from GATTServer. + * Storing Adapter state information. */ -static CAQueueingThread_t *g_sendQueueHandle = NULL; +static CAAdapterState_t g_bleAdapterState = CA_ADAPTER_DISABLED; /** - * @var g_bleServerReceiverQueue - * @brief Queue to process the incoming packets to GATTServer + * BLE Server Status. + * + * This enumeration provides information of LE Adapter Server status. */ -static CAQueueingThread_t *g_bleServerReceiverQueue = NULL; +typedef enum +{ + CA_SERVER_NOTSTARTED = 0, + CA_LISTENING_SERVER, + CA_DISCOVERY_SERVER +} CALeServerStatus; /** - * @var g_bleServerSendDataMutex - * @brief Mutex to synchronize the queing of the data from SenderQueue. + * Structure to maintain the status of the server. */ -static ca_mutex g_bleServerSendDataMutex = NULL; +static CALeServerStatus gLeServerStatus = CA_SERVER_NOTSTARTED; /** - * @var g_bleServerReceiveDataMutex - * @brief Mutex to synchronize the queing of the data from ReceiverQueue. + * Register network change notification callback. + * + * @param[in] netCallback CANetworkChangeCallback callback which will + * be set for the change in network. + * + * @return 0 on success otherwise a positive error value. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + * */ -static ca_mutex g_bleServerReceiveDataMutex = NULL; +static CAResult_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback); /** - * @var g_bleAdapterReqRespCbMutex - * @brief Mutex to synchronize the callback to be called for the adapterReqResponse. + * Set the thread pool handle which is required for spawning new + * thread. + * + * @param[in] handle Thread pool handle which is given by above layer + * for using thread creation task. + * */ -static ca_mutex g_bleAdapterReqRespCbMutex = NULL; +static void CASetLEAdapterThreadPoolHandle(ca_thread_pool_t handle); /** - * @var g_networkPacketReceivedCallback - * @brief Callback to be called when the network packet recieved from either GattServer or GattClient. + * Call the callback to the upper layer when the device state gets + * changed. + * + * @param[in] adapter_state New state of the adapter to be notified to + * the upper layer. */ -static CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL; +static void CALEDeviceStateChangedCb(CAAdapterState_t adapter_state); /** - * @ENUM CALeServerStatus - * @brief status of BLE Server Status + * Used to initialize all required mutex variable for LE Adapter + * implementation. + * + * @return 0 on success otherwise a positive error value. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. * - * This ENUM provides information of LE Adapter Server status */ -typedef enum -{ - CA_SERVER_NOTSTARTED = 0, - CA_LISTENING_SERVER, - CA_DISCOVERY_SERVER -} CALeServerStatus; +static CAResult_t CAInitLEAdapterMutex(); /** - * @var gLeServerStatus - * @brief structure to maintain the status of the server. + * Terminate all required mutex variables for LE adapter + * implementation. */ -static CALeServerStatus gLeServerStatus = CA_SERVER_NOTSTARTED; +static void CATerminateLEAdapterMutex(); /** -* @fn CALERegisterNetworkNotifications -* @brief This function is used to register network change notification callback. -* -* @param[in] netCallback CANetworkChangeCallback callback which will be set for the change in nwk. -* -* @return 0 for success. -* -*/ -int32_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback); + * Prepares and notify error through error callback. + */ +static void CALEErrorHandler(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLen, + CAResult_t result); +#ifndef SINGLE_THREAD /** -* @fn CASetBleAdapterThreadPoolHandle -* @brief Used to Set the gThreadPool handle which is required for spawning new thread. -* -* @param[in] handle - Thread pool handle which is given by above layer for using thread creation task. -* -* @return void -* -*/ -void CASetBleAdapterThreadPoolHandle(u_thread_pool_t handle); + * Stop condition of recvhandler. + */ +static bool g_dataReceiverHandlerState = false; /** -* @fn CALEDeviceStateChangedCb -* @brief This function is used to call the callback to the upper layer when the device state gets changed. -* -* @param[in] adapter_state New state of the adapter to be notified to the upper layer. -* -* @return None. -* -*/ -void CALEDeviceStateChangedCb( CAAdapterState_t adapter_state); + * Sender information. + */ +static u_arraylist_t *g_senderInfo = NULL; /** -* @fn CAInitBleAdapterMutex -* @brief Used to initialize all required mutex variable for LE Adapter implementation. -* -* @return 0 on success otherwise a positive error value. -* @retval CA_STATUS_OK Successful -* @retval CA_STATUS_INVALID_PARAM Invalid input argumets -* @retval CA_STATUS_FAILED Operation failed -* -*/ -CAResult_t CAInitBleAdapterMutex(); + * Queue to process the outgoing packets from GATTClient. + */ +static CAQueueingThread_t *g_bleClientSendQueueHandle = NULL; /** -* @fn CATerminateBleAdapterMutex -* @brief Used to terminate all required mutex variable for LE adapter implementation. -* -* @return void -* -*/ -void CATerminateBleAdapterMutex(); -static void CALEDataDestroyer(void *data, uint32_t size); + * Queue to process the incoming packets to GATT Client. + */ +static CAQueueingThread_t *g_bleReceiverQueue = NULL; -CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, - CANetworkPacketReceivedCallback reqRespCallback, - CANetworkChangeCallback netCallback, - u_thread_pool_t handle) -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +/** + * Queue to process the outgoing packets from GATTServer. + */ +static CAQueueingThread_t *g_bleServerSendQueueHandle = NULL; - //Input validation - VERIFY_NON_NULL(registerCallback, NULL, "RegisterConnectivity callback is null"); - VERIFY_NON_NULL(reqRespCallback, NULL, "PacketReceived Callback is null"); - VERIFY_NON_NULL(netCallback, NULL, "NetworkChange Callback is null"); +/** + * Starting LE connectivity adapters. + * + * As its peer to peer it does not require to start any servers. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAStartLE(); - CAResult_t result = CAInitBleAdapterMutex(); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleAdapterMutex failed!"); - return CA_STATUS_FAILED; - } +/** + * Start listening server for receiving multicast search requests. + * + * Transport Specific Behavior: + * LE Starts GATT Server with prefixed UUID and Characteristics + * per OIC Specification. + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAStartLEListeningServer(); - result = CAInitializeLENetworkMonitor(); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitializeLENetworkMonitor() failed"); - return CA_STATUS_FAILED; - } +/** + * Sarting discovery of servers for receiving multicast + * advertisements. + * + * Transport Specific Behavior: + * LE Starts GATT Server with prefixed UUID and Characteristics + * per OIC Specification. + * + * @return ::CA_STATUS_OK or Appropriate error code + */ +static CAResult_t CAStartLEDiscoveryServer(); - CAInitializeLEAdapter(); +/** + * Send data to the endpoint using the adapter connectivity. + * + * @param[in] endpoint Remote Endpoint information (like MAC address, + * reference URI and connectivity type) to which + * the unicast data has to be sent. + * @param[in] data Data which required to be sent. + * @param[in] dataLen Size of data to be sent. + * + * @note dataLen must be > 0. + * + * @return The number of bytes sent on the network, or -1 on error. + */ +static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen); - CASetBleServerThreadPoolHandle(handle); - CASetBleClientThreadPoolHandle(handle); - CASetBleAdapterThreadPoolHandle(handle); - CASetBLEReqRespServerCallback(CABLEServerReceivedData); - CASetBLEReqRespClientCallback(CABLEClientReceivedData); - CASetBLEReqRespAdapterCallback(reqRespCallback); +/** + * Send multicast data to the endpoint using the LE connectivity. + * + * @param[in] endpoint Remote Endpoint information to which the + * multicast data has to be sent. + * @param[in] data Data which required to be sent. + * @param[in] dataLen Size of data to be sent. + * + * @note dataLen must be > 0. + * + * @return The number of bytes sent on the network, or -1 on error. + */ +static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen); - CALERegisterNetworkNotifications(netCallback); +/** + * Get LE Connectivity network information. + * + * @param[out] info Local connectivity information structures. + * @param[out] size Number of local connectivity structures. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, + uint32_t *size); - CAConnectivityHandler_t connHandler; - connHandler.startAdapter = NULL; - connHandler.stopAdapter = CAStopLE; - connHandler.startListenServer = CAStartLEListeningServer; - connHandler.startDiscoveryServer = CAStartLEDiscoveryServer; - connHandler.sendData = CASendLEUnicastData; - connHandler.sendDataToAll = CASendLEMulticastData; - connHandler.GetnetInfo = CAGetLEInterfaceInformation; - connHandler.readData = CAReadLEData; - connHandler.terminate = CATerminateLE; - registerCallback(connHandler, CA_LE); +/** + * Read Synchronous API callback. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAReadLEData(); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); +/** + * Stopping the adapters and close socket connections. + * + * LE Stops all GATT servers and GATT Clients. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAStopLE(); - return CA_STATUS_OK; -} +/** + * Terminate the LE connectivity adapter. + * + * Configuration information will be deleted from further use. + */ +static void CATerminateLE(); -CAResult_t CAStopLE() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +/** + * Set the NetworkPacket received callback to CA layer from adapter + * layer. + * + * @param[in] callback Callback handle sent from the upper layer. + */ +static void CASetLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback); - CAStopBleQueues(); +/** + * Push the data from CA layer to the Sender processor queue. + * + * @param[in] remoteEndpoint Remote endpoint information of the + * server. + * @param[in] data Data to be transmitted from LE. + * @param[in] dataLen Length of the Data being transmitted. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLen); - ca_mutex_lock(g_bleIsServerMutex); - if (true == g_isServer) - { - CAStopBleGattServer(); - } - else - { - CAStopBLEGattClient(); - } - ca_mutex_unlock(g_bleIsServerMutex); +/** + * Push the data from CA layer to the Sender processor queue. + * + * @param[in] remoteEndpoint Remote endpoint information of the + * server. + * @param[in] data Data to be transmitted from LE. + * @param[in] dataLen Length of the Data being transmitted. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLen); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); +/** + * This function will receive the data from the GattServer and add the + * data to the Server receiver queue. + * + * @param[in] remoteAddress Remote address of the device from where + * data is received. + * @param[in] data Actual data recevied from the remote + * device. + * @param[in] dataLength Length of the data received from the + * remote device. + * @param[in] sentLength Length of the data sent from the remote + * device. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + * + */ +static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLength, + uint32_t *sentLength); - return CA_STATUS_OK; -} +/** + * This function will receive the data from the GattClient and add the + * data into the Client receiver queue. + * + * @param[in] remoteAddress Remote address of the device from where + * data is received. + * @param[in] data Actual data recevied from the remote + * device. + * @param[in] dataLength Length of the data received from the + * remote device. + * @param[in] sentLength Length of the data sent from the remote + * device. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLength, + uint32_t *sentLength); -void CATerminateLE() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +/** + * This function will be associated with the sender queue for + * GattServer. + * + * This function will fragment the data to the MTU of the transport + * and send the data in fragments to the adapters. The function will + * be blocked until all data is sent out from the adapter. + * + * @param[in] threadData Data pushed to the queue which contains the + * info about RemoteEndpoint and Data. + */ +static void CALEServerSendDataThread(void *threadData); - CASetBLEReqRespServerCallback(NULL); - CASetBLEReqRespClientCallback(NULL); - CALERegisterNetworkNotifications(NULL); - CASetBLEReqRespAdapterCallback(NULL); - CATerminateLENetworkMonitor(); +/** + * This function will be associated with the sender queue for + * GattClient. + * + * This function will fragment the data to the MTU of the transport + * and send the data in fragments to the adapters. The function will + * be blocked until all data is sent out from the adapter. + * + * @param[in] threadData Data pushed to the queue which contains the + * info about RemoteEndpoint and Data. + */ +static void CALEClientSendDataThread(void *threadData); - ca_mutex_lock(g_bleIsServerMutex); - if (true == g_isServer) - { - CATerminateBleGattServer(); - } - else - { - CATerminateBLEGattClient(); - } - ca_mutex_unlock(g_bleIsServerMutex); +/** + * This function will be associated with the receiver queue. + * + * This function will defragment the received data from each sender + * respectively and will send it up to CA layer. Respective sender's + * header will provide the length of the data sent. + * + * @param[in] threadData Data pushed to the queue which contains the + * info about RemoteEndpoint and Data. + */ +static void CALEDataReceiverHandler(void *threadData); - CATerminateBleQueues(); +/** + * This function will stop all queues created for GattServer and + * GattClient. All four queues will be be stopped with this function + * invocations. + */ +static void CAStopLEQueues(); - CATerminateBleAdapterMutex(); +/** + * This function will terminate all queues created for GattServer and + * GattClient. All four queues will be be terminated with this + * function invocations. + */ +static void CATerminateLEQueues(); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return; -} +/** + * This function will initalize the Receiver and Sender queues for + * GattServer. This function will in turn call the functions + * CAInitBleServerReceiverQueue() and CAInitBleServerSenderQueue() to + * initialize the queues. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CAInitLEServerQueues(); + +/** + * This function will initalize the Receiver and Sender queues for + * GattClient. This function will inturn call the functions + * CAInitBleClientReceiverQueue() and CAInitBleClientSenderQueue() to + * initialize the queues. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + * + */ +static CAResult_t CAInitLEClientQueues(); + +/** + * This function will initalize the Receiver queue for + * GattServer. This will initialize the queue to process the function + * CABLEServerSendDataThread() when ever the task is added to this + * queue. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CAInitLEServerSenderQueue(); + +/** + * This function will initalize the Receiver queue for + * GattClient. This will initialize the queue to process the function + * CABLEClientSendDataThread() when ever the task is added to this + * queue. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CAInitLEClientSenderQueue(); -CAResult_t CAStartLEListeningServer() +/** + * This function will initialize the Receiver queue for + * LEAdapter. This will initialize the queue to process the function + * CABLEDataReceiverHandler() when ever the task is added to this + * queue. + * + * @return ::CA_STATUS_OK or Appropriate error code + * @retval ::CA_STATUS_OK Successful + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments + * @retval ::CA_STATUS_FAILED Operation failed + * + */ +static CAResult_t CAInitLEReceiverQueue(); + +/** + * This function will create the Data required to send it in the + * queue. + * + * @param[in] remoteEndpoint Remote endpoint information of the + * server. + * @param[in] data Data to be transmitted from LE. + * @param[in] dataLength Length of the Data being transmitted. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CALEData_t *CACreateLEData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLength); + +/** + * Used to free the BLE information stored in the sender/receiver + * queues. + * + * @param[in] bleData Information for a particular data segment. + */ +static void CAFreeLEData(CALEData_t *bleData); + +/** + * Free data. + */ +static void CALEDataDestroyer(void *data, uint32_t size); + +static CAResult_t CAInitLEServerQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAResult_t result = CAInitBleServerQueues(); + ca_mutex_lock(g_bleAdapterThreadPoolMutex); + + CAResult_t result = CAInitLEServerSenderQueue(); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientQueues failed"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerSenderQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); return CA_STATUS_FAILED; } - result = CAGetLEAdapterState(); - if (CA_ADAPTER_NOT_ENABLED == result) - { - gLeServerStatus = CA_LISTENING_SERVER; - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); - return CA_STATUS_OK; - } - - if (CA_STATUS_FAILED == result) + result = CAInitLEReceiverQueue(); + if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerReceiverQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); return CA_STATUS_FAILED; } - CAStartBleGattServer(); + g_dataReceiverHandlerState = true; + + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - ca_mutex_lock(g_bleIsServerMutex); - g_isServer = true; - ca_mutex_unlock(g_bleIsServerMutex); return CA_STATUS_OK; } -CAResult_t CAStartLEDiscoveryServer() +static CAResult_t CAInitLEClientQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAResult_t result = CAInitBleClientQueues(); + ca_mutex_lock(g_bleAdapterThreadPoolMutex); + + CAResult_t result = CAInitLEClientSenderQueue(); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientQueues failed"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientSenderQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); return CA_STATUS_FAILED; } - result = CAGetLEAdapterState(); - if (CA_ADAPTER_NOT_ENABLED == result) - { - gLeServerStatus = CA_DISCOVERY_SERVER; - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); - return CA_STATUS_OK; - } - - if (CA_STATUS_FAILED == result) + result = CAInitLEReceiverQueue(); + if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientReceiverQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); return CA_STATUS_FAILED; } - CAStartBLEGattClient(); + g_dataReceiverHandlerState = true; - ca_mutex_lock(g_bleIsServerMutex); - g_isServer = false; - ca_mutex_unlock(g_bleIsServerMutex); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CAStartLENotifyServer() +static CAResult_t CAInitLEReceiverQueue() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + // Check if the message queue is already initialized + if (g_bleReceiverQueue) + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); + return CA_STATUS_OK; + } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} - -uint32_t CASendLENotification(const CARemoteEndpoint_t *endpoint, const void *data, uint32_t dataLen) -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + // Create recv message queue + g_bleReceiverQueue = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); + if (!g_bleReceiverQueue) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + return CA_MEMORY_ALLOC_FAILED; + } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} + g_senderInfo = u_arraylist_create(); + if (!g_senderInfo) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ClientInfo memory allcation failed!"); + OICFree(g_bleReceiverQueue); + g_bleReceiverQueue = NULL; + return CA_MEMORY_ALLOC_FAILED; + } -CAResult_t CAReadLEData() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleReceiverQueue, g_bleAdapterThreadPool, + CALEDataReceiverHandler, CALEDataDestroyer)) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); + OICFree(g_bleReceiverQueue); + g_bleReceiverQueue = NULL; + u_arraylist_free(&g_senderInfo); + return CA_STATUS_FAILED; + } + + if (CA_STATUS_OK != CAQueueingThreadStart(g_bleReceiverQueue)) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); + OICFree(g_bleReceiverQueue); + g_bleReceiverQueue = NULL; + u_arraylist_free(&g_senderInfo); + return CA_STATUS_FAILED; + } OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -int32_t CASendLEUnicastData(const CARemoteEndpoint_t *endpoint, const void *data, uint32_t dataLen) +static CAResult_t CAInitLEServerSenderQueue() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + // Check if the message queue is already initialized + if (g_bleServerSendQueueHandle) + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Queue is already initialized!"); + return CA_STATUS_OK; + } - //Input validation - VERIFY_NON_NULL_RET(endpoint, NULL, "Remote endpoint is null", -1); - VERIFY_NON_NULL_RET(data, NULL, "Data is null", -1); - - CAResult_t result = CA_STATUS_FAILED; + // Create send message queue + g_bleServerSendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); + if (!g_bleServerSendQueueHandle) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + return CA_MEMORY_ALLOC_FAILED; + } - ca_mutex_lock(g_bleIsServerMutex); - if (true == g_isServer) + if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleServerSendQueueHandle, + g_bleAdapterThreadPool, + CALEServerSendDataThread, CALEDataDestroyer)) { - result = CABLEServerSendData(endpoint, data, dataLen); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, - "[SendLEUnicastData] CABleServerSenderQueueEnqueueMessage failed \n"); - ca_mutex_unlock(g_bleIsServerMutex); - return -1; - } + OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); + OICFree(g_bleServerSendQueueHandle); + g_bleServerSendQueueHandle = NULL; + return CA_STATUS_FAILED; } - else + + if (CA_STATUS_OK != CAQueueingThreadStart(g_bleServerSendQueueHandle)) { - result = CABLEClientSendData(endpoint, data, dataLen); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, - "[SendLEUnicastData] CABleClientSenderQueueEnqueueMessage failed \n"); - ca_mutex_unlock(g_bleIsServerMutex); - return -1; - } + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); + OICFree(g_bleServerSendQueueHandle); + g_bleServerSendQueueHandle = NULL; + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_bleIsServerMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return dataLen; + return CA_STATUS_OK; } -int32_t CASendLEMulticastData(const void *data, uint32_t dataLen) +static void CALEClearSenderInfo() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - //Input validation - VERIFY_NON_NULL_RET(data, NULL, "Data is null", -1); - - if (0 >= dataLen) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Invalid Parameter"); - return -1; - } - - CAResult_t result = CA_STATUS_FAILED; - - ca_mutex_lock(g_bleIsServerMutex); - if (true == g_isServer) - { - result = CABLEServerSendData(NULL, data, dataLen); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, - "[SendLEMulticastDataToAll] CABleServerSenderQueueEnqueueMessage failed" ); - ca_mutex_unlock(g_bleIsServerMutex); - return -1; - } - } - else + uint32_t listIndex = 0; + uint32_t listLength = u_arraylist_length(g_senderInfo); + for (listIndex = 0; listIndex < listLength; listIndex++) { - result = CABLEClientSendData(NULL, data, dataLen); - if (CA_STATUS_OK != result) + CABLESenderInfo_t *info = (CABLESenderInfo_t *) u_arraylist_get(g_senderInfo, listIndex); + if(!info) { - OIC_LOG(ERROR, CALEADAPTER_TAG, - "[SendLEMulticastDataToAll] CABleClientSenderQueueEnqueueMessage failed" ); - ca_mutex_unlock(g_bleIsServerMutex); - return -1; + continue; } - } - ca_mutex_unlock(g_bleIsServerMutex); + OICFree(info->defragData); + CAFreeEndpoint(info->remoteEndpoint); + OICFree(info); + } + u_arraylist_free(&g_senderInfo); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return dataLen; } -CAResult_t CAGetLEInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size) +static CAResult_t CAInitLEClientSenderQueue() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - VERIFY_NON_NULL(info, NULL, "CALocalConnectivity info is null"); + if (g_bleClientSendQueueHandle) + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); + return CA_STATUS_OK; + } - char *local_address = NULL; + // Create send message queue + g_bleClientSendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); + if (!g_bleClientSendQueueHandle) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + return CA_MEMORY_ALLOC_FAILED; + } - CAGetLEAddress(&local_address); - if (NULL == local_address) + if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleClientSendQueueHandle, + g_bleAdapterThreadPool, + CALEClientSendDataThread, CALEDataDestroyer)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Get local bt adapter address failed"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); + OICFree(g_bleClientSendQueueHandle); + g_bleClientSendQueueHandle = NULL; return CA_STATUS_FAILED; } - *size = 0; - (*info) = (CALocalConnectivity_t *) OICCalloc(1, sizeof(CALocalConnectivity_t)); - if (NULL == (*info)) + if (CA_STATUS_OK != CAQueueingThreadStart(g_bleClientSendQueueHandle)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failure!"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); + OICFree(g_bleClientSendQueueHandle); + g_bleClientSendQueueHandle = NULL; return CA_STATUS_FAILED; } - strncpy((*info)->addressInfo.BT.btMacAddress, local_address, strlen(local_address)); - ca_mutex_lock(g_bleLocalAddressMutex); - strncpy(g_localBLEAddress, local_address, sizeof(g_localBLEAddress)); - ca_mutex_unlock(g_bleLocalAddressMutex); - - (*info)->type = CA_LE; - *size = 1; - OICFree(local_address); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -int32_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback) +static void CAStopLEQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - ca_mutex_lock(g_bleNetworkCbMutex); - g_networkCallback = netCallback; - ca_mutex_unlock(g_bleNetworkCbMutex); + ca_mutex_lock(g_bleClientSendDataMutex); + if (NULL != g_bleClientSendQueueHandle) + { + CAQueueingThreadStop(g_bleClientSendQueueHandle); + } + ca_mutex_unlock(g_bleClientSendDataMutex); - if (netCallback) + ca_mutex_lock(g_bleServerSendDataMutex); + if (NULL != g_bleServerSendQueueHandle) { - CAResult_t res = CASetLEAdapterStateChangedCb(CALEDeviceStateChangedCb); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); - } + CAQueueingThreadStop(g_bleServerSendQueueHandle); } - else + ca_mutex_unlock(g_bleServerSendDataMutex); + + ca_mutex_lock(g_bleReceiveDataMutex); + if (NULL != g_bleReceiverQueue) { - CAResult_t res = CAUnSetLEAdapterStateChangedCb(); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); - } + CAQueueingThreadStop(g_bleReceiverQueue); } + ca_mutex_unlock(g_bleReceiveDataMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; } -void CALEDeviceStateChangedCb( CAAdapterState_t adapter_state) +static void CATerminateLEQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CALocalConnectivity_t localEndpoint = {}; + CAQueueingThreadDestroy(g_bleClientSendQueueHandle); + OICFree(g_bleClientSendQueueHandle); + g_bleClientSendQueueHandle = NULL; - ca_mutex_lock(g_bleLocalAddressMutex); - strncpy(localEndpoint.addressInfo.BT.btMacAddress, g_localBLEAddress, strlen(g_localBLEAddress)); - ca_mutex_unlock(g_bleLocalAddressMutex); + CAQueueingThreadDestroy(g_bleServerSendQueueHandle); + OICFree(g_bleServerSendQueueHandle); + g_bleServerSendQueueHandle = NULL; - // Start a GattServer/Client if gLeServerStatus is SET - if (CA_LISTENING_SERVER == gLeServerStatus) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Before CAStartBleGattServer"); - CAStartBleGattServer(); - } - else if (CA_DISCOVERY_SERVER == gLeServerStatus) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Before CAStartBleGattClient"); - CAStartBLEGattClient(); - } - gLeServerStatus = CA_SERVER_NOTSTARTED; + CAQueueingThreadDestroy(g_bleReceiverQueue); + OICFree(g_bleReceiverQueue); + g_bleReceiverQueue = NULL; - ca_mutex_lock(g_bleNetworkCbMutex); - if (NULL != g_networkCallback) - { - g_networkCallback(&localEndpoint, adapter_state); - } - else - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "g_networkCallback is NULL"); - } - ca_mutex_unlock(g_bleNetworkCbMutex); + CALEClearSenderInfo(); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return; } -CAResult_t CAInitBleAdapterMutex() +static CAResult_t CALEGetSenderInfo(const char *leAddress, + CABLESenderInfo_t **senderInfo, + uint32_t *senderIndex) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - if (NULL == g_bleIsServerMutex) - { - g_bleIsServerMutex = ca_mutex_new(); - if (NULL == g_bleIsServerMutex) + VERIFY_NON_NULL_RET(leAddress, + CALEADAPTER_TAG, + "NULL BLE address argument", + CA_STATUS_INVALID_PARAM); + VERIFY_NON_NULL_RET(senderIndex, + CALEADAPTER_TAG, + "NULL index argument", + CA_STATUS_INVALID_PARAM); + + const uint32_t listLength = u_arraylist_length(g_senderInfo); + const uint32_t addrLength = strlen(leAddress); + for (uint32_t index = 0; index < listLength; index++) + { + CABLESenderInfo_t *info = (CABLESenderInfo_t *) u_arraylist_get(g_senderInfo, index); + if(!info || !(info->remoteEndpoint)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + continue; } - } - if (NULL == g_bleNetworkCbMutex) - { - g_bleNetworkCbMutex = ca_mutex_new(); - if (NULL == g_bleNetworkCbMutex) + if(!strncmp(info->remoteEndpoint->addr, leAddress, addrLength)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + *senderIndex = index; + if(senderInfo) + { + *senderInfo = info; + } + return CA_STATUS_OK; } } - if (NULL == g_bleLocalAddressMutex) - { - g_bleLocalAddressMutex = ca_mutex_new(); - if (NULL == g_bleLocalAddressMutex) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; - } - } + return CA_STATUS_FAILED; +} - if (NULL == g_bleAdapterThreadPoolMutex) - { - g_bleAdapterThreadPoolMutex = ca_mutex_new(); - if (NULL == g_bleAdapterThreadPoolMutex) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; - } - } +static void CALEDataReceiverHandler(void *threadData) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - if (NULL == g_bleClientSendDataMutex) - { - g_bleClientSendDataMutex = ca_mutex_new(); - if (NULL == g_bleClientSendDataMutex) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; - } - } + ca_mutex_lock(g_bleReceiveDataMutex); - if (NULL == g_bleClientReceiveDataMutex) + if (g_dataReceiverHandlerState) { - g_bleClientReceiveDataMutex = ca_mutex_new(); - if (NULL == g_bleClientReceiveDataMutex) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; - } - } + OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); - if (NULL == g_bleServerSendDataMutex) - { - g_bleServerSendDataMutex = ca_mutex_new(); - if (NULL == g_bleServerSendDataMutex) + CALEData_t *bleData = (CALEData_t *) threadData; + if (!bleData) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bleData!"); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; } - } - if (NULL == g_bleServerReceiveDataMutex) - { - g_bleServerReceiveDataMutex = ca_mutex_new(); - if (NULL == g_bleServerReceiveDataMutex) + if(!(bleData->remoteEndpoint)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Client RemoteEndPoint NULL!!"); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; } - } - if (NULL == g_bleAdapterReqRespCbMutex) - { - g_bleAdapterReqRespCbMutex = ca_mutex_new(); - if (NULL == g_bleAdapterReqRespCbMutex) + CABLESenderInfo_t *senderInfo = NULL; + uint32_t senderIndex = 0; + + if(CA_STATUS_OK != CALEGetSenderInfo(bleData->remoteEndpoint->addr, + &senderInfo, &senderIndex)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "This is a new client [%s]", + bleData->remoteEndpoint->addr); } - } - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - return CA_STATUS_OK; -} -void CATerminateBleAdapterMutex() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + if(!senderInfo) + { + CABLESenderInfo_t *newSender = OICMalloc(sizeof(CABLESenderInfo_t)); + if(!newSender) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed for new sender"); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } + newSender->recvDataLen = 0; + newSender->totalDataLen = 0; + newSender->defragData = NULL; + newSender->remoteEndpoint = NULL; - ca_mutex_free(g_bleIsServerMutex); - g_bleIsServerMutex = NULL; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Parsing the header"); + newSender->totalDataLen = CAParseHeader(bleData->data, + bleData->dataLen); + if(!(newSender->totalDataLen)) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Total Data Length is parsed as 0!!!"); + OICFree(newSender); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } - ca_mutex_free(g_bleNetworkCbMutex); - g_bleNetworkCbMutex = NULL; + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Total data to be accumulated [%u] bytes", + newSender->totalDataLen); + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "data received in the first packet [%u] bytes", + bleData->dataLen); - ca_mutex_free(g_bleLocalAddressMutex); - g_bleLocalAddressMutex = NULL; + newSender->defragData = OICCalloc(newSender->totalDataLen + 1, + sizeof(*newSender->defragData)); - ca_mutex_free(g_bleAdapterThreadPoolMutex); - g_bleAdapterThreadPoolMutex = NULL; + if (NULL == newSender->defragData) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "defragData is NULL!"); + OICFree(newSender); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } - ca_mutex_free(g_bleClientSendDataMutex); - g_bleClientSendDataMutex = NULL; - - ca_mutex_free(g_bleClientReceiveDataMutex); - g_bleClientReceiveDataMutex = NULL; - - ca_mutex_free(g_bleServerSendDataMutex); - g_bleServerSendDataMutex = NULL; - - ca_mutex_free(g_bleServerReceiveDataMutex); - g_bleServerReceiveDataMutex = NULL; + const char *remoteAddress = bleData->remoteEndpoint->addr; + newSender->remoteEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, + CA_ADAPTER_GATT_BTLE, remoteAddress, 0); + if (NULL == newSender->remoteEndpoint) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "remoteEndpoint is NULL!"); + OICFree(newSender->defragData); + OICFree(newSender); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } + memcpy(newSender->defragData, bleData->data + CA_HEADER_LENGTH, + bleData->dataLen - CA_HEADER_LENGTH); + newSender->recvDataLen += bleData->dataLen - CA_HEADER_LENGTH; + u_arraylist_add(g_senderInfo,(void *)newSender); + + //Getting newSender index position in g_senderInfo array list + if(CA_STATUS_OK != + CALEGetSenderInfo(newSender->remoteEndpoint->addr, NULL, &senderIndex)) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Existing sender index not found!!"); + OICFree(newSender->defragData); + CAFreeEndpoint(newSender->remoteEndpoint); + OICFree(newSender); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } + senderInfo = newSender; + } + else + { + if(senderInfo->recvDataLen + bleData->dataLen > senderInfo->totalDataLen) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, + "Data Length exceeding error!! Receiving [%d] total length [%d]", + senderInfo->recvDataLen + bleData->dataLen, senderInfo->totalDataLen); + u_arraylist_remove(g_senderInfo, senderIndex); + OICFree(senderInfo->defragData); + OICFree(senderInfo); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Copying the data of length [%d]", bleData->dataLen); + memcpy(senderInfo->defragData + senderInfo->recvDataLen, bleData->data, + bleData->dataLen); + senderInfo->recvDataLen += bleData->dataLen ; + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "totalDatalength [%d] recveived Datalen [%d]", + senderInfo->totalDataLen, senderInfo->recvDataLen); + } - ca_mutex_free(g_bleAdapterReqRespCbMutex); - g_bleAdapterReqRespCbMutex = NULL; + if (senderInfo->totalDataLen == senderInfo->recvDataLen) + { + ca_mutex_lock(g_bleAdapterReqRespCbMutex); + if (NULL == g_networkPacketReceivedCallback) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "gReqRespCallback is NULL!"); + u_arraylist_remove(g_senderInfo, senderIndex); + OICFree(senderInfo->defragData); + OICFree(senderInfo); + ca_mutex_unlock(g_bleAdapterReqRespCbMutex); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending data up !"); + g_networkPacketReceivedCallback(senderInfo->remoteEndpoint, + senderInfo->defragData, senderInfo->recvDataLen); + ca_mutex_unlock(g_bleAdapterReqRespCbMutex); + u_arraylist_remove(g_senderInfo, senderIndex); + senderInfo->remoteEndpoint = NULL; + senderInfo->defragData = NULL; + OICFree(senderInfo); + } + } + ca_mutex_unlock(g_bleReceiveDataMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return; } -void CAInitBleQueues() +static void CALEServerSendDataThread(void *threadData) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAResult_t result = CAInitBleServerQueues(); - if (CA_STATUS_OK != result) + CALEData_t * const bleData = (CALEData_t *) threadData; + if (!bleData) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerQueues failed"); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); return; } - result = CAInitBleClientQueues(); - if (CA_STATUS_OK != result) + uint8_t * const header = OICCalloc(CA_HEADER_LENGTH, 1); + VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed"); + + const uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH; + + OIC_LOG_V(DEBUG, + CALEADAPTER_TAG, + "Server total Data length with header is [%u]", + totalLength); + + uint8_t * const dataSegment = OICCalloc(totalLength, 1); + + if (NULL == dataSegment) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientQueues failed"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); + OICFree(header); + return; + } + + CAResult_t result = CAGenerateHeader(header, + CA_HEADER_LENGTH, + bleData->dataLen); + if (CA_STATUS_OK != result ) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); + OICFree(header); + OICFree(dataSegment); return; } + memcpy(dataSegment, header, CA_HEADER_LENGTH); + OICFree(header); + + uint32_t length = 0; + if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength) + { + length = totalLength; + memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, bleData->dataLen); + } + else + { + length = CA_SUPPORTED_BLE_MTU_SIZE; + memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, + CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); + } + + uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE; + uint32_t index = 0; + + // Send the first segment with the header. + if (NULL != bleData->remoteEndpoint) // Sending Unicast Data + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Server Sending Unicast Data"); + + result = CAUpdateCharacteristicsToGattClient( + bleData->remoteEndpoint->addr, dataSegment, length); + + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, + CALEADAPTER_TAG, + "Update characteristics failed, result [%d]", + result); + + g_errorHandler(bleData->remoteEndpoint, + bleData->data, + bleData->dataLen, + result); + OICFree(dataSegment); + return; + } + + OIC_LOG_V(DEBUG, + CALEADAPTER_TAG, + "Server Sent data length [%u]", + length); + for (index = 1; index < iter; index++) + { + // Send the remaining header. + OIC_LOG_V(DEBUG, + CALEADAPTER_TAG, + "Sending the chunk number [%u]", + index); + + result = + CAUpdateCharacteristicsToGattClient( + bleData->remoteEndpoint->addr, + bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH), + CA_SUPPORTED_BLE_MTU_SIZE); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, + "Update characteristics failed, result [%d]", result); + g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", + CA_SUPPORTED_BLE_MTU_SIZE); + } + + const uint32_t remainingLen = + totalLength % CA_SUPPORTED_BLE_MTU_SIZE; + + if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE)) + { + // send the last segment of the data (Ex: 22 bytes of 622 + // bytes of data when MTU is 200) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); + result = CAUpdateCharacteristicsToGattClient( + bleData->remoteEndpoint->addr, + bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, + remainingLen); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, + CALEADAPTER_TAG, + "Update characteristics failed, result [%d]", + result); + g_errorHandler(bleData->remoteEndpoint, + bleData->data, + bleData->dataLen, + result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", remainingLen); + } + } + else + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Server Sending Multicast data"); + result = CAUpdateCharacteristicsToAllGattClients(dataSegment, length); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", + result); + CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", length); + for (index = 1; index < iter; index++) + { + // Send the remaining header. + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Sending the chunk number [%d]", index); + result = CAUpdateCharacteristicsToAllGattClients( + bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH), + CA_SUPPORTED_BLE_MTU_SIZE); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", + result); + CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%u]", CA_SUPPORTED_BLE_MTU_SIZE); + } + + const uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE; + if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE)) + { + // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); + result = CAUpdateCharacteristicsToAllGattClients( + bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, + remainingLen); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", + result); + CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", remainingLen); + } + } + OICFree(dataSegment); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return; } -CAResult_t CAInitBleServerQueues() +static void CALEClientSendDataThread(void *threadData) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - ca_mutex_lock(g_bleAdapterThreadPoolMutex); + CALEData_t *bleData = (CALEData_t *) threadData; + if (!bleData) + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); + return; + } - CAResult_t result = CAInitBleServerSenderQueue(); - if (CA_STATUS_OK != result) + uint8_t * const header = OICCalloc(CA_HEADER_LENGTH, 1); + VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed"); + + const uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH; + uint8_t *dataSegment = OICCalloc(totalLength, 1); + if (NULL == dataSegment) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerSenderQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); + OICFree(header); + return; } - result = CAInitBleServerReceiverQueue(); - if (CA_STATUS_OK != result) + CAResult_t result = CAGenerateHeader(header, + CA_HEADER_LENGTH, + bleData->dataLen); + if (CA_STATUS_OK != result ) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerReceiverQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); + OICFree(header); + OICFree(dataSegment); + return ; } + memcpy(dataSegment, header, CA_HEADER_LENGTH); + OICFree(header); - g_dataReceiverHandlerState = true; + uint32_t length = 0; + if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength) + { + length = totalLength; + memcpy(dataSegment + CA_HEADER_LENGTH, + bleData->data, + bleData->dataLen); + } + else + { + length = CA_SUPPORTED_BLE_MTU_SIZE; + memcpy(dataSegment + CA_HEADER_LENGTH, + bleData->data, + CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); + } - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + const uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE; + uint32_t index = 0; + if (NULL != bleData->remoteEndpoint) //Sending Unicast Data + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending Unicast Data"); + // Send the first segment with the header. + result = + CAUpdateCharacteristicsToGattServer( + bleData->remoteEndpoint->addr, + dataSegment, + length, + LE_UNICAST, + 0); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, + CALEADAPTER_TAG, + "Update characteristics failed, result [%d]", + result); + g_errorHandler(bleData->remoteEndpoint, + bleData->data, + bleData->dataLen, + result); + OICFree(dataSegment); + return; + } + + OIC_LOG_V(DEBUG, + CALEADAPTER_TAG, + "Client Sent Data length is [%u]", + length); + + for (index = 1; index < iter; index++) + { + // Send the remaining header. + result = CAUpdateCharacteristicsToGattServer( + bleData->remoteEndpoint->addr, + bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, + CA_SUPPORTED_BLE_MTU_SIZE, + LE_UNICAST, 0); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, + CALEADAPTER_TAG, + "Update characteristics failed, result [%d]", + result); + g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", + CA_SUPPORTED_BLE_MTU_SIZE); + } + + const uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE; + if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE)) + { + // send the last segment of the data (Ex: 22 bytes of 622 + // bytes of data when MTU is 200) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); + result = CAUpdateCharacteristicsToGattServer( + bleData->remoteEndpoint->addr, + bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, + remainingLen, + LE_UNICAST, 0); + + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", + result); + g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", remainingLen); + } + } + else + { + //Sending Mulitcast Data + // Send the first segment with the header. + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending Multicast Data"); + result = CAUpdateCharacteristicsToAllGattServers(dataSegment, length); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, + "Update characteristics (all) failed, result [%d]", result); + CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return ; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", length); + // Send the remaining header. + for (index = 1; index < iter; index++) + { + result = CAUpdateCharacteristicsToAllGattServers( + bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, + CA_SUPPORTED_BLE_MTU_SIZE); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics (all) failed, result [%d]", + result); + CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", + CA_SUPPORTED_BLE_MTU_SIZE); + } + + uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE; + if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE)) + { + // send the last segment of the data (Ex: 22 bytes of 622 + // bytes of data when MTU is 200) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); + result = + CAUpdateCharacteristicsToAllGattServers( + bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, + remainingLen); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, + "Update characteristics (all) failed, result [%d]", result); + CALEErrorHandler(NULL, bleData->data, bleData->dataLen, result); + OICFree(dataSegment); + return; + } + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", remainingLen); + } + + } + + OICFree(dataSegment); + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT - CABLEClientSendDataThread"); } -CAResult_t CAInitBleClientQueues() +static CALEData_t *CACreateLEData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLength) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - ca_mutex_lock(g_bleAdapterThreadPoolMutex); + CALEData_t * const bleData = OICMalloc(sizeof(CALEData_t)); - CAResult_t result = CAInitBleClientSenderQueue(); - if (CA_STATUS_OK != result) + if (!bleData) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientSenderQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + return NULL; } - result = CAInitBleClientReceiverQueue(); - if (CA_STATUS_OK != result) + bleData->remoteEndpoint = CACloneEndpoint(remoteEndpoint); + bleData->data = OICCalloc(dataLength + 1, 1); + + if (NULL == bleData->data) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientReceiverQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + CAFreeLEData(bleData); + return NULL; } - g_dataReceiverHandlerState = true; + memcpy(bleData->data, data, dataLength); + bleData->dataLen = dataLength; - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + return bleData; +} - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; +static void CAFreeLEData(CALEData_t *bleData) +{ + VERIFY_NON_NULL_VOID(bleData, CALEADAPTER_TAG, "Param bleData is NULL"); + + CAFreeEndpoint(bleData->remoteEndpoint); + OICFree(bleData->data); + OICFree(bleData); } -CAResult_t CAInitBleServerSenderQueue() +static void CALEDataDestroyer(void *data, uint32_t size) +{ + if ((size_t)size < sizeof(CALEData_t *)) + { + OIC_LOG_V(ERROR, CALEADAPTER_TAG, + "Destroy data too small %p %d", data, size); + } + CALEData_t *ledata = (CALEData_t *) data; + + CAFreeLEData(ledata); +} +#endif + +static CAResult_t CAInitLEAdapterMutex() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - // Check if the message queue is already initialized - if (g_sendQueueHandle) + + if (NULL == g_bleIsServerMutex) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Queue is already initialized!"); - return CA_STATUS_OK; + g_bleIsServerMutex = ca_mutex_new(); + if (NULL == g_bleIsServerMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } } - // Create send message queue - g_sendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_sendQueueHandle) + if (NULL == g_bleNetworkCbMutex) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - return CA_MEMORY_ALLOC_FAILED; + g_bleNetworkCbMutex = ca_mutex_new(); + if (NULL == g_bleNetworkCbMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } } - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle, g_bleAdapterThreadPool, - CABLEServerSendDataThread, CALEDataDestroyer)) + if (NULL == g_bleLocalAddressMutex) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; - return CA_STATUS_FAILED; + g_bleLocalAddressMutex = ca_mutex_new(); + if (NULL == g_bleLocalAddressMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_bleAdapterThreadPoolMutex) + { + g_bleAdapterThreadPoolMutex = ca_mutex_new(); + if (NULL == g_bleAdapterThreadPoolMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_bleClientSendDataMutex) + { + g_bleClientSendDataMutex = ca_mutex_new(); + if (NULL == g_bleClientSendDataMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_bleServerSendDataMutex) + { + g_bleServerSendDataMutex = ca_mutex_new(); + if (NULL == g_bleServerSendDataMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } } - if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle)) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "u_thread_pool_add_task failed "); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; - return CA_STATUS_FAILED; - } + if (NULL == g_bleAdapterReqRespCbMutex) + { + g_bleAdapterReqRespCbMutex = ca_mutex_new(); + if (NULL == g_bleAdapterReqRespCbMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_bleReceiveDataMutex) + { + g_bleReceiveDataMutex = ca_mutex_new(); + if (NULL == g_bleReceiveDataMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +static void CATerminateLEAdapterMutex() +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + ca_mutex_free(g_bleIsServerMutex); + g_bleIsServerMutex = NULL; + + ca_mutex_free(g_bleNetworkCbMutex); + g_bleNetworkCbMutex = NULL; + + ca_mutex_free(g_bleLocalAddressMutex); + g_bleLocalAddressMutex = NULL; + + ca_mutex_free(g_bleAdapterThreadPoolMutex); + g_bleAdapterThreadPoolMutex = NULL; + + ca_mutex_free(g_bleClientSendDataMutex); + g_bleClientSendDataMutex = NULL; + + ca_mutex_free(g_bleServerSendDataMutex); + g_bleServerSendDataMutex = NULL; + + ca_mutex_free(g_bleAdapterReqRespCbMutex); + g_bleAdapterReqRespCbMutex = NULL; + + ca_mutex_free(g_bleReceiveDataMutex); + g_bleReceiveDataMutex = NULL; OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; } -CAResult_t CAInitBleClientSenderQueue() +CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, + CANetworkChangeCallback netCallback, + CAErrorHandleCallback errorCallback, + ca_thread_pool_t handle) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - if (g_bLEClientSendQueueHandle) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); - return CA_STATUS_OK; - } - - // Create send message queue - g_bLEClientSendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_bLEClientSendQueueHandle) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - return CA_MEMORY_ALLOC_FAILED; - } + //Input validation + VERIFY_NON_NULL(registerCallback, CALEADAPTER_TAG, "RegisterConnectivity callback is null"); + VERIFY_NON_NULL(reqRespCallback, CALEADAPTER_TAG, "PacketReceived Callback is null"); + VERIFY_NON_NULL(netCallback, CALEADAPTER_TAG, "NetworkChange Callback is null"); - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bLEClientSendQueueHandle, g_bleAdapterThreadPool, - CABLEClientSendDataThread, CALEDataDestroyer)) + CAResult_t result = CA_STATUS_OK; + result = CAInitLEAdapterMutex(); + if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_bLEClientSendQueueHandle); - g_bLEClientSendQueueHandle = NULL; + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleAdapterMutex failed!"); return CA_STATUS_FAILED; } - - if (CA_STATUS_OK != CAQueueingThreadStart(g_bLEClientSendQueueHandle)) + result = CAInitializeLENetworkMonitor(); + if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "u_thread_pool_add_task failed "); - OICFree(g_bLEClientSendQueueHandle); - g_bLEClientSendQueueHandle = NULL; + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitializeLENetworkMonitor() failed"); return CA_STATUS_FAILED; } + CAInitializeLEAdapter(); + + CASetLEClientThreadPoolHandle(handle); + CASetLEReqRespClientCallback(CALEAdapterClientReceivedData); + CASetLEServerThreadPoolHandle(handle); + CASetLEAdapterThreadPoolHandle(handle); + CASetLEReqRespServerCallback(CALEAdapterServerReceivedData); + CASetLEReqRespAdapterCallback(reqRespCallback); + + CASetBLEClientErrorHandleCallback(CALEErrorHandler); + CASetBLEServerErrorHandleCallback(CALEErrorHandler); + CALERegisterNetworkNotifications(netCallback); + + g_errorHandler = errorCallback; + + static const CAConnectivityHandler_t connHandler = + { + .startAdapter = CAStartLE, + .stopAdapter = CAStopLE, + .startListenServer = CAStartLEListeningServer, + .startDiscoveryServer = CAStartLEDiscoveryServer, + .sendData = CASendLEUnicastData, + .sendDataToAll = CASendLEMulticastData, + .GetnetInfo = CAGetLEInterfaceInformation, + .readData = CAReadLEData, + .terminate = CATerminateLE + }; + + registerCallback(connHandler, CA_ADAPTER_GATT_BTLE); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -CAResult_t CAInitBleServerReceiverQueue() +static CAResult_t CAStartLE() { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - // Check if the message queue is already initialized - if (g_bleServerReceiverQueue) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); - return CA_STATUS_OK; - } + OIC_LOG(DEBUG, CALEADAPTER_TAG, __func__); - // Create send message queue - g_bleServerReceiverQueue = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_bleServerReceiverQueue) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - OICFree(g_sendQueueHandle); - return CA_MEMORY_ALLOC_FAILED; - } + return CAStartLEAdapter(); +} + +static CAResult_t CAStopLE() +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +#ifndef SINGLE_THREAD + CAStopLEQueues(); +#endif - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleServerReceiverQueue, g_bleAdapterThreadPool, - CABLEServerDataReceiverHandler, CALEDataDestroyer)) + ca_mutex_lock(g_bleIsServerMutex); + if (true == g_isServer) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_bleServerReceiverQueue); - g_bleServerReceiverQueue = NULL; - return CA_STATUS_FAILED; + CAStopLEGattServer(); } - - if (CA_STATUS_OK != CAQueueingThreadStart(g_bleServerReceiverQueue)) + else { - OIC_LOG(ERROR, CALEADAPTER_TAG, "u_thread_pool_add_task failed "); - OICFree(g_bleServerReceiverQueue); - g_bleServerReceiverQueue = NULL; - return CA_STATUS_FAILED; + CAStopLEGattClient(); } + ca_mutex_unlock(g_bleIsServerMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -CAResult_t CAInitBleClientReceiverQueue() +static void CATerminateLE() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - // Check if the message queue is already initialized - if (g_bleClientReceiverQueue) + CASetLEReqRespServerCallback(NULL); + CASetLEReqRespClientCallback(NULL); + CALERegisterNetworkNotifications(NULL); + CASetLEReqRespAdapterCallback(NULL); + CATerminateLENetworkMonitor(); + + ca_mutex_lock(g_bleIsServerMutex); + if (true == g_isServer) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); + CATerminateLEGattServer(); } else { - // Create send message queue - g_bleClientReceiverQueue = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_bleClientReceiverQueue) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - OICFree(g_bLEClientSendQueueHandle); - return CA_MEMORY_ALLOC_FAILED; - } - - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleClientReceiverQueue, g_bleAdapterThreadPool, - CABLEClientDataReceiverHandler, NULL)) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_bLEClientSendQueueHandle); - OICFree(g_bleClientReceiverQueue); - g_bleClientReceiverQueue = NULL; - return CA_STATUS_FAILED; - } - } - if (CA_STATUS_OK != CAQueueingThreadStart(g_bleClientReceiverQueue)) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "u_thread_pool_add_task failed "); - OICFree(g_bleClientReceiverQueue); - g_bleClientReceiverQueue = NULL; - return CA_STATUS_FAILED; + CATerminateLEGattClient(); } + ca_mutex_unlock(g_bleIsServerMutex); + +#ifndef SINGLE_THREAD + CATerminateLEQueues(); +#endif + CATerminateLEAdapterMutex(); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; } -void CAStopBleQueues() +static CAResult_t CAStartLEListeningServer() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - ca_mutex_lock(g_bleClientSendDataMutex); - if (NULL != g_bLEClientSendQueueHandle) + CAResult_t result = CA_STATUS_OK; +#ifndef SINGLE_THREAD + result = CAInitLEServerQueues(); + if (CA_STATUS_OK != result) { - CAQueueingThreadStop(g_bLEClientSendQueueHandle); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitLEServerQueues failed"); + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_bleClientSendDataMutex); +#endif - ca_mutex_lock(g_bleClientReceiveDataMutex); - if (NULL != g_bleClientReceiverQueue) + result = CAGetLEAdapterState(); + if (CA_ADAPTER_NOT_ENABLED == result) { - CAQueueingThreadStop(g_bleClientReceiverQueue); + gLeServerStatus = CA_LISTENING_SERVER; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); + return CA_STATUS_OK; } - ca_mutex_unlock(g_bleClientReceiveDataMutex); - ca_mutex_lock(g_bleServerSendDataMutex); - if (NULL != g_sendQueueHandle) + if (CA_STATUS_FAILED == result) { - CAQueueingThreadStop(g_sendQueueHandle); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_bleServerSendDataMutex); - ca_mutex_lock(g_bleServerReceiveDataMutex); - if (NULL != g_bleServerReceiverQueue) - { - CAQueueingThreadStop(g_bleServerReceiverQueue); - } - ca_mutex_unlock(g_bleServerReceiveDataMutex); + CAStartLEGattServer(); + + ca_mutex_lock(g_bleIsServerMutex); + g_isServer = true; + ca_mutex_unlock(g_bleIsServerMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -void CATerminateBleQueues() +static CAResult_t CAStartLEDiscoveryServer() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + CAResult_t result = CA_STATUS_OK; +#ifndef SINGLE_THREAD + result = CAInitLEClientQueues(); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitLEClientQueues failed"); + return CA_STATUS_FAILED; + } +#endif + result = CAGetLEAdapterState(); + if (CA_ADAPTER_NOT_ENABLED == result) + { + gLeServerStatus = CA_DISCOVERY_SERVER; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); + return CA_STATUS_OK; + } - CAQueueingThreadDestroy(g_bLEClientSendQueueHandle); - OICFree(g_bLEClientSendQueueHandle); - g_bLEClientSendQueueHandle = NULL; - - - CAQueueingThreadDestroy(g_bleClientReceiverQueue); - OICFree(g_bleClientReceiverQueue); - g_bleClientReceiverQueue = NULL; - - - CAQueueingThreadDestroy(g_sendQueueHandle); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; + if (CA_STATUS_FAILED == result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); + return CA_STATUS_FAILED; + } + CAStartLEGattClient(); - CAQueueingThreadDestroy(g_bleServerReceiverQueue); - OICFree(g_bleServerReceiverQueue); - g_bleServerReceiverQueue = NULL; + ca_mutex_lock(g_bleIsServerMutex); + g_isServer = false; + ca_mutex_unlock(g_bleIsServerMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -void CABLEServerDataReceiverHandler(void *threadData) + +static CAResult_t CAReadLEData() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - static uint32_t recvDataLen = 0; - static uint32_t totalDataLen = 0; - static char *defragData = NULL; - static bool isHeaderAvailable = false; - static CARemoteEndpoint_t *remoteEndpoint = NULL; - - ca_mutex_lock(g_bleClientReceiveDataMutex); - - if (g_dataReceiverHandlerState) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); - - CALEData_t *bleData = (CALEData_t *) threadData; - if (!bleData) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid wifidata!"); - return; - } - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); - - if (!isHeaderAvailable) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Parsing the header"); - totalDataLen = CAParseHeader((char*)bleData->data); - - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Total data to be accumulated [%d] bytes", totalDataLen); - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "data received in the first packet [%d] bytes", bleData->dataLen); - - defragData = (char *) OICCalloc(totalDataLen + 1, sizeof(char)); - if (NULL == defragData) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "defragData is NULL!"); - return; - } - - const char *remoteAddress = bleData->remoteEndpoint->addressInfo.LE.leMacAddress; - const char *serviceUUID = bleData->remoteEndpoint->resourceUri; - - remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_LE, remoteAddress, - serviceUUID); - - memcpy(defragData + recvDataLen, bleData->data + CA_HEADER_LENGTH, - bleData->dataLen - CA_HEADER_LENGTH); - recvDataLen += bleData->dataLen - CA_HEADER_LENGTH; - isHeaderAvailable = true; - } - else - { - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Copying the data of length [%d]", bleData->dataLen); - memcpy(defragData + recvDataLen, bleData->data, bleData->dataLen); - recvDataLen += bleData->dataLen ; - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "totalDatalength [%d] recveived Datalen [%d]", - totalDataLen, recvDataLen); - } - if (totalDataLen == recvDataLen) - { - ca_mutex_lock(g_bleAdapterReqRespCbMutex); - if (NULL == g_networkPacketReceivedCallback) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "gReqRespCallback is NULL!"); - ca_mutex_unlock(g_bleAdapterReqRespCbMutex); - return; - } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending data up !"); - g_networkPacketReceivedCallback(remoteEndpoint, defragData, recvDataLen); - recvDataLen = 0; - totalDataLen = 0; - isHeaderAvailable = false; - remoteEndpoint = NULL; - defragData = NULL; - ca_mutex_unlock(g_bleAdapterReqRespCbMutex); - } - - if (false == g_dataReceiverHandlerState) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "GATTClient is terminating. Cleaning up"); - recvDataLen = 0; - totalDataLen = 0; - isHeaderAvailable = false; - OICFree(defragData); - CAAdapterFreeRemoteEndpoint(remoteEndpoint); - ca_mutex_unlock(g_bleClientReceiveDataMutex); - return; - } - } - ca_mutex_unlock(g_bleClientReceiveDataMutex); +#ifdef SINGLE_THREAD + CACheckLEData(); +#endif OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -void CABLEClientDataReceiverHandler(void *threadData) +static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - static const char *remoteAddress = NULL; - static const char *serviceUUID = NULL; - static uint32_t recvDataLen = 0; - static uint32_t totalDataLen = 0; - static char *defragData = NULL; - static bool isHeaderAvailable = false; - static CARemoteEndpoint_t *remoteEndpoint = NULL; + //Input validation + VERIFY_NON_NULL_RET(endpoint, CALEADAPTER_TAG, "Remote endpoint is null", -1); + VERIFY_NON_NULL_RET(data, CALEADAPTER_TAG, "Data is null", -1); - ca_mutex_lock(g_bleClientReceiveDataMutex); + CAResult_t result = CA_STATUS_FAILED; - if (g_dataReceiverHandlerState) + ca_mutex_lock(g_bleIsServerMutex); + if (true == g_isServer) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); - - CALEData_t *bleData = (CALEData_t *) threadData; - if (!bleData) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid wifidata!"); - return; - } - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); - - if (!isHeaderAvailable) + result = CALEAdapterServerSendData(endpoint, data, dataLen); + if (CA_STATUS_OK != result) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Parsing the header"); - - totalDataLen = CAParseHeader(bleData->data); - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Total data to be accumulated [%d] bytes", - totalDataLen); - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received in the first packet [%d] bytes", - bleData->dataLen); - - defragData = (char *) OICMalloc(sizeof(char) * totalDataLen); - if (NULL == defragData) + OIC_LOG(ERROR, CALEADAPTER_TAG, "Send unicast data failed\n"); + if (g_errorHandler) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "defragData is NULL!"); - return; + g_errorHandler(endpoint, data, dataLen, result); } - - remoteAddress = bleData->remoteEndpoint->addressInfo.LE.leMacAddress; - serviceUUID = bleData->remoteEndpoint->resourceUri; - - remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_LE, remoteAddress, - serviceUUID); - - memcpy(defragData, bleData->data + CA_HEADER_LENGTH, - bleData->dataLen - CA_HEADER_LENGTH); - recvDataLen += bleData->dataLen - CA_HEADER_LENGTH; - isHeaderAvailable = true; - } - else - { - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Copying the data of length [%d]", bleData->dataLen); - memcpy(defragData + recvDataLen, bleData->data, bleData->dataLen); - recvDataLen += bleData->dataLen ; - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "totalDatalength [%d] recveived Datalen [%d]", - totalDataLen, recvDataLen); + ca_mutex_unlock(g_bleIsServerMutex); + return -1; } - if (totalDataLen == recvDataLen) + } + else + { + result = CALEAdapterClientSendData(endpoint, data, dataLen); + if (CA_STATUS_OK != result) { - ca_mutex_lock(g_bleAdapterReqRespCbMutex); - if (NULL == g_networkPacketReceivedCallback) + OIC_LOG(ERROR, CALEADAPTER_TAG, "Send unicast data failed \n"); + if (g_errorHandler) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "gReqRespCallback is NULL!"); - ca_mutex_unlock(g_bleAdapterReqRespCbMutex); - return; + g_errorHandler(endpoint, data, dataLen, result); } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending data up !"); - g_networkPacketReceivedCallback(remoteEndpoint, defragData, recvDataLen); - recvDataLen = 0; - totalDataLen = 0; - isHeaderAvailable = false; - remoteEndpoint = NULL; - defragData = NULL; - ca_mutex_unlock(g_bleAdapterReqRespCbMutex); - } - - if (false == g_dataReceiverHandlerState) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "GATTClient is terminating. Cleaning up"); - OICFree(defragData); - CAAdapterFreeRemoteEndpoint(remoteEndpoint); - ca_mutex_unlock(g_bleClientReceiveDataMutex); - return; + ca_mutex_unlock(g_bleIsServerMutex); + return -1; } } - ca_mutex_unlock(g_bleClientReceiveDataMutex); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); -} - -void CABLEServerSendDataThread(void *threadData) -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - CALEData_t *bleData = (CALEData_t *) threadData; - if (!bleData) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); - return; - } - - char *header = (char *) OICCalloc(CA_HEADER_LENGTH, sizeof(char)); - VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed"); - - char *dataSegment = (char *) OICCalloc(bleData->dataLen + CA_HEADER_LENGTH + 1, sizeof(char)); - if (NULL == dataSegment) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); - OICFree(header); - return; - } + ca_mutex_unlock(g_bleIsServerMutex); - CAResult_t result = CAGenerateHeader(header, bleData->dataLen); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); - OICFree(header); - OICFree(dataSegment); - return ; - } + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return dataLen; +} - memcpy(dataSegment, header, CA_HEADER_LENGTH); - OICFree(header); +static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - int32_t length = 0; - if (CA_SUPPORTED_BLE_MTU_SIZE >= bleData->dataLen) - { - length = bleData->dataLen + CA_HEADER_LENGTH; - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "length [%d]", length); - memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, bleData->dataLen); - } - else - { - length = CA_SUPPORTED_BLE_MTU_SIZE; - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "length [%d]", length); - memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, - CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); - } + //Input validation + VERIFY_NON_NULL_RET(data, CALEADAPTER_TAG, "Data is null", -1); - int32_t iter = bleData->dataLen / CA_SUPPORTED_BLE_MTU_SIZE; - int32_t index = 0; - ca_mutex_lock(g_bleServerSendDataMutex); - // Send the first segment with the header. - result = CAUpdateCharacteristicsInGattServer(dataSegment, length); - if (CA_STATUS_OK != result ) + if (0 >= dataLen) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsInGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleServerSendDataMutex); - return ; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Invalid Parameter"); + return -1; } - for (index = 1; index < iter; index++) + CAResult_t result = CA_STATUS_FAILED; + + ca_mutex_lock(g_bleIsServerMutex); + if (true == g_isServer) { - // Send the remaining header. - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Sending the chunk number [%d]", index); - result = CAUpdateCharacteristicsInGattServer( - bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH), - CA_SUPPORTED_BLE_MTU_SIZE); - if (CA_STATUS_OK != result ) + result = CALEAdapterServerSendData(NULL, data, dataLen); + if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsInGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleServerSendDataMutex); - return ; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Send multicast data failed" ); + + ca_mutex_unlock(g_bleIsServerMutex); + if (g_errorHandler) + { + g_errorHandler(endpoint, data, dataLen, result); + } + return -1; } } - - if (bleData->dataLen / CA_SUPPORTED_BLE_MTU_SIZE) + else { - // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200) - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); - result = CAUpdateCharacteristicsInGattServer( - bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, - bleData->dataLen % CA_SUPPORTED_BLE_MTU_SIZE + CA_HEADER_LENGTH); - if (CA_STATUS_OK != result ) + result = CALEAdapterClientSendData(NULL, data, dataLen); + if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsInGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleServerSendDataMutex); - return ; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Send Multicast data failed" ); + if (g_errorHandler) + { + g_errorHandler(endpoint, data, dataLen, result); + } + ca_mutex_unlock(g_bleIsServerMutex); + return -1; } } - - OICFree(dataSegment); - ca_mutex_unlock(g_bleServerSendDataMutex); // TODO: this mutex required ? + ca_mutex_unlock(g_bleIsServerMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return dataLen; } -void CABLEClientSendDataThread(void *threadData) +static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CALEData_t *bleData = (CALEData_t *) threadData; - if (!bleData) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); - return; - } + VERIFY_NON_NULL(info, CALEADAPTER_TAG, "CALocalConnectivity info is null"); - char *header = (char *) OICCalloc(CA_HEADER_LENGTH, sizeof(char)); - VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed"); + char *local_address = NULL; - char *dataSegment = (char *) OICCalloc(bleData->dataLen + CA_HEADER_LENGTH + 1, sizeof(char)); - if (NULL == dataSegment) + CAResult_t res = CAGetLEAddress(&local_address); + if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); - OICFree(header); - return; + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAGetLEAddress has failed"); + return res; } - CAResult_t result = CAGenerateHeader(header, bleData->dataLen); - if (CA_STATUS_OK != result ) + if (NULL == local_address) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); - OICFree(header); - OICFree(dataSegment); - return ; + OIC_LOG(ERROR, CALEADAPTER_TAG, "local_address is NULL"); + return CA_STATUS_FAILED; } - memcpy(dataSegment, header, CA_HEADER_LENGTH); - OICFree(header); - int32_t length = 0; - if (CA_SUPPORTED_BLE_MTU_SIZE >= bleData->dataLen) + *size = 0; + (*info) = (CAEndpoint_t *) OICCalloc(1, sizeof(CAEndpoint_t)); + if (NULL == (*info)) { - length = bleData->dataLen + CA_HEADER_LENGTH; - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "length [%d]", length); - memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, bleData->dataLen); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failure!"); + OICFree(local_address); + return CA_STATUS_FAILED; } - else + + size_t local_address_len = strlen(local_address); + + if(local_address_len >= sizeof(g_localBLEAddress) || + local_address_len >= MAX_ADDR_STR_SIZE_CA - 1) { - length = CA_SUPPORTED_BLE_MTU_SIZE; - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "length [%d]", length); - memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, - CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); + OIC_LOG(ERROR, CALEADAPTER_TAG, "local_address is too long"); + OICFree(*info); + OICFree(local_address); + return CA_STATUS_FAILED; } - int32_t iter = bleData->dataLen / CA_SUPPORTED_BLE_MTU_SIZE; - int32_t index = 0; - ca_mutex_lock(g_bleClientSendDataMutex); - if (NULL != bleData->remoteEndpoint) - { - // Send the first segment with the header. - result = CAUpdateCharacteristicsToGattServer(bleData->remoteEndpoint->addressInfo.LE.leMacAddress, - dataSegment, - length, - LE_UNICAST, 0); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsToGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - return ; - } + OICStrcpy((*info)->addr, sizeof((*info)->addr), local_address); + ca_mutex_lock(g_bleLocalAddressMutex); + OICStrcpy(g_localBLEAddress, sizeof(g_localBLEAddress), local_address); + ca_mutex_unlock(g_bleLocalAddressMutex); - for (index = 1; index < iter; index++) - { - // Send the remaining header. - result = CAUpdateCharacteristicsToGattServer(bleData->remoteEndpoint->addressInfo.LE.leMacAddress, - bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, - CA_SUPPORTED_BLE_MTU_SIZE, - LE_UNICAST, 0); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsToGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - return ; - } - } + (*info)->adapter = CA_ADAPTER_GATT_BTLE; + *size = 1; + OICFree(local_address); - if (bleData->dataLen / CA_SUPPORTED_BLE_MTU_SIZE) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +static CAResult_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + ca_mutex_lock(g_bleNetworkCbMutex); + g_networkCallback = netCallback; + ca_mutex_unlock(g_bleNetworkCbMutex); + CAResult_t res = CA_STATUS_OK; + if (netCallback) + { + res = CASetLEAdapterStateChangedCb(CALEDeviceStateChangedCb); + if (CA_STATUS_OK != res) { - // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200) - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); - result = CAUpdateCharacteristicsToGattServer(bleData->remoteEndpoint->addressInfo.LE.leMacAddress, - bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, - bleData->dataLen % CA_SUPPORTED_BLE_MTU_SIZE + CA_HEADER_LENGTH, - LE_UNICAST, 0); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsToGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - return ; - } + OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); } } else { - // Send the first segment with the header. - result = CAUpdateCharacteristicsToAllGattServers(dataSegment + (index * length), - length); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsToGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - return ; - } - // Send the remaining header. - for (index = 1; index < iter; index++) - { - result = CAUpdateCharacteristicsToAllGattServers( - bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, - CA_SUPPORTED_BLE_MTU_SIZE); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsToGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - return ; - } - } - if (bleData->dataLen / CA_SUPPORTED_BLE_MTU_SIZE) + res = CAUnSetLEAdapterStateChangedCb(); + if (CA_STATUS_OK != res) { - // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200) - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk"); - result = CAUpdateCharacteristicsToAllGattServers( - bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH, - bleData->dataLen % CA_SUPPORTED_BLE_MTU_SIZE + CA_HEADER_LENGTH); - if (CA_STATUS_OK != result ) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAUpdateCharacteristicsToGattServer failed"); - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - return ; - } + OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); } } - OICFree(dataSegment); - ca_mutex_unlock(g_bleClientSendDataMutex); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return res; } -CALEData_t *CACreateBLEData(const CARemoteEndpoint_t *remoteEndpoint, const void *data, - uint32_t dataLength) +static void CALEDeviceStateChangedCb(CAAdapterState_t adapter_state) { - CALEData_t *bleData = (CALEData_t *) OICMalloc(sizeof(CALEData_t)); - if (!bleData) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + VERIFY_NON_NULL_VOID(g_localBLEAddress, CALEADAPTER_TAG, "g_localBLEAddress is null"); + CAEndpoint_t localEndpoint = { .adapter = CA_ADAPTER_GATT_BTLE }; + + ca_mutex_lock(g_bleLocalAddressMutex); + OICStrcpy(localEndpoint.addr, + sizeof(localEndpoint.addr), + g_localBLEAddress); + ca_mutex_unlock(g_bleLocalAddressMutex); + + g_bleAdapterState = adapter_state; + // Start a GattServer/Client if gLeServerStatus is SET + if (CA_LISTENING_SERVER == gLeServerStatus) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - return NULL; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Before CAStartLEGattServer"); + CAStartLEGattServer(); } - - bleData->remoteEndpoint = CAAdapterCopyRemoteEndpoint(remoteEndpoint); - bleData->data = (void *)OICCalloc(dataLength + 1, 1); - if (NULL == bleData->data) + else if (CA_DISCOVERY_SERVER == gLeServerStatus) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - CAFreeBLEData(bleData); - return NULL; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Before CAStartBleGattClient"); + CAStartLEGattClient(); } - memcpy(bleData->data, data, dataLength); - bleData->dataLen = dataLength; - - return bleData; -} - -void CAFreeBLEData(CALEData_t *bleData) -{ - if (!bleData) - return; - - CAAdapterFreeRemoteEndpoint(bleData->remoteEndpoint); - OICFree(bleData->data); - OICFree(bleData); -} + gLeServerStatus = CA_SERVER_NOTSTARTED; -void CALEDataDestroyer(void *data, uint32_t size) -{ - CALEData_t *ledata = (CALEData_t *) data; + ca_mutex_lock(g_bleNetworkCbMutex); + if (NULL != g_networkCallback) + { + g_networkCallback(&localEndpoint, adapter_state); + } + else + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "g_networkCallback is NULL"); + } + ca_mutex_unlock(g_bleNetworkCbMutex); - CAFreeBLEData(ledata); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } - -CAResult_t CABLEClientSendData(const CARemoteEndpoint_t *remoteEndpoint, - const void *data, - uint32_t dataLen) +static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLen) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - VERIFY_NON_NULL(data, NULL, "Param data is NULL"); - - VERIFY_NON_NULL_RET(g_bLEClientSendQueueHandle, CALEADAPTER_TAG, - "g_bLEClientSendQueueHandle is NULL", + VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Param data is NULL"); +#ifndef SINGLE_THREAD + VERIFY_NON_NULL_RET(g_bleClientSendQueueHandle, CALEADAPTER_TAG, + "g_bleClientSendQueueHandle is NULL", CA_STATUS_FAILED); VERIFY_NON_NULL_RET(g_bleClientSendDataMutex, CALEADAPTER_TAG, "g_bleClientSendDataMutex is NULL", CA_STATUS_FAILED); - VERIFY_NON_NULL_RET(g_bLEClientSendQueueHandle, CALEADAPTER_TAG, "g_bLEClientSendQueueHandle", + VERIFY_NON_NULL_RET(g_bleClientSendQueueHandle, CALEADAPTER_TAG, "g_bleClientSendQueueHandle", CA_STATUS_FAILED); - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data Sending to LE layer [%d]", dataLen); + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data Sending to LE layer [%u]", dataLen); - CALEData_t *bleData = CACreateBLEData(remoteEndpoint, data, dataLen); + CALEData_t *bleData = CACreateLEData(remoteEndpoint, data, dataLen); if (!bleData) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create bledata!"); @@ -1551,64 +2062,143 @@ CAResult_t CABLEClientSendData(const CARemoteEndpoint_t *remoteEndpoint, } // Add message to send queue ca_mutex_lock(g_bleClientSendDataMutex); - CAQueueingThreadAddData(g_bLEClientSendQueueHandle, bleData, sizeof(CALEData_t)); + CAQueueingThreadAddData(g_bleClientSendQueueHandle, bleData, sizeof(CALEData_t)); ca_mutex_unlock(g_bleClientSendDataMutex); - +#endif OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } - -CAResult_t CABLEServerSendData(const CARemoteEndpoint_t *remoteEndpoint, - const void *data, - uint32_t dataLen) +static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLen) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - VERIFY_NON_NULL(data, NULL, "Param data is NULL"); + VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Param data is NULL"); + +#ifdef SINGLE_THREAD + uint8_t header[CA_HEADER_LENGTH] = { 0 }; + + CAResult_t result = + CAGenerateHeader(header, CA_HEADER_LENGTH, dataLen); + + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); + return CA_STATUS_FAILED; + } + + if (!CAIsLEConnected()) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "le not conn"); + return CA_STATUS_FAILED; + } + + result = CAUpdateCharacteristicsToAllGattClients(header, CA_HEADER_LENGTH); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed"); + return CA_STATUS_FAILED; + } + + const uint32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE; + for (uint32_t iter = 0; iter < dataLimit; iter++) + { + result = + CAUpdateCharacteristicsToAllGattClients( + data + (iter * CA_SUPPORTED_BLE_MTU_SIZE), + CA_SUPPORTED_BLE_MTU_SIZE); + + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed"); + return CA_STATUS_FAILED; + } + + CALEDoEvents(); + } - VERIFY_NON_NULL_RET(g_sendQueueHandle, CALEADAPTER_TAG, + const uint32_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE; + if (remainingLen) + { + result = + CAUpdateCharacteristicsToAllGattClients( + data + (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE), + remainingLen); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed"); + return CA_STATUS_FAILED; + } + CALEDoEvents(); + } +#else + VERIFY_NON_NULL_RET(g_bleServerSendQueueHandle, CALEADAPTER_TAG, "BleClientReceiverQueue is NULL", CA_STATUS_FAILED); - VERIFY_NON_NULL_RET(g_bleClientSendDataMutex, CALEADAPTER_TAG, + VERIFY_NON_NULL_RET(g_bleServerSendDataMutex, CALEADAPTER_TAG, "BleClientSendDataMutex is NULL", CA_STATUS_FAILED); - VERIFY_NON_NULL_RET(g_sendQueueHandle, CALEADAPTER_TAG, "sendQueueHandle", + VERIFY_NON_NULL_RET(g_bleServerSendQueueHandle, CALEADAPTER_TAG, "sendQueueHandle", CA_STATUS_FAILED); OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data Sending to LE layer [%d]", dataLen); - CALEData_t *bleData = CACreateBLEData(remoteEndpoint, data, dataLen); + CALEData_t * const bleData = + CACreateLEData(remoteEndpoint, data, dataLen); + if (!bleData) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create bledata!"); return CA_MEMORY_ALLOC_FAILED; } + // Add message to send queue ca_mutex_lock(g_bleServerSendDataMutex); - CAQueueingThreadAddData(g_sendQueueHandle, bleData, sizeof(CALEData_t)); + CAQueueingThreadAddData(g_bleServerSendQueueHandle, + bleData, + sizeof(CALEData_t)); ca_mutex_unlock(g_bleServerSendDataMutex); - +#endif OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CABLEServerReceivedData(const char *remoteAddress, const char *serviceUUID, - const void *data, uint32_t dataLength, uint32_t *sentLength) +static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLength, + uint32_t *sentLength) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); //Input validation - VERIFY_NON_NULL(serviceUUID, CALEADAPTER_TAG, "service UUID is null"); VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Data is null"); VERIFY_NON_NULL(sentLength, CALEADAPTER_TAG, "Sent data length holder is null"); - VERIFY_NON_NULL_RET(g_bleServerReceiverQueue, CALEADAPTER_TAG, "g_bleServerReceiverQueue", + +#ifdef SINGLE_THREAD + if(g_networkPacketReceivedCallback) + { + CAEndpoint_t endPoint = + { .adapter = CA_ADAPTER_GATT_BTLE }; // will be filled by + // upper layer + + g_networkPacketReceivedCallback(&endPoint, data, dataLength); + } +#else + VERIFY_NON_NULL_RET(g_bleReceiverQueue, + CALEADAPTER_TAG, + "g_bleReceiverQueue", CA_STATUS_FAILED); //Add message to data queue - CARemoteEndpoint_t *remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_LE, remoteAddress, - serviceUUID); + CAEndpoint_t * const remoteEndpoint = + CACreateEndpointObject(CA_DEFAULT_FLAGS, + CA_ADAPTER_GATT_BTLE, + remoteAddress, + 0); + if (NULL == remoteEndpoint) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create remote endpoint !"); @@ -1616,80 +2206,88 @@ CAResult_t CABLEServerReceivedData(const char *remoteAddress, const char *servic } // Create bleData to add to queue - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received from LE layer [%d]", dataLength); + OIC_LOG_V(DEBUG, + CALEADAPTER_TAG, + "Data received from LE layer [%d]", + dataLength); + + CALEData_t * const bleData = + CACreateLEData(remoteEndpoint, data, dataLength); - CALEData_t *bleData = CACreateBLEData(remoteEndpoint, data, dataLength); if (!bleData) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create bledata!"); - CAAdapterFreeRemoteEndpoint(remoteEndpoint); + CAFreeEndpoint(remoteEndpoint); return CA_MEMORY_ALLOC_FAILED; } - CAAdapterFreeRemoteEndpoint(remoteEndpoint); - // Add message to send queue - CAQueueingThreadAddData(g_bleServerReceiverQueue, bleData, sizeof(CALEData_t)); + CAFreeEndpoint(remoteEndpoint); + // Add message to receiver queue + CAQueueingThreadAddData(g_bleReceiverQueue, bleData, sizeof(CALEData_t)); *sentLength = dataLength; - +#endif OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CABLEClientReceivedData(const char *remoteAddress, const char *serviceUUID, - const void *data, uint32_t dataLength, uint32_t *sentLength) +static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLength, + uint32_t *sentLength) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); //Input validation - VERIFY_NON_NULL(serviceUUID, CALEADAPTER_TAG, "service UUID is null"); VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Data is null"); VERIFY_NON_NULL(sentLength, CALEADAPTER_TAG, "Sent data length holder is null"); - VERIFY_NON_NULL_RET(g_bleClientReceiverQueue, CALEADAPTER_TAG, "g_bleClientReceiverQueue", +#ifndef SINGLE_THREAD + VERIFY_NON_NULL_RET(g_bleReceiverQueue, CALEADAPTER_TAG, "g_bleReceiverQueue", CA_STATUS_FAILED); //Add message to data queue - CARemoteEndpoint_t *remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_LE, remoteAddress, - serviceUUID); + CAEndpoint_t *remoteEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, + CA_ADAPTER_GATT_BTLE, + remoteAddress, 0); if (NULL == remoteEndpoint) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create remote endpoint !"); return CA_STATUS_FAILED; } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received from LE layer [%d]", dataLength); + OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received from LE layer [%u]", dataLength); // Create bleData to add to queue - CALEData_t *bleData = CACreateBLEData(remoteEndpoint, data, dataLength); + CALEData_t *bleData = CACreateLEData(remoteEndpoint, data, dataLength); if (!bleData) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create bledata!"); - CAAdapterFreeRemoteEndpoint(remoteEndpoint); + CAFreeEndpoint(remoteEndpoint); return CA_MEMORY_ALLOC_FAILED; } - CAAdapterFreeRemoteEndpoint(remoteEndpoint); - // Add message to send queue - CAQueueingThreadAddData(g_bleClientReceiverQueue, bleData, sizeof(CALEData_t)); + CAFreeEndpoint(remoteEndpoint); + // Add message to receiver queue + CAQueueingThreadAddData(g_bleReceiverQueue, bleData, sizeof(CALEData_t)); *sentLength = dataLength; - +#endif OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -void CASetBleAdapterThreadPoolHandle(u_thread_pool_t handle) +static void CASetLEAdapterThreadPoolHandle(ca_thread_pool_t handle) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + ca_mutex_lock(g_bleAdapterThreadPoolMutex); g_bleAdapterThreadPool = handle; ca_mutex_unlock(g_bleAdapterThreadPoolMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } -void CASetBLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback) +static void CASetLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); @@ -1702,3 +2300,24 @@ void CASetBLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback) OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } +static void CALEErrorHandler(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLen, + CAResult_t result) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "CALEErrorHandler IN"); + + VERIFY_NON_NULL_VOID(data, CALEADAPTER_TAG, "Data is null"); + + CAEndpoint_t *rep = CACreateEndpointObject(CA_DEFAULT_FLAGS, + CA_ADAPTER_GATT_BTLE, + remoteAddress, + 0); + + // if required, will be used to build remote endpoint + g_errorHandler(rep, data, dataLen, result); + + CAFreeEndpoint(rep); + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "CALEErrorHandler OUT"); +}