Implementation of connectivity abstraction feature Release v0.5
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / cableserver.c
index da9cd2a..1ba782f 100644 (file)
@@ -26,6 +26,8 @@
 #include "umutex.h"
 #include "camessagequeue.h"
 #include "caadapterutils.h"
+#include "camsgparser.h"
+#include "cableclientutil.h"
 
 /**
  * @def TZ_BLE_SERVER_TAG
@@ -129,6 +131,31 @@ static u_mutex gBleServerThreadPoolMutex = NULL;
 static u_cond gBleServerSendCondWait = NULL;
 
 /**
+ * @var gReceiverDataCond
+ * @brief Condition used for notifying handler the presence of data in recv queue.
+ */
+static u_cond gReceiverDataCond = NULL;
+
+/**
+ * @var gDataReceiverHandlerState
+ * @brief Stop condition of redvhandler.
+ */
+static bool gDataReceiverHandlerState = false;
+
+/**
+ * @var isHeaderAvailable
+ * @brief to differentiate btw header and data packet.
+ */
+static CABool_t isHeaderAvailable = false;
+
+/**
+ * @struct gRemoteAddress
+ * @brief Remote address of Gatt client
+ *
+ */
+static const char *gRemoteClientAddress = "DB:F7:EB:B5:0F:07";
+///TODO: later this will be replaced with the platform apis.
+/**
  * @var gBleServerReceiveDataMutex
  * @brief Mutex to synchronize the queing of the data from ReceiverQueue.
  */
@@ -152,14 +179,65 @@ static u_thread_pool_t gBleServerThreadPool = NULL;
  */
 static CABool_t gServerUp = CA_FALSE;
 
+/**
+ * @fn CABLEDataReceiverHandler
+ * @brief This function handles data from recv message queue.
+ */
+static void CABLEDataReceiverHandler(void *context);
+
+CAResult_t CABLEPushDataToServerReceiverQueue(const char *remoteAddress, const char *serviceUUID,
+        void *data, uint32_t dataLength, uint32_t *sentLength)
+{
+    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+    //Input validation
+    VERIFY_NON_NULL(serviceUUID, TZ_BLE_SERVER_TAG, "service UUID is null");
+    VERIFY_NON_NULL(data, TZ_BLE_SERVER_TAG, "Data is null");
+    VERIFY_NON_NULL(sentLength, TZ_BLE_SERVER_TAG, "Sent data length holder is null");
+
+    //Add message to data queue
+    CARemoteEndpoint_t *remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_LE, remoteAddress,
+                                         serviceUUID);
+    if (NULL == remoteEndpoint)
+    {
+        OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "Failed to create remote endpoint !");
+        return CA_STATUS_FAILED;
+    }
+
+    if (CA_STATUS_OK != CAAdapterEnqueueMessage(gCABleServerReceiverQueue, remoteEndpoint, data,
+            dataLength))
+    {
+        OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "Failed to add message to queue !");
+
+        CAAdapterFreeRemoteEndpoint(remoteEndpoint);
+        return CA_STATUS_FAILED;
+    }
 
+    *sentLength = dataLength;
+
+    OICFree(data);
+    data = NULL;
+
+    //Signal message handler for processing data for sending
+    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "Signalling message send handler");
+    u_mutex_lock(gBleServerReceiveDataMutex);
+    u_cond_signal(gReceiverDataCond);
+    u_mutex_unlock(gBleServerReceiveDataMutex);
+
+    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+    return CA_STATUS_OK;
+}
 void *CABleServerSenderQueueProcessor()
 {
     OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN ");
 
     while (gServerUp)
     {
-        CAAdapterMessage_t *senderData = NULL;
+        CAAdapterMessage_t *message = NULL;
+        const char *remoteAddress = NULL;
+        const char *serviceUUID = NULL;
+        uint32_t sentLength = 0;
+        int32_t headerAdded = 0;
 
         OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, " conditional wait");
 
@@ -170,23 +248,62 @@ void *CABleServerSenderQueueProcessor()
 
         CAResult_t result = CA_STATUS_FAILED;
 
-        while (CA_STATUS_OK == CAAdapterDequeueMessage(gCABleServerSenderQueue, &senderData))
+        while (CA_STATUS_OK == CAAdapterDequeueMessage(gCABleServerSenderQueue, &message))
         {
-            if (senderData == NULL)
+            if (message == NULL)
             {
                 OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "senderData is NULL");
                 continue;
             }
-            result = CAUpdateCharacteristicsInGattServer(senderData->data, senderData->dataLen);
-            if (CA_STATUS_OK != result)
-            {
-                OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Failed to CAUpdateCharacteristicsInGattServer");
-            }
-            else
+            char *dataSegment = NULL;
+            uint32_t offset = 0, ret = 1;
+            int32_t datalen = message->dataLen;
+            while ( 1)
             {
-                OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Failed to CAUpdateCharacteristicsInGattServer !");
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "fragmenting the data DataLen [%d] Offset [%d]", datalen,
+                          offset);
+                ret = CAFragmentData(message->data, &dataSegment, datalen, offset);
+                sleep(1);
+                if (0 == ret)
+                {
+                    break;
+                }
+
+                OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "Sending Multicast data");
+                result = CAUpdateCharacteristicsInGattServer(dataSegment, ret);
+                if (CA_STATUS_OK != result)
+                {
+                    OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG,
+                              "Failed to CAUpdateCharacteristicsInGattServer !");
+                }
+
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "freeing dataSegment");
+
+                OICFree(dataSegment);
+                dataSegment = NULL;
+                offset += ret;
+                if (headerAdded == 0)
+                {
+                    datalen -= offset - CA_HEADER_LENGTH;
+                    offset = offset - CA_HEADER_LENGTH;
+                    headerAdded = 1;
+                }
+                else
+                {
+                    datalen -= ret;
+                }
+
+                if (datalen < 0)
+                {
+                    datalen += ret ;
+                }
+                if (datalen == message->dataLen)
+                {
+                    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "All data has been fragmented and sent");
+                    break;
+                }
             }
-            CAAdapterFreeMessage(senderData);
+            CAAdapterFreeMessage(message);
         }
 
         u_mutex_unlock(gBleServerSendDataMutex);
@@ -196,6 +313,97 @@ void *CABleServerSenderQueueProcessor()
     return NULL;
 }
 
+void CABLEDataReceiverHandler(void *context)
+{
+    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "IN");
+
+    CAAdapterMessage_t *message = NULL;
+    const char *remoteAddress = NULL;
+    const char *serviceUUID = NULL;
+    uint32_t recvDataLen = 0;
+    uint32_t totalDataLen = 0;
+    char *dataSegment = NULL;
+    char *defragData = NULL;
+    isHeaderAvailable = false;
+    CARemoteEndpoint_t *remoteEndpoint = NULL;
+
+    u_mutex_lock(gBleServerReceiveDataMutex);
+
+    while (gDataReceiverHandlerState)
+    {
+
+        OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, " waiting for the data");
+
+        u_cond_wait(gReceiverDataCond, gBleServerReceiveDataMutex);
+
+        OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "wait unlocked");
+
+        //Extract the message from queue and send to remote ble device
+        while (CA_STATUS_OK == CAAdapterDequeueMessage(gCABleServerReceiverQueue, &message))
+        {
+            OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "checking for DE Fragmentation");
+
+            if (!isHeaderAvailable)
+            {
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "Parsing the header");
+                char *header = (char *) OICMalloc(sizeof(char) * CA_HEADER_LENGTH);
+                memcpy(header, message->data, CA_HEADER_LENGTH);
+                totalDataLen = CAParseHeader(header);
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "Total data to be accumulated [%d] bytes", totalDataLen);
+                defragData = (char *) OICMalloc(sizeof(char) * totalDataLen);
+                OICFree(header);
+
+                remoteAddress = message->remoteEndpoint->addressInfo.BT.btMacAddress;
+                serviceUUID = message->remoteEndpoint->resourceUri;
+
+                remoteEndpoint = CAAdapterCreateRemoteEndpoint(CA_EDR, remoteAddress,
+                                 serviceUUID);
+
+                memcpy(defragData + recvDataLen, message->data + CA_HEADER_LENGTH,
+                       message->dataLen - CA_HEADER_LENGTH);
+                recvDataLen += message->dataLen - CA_HEADER_LENGTH;
+                isHeaderAvailable = true;
+            }
+            else
+            {
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "Copying the data of length [%d]", message->dataLen);
+                memcpy(defragData + recvDataLen, message->data, message->dataLen);
+                recvDataLen += message->dataLen ;
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "totalDatalength  [%d] recveived Datalen [%d]",
+                          totalDataLen, recvDataLen);
+            }
+            CAAdapterFreeMessage(message);
+            if (totalDataLen == recvDataLen)
+            {
+                u_mutex_lock(gBleReqRespCbMutex);
+                if (NULL == gNetworkPacketReceivedServerCallback)
+                {
+                    OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "gReqRespCallback is NULL!");
+                    u_mutex_unlock(gBleReqRespCbMutex);
+                    return;
+                }
+                OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "Sending data up !");
+                gNetworkPacketReceivedServerCallback(remoteEndpoint, defragData, recvDataLen);
+                OICFree(remoteEndpoint);
+                OICFree(defragData);
+                recvDataLen = 0;
+                totalDataLen = 0;
+                isHeaderAvailable = false;
+                u_mutex_unlock(gBleReqRespCbMutex);
+            }
+
+        }
+
+        if (false == gDataReceiverHandlerState)
+        {
+            break;
+        }
+
+
+    }
+    u_mutex_unlock(gBleServerReceiveDataMutex);
+    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
+}
 
 CAResult_t CAStartBleGattServer()
 {
@@ -254,10 +462,15 @@ CAResult_t CAStartBleGattServer()
     {
         OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "u_thread_pool_add_task failed with ret [%d]", ret);
 
-        //CARemoveBLEServiceInfoToList(&gBLEServiceList, bleServiceInfo, bleServiceInfo->bdAddress);
         u_mutex_unlock(gBleServerThreadPoolMutex);
         return CA_STATUS_FAILED;
     }
+    gDataReceiverHandlerState = true;
+    if (CA_STATUS_OK != u_thread_pool_add_task(gBleServerThreadPool, CABLEDataReceiverHandler, NULL))
+    {
+        OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "Failed to start data send handler!");
+        return ;
+    }
     u_mutex_unlock(gBleServerThreadPoolMutex);
     OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
     return CA_STATUS_OK;
@@ -287,7 +500,7 @@ void *CAStartBleGattServerThread(void *data)
 
     sleep(5); // Sleep is must. otherwise its crashing
 
-    char *serviceUUID = "000018f3-0000-1000-8000-00805f9b34fb";
+    char *serviceUUID = "713d0000-503e-4c75-ba94-3148f18d941e";
 
     ret  = CAAddNewBleServiceInGattServer(serviceUUID);
 
@@ -350,7 +563,6 @@ void *CAStartBleGattServerThread(void *data)
     }
 
     int32_t retVal = bt_adapter_le_start_advertising(hAdvertiser, NULL, NULL, NULL);
-
     if (BT_ERROR_NONE != retVal)
     {
         OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "bt_adapter_le_start_advertising failed with ret [%d] ",
@@ -399,6 +611,15 @@ CAResult_t CAStopBleGattServer()
     }
     u_mutex_unlock(gBleServerStateMutex);
 
+    //Stop data send and receive handlers
+    if (gBleServerReceiveDataMutex && gReceiverDataCond && gDataReceiverHandlerState)
+    {
+        u_mutex_lock(gBleServerReceiveDataMutex);
+        gDataReceiverHandlerState = CA_FALSE;
+        u_cond_signal(gReceiverDataCond);
+        u_mutex_unlock(gBleServerReceiveDataMutex);
+    }
+
     CATerminateBleGattServer();
 
     OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
@@ -410,7 +631,9 @@ void CATerminateBleGattServer()
 {
     OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
 
-    int32_t ret = 0;
+    gIsBleGattServerStarted = CA_FALSE;
+    gServerUp = CA_FALSE;
+    u_cond_signal(gBleServerSendCondWait);
 
     u_mutex_lock(gBleServerStateMutex);
     // Required for waking up the thread which is running in gmain loop
@@ -429,6 +652,8 @@ void CATerminateBleGattServer()
     // Kill g main loops and kill threads
     g_main_loop_quit(g_event_loop);
 
+    int32_t ret = 0;
+
     if (NULL != hAdvertiser )
     {
         ret  = bt_adapter_le_stop_advertising(hAdvertiser);
@@ -471,8 +696,6 @@ void CATerminateBleGattServer()
     gGattWriteCharPath = NULL;
     u_mutex_unlock(gBleCharacteristicMutex);
 
-    gIsBleGattServerStarted = CA_FALSE;
-    gServerUp = CA_FALSE;
     u_mutex_unlock(gBleServerStateMutex);
 
     // Terminating gCABleServerSenderQueue
@@ -572,6 +795,16 @@ CAResult_t CAInitGattServerMutexVaraibles()
         }
     }
 
+    if (!gReceiverDataCond)
+    {
+        gReceiverDataCond = u_cond_new();
+        if (NULL == gReceiverDataCond)
+        {
+            OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "u_cond_new failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
     return CA_STATUS_OK;
 }
 void CATerminateGattServerMutexVaraibles()
@@ -593,9 +826,15 @@ void CATerminateGattServerMutexVaraibles()
     u_mutex_free(gBleReqRespCbMutex);
     gBleReqRespCbMutex = NULL;
 
-    u_mutex_free(gBleServerSendCondWait);
+    u_cond_free(gBleServerSendCondWait);
     gBleServerSendCondWait = NULL;
 
+    if (gReceiverDataCond)
+    {
+        u_cond_free(gReceiverDataCond);
+        gReceiverDataCond = NULL;
+    }
+
     OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
 }
 CAResult_t CAInitBleGattService()
@@ -733,32 +972,12 @@ void CABleGattRemoteCharacteristicWriteCb(char *charPath,
 
     OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "charPath = [%s] charValue = [%s] len [%d]", charPath,
               charValue, charValueLen);
-    CARemoteEndpoint_t  *remoteEndPoint = (CARemoteEndpoint_t *) OICMalloc(sizeof(CARemoteEndpoint_t));
-    if (NULL == remoteEndPoint)
-    {
-        OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Malloc Failure!");
-        return;
-    }
-    memset(remoteEndPoint, 0x0, sizeof(CARemoteEndpoint_t));
-    ///TODO: Currently Empty endpoint is being sent.
-    ///TODO:Later proper remote address has to be added when tizen team changed their code
-#if 0
-    VERIFY_NON_NULL(gCABleServerReceiverQueue, TZ_BLE_SERVER_TAG, "BleServerReceiverQueue is  NULL");
-
-    CAResult_t retVal = CAAdapterEnqueueMessage(gCABleServerReceiverQueue, remoteEndPoint, charValue,
-                        charValueLen);
-    if (CA_STATUS_OK != retVal )
-    {
-        OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "CAAdapterEnqueueMessage failed!");
-        return;
-    }
-#endif
 
     char *data = (char *)OICMalloc(sizeof(char) * charValueLen + 1);
     if (NULL == data)
     {
         OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Malloc failed!");
-        OICFree(remoteEndPoint);
+        //    OICFree(remoteEndPoint);
         return;
     }
 
@@ -766,19 +985,17 @@ void CABleGattRemoteCharacteristicWriteCb(char *charPath,
 
     strncpy(data, charValue, charValueLen);
 
-    u_mutex_lock(gBleReqRespCbMutex);
-    if (NULL == gNetworkPacketReceivedServerCallback)
+    uint32_t sentLength = 0;
+
+    CAResult_t res = CABLEPushDataToServerReceiverQueue(gRemoteClientAddress, OIC_BLE_SERVICE_ID,
+                     data, strlen(data), &sentLength);
+    if (CA_STATUS_OK != res)
     {
-        OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "gNetworkPacketReceivedServerCallback is NULL!");
-        OICFree(charValue);
-        OICFree(remoteEndPoint);
+        OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "CABLEPushDataToReceiverQueue failed");
         OICFree(data);
-        u_mutex_unlock(gBleReqRespCbMutex);
-        return;
+        return ;
     }
 
-    gNetworkPacketReceivedServerCallback(remoteEndPoint, data, charValueLen);
-    u_mutex_unlock(gBleReqRespCbMutex);
     OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT");
 }
 
@@ -919,17 +1136,20 @@ CAResult_t CAUpdateCharacteristicsInGattServer(const char *charValue, int32_t ch
 
     strncpy(data, charValue, charValueLen);
 
-    int32_t ret =  bt_gatt_update_characteristic(gGattWriteCharPath, data, charValueLen);
-
-    OICFree(data);
-    data = NULL;
+    OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%s] dataLen [%d]",
+              (const char *)gGattWriteCharPath, data, charValueLen);
 
+    int32_t ret =  bt_gatt_update_characteristic(gGattWriteCharPath, data, charValueLen);
     if (0 != ret)
     {
         OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, "bt_gatt_update_characteristic failed with return [%d]", ret);
+        OICFree(data);
+        data = NULL;
         u_mutex_unlock(gBleCharacteristicMutex);
         return CA_STATUS_FAILED;
     }
+    OICFree(data);
+    data = NULL;
 
     u_mutex_unlock(gBleCharacteristicMutex);