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=69cde767a1d795b9dea34be78eda0ecde5961e20;hpb=1b3989f5777db18d830407badd8e0332c1b1e33e;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 69cde76..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,1605 +26,2022 @@ #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 g_bleAdapterThreadPool - * @brief reference to threadpool + * Reference to thread pool. */ 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; + +/** + * Mutex to synchronize the queing of the data from ReceiverQueue. + */ +static ca_mutex g_bleReceiveDataMutex = NULL; + /** - * @var g_bleClientReceiverQueue - * @brief Queue to process the incoming packets to GATT Client. + * Mutex to synchronize the queing of the data from SenderQueue. */ -static CAQueueingThread_t *g_bleClientReceiverQueue = NULL; +static ca_mutex g_bleServerSendDataMutex = NULL; /** - * @var g_bleClientSendDataMutex - * @brief Mutex to synchronize the queing of the data from SenderQueue. + * Mutex to synchronize the callback to be called for the + * adapterReqResponse. */ -static ca_mutex g_bleClientSendDataMutex = NULL; +static ca_mutex g_bleAdapterReqRespCbMutex = NULL; + +/** + * Callback to be called when network packet received from either + * GattServer or GattClient. + */ +static CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL; + +/** + * Callback to notify error from the BLE adapter. + */ +static CAErrorHandleCallback g_errorHandler = NULL; + +/** + * Storing Adapter state information. + */ +static CAAdapterState_t g_bleAdapterState = CA_ADAPTER_DISABLED; + +/** + * BLE Server Status. + * + * This enumeration provides information of LE Adapter Server status. + */ +typedef enum +{ + CA_SERVER_NOTSTARTED = 0, + CA_LISTENING_SERVER, + CA_DISCOVERY_SERVER +} CALeServerStatus; + +/** + * Structure to maintain the status of the server. + */ +static CALeServerStatus gLeServerStatus = CA_SERVER_NOTSTARTED; + +/** + * 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 CAResult_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback); + +/** + * 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 void CASetLEAdapterThreadPoolHandle(ca_thread_pool_t handle); + +/** + * 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 void CALEDeviceStateChangedCb(CAAdapterState_t adapter_state); + +/** + * 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. + * + */ +static CAResult_t CAInitLEAdapterMutex(); + +/** + * Terminate all required mutex variables for LE adapter + * implementation. + */ +static void CATerminateLEAdapterMutex(); /** - * @var g_bleClientReceiveDataMutex - * @brief Mutex to synchronize the queing of the data from ReceiverQueue. + * Prepares and notify error through error callback. */ -static ca_mutex g_bleClientReceiveDataMutex = NULL; +static void CALEErrorHandler(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLen, + CAResult_t result); +#ifndef SINGLE_THREAD /** - * @var g_dataReceiverHandlerState - * @brief Stop condition of recvhandler. + * Stop condition of recvhandler. */ static bool g_dataReceiverHandlerState = false; /** - * @var g_sendQueueHandle - * @brief Queue to process the outgoing packets from GATTServer. + * Sender information. */ -static CAQueueingThread_t *g_sendQueueHandle = NULL; +static u_arraylist_t *g_senderInfo = NULL; /** - * @var g_bleServerReceiverQueue - * @brief Queue to process the incoming packets to GATTServer + * Queue to process the outgoing packets from GATTClient. */ -static CAQueueingThread_t *g_bleServerReceiverQueue = NULL; +static CAQueueingThread_t *g_bleClientSendQueueHandle = NULL; /** - * @var g_bleServerSendDataMutex - * @brief Mutex to synchronize the queing of the data from SenderQueue. + * Queue to process the incoming packets to GATT Client. */ -static ca_mutex g_bleServerSendDataMutex = NULL; +static CAQueueingThread_t *g_bleReceiverQueue = NULL; /** - * @var g_bleServerReceiveDataMutex - * @brief Mutex to synchronize the queing of the data from ReceiverQueue. + * Queue to process the outgoing packets from GATTServer. */ -static ca_mutex g_bleServerReceiveDataMutex = NULL; +static CAQueueingThread_t *g_bleServerSendQueueHandle = NULL; /** - * @var g_bleAdapterReqRespCbMutex - * @brief Mutex to synchronize the callback to be called for the adapterReqResponse. + * 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 ca_mutex g_bleAdapterReqRespCbMutex = NULL; +static CAResult_t CAStartLE(); /** - * @var g_networkPacketReceivedCallback - * @brief Callback to be called when network packet recieved from either GattServer or GattClient. + * 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 CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL; +static CAResult_t CAStartLEListeningServer(); /** - * @ENUM CALeServerStatus - * @brief status of BLE Server Status - * This ENUM provides information of LE Adapter Server status + * 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 */ -typedef enum -{ - CA_SERVER_NOTSTARTED = 0, - CA_LISTENING_SERVER, - CA_DISCOVERY_SERVER -} CALeServerStatus; +static CAResult_t CAStartLEDiscoveryServer(); /** - * @var gLeServerStatus - * @brief structure to maintain the status of the server. + * 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 CALeServerStatus gLeServerStatus = CA_SERVER_NOTSTARTED; +static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen); /** -* @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 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 CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback); + * 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); /** -* @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(ca_thread_pool_t handle); + * 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); /** -* @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); + * Read Synchronous API callback. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAReadLEData(); /** -* @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(); + * 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(); /** -* @fn CATerminateBleAdapterMutex -* @brief Used to terminate all required mutex variable for LE adapter implementation. -* -* @return void -*/ -void CATerminateBleAdapterMutex(); + * Terminate the LE connectivity adapter. + * + * Configuration information will be deleted from further use. + */ +static void CATerminateLE(); /** -* @fn CALEDataDestroyer -* @brief Used to free data -* -* @return void -*/ -static void CALEDataDestroyer(void *data, uint32_t size); + * 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); -CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, - CANetworkPacketReceivedCallback reqRespCallback, - CANetworkChangeCallback netCallback, - ca_thread_pool_t handle) -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +/** + * 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); - //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"); +/** + * 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); - CAResult_t result = CAInitBleAdapterMutex(); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleAdapterMutex failed!"); - return CA_STATUS_FAILED; - } +/** + * 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); - result = CAInitializeLENetworkMonitor(); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitializeLENetworkMonitor() failed"); - return CA_STATUS_FAILED; - } +/** + * 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); - CAInitializeLEAdapter(); +/** + * 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); - CASetBleClientThreadPoolHandle(handle); - CASetBleServerThreadPoolHandle(handle); - CASetBleAdapterThreadPoolHandle(handle); - CASetBLEReqRespServerCallback(CABLEServerReceivedData); - CASetBLEReqRespClientCallback(CABLEClientReceivedData); - CASetBLEReqRespAdapterCallback(reqRespCallback); +/** + * 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); - CALERegisterNetworkNotifications(netCallback); +/** + * 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); - CAConnectivityHandler_t connHandler; - connHandler.startAdapter = CAStartLE; - 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_ADAPTER_GATT_BTLE); +/** + * 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(); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); +/** + * 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(); - return CA_STATUS_OK; -} +/** + * 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(); -CAResult_t CAStartLE() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - OIC_LOG(DEBUG, CALEADAPTER_TAG, - "There is no concept of unicast/multicast in LE. So This function is not implemented"); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} +/** + * 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(); -CAResult_t CAStopLE() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +/** + * 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(); - CAStopBleQueues(); +/** + * 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(); - ca_mutex_lock(g_bleIsServerMutex); - if (true == g_isServer) - { - CAStopBleGattServer(); - } - else - { - CAStopBLEGattClient(); - } - ca_mutex_unlock(g_bleIsServerMutex); +/** + * 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(); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); +/** + * 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); - return CA_STATUS_OK; -} +/** + * 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); -void CATerminateLE() +static CAResult_t CAInitLEServerQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CASetBLEReqRespServerCallback(NULL); - CASetBLEReqRespClientCallback(NULL); - CALERegisterNetworkNotifications(NULL); - CASetBLEReqRespAdapterCallback(NULL); - CATerminateLENetworkMonitor(); + ca_mutex_lock(g_bleAdapterThreadPoolMutex); - ca_mutex_lock(g_bleIsServerMutex); - if (true == g_isServer) + CAResult_t result = CAInitLEServerSenderQueue(); + if (CA_STATUS_OK != result) { - CATerminateBleGattServer(); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerSenderQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + return CA_STATUS_FAILED; } - else + + result = CAInitLEReceiverQueue(); + if (CA_STATUS_OK != result) { - CATerminateBLEGattClient(); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerReceiverQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_bleIsServerMutex); - CATerminateBleQueues(); + g_dataReceiverHandlerState = true; - CATerminateBleAdapterMutex(); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -CAResult_t CAStartLEListeningServer() +static CAResult_t CAInitLEClientQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAResult_t result = CAInitBleServerQueues(); + 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_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, "CAInitBleClientReceiverQueue failed"); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); return CA_STATUS_FAILED; } - CAStartBleGattServer(); + g_dataReceiverHandlerState = true; - ca_mutex_lock(g_bleIsServerMutex); - g_isServer = true; - ca_mutex_unlock(g_bleIsServerMutex); + ca_mutex_unlock(g_bleAdapterThreadPoolMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CAStartLEDiscoveryServer() +static CAResult_t CAInitLEReceiverQueue() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - CAResult_t result = CAInitBleClientQueues(); - if (CA_STATUS_OK != result) + // Check if the message queue is already initialized + if (g_bleReceiverQueue) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientQueues failed"); - return CA_STATUS_FAILED; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); + return CA_STATUS_OK; } - result = CAGetLEAdapterState(); - if (CA_ADAPTER_NOT_ENABLED == result) + // Create recv message queue + g_bleReceiverQueue = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); + if (!g_bleReceiverQueue) { - gLeServerStatus = CA_DISCOVERY_SERVER; - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); - return CA_STATUS_OK; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + return CA_MEMORY_ALLOC_FAILED; } - if (CA_STATUS_FAILED == result) + g_senderInfo = u_arraylist_create(); + if (!g_senderInfo) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "ClientInfo memory allcation failed!"); + OICFree(g_bleReceiverQueue); + g_bleReceiverQueue = NULL; + return CA_MEMORY_ALLOC_FAILED; } - CAStartBLEGattClient(); - - ca_mutex_lock(g_bleIsServerMutex); - g_isServer = false; - ca_mutex_unlock(g_bleIsServerMutex); - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAStartLENotifyServer() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} - -uint32_t CASendLENotification(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLen) -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return 0; -} + 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; + } -CAResult_t CAReadLEData() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + 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 CAEndpoint_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 CAEndpoint_t *endpoint, 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(CAEndpoint_t **info, uint32_t *size) +static CAResult_t CAInitLEClientSenderQueue() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - VERIFY_NON_NULL(info, NULL, "CALocalConnectivity info is null"); - - char *local_address = NULL; - - CAResult_t res = CAGetLEAddress(&local_address); - if (CA_STATUS_OK != res) + if (g_bleClientSendQueueHandle) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAGetLEAddress has failed"); - return res; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); + return CA_STATUS_OK; } - if (NULL == local_address) + // Create send message queue + g_bleClientSendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); + if (!g_bleClientSendQueueHandle) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "local_address is NULL"); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + return CA_MEMORY_ALLOC_FAILED; } - *size = 0; - (*info) = (CAEndpoint_t *) OICCalloc(1, sizeof (CAEndpoint_t)); - if (NULL == (*info)) + if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleClientSendQueueHandle, + g_bleAdapterThreadPool, + CALEClientSendDataThread, CALEDataDestroyer)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failure!"); - OICFree(local_address); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); + OICFree(g_bleClientSendQueueHandle); + g_bleClientSendQueueHandle = NULL; return CA_STATUS_FAILED; } - size_t local_address_len = strlen(local_address); - - if(local_address_len >= sizeof(g_localBLEAddress) || - local_address_len >= MAX_ADDR_STR_SIZE_CA - 1) + if (CA_STATUS_OK != CAQueueingThreadStart(g_bleClientSendQueueHandle)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "local_address is too long"); - OICFree(*info); - OICFree(local_address); + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); + OICFree(g_bleClientSendQueueHandle); + g_bleClientSendQueueHandle = NULL; return CA_STATUS_FAILED; } - 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); - - (*info)->adapter = CA_ADAPTER_GATT_BTLE; - *size = 1; - OICFree(local_address); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); return CA_STATUS_OK; } -CAResult_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); - CAResult_t res = CA_STATUS_OK; - if (netCallback) + ca_mutex_lock(g_bleClientSendDataMutex); + if (NULL != g_bleClientSendQueueHandle) { - res = CASetLEAdapterStateChangedCb(CALEDeviceStateChangedCb); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); - } + CAQueueingThreadStop(g_bleClientSendQueueHandle); } - else + ca_mutex_unlock(g_bleClientSendDataMutex); + + ca_mutex_lock(g_bleServerSendDataMutex); + if (NULL != g_bleServerSendQueueHandle) { - res = CAUnSetLEAdapterStateChangedCb(); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); - } + CAQueueingThreadStop(g_bleServerSendQueueHandle); + } + ca_mutex_unlock(g_bleServerSendDataMutex); + + ca_mutex_lock(g_bleReceiveDataMutex); + if (NULL != g_bleReceiverQueue) + { + CAQueueingThreadStop(g_bleReceiverQueue); } + ca_mutex_unlock(g_bleReceiveDataMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return res; } -void CALEDeviceStateChangedCb( CAAdapterState_t adapter_state) +static void CATerminateLEQueues() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - VERIFY_NON_NULL_VOID(g_localBLEAddress, NULL, "g_localBLEAddress is null"); - CAEndpoint_t localEndpoint = {}; - localEndpoint.adapter = CA_ADAPTER_GATT_BTLE; - ca_mutex_lock(g_bleLocalAddressMutex); - OICStrcpy(localEndpoint.addr, sizeof(localEndpoint.addr), g_localBLEAddress); - ca_mutex_unlock(g_bleLocalAddressMutex); + CAQueueingThreadDestroy(g_bleClientSendQueueHandle); + OICFree(g_bleClientSendQueueHandle); + g_bleClientSendQueueHandle = 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_bleServerSendQueueHandle); + OICFree(g_bleServerSendQueueHandle); + g_bleServerSendQueueHandle = 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); + CAQueueingThreadDestroy(g_bleReceiverQueue); + OICFree(g_bleReceiverQueue); + g_bleReceiverQueue = NULL; + + CALEClearSenderInfo(); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } -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) +static void CALEDataReceiverHandler(void *threadData) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + ca_mutex_lock(g_bleReceiveDataMutex); + + if (g_dataReceiverHandlerState) { - g_bleAdapterThreadPoolMutex = ca_mutex_new(); - if (NULL == g_bleAdapterThreadPoolMutex) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); + + 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_bleClientSendDataMutex) - { - g_bleClientSendDataMutex = ca_mutex_new(); - if (NULL == g_bleClientSendDataMutex) + 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_bleClientReceiveDataMutex) - { - g_bleClientReceiveDataMutex = ca_mutex_new(); - if (NULL == g_bleClientReceiveDataMutex) + 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); } - } - if (NULL == g_bleServerSendDataMutex) - { - g_bleServerSendDataMutex = ca_mutex_new(); - if (NULL == g_bleServerSendDataMutex) + if(!senderInfo) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; - } - } + 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; - if (NULL == g_bleServerReceiveDataMutex) - { - g_bleServerReceiveDataMutex = ca_mutex_new(); - if (NULL == g_bleServerReceiveDataMutex) + 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; + } + + 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); + + newSender->defragData = OICCalloc(newSender->totalDataLen + 1, + sizeof(*newSender->defragData)); + + if (NULL == newSender->defragData) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "defragData is NULL!"); + OICFree(newSender); + ca_mutex_unlock(g_bleReceiveDataMutex); + return; + } + + 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 { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + 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); } - } - if (NULL == g_bleAdapterReqRespCbMutex) - { - g_bleAdapterReqRespCbMutex = ca_mutex_new(); - if (NULL == g_bleAdapterReqRespCbMutex) + if (senderInfo->totalDataLen == senderInfo->recvDataLen) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); - return CA_STATUS_FAILED; + 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); } } - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - return CA_STATUS_OK; + ca_mutex_unlock(g_bleReceiveDataMutex); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } -void CATerminateBleAdapterMutex() +static void CALEServerSendDataThread(void *threadData) { 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_bleClientReceiveDataMutex); - g_bleClientReceiveDataMutex = NULL; - - ca_mutex_free(g_bleServerSendDataMutex); - g_bleServerSendDataMutex = NULL; + CALEData_t * const bleData = (CALEData_t *) threadData; + if (!bleData) + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); + return; + } - ca_mutex_free(g_bleServerReceiveDataMutex); - g_bleServerReceiveDataMutex = NULL; + uint8_t * const header = OICCalloc(CA_HEADER_LENGTH, 1); + VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed"); - ca_mutex_free(g_bleAdapterReqRespCbMutex); - g_bleAdapterReqRespCbMutex = NULL; + const uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH; - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); -} + OIC_LOG_V(DEBUG, + CALEADAPTER_TAG, + "Server total Data length with header is [%u]", + totalLength); -void CAInitBleQueues() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + uint8_t * const dataSegment = OICCalloc(totalLength, 1); - CAResult_t result = CAInitBleServerQueues(); - if (CA_STATUS_OK != result) + if (NULL == dataSegment) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerQueues failed"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); + OICFree(header); return; } - result = CAInitBleClientQueues(); - 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, "CAInitBleClientQueues failed"); + OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); + OICFree(header); + OICFree(dataSegment); return; } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); -} - -CAResult_t CAInitBleServerQueues() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - ca_mutex_lock(g_bleAdapterThreadPoolMutex); + memcpy(dataSegment, header, CA_HEADER_LENGTH); + OICFree(header); - CAResult_t result = CAInitBleServerSenderQueue(); - if (CA_STATUS_OK != result) + uint32_t length = 0; + if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerSenderQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; + length = totalLength; + memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, bleData->dataLen); } - - result = CAInitBleServerReceiverQueue(); - if (CA_STATUS_OK != result) + else { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleServerReceiverQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; + length = CA_SUPPORTED_BLE_MTU_SIZE; + memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, + CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); } - g_dataReceiverHandlerState = true; + uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE; + uint32_t index = 0; - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + // Send the first segment with the header. + if (NULL != bleData->remoteEndpoint) // Sending Unicast Data + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Server Sending Unicast Data"); - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} + result = CAUpdateCharacteristicsToGattClient( + bleData->remoteEndpoint->addr, dataSegment, length); -CAResult_t CAInitBleClientQueues() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + 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; + } - ca_mutex_lock(g_bleAdapterThreadPoolMutex); + 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); + } - CAResult_t result = CAInitBleClientSenderQueue(); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitBleClientSenderQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; - } + const uint32_t remainingLen = + totalLength % CA_SUPPORTED_BLE_MTU_SIZE; - result = CAInitBleClientReceiverQueue(); - if (CA_STATUS_OK != result) + 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(ERROR, CALEADAPTER_TAG, "CAInitBleClientReceiverQueue failed"); - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); - return CA_STATUS_FAILED; - } - - g_dataReceiverHandlerState = true; + 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); + } - ca_mutex_unlock(g_bleAdapterThreadPoolMutex); + 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 CA_STATUS_OK; } -CAResult_t CAInitBleServerSenderQueue() +static void CALEClientSendDataThread(void *threadData) { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - // Check if the message queue is already initialized - if (g_sendQueueHandle) + + CALEData_t *bleData = (CALEData_t *) threadData; + if (!bleData) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Queue is already initialized!"); - return CA_STATUS_OK; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); + return; } - // Create send message queue - g_sendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_sendQueueHandle) + 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, "Memory allocation failed!"); - return CA_MEMORY_ALLOC_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); + OICFree(header); + return; } - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle, g_bleAdapterThreadPool, - CABLEServerSendDataThread, CALEDataDestroyer)) + CAResult_t result = CAGenerateHeader(header, + CA_HEADER_LENGTH, + bleData->dataLen); + if (CA_STATUS_OK != result ) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; - 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); - if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle)) + uint32_t length = 0; + if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; - return CA_STATUS_FAILED; + length = totalLength; + memcpy(dataSegment + CA_HEADER_LENGTH, + bleData->data, + bleData->dataLen); } - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} - -CAResult_t CAInitBleClientSenderQueue() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - if (g_bleClientSendQueueHandle) + else { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); - return CA_STATUS_OK; + length = CA_SUPPORTED_BLE_MTU_SIZE; + memcpy(dataSegment + CA_HEADER_LENGTH, + bleData->data, + CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); } - // Create send message queue - g_bleClientSendQueueHandle = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_bleClientSendQueueHandle) + const uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE; + uint32_t index = 0; + if (NULL != bleData->remoteEndpoint) //Sending Unicast Data { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - return CA_MEMORY_ALLOC_FAILED; - } + 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); - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleClientSendQueueHandle, g_bleAdapterThreadPool, - CABLEClientSendDataThread, CALEDataDestroyer)) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_bleClientSendQueueHandle); - g_bleClientSendQueueHandle = NULL; - return CA_STATUS_FAILED; - } + 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; + } - if (CA_STATUS_OK != CAQueueingThreadStart(g_bleClientSendQueueHandle)) + 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 { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); - OICFree(g_bleClientSendQueueHandle); - g_bleClientSendQueueHandle = NULL; - return CA_STATUS_FAILED; + //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); + } + } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; + OICFree(dataSegment); + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT - CABLEClientSendDataThread"); } -CAResult_t CAInitBleServerReceiverQueue() +static CALEData_t *CACreateLEData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLength) { - 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; - } + CALEData_t * const bleData = OICMalloc(sizeof(CALEData_t)); - // Create send message queue - g_bleServerReceiverQueue = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_bleServerReceiverQueue) + if (!bleData) { OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - OICFree(g_sendQueueHandle); - return CA_MEMORY_ALLOC_FAILED; + return NULL; } - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleServerReceiverQueue, g_bleAdapterThreadPool, - CABLEServerDataReceiverHandler, CALEDataDestroyer)) + bleData->remoteEndpoint = CACloneEndpoint(remoteEndpoint); + bleData->data = OICCalloc(dataLength + 1, 1); + + if (NULL == bleData->data) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_bleServerReceiverQueue); - g_bleServerReceiverQueue = NULL; - return CA_STATUS_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); + CAFreeLEData(bleData); + return NULL; } - if (CA_STATUS_OK != CAQueueingThreadStart(g_bleServerReceiverQueue)) + memcpy(bleData->data, data, dataLength); + bleData->dataLen = dataLength; + + return bleData; +} + +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); +} + +static void CALEDataDestroyer(void *data, uint32_t size) +{ + if ((size_t)size < sizeof(CALEData_t *)) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); - OICFree(g_bleServerReceiverQueue); - g_bleServerReceiverQueue = NULL; - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, CALEADAPTER_TAG, + "Destroy data too small %p %d", data, size); } + CALEData_t *ledata = (CALEData_t *) data; - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; + CAFreeLEData(ledata); } +#endif -CAResult_t CAInitBleClientReceiverQueue() +static CAResult_t CAInitLEAdapterMutex() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - // Check if the message queue is already initialized - if (g_bleClientReceiverQueue) + if (NULL == g_bleIsServerMutex) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Already queue is initialized!"); + g_bleIsServerMutex = ca_mutex_new(); + if (NULL == g_bleIsServerMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } } - else + + if (NULL == g_bleNetworkCbMutex) { - // Create send message queue - g_bleClientReceiverQueue = (CAQueueingThread_t *) OICMalloc(sizeof(CAQueueingThread_t)); - if (!g_bleClientReceiverQueue) + g_bleNetworkCbMutex = ca_mutex_new(); + if (NULL == g_bleNetworkCbMutex) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - OICFree(g_bleClientSendQueueHandle); - return CA_MEMORY_ALLOC_FAILED; + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; } + } - if (CA_STATUS_OK != CAQueueingThreadInitialize(g_bleClientReceiverQueue, g_bleAdapterThreadPool, - CABLEClientDataReceiverHandler, NULL)) + if (NULL == g_bleLocalAddressMutex) + { + g_bleLocalAddressMutex = ca_mutex_new(); + if (NULL == g_bleLocalAddressMutex) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to Initialize send queue thread"); - OICFree(g_bleClientSendQueueHandle); - OICFree(g_bleClientReceiverQueue); - g_bleClientReceiverQueue = NULL; + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); return CA_STATUS_FAILED; } } - if (CA_STATUS_OK != CAQueueingThreadStart(g_bleClientReceiverQueue)) + + if (NULL == g_bleAdapterThreadPoolMutex) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_thread_pool_add_task failed "); - OICFree(g_bleClientReceiverQueue); - g_bleClientReceiverQueue = NULL; - return CA_STATUS_FAILED; + g_bleAdapterThreadPoolMutex = ca_mutex_new(); + if (NULL == g_bleAdapterThreadPoolMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } } - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); - return CA_STATUS_OK; -} - -void CAStopBleQueues() -{ - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - ca_mutex_lock(g_bleClientSendDataMutex); - if (NULL != g_bleClientSendQueueHandle) + if (NULL == g_bleClientSendDataMutex) { - CAQueueingThreadStop(g_bleClientSendQueueHandle); + g_bleClientSendDataMutex = ca_mutex_new(); + if (NULL == g_bleClientSendDataMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } } - ca_mutex_unlock(g_bleClientSendDataMutex); - ca_mutex_lock(g_bleClientReceiveDataMutex); - if (NULL != g_bleClientReceiverQueue) + if (NULL == g_bleServerSendDataMutex) { - CAQueueingThreadStop(g_bleClientReceiverQueue); + g_bleServerSendDataMutex = ca_mutex_new(); + if (NULL == g_bleServerSendDataMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } } - ca_mutex_unlock(g_bleClientReceiveDataMutex); - ca_mutex_lock(g_bleServerSendDataMutex); - if (NULL != g_sendQueueHandle) + if (NULL == g_bleAdapterReqRespCbMutex) { - CAQueueingThreadStop(g_sendQueueHandle); + g_bleAdapterReqRespCbMutex = ca_mutex_new(); + if (NULL == g_bleAdapterReqRespCbMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + CATerminateLEAdapterMutex(); + return CA_STATUS_FAILED; + } } - ca_mutex_unlock(g_bleServerSendDataMutex); - ca_mutex_lock(g_bleServerReceiveDataMutex); - if (NULL != g_bleServerReceiverQueue) + if (NULL == g_bleReceiveDataMutex) { - CAQueueingThreadStop(g_bleServerReceiverQueue); + g_bleReceiveDataMutex = ca_mutex_new(); + if (NULL == g_bleReceiveDataMutex) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } } - ca_mutex_unlock(g_bleServerReceiveDataMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -void CATerminateBleQueues() +static void CATerminateLEAdapterMutex() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAQueueingThreadDestroy(g_bleClientSendQueueHandle); - OICFree(g_bleClientSendQueueHandle); - g_bleClientSendQueueHandle = NULL; + ca_mutex_free(g_bleIsServerMutex); + g_bleIsServerMutex = NULL; + + ca_mutex_free(g_bleNetworkCbMutex); + g_bleNetworkCbMutex = NULL; + ca_mutex_free(g_bleLocalAddressMutex); + g_bleLocalAddressMutex = NULL; - CAQueueingThreadDestroy(g_bleClientReceiverQueue); - OICFree(g_bleClientReceiverQueue); - g_bleClientReceiverQueue = NULL; + ca_mutex_free(g_bleAdapterThreadPoolMutex); + g_bleAdapterThreadPoolMutex = NULL; + ca_mutex_free(g_bleClientSendDataMutex); + g_bleClientSendDataMutex = NULL; - CAQueueingThreadDestroy(g_sendQueueHandle); - OICFree(g_sendQueueHandle); - g_sendQueueHandle = NULL; + ca_mutex_free(g_bleServerSendDataMutex); + g_bleServerSendDataMutex = NULL; + ca_mutex_free(g_bleAdapterReqRespCbMutex); + g_bleAdapterReqRespCbMutex = NULL; - CAQueueingThreadDestroy(g_bleServerReceiverQueue); - OICFree(g_bleServerReceiverQueue); - g_bleServerReceiverQueue = NULL; + ca_mutex_free(g_bleReceiveDataMutex); + g_bleReceiveDataMutex = NULL; OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } -void CABLEServerDataReceiverHandler(void *threadData) + +CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, + CANetworkPacketReceivedCallback reqRespCallback, + CANetworkChangeCallback netCallback, + CAErrorHandleCallback errorCallback, + ca_thread_pool_t handle) { 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 CAEndpoint_t *remoteEndpoint = NULL; - - ca_mutex_lock(g_bleServerReceiveDataMutex); + //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 (g_dataReceiverHandlerState) + CAResult_t result = CA_STATUS_OK; + result = CAInitLEAdapterMutex(); + if (CA_STATUS_OK != result) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "checking for DE Fragmentation"); - - CALEData_t *bleData = (CALEData_t *) threadData; - if (!bleData) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bleData!"); - 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(ERROR, CALEADAPTER_TAG, "CAInitBleAdapterMutex failed!"); + return CA_STATUS_FAILED; + } + result = CAInitializeLENetworkMonitor(); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitializeLENetworkMonitor() failed"); + return CA_STATUS_FAILED; + } - 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); + CAInitializeLEAdapter(); - defragData = (char *) OICCalloc(totalDataLen + 1, sizeof(char)); - if (NULL == defragData) - { - OIC_LOG(ERROR, CALEADAPTER_TAG, "defragData is NULL!"); - return; - } + CASetLEClientThreadPoolHandle(handle); + CASetLEReqRespClientCallback(CALEAdapterClientReceivedData); + CASetLEServerThreadPoolHandle(handle); + CASetLEAdapterThreadPoolHandle(handle); + CASetLEReqRespServerCallback(CALEAdapterServerReceivedData); + CASetLEReqRespAdapterCallback(reqRespCallback); - const char *remoteAddress = bleData->remoteEndpoint->addr; + CASetBLEClientErrorHandleCallback(CALEErrorHandler); + CASetBLEServerErrorHandleCallback(CALEErrorHandler); + CALERegisterNetworkNotifications(netCallback); - remoteEndpoint = CAAdapterCreateEndpoint(0, CA_ADAPTER_GATT_BTLE, remoteAddress, 0); + g_errorHandler = errorCallback; - memcpy(defragData + recvDataLen, bleData->data + CA_HEADER_LENGTH, - bleData->dataLen - CA_HEADER_LENGTH); - recvDataLen += bleData->dataLen - CA_HEADER_LENGTH; - isHeaderAvailable = true; - } - else + static const CAConnectivityHandler_t connHandler = { - 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); - } + .startAdapter = CAStartLE, + .stopAdapter = CAStopLE, + .startListenServer = CAStartLEListeningServer, + .startDiscoveryServer = CAStartLEDiscoveryServer, + .sendData = CASendLEUnicastData, + .sendDataToAll = CASendLEMulticastData, + .GetnetInfo = CAGetLEInterfaceInformation, + .readData = CAReadLEData, + .terminate = CATerminateLE + }; + + registerCallback(connHandler, CA_ADAPTER_GATT_BTLE); - if (false == g_dataReceiverHandlerState) - { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "GATTClient is terminating. Cleaning up"); - recvDataLen = 0; - totalDataLen = 0; - isHeaderAvailable = false; - OICFree(defragData); - CAAdapterFreeEndpoint(remoteEndpoint); - ca_mutex_unlock(g_bleServerReceiveDataMutex); - return; - } - } - ca_mutex_unlock(g_bleServerReceiveDataMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + + return CA_STATUS_OK; } -void CABLEClientDataReceiverHandler(void *threadData) +static CAResult_t CAStartLE() { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + OIC_LOG(DEBUG, CALEADAPTER_TAG, __func__); - static const char *remoteAddress = NULL; - static uint32_t recvDataLen = 0; - static uint32_t totalDataLen = 0; - static char *defragData = NULL; - static bool isHeaderAvailable = false; - static CAEndpoint_t *remoteEndpoint = NULL; + return CAStartLEAdapter(); +} - ca_mutex_lock(g_bleClientReceiveDataMutex); +static CAResult_t CAStopLE() +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +#ifndef SINGLE_THREAD + CAStopLEQueues(); +#endif - 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) - { - 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, "defragData is NULL!"); - return; - } - - remoteAddress = bleData->remoteEndpoint->addr; - - remoteEndpoint = CAAdapterCreateEndpoint(0, CA_ADAPTER_GATT_BTLE, remoteAddress, 0); - - 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); - } - 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"); - OICFree(defragData); - CAAdapterFreeEndpoint(remoteEndpoint); - ca_mutex_unlock(g_bleClientReceiveDataMutex); - return; - } + CAStopLEGattServer(); } - ca_mutex_unlock(g_bleClientReceiveDataMutex); + else + { + CAStopLEGattClient(); + } + ca_mutex_unlock(g_bleIsServerMutex); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + + return CA_STATUS_OK; } -void CABLEServerSendDataThread(void *threadData) +static void CATerminateLE() { 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"); - - int32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH; + CASetLEReqRespServerCallback(NULL); + CASetLEReqRespClientCallback(NULL); + CALERegisterNetworkNotifications(NULL); + CASetLEReqRespAdapterCallback(NULL); + CATerminateLENetworkMonitor(); - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server total Data length with header is [%d]", totalLength); - char *dataSegment = (char *) OICCalloc(totalLength + 1, sizeof(char)); - if (NULL == dataSegment) + ca_mutex_lock(g_bleIsServerMutex); + if (true == g_isServer) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); - OICFree(header); - return; + CATerminateLEGattServer(); } - - CAResult_t result = CAGenerateHeader(header, bleData->dataLen); - if (CA_STATUS_OK != result ) + else { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); - OICFree(header); - OICFree(dataSegment); - return ; + CATerminateLEGattClient(); } + ca_mutex_unlock(g_bleIsServerMutex); - memcpy(dataSegment, header, CA_HEADER_LENGTH); - OICFree(header); +#ifndef SINGLE_THREAD + CATerminateLEQueues(); +#endif + CATerminateLEAdapterMutex(); - int32_t length = 0; - if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); +} + +static CAResult_t CAStartLEListeningServer() +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + CAResult_t result = CA_STATUS_OK; +#ifndef SINGLE_THREAD + result = CAInitLEServerQueues(); + if (CA_STATUS_OK != result) { - length = totalLength; - memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, bleData->dataLen); + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitLEServerQueues failed"); + return CA_STATUS_FAILED; } - else +#endif + + result = CAGetLEAdapterState(); + if (CA_ADAPTER_NOT_ENABLED == result) { - length = CA_SUPPORTED_BLE_MTU_SIZE; - memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, - CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH); + gLeServerStatus = CA_LISTENING_SERVER; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); + return CA_STATUS_OK; } - int32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE; - int32_t index = 0; - // Send the first segment with the header. - if (NULL != bleData->remoteEndpoint) //Sending Unicast Data + if (CA_STATUS_FAILED == result) { - 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); - 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 = 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); - OICFree(dataSegment); - return; - } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", - CA_SUPPORTED_BLE_MTU_SIZE); - } + OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); + return CA_STATUS_FAILED; + } - int32_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); - 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); - 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); - OICFree(dataSegment); - return; - } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", CA_SUPPORTED_BLE_MTU_SIZE); - } + CAStartLEGattServer(); - int32_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); - OICFree(dataSegment); - return; - } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", remainingLen); - } - } - OICFree(dataSegment); + ca_mutex_lock(g_bleIsServerMutex); + g_isServer = true; + ca_mutex_unlock(g_bleIsServerMutex); OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -void CABLEClientSendDataThread(void *threadData) +static CAResult_t CAStartLEDiscoveryServer() { OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - - CALEData_t *bleData = (CALEData_t *) threadData; - if (!bleData) + CAResult_t result = CA_STATUS_OK; +#ifndef SINGLE_THREAD + result = CAInitLEClientQueues(); + if (CA_STATUS_OK != result) { - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!"); - return; + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAInitLEClientQueues failed"); + return CA_STATUS_FAILED; } - - char *header = (char *) OICCalloc(CA_HEADER_LENGTH, sizeof(char)); - VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed"); - - uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH; - char *dataSegment = (char *) OICCalloc(totalLength + 1, sizeof(char)); - if (NULL == dataSegment) +#endif + result = CAGetLEAdapterState(); + if (CA_ADAPTER_NOT_ENABLED == result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed"); - OICFree(header); - return; + gLeServerStatus = CA_DISCOVERY_SERVER; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Listen Server will be started once BT Adapter is enabled"); + return CA_STATUS_OK; } - CAResult_t result = CAGenerateHeader(header, bleData->dataLen); - if (CA_STATUS_OK != result ) + if (CA_STATUS_FAILED == result) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed"); - OICFree(header); - OICFree(dataSegment); - return ; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Bluetooth get state failed!"); + return CA_STATUS_FAILED; } - memcpy(dataSegment, header, CA_HEADER_LENGTH); - OICFree(header); - uint32_t length = 0; - if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength) - { - length = totalLength; - 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); - } + CAStartLEGattClient(); - 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); + ca_mutex_lock(g_bleIsServerMutex); + g_isServer = false; + ca_mutex_unlock(g_bleIsServerMutex); - if (CA_STATUS_OK != result) - { - OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", result); - OICFree(dataSegment); - return ; - } + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", 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); - OICFree(dataSegment); - return; - } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", - CA_SUPPORTED_BLE_MTU_SIZE); - } +static CAResult_t CAReadLEData() +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); +#ifdef SINGLE_THREAD + CACheckLEData(); +#endif + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; +} + +static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + //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); + + CAResult_t result = CA_STATUS_FAILED; - uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE; - if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE)) + ca_mutex_lock(g_bleIsServerMutex); + if (true == g_isServer) + { + result = CALEAdapterServerSendData(endpoint, data, dataLen); + if (CA_STATUS_OK != result) { - // 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(ERROR, CALEADAPTER_TAG, "Send unicast data failed\n"); + if (g_errorHandler) { - OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", - result); - OICFree(dataSegment); - return; + g_errorHandler(endpoint, data, dataLen, result); } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", remainingLen); + ca_mutex_unlock(g_bleIsServerMutex); + return -1; } } else { - //Sending Mulitcast Data - // Send the first segment with the header. - OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending Multicast Data"); - result = CAUpdateCharacteristicsToAllGattServers(dataSegment, length); + result = CALEAdapterClientSendData(endpoint, data, dataLen); if (CA_STATUS_OK != result) { - OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed (all), result [%d]", result); - OICFree(dataSegment); - return ; + OIC_LOG(ERROR, CALEADAPTER_TAG, "Send unicast data failed \n"); + if (g_errorHandler) + { + g_errorHandler(endpoint, data, dataLen, result); + } + ca_mutex_unlock(g_bleIsServerMutex); + return -1; } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", length); - // Send the remaining header. - for (index = 1; index < iter; index++) + } + ca_mutex_unlock(g_bleIsServerMutex); + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return dataLen; +} + +static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen) +{ + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + //Input validation + VERIFY_NON_NULL_RET(data, CALEADAPTER_TAG, "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 = CALEAdapterServerSendData(NULL, data, dataLen); + if (CA_STATUS_OK != result) { - 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, "Send multicast data failed" ); + + ca_mutex_unlock(g_bleIsServerMutex); + if (g_errorHandler) { - OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics (all) failed, result [%d]", result); - OICFree(dataSegment); - return; + g_errorHandler(endpoint, data, dataLen, result); } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", CA_SUPPORTED_BLE_MTU_SIZE); + return -1; } - - uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE; - if ( remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE)) + } + else + { + result = CALEAdapterClientSendData(NULL, data, dataLen); + if (CA_STATUS_OK != result) { - // 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(ERROR, CALEADAPTER_TAG, "Send Multicast data failed" ); + if (g_errorHandler) { - OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics (all) failed, result [%d]", result); - OICFree(dataSegment); - return; + g_errorHandler(endpoint, data, dataLen, result); } - OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", remainingLen); + ca_mutex_unlock(g_bleIsServerMutex); + return -1; } - } + ca_mutex_unlock(g_bleIsServerMutex); - OICFree(dataSegment); - - OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT - CABLEClientSendDataThread"); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return dataLen; } -CALEData_t *CACreateBLEData(const CAEndpoint_t *remoteEndpoint, const void *data, - uint32_t dataLength) +static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { - CALEData_t *bleData = (CALEData_t *) OICMalloc(sizeof(CALEData_t)); - if (!bleData) + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); + + VERIFY_NON_NULL(info, CALEADAPTER_TAG, "CALocalConnectivity info is null"); + + char *local_address = NULL; + + CAResult_t res = CAGetLEAddress(&local_address); + if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - return NULL; + OIC_LOG(ERROR, CALEADAPTER_TAG, "CAGetLEAddress has failed"); + return res; } - bleData->remoteEndpoint = CAAdapterCloneEndpoint(remoteEndpoint); - bleData->data = (void *)OICCalloc(dataLength + 1, 1); - if (NULL == bleData->data) + if (NULL == local_address) { - OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!"); - CAFreeBLEData(bleData); - return NULL; + OIC_LOG(ERROR, CALEADAPTER_TAG, "local_address is NULL"); + return CA_STATUS_FAILED; } - memcpy(bleData->data, data, dataLength); - bleData->dataLen = dataLength; - return bleData; + *size = 0; + (*info) = (CAEndpoint_t *) OICCalloc(1, sizeof(CAEndpoint_t)); + if (NULL == (*info)) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failure!"); + OICFree(local_address); + return CA_STATUS_FAILED; + } + + size_t local_address_len = strlen(local_address); + + if(local_address_len >= sizeof(g_localBLEAddress) || + local_address_len >= MAX_ADDR_STR_SIZE_CA - 1) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "local_address is too long"); + OICFree(*info); + OICFree(local_address); + return CA_STATUS_FAILED; + } + + 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); + + (*info)->adapter = CA_ADAPTER_GATT_BTLE; + *size = 1; + OICFree(local_address); + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return CA_STATUS_OK; } -void CAFreeBLEData(CALEData_t *bleData) +static CAResult_t CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback) { - VERIFY_NON_NULL_VOID(bleData, NULL, "Param bleData is NULL"); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAAdapterFreeEndpoint(bleData->remoteEndpoint); - OICFree(bleData->data); - OICFree(bleData); + 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) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); + } + } + else + { + res = CAUnSetLEAdapterStateChangedCb(); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, CALEADAPTER_TAG, "CASetLEAdapterStateChangedCb failed!"); + } + } + + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); + return res; } -void CALEDataDestroyer(void *data, uint32_t size) +static void CALEDeviceStateChangedCb(CAAdapterState_t adapter_state) { - CALEData_t *ledata = (CALEData_t *) data; + OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN"); - CAFreeBLEData(ledata); -} + 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(DEBUG, CALEADAPTER_TAG, "Before CAStartLEGattServer"); + CAStartLEGattServer(); + } + else if (CA_DISCOVERY_SERVER == gLeServerStatus) + { + OIC_LOG(DEBUG, CALEADAPTER_TAG, "Before CAStartBleGattClient"); + CAStartLEGattClient(); + } + gLeServerStatus = CA_SERVER_NOTSTARTED; + + 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); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); +} -CAResult_t CABLEClientSendData(const CAEndpoint_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(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); @@ -1635,9 +2052,9 @@ CAResult_t CABLEClientSendData(const CAEndpoint_t *remoteEndpoint, 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!"); @@ -1647,61 +2064,141 @@ CAResult_t CABLEClientSendData(const CAEndpoint_t *remoteEndpoint, ca_mutex_lock(g_bleClientSendDataMutex); 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 CAEndpoint_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_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 - CAEndpoint_t *remoteEndpoint = CAAdapterCreateEndpoint(0, CA_ADAPTER_GATT_BTLE, remoteAddress, 0); + 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 !"); @@ -1709,79 +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!"); - CAAdapterFreeEndpoint(remoteEndpoint); + CAFreeEndpoint(remoteEndpoint); return CA_MEMORY_ALLOC_FAILED; } - CAAdapterFreeEndpoint(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 - CAEndpoint_t *remoteEndpoint = CAAdapterCreateEndpoint(0, CA_ADAPTER_GATT_BTLE, remoteAddress, 0); + 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!"); - CAAdapterFreeEndpoint(remoteEndpoint); + CAFreeEndpoint(remoteEndpoint); return CA_MEMORY_ALLOC_FAILED; } - CAAdapterFreeEndpoint(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(ca_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"); @@ -1794,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"); +}