#include "umutex.h"
#include "camessagequeue.h"
#include "caadapterutils.h"
+#include "camsgparser.h"
+#include "cableclientutil.h"
/**
* @def TZ_BLE_SERVER_TAG
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.
*/
*/
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");
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);
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()
{
{
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;
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);
}
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] ",
}
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");
{
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
// 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);
gGattWriteCharPath = NULL;
u_mutex_unlock(gBleCharacteristicMutex);
- gIsBleGattServerStarted = CA_FALSE;
- gServerUp = CA_FALSE;
u_mutex_unlock(gBleServerStateMutex);
// Terminating gCABleServerSenderQueue
}
}
+ 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()
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()
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;
}
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");
}
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);