*
******************************************************************/
+// Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
+// definitions that may otherwise be skipped. Skipping can cause implicit
+// declaration warnings and/or bugs and subtle problems in code execution.
+// For glibc information on feature test macros,
+// Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+//
+// This file requires #define use due to random()
+// For details on compatibility and glibc support,
+// Refer http://www.gnu.org/software/libc/manual/html_node/BSD-Random.html
+#define _DEFAULT_SOURCE
+
+// Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1b, Real-time extensions
+// (IEEE Std 1003.1b-1993) specification
+//
+// For this specific file, see use of clock_gettime,
+// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
+// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#ifdef __TIZENRT__
+#include <tinyara/config.h>
+#endif
+
+#include "iotivity_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef TB_LOG
+#include <inttypes.h>
+#endif
+
+#ifndef SINGLE_THREAD
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#include <glib.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_TIMEB_H
+#include <sys/timeb.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#endif
-#ifdef __ANDROID__
+#if defined(__ANDROID__)
#include <linux/time.h>
#endif
#include "caremotehandler.h"
#include "caprotocolmessage.h"
#include "oic_malloc.h"
+#include "oic_time.h"
+#include "ocrandom.h"
#include "logger.h"
-#define TAG PCF("RET")
+#define TAG "OIC_CA_RETRANS"
typedef struct
{
- /** last sent time. microseconds **/
- uint64_t timeStamp;
- /** timeout value. milliseconds **/
- uint32_t timeout;
- /** retransmission count **/
- uint8_t triedCount;
- /** coap PDU message id **/
- uint16_t messageId;
- /** remote endpoint **/
- CARemoteEndpoint_t *endpoint;
- /** coap PDU **/
- void *pdu;
- /** coap PDU size**/
- uint32_t size;
+ uint64_t timeStamp; /**< last sent time. microseconds */
+#ifndef SINGLE_THREAD
+ uint64_t timeout; /**< timeout value. microseconds */
+#endif
+ uint8_t triedCount; /**< retransmission count */
+ uint16_t messageId; /**< coap PDU message id */
+ CADataType_t dataType; /**< data Type (Request/Response) */
+ CAEndpoint_t *endpoint; /**< remote endpoint */
+ void *pdu; /**< coap PDU */
+ uint32_t size; /**< coap PDU size */
} CARetransmissionData_t;
-/**
- * getCurrent monotonic time
- *
- * microseconds
- */
-uint64_t getCurrentTimeInMicroSeconds();
+static const uint64_t USECS_PER_SEC = 1000000;
+static const uint64_t MSECS_PER_SEC = 1000;
+#ifndef SINGLE_THREAD
/**
- * @brief check timeout routine
- * @param currentTime [IN]microseconds
- * @param timeStamp [IN]microseconds
- * @param timeoutValue [IN]milliseconds
- * @param triedCount [IN]
- * @return CA_TRUE(timeout) or CA_FALSE
- *
- * microseconds
+ * @brief timeout value is
+ * between DEFAULT_ACK_TIMEOUT_SEC and
+ * (DEFAULT_ACK_TIMEOUT_SEC * DEFAULT_RANDOM_FACTOR) second.
+ * DEFAULT_RANDOM_FACTOR 1.5 (CoAP)
+ * @return microseconds.
*/
-static CABool_t CACheckTimeout(uint64_t currentTime, uint64_t timeStamp, uint32_t timeoutValue,
- uint8_t triedCount)
+static uint64_t CAGetTimeoutValue()
{
- // #1. calculate timeout
- uint64_t timeout = (timeoutValue << triedCount) * (uint64_t) 1000;
+ return ((DEFAULT_ACK_TIMEOUT_SEC * MSECS_PER_SEC)
+ + ((MSECS_PER_SEC * OCGetRandomByte()) >> 8)) * MSECS_PER_SEC;
+}
- if (currentTime >= timeStamp + timeout)
+CAResult_t CARetransmissionStart(CARetransmission_t *context)
+{
+ if (NULL == context)
{
- OIC_LOG_V(DEBUG, TAG, "%d milliseconds time out!!, tried count(%d)",
- (timeoutValue << triedCount), triedCount);
- return CA_TRUE;
+ OIC_LOG(ERROR, TAG, "context is empty");
+ return CA_STATUS_INVALID_PARAM;
}
- return CA_FALSE;
+ if (NULL == context->threadPool)
+ {
+ OIC_LOG(ERROR, TAG, "thread pool handle is empty..");
+ return CA_STATUS_INVALID_PARAM;
+ }
+#ifndef __TIZENRT__
+ CAResult_t res = ca_thread_pool_add_task(context->threadPool, CARetransmissionBaseRoutine,
+ context, NULL);
+#else
+ CAResult_t res = ca_thread_pool_add_task(context->threadPool, CARetransmissionBaseRoutine,
+ context, NULL, "IoT_Retransmit",
+ CONFIG_IOTIVITY_RETRANSMIT_PTHREAD_STACKSIZE);
+#endif
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "thread pool add task error(send thread).");
+ return res;
+ }
+
+ return res;
}
+#endif
/**
- * @brief timeout value is
- * between DEFAULT_ACK_TIMEOUT and (DEFAULT_ACK_TIMEOUT * DEFAULT_RANDOM_FACTOR) second.
- * DEFAULT_RANDOM_FACTOR 1.5 (CoAP)
- * @return milliseconds.
+ * @brief check timeout routine
+ * @param currentTime [IN]microseconds
+ * @param retData [IN]retransmission data
+ * @return true if the timeout period has elapsed, false otherwise
*/
-static uint32_t CAGetTimeoutValue()
+static bool CACheckTimeout(uint64_t currentTime, CARetransmissionData_t *retData)
{
- return (DEFAULT_ACK_TIMEOUT * 1000) + ((1000 * (rand() & 0xFF)) >> 8);
+#ifndef SINGLE_THREAD
+ // #1. calculate timeout
+ uint32_t milliTimeoutValue = retData->timeout * 0.001;
+ uint64_t timeout = ((uint64_t) milliTimeoutValue << retData->triedCount) * MSECS_PER_SEC;
+
+ if (currentTime >= retData->timeStamp + timeout)
+ {
+#ifndef __TIZENRT__
+ OIC_LOG_V(DEBUG, TAG, "%" PRIu64 " microseconds time out!!, tried count(%d)",
+ timeout, retData->triedCount);
+#endif
+ return true;
+ }
+#else
+ // #1. calculate timeout
+ uint64_t timeOut = (2 << retData->triedCount) * USECS_PER_SEC;
+
+ if (currentTime >= retData->timeStamp + timeOut)
+ {
+ OIC_LOG_V(DEBUG, TAG, "timeout=%d, tried cnt=%d",
+ (2 << retData->triedCount), retData->triedCount);
+ return true;
+ }
+#endif
+ return false;
}
static void CACheckRetransmissionList(CARetransmission_t *context)
{
+ if (NULL == context)
+ {
+ OIC_LOG(ERROR, TAG, "context is null");
+ return;
+ }
+
// mutex lock
- u_mutex_lock(context->threadMutex);
- uint64_t currentTime = 0;
+ oc_mutex_lock(context->threadMutex);
uint32_t i = 0;
uint32_t len = u_arraylist_length(context->dataList);
{
CARetransmissionData_t *retData = u_arraylist_get(context->dataList, i);
- if (retData == NULL)
+ if (NULL == retData)
+ {
continue;
+ }
- currentTime = getCurrentTimeInMicroSeconds();
+ uint64_t currentTime = OICGetCurrentTime(TIME_IN_US);
- if (CACheckTimeout(currentTime, retData->timeStamp, retData->timeout, retData->triedCount))
+ if (CACheckTimeout(currentTime, retData))
{
// #2. if time's up, send the data.
- if (context->dataSendMethod != NULL)
+ if (NULL != context->dataSendMethod)
{
- OIC_LOG_V(DEBUG, TAG, "retransmission CON data!!, message id(%d)",
+ OIC_LOG_V(DEBUG, TAG, "retransmission CON data!!, msgid=%d",
retData->messageId);
- context->dataSendMethod(retData->endpoint, retData->pdu, retData->size);
+ context->dataSendMethod(retData->endpoint, retData->pdu,
+ retData->size, retData->dataType);
}
// #3. increase the retransmission count and update timestamp.
if (retData->triedCount >= context->config.tryingCount)
{
CARetransmissionData_t *removedData = u_arraylist_remove(context->dataList, i);
-
- if (removedData != NULL)
+ if (NULL == removedData)
{
- OIC_LOG_V(DEBUG, TAG, "max trying count, remove retransmission CON data!!,\
- message id(%d)", removedData->messageId);
-
- // callback for retransmit timeout
- if (context->timeoutCallback != NULL)
- {
- context->timeoutCallback(removedData->endpoint, removedData->pdu,
- removedData->size);
- }
-
- CADestroyRemoteEndpointInternal(removedData->endpoint);
- OICFree(removedData->pdu);
-
- OICFree(removedData);
-
- // modify loop value.
- len = u_arraylist_length(context->dataList);
- --i;
+ OIC_LOG(ERROR, TAG, "Removed data is NULL");
+ // mutex unlock
+ oc_mutex_unlock(context->threadMutex);
+ return;
}
- else
+ OIC_LOG_V(DEBUG, TAG, "max trying count, remove RTCON data,"
+ "msgid=%d", removedData->messageId);
+
+ // callback for retransmit timeout
+ if (NULL != context->timeoutCallback)
{
- OIC_LOG_V(DEBUG, TAG, "arraylist remove error");
+ context->timeoutCallback(removedData->endpoint, removedData->pdu,
+ removedData->size);
}
+ CAFreeEndpoint(removedData->endpoint);
+ OICFree(removedData->pdu);
+
+ OICFree(removedData);
+
+ // modify loop value.
+ len = u_arraylist_length(context->dataList);
+ --i;
}
}
// mutex unlock
- u_mutex_unlock(context->threadMutex);
+ oc_mutex_unlock(context->threadMutex);
}
-static void CARetransmissionBaseRoutine(void *threadValue)
+void CARetransmissionBaseRoutine(void *threadValue)
{
- OIC_LOG_V(DEBUG, TAG, "retransmission main thread start..");
+ OIC_LOG(DEBUG, TAG, "retransmission main thread start");
CARetransmission_t *context = (CARetransmission_t *) threadValue;
- if (context == NULL)
+ if (NULL == context)
{
- OIC_LOG_V(DEBUG, TAG, "thread data passing error!!");
+ OIC_LOG(ERROR, TAG, "thread data passing error");
+
+ return;
+ }
+#ifdef SINGLE_THREAD
+ if (true == context->isStop)
+ {
+ OIC_LOG(DEBUG, TAG, "thread stopped");
return;
}
+ CACheckRetransmissionList(context);
+#else
while (!context->isStop)
{
// mutex lock
- u_mutex_lock(context->threadMutex);
+ oc_mutex_lock(context->threadMutex);
- if (u_arraylist_length(context->dataList) <= 0)
+ if (!context->isStop && u_arraylist_length(context->dataList) <= 0)
{
// if list is empty, thread will wait
- OIC_LOG_V(DEBUG, TAG, "wait..there is no retransmission data.");
+ OIC_LOG(DEBUG, TAG, "wait..there is no retransmission data.");
// wait
- u_cond_wait(context->threadCond, context->threadMutex);
+ oc_cond_wait(context->threadCond, context->threadMutex);
- OIC_LOG_V(DEBUG, TAG, "wake up..");
+ OIC_LOG(DEBUG, TAG, "wake up..");
}
- else
+ else if (!context->isStop)
{
- // check each RETRANSMISSION_CHECK_PERIOD time.
- OIC_LOG_V(DEBUG, TAG, "wait..(%d)microseconds", RETRANSMISSION_CHECK_PERIOD);
+ // check each RETRANSMISSION_CHECK_PERIOD_SEC time.
+#ifndef __TIZENRT__
+ OIC_LOG_V(DEBUG, TAG, "wait..(%" PRIu64 ")microseconds",
+ RETRANSMISSION_CHECK_PERIOD_SEC * (uint64_t) USECS_PER_SEC);
+#endif
// wait
- u_cond_timed_wait(context->threadCond, context->threadMutex,
- RETRANSMISSION_CHECK_PERIOD);
+ uint64_t absTime = RETRANSMISSION_CHECK_PERIOD_SEC * (uint64_t) USECS_PER_SEC;
+ oc_cond_wait_for(context->threadCond, context->threadMutex, absTime );
+ }
+ else
+ {
+ // we are stopping, so we want to unlock and finish stopping
}
// mutex unlock
- u_mutex_unlock(context->threadMutex);
+ oc_mutex_unlock(context->threadMutex);
// check stop flag
if (context->isStop)
+ {
continue;
+ }
CACheckRetransmissionList(context);
}
- u_cond_signal(context->threadCond);
+ oc_mutex_lock(context->threadMutex);
+ oc_cond_signal(context->threadCond);
+ oc_mutex_unlock(context->threadMutex);
- OIC_LOG_V(DEBUG, TAG, "retransmission main thread end..");
+#endif
+ OIC_LOG(DEBUG, TAG, "retransmission main thread end");
}
-CAResult_t CARetransmissionInitialize(CARetransmission_t *context, u_thread_pool_t handle,
- CADataSendMethod_t retransmissionSendMethod, CATimeoutCallback_t timeoutCallback,
- CARetransmissionConfig_t* config)
+CAResult_t CARetransmissionInitialize(CARetransmission_t *context,
+ ca_thread_pool_t handle,
+ CADataSendMethod_t retransmissionSendMethod,
+ CATimeoutCallback_t timeoutCallback,
+ CARetransmissionConfig_t* config)
{
- if (context == NULL)
+ if (NULL == context)
{
- OIC_LOG_V(DEBUG, TAG, "thread instance is empty..");
- return CA_STATUS_FAILED;
+ OIC_LOG(ERROR, TAG, "thread instance is empty");
+ return CA_STATUS_INVALID_PARAM;
}
-
- if (handle == NULL)
+#ifndef SINGLE_THREAD
+ if (NULL == handle)
{
- OIC_LOG_V(DEBUG, TAG, "thread pool handle is empty..");
- return CA_STATUS_FAILED;
+ OIC_LOG(ERROR, TAG, "thread pool handle is empty");
+ return CA_STATUS_INVALID_PARAM;
}
-
- OIC_LOG_V(DEBUG, TAG, "thread initialize..");
+#endif
+ OIC_LOG(DEBUG, TAG, "thread initialize");
memset(context, 0, sizeof(CARetransmission_t));
- CARetransmissionConfig_t cfg;
- memset(&cfg, 0, sizeof(CARetransmissionConfig_t));
+ CARetransmissionConfig_t cfg = { .supportType = DEFAULT_RETRANSMISSION_TYPE,
+ .tryingCount = DEFAULT_RETRANSMISSION_COUNT };
- if (config == NULL)
- {
- // setDefault
- cfg.supportType = DEFAULT_RETRANSMISSION_TYPE;
- cfg.tryingCount = DEFAULT_MAX_RETRANSMIT;
- }
- else
+ if (config)
{
cfg = *config;
}
- // mutex init
- u_mutex_init();
-
// set send thread data
context->threadPool = handle;
- context->threadMutex = u_mutex_new();
- context->threadCond = u_cond_new();
+ context->threadMutex = oc_mutex_new();
+ context->threadCond = oc_cond_new();
context->dataSendMethod = retransmissionSendMethod;
context->timeoutCallback = timeoutCallback;
context->config = cfg;
- context->isStop = CA_FALSE;
+ context->isStop = false;
context->dataList = u_arraylist_create();
return CA_STATUS_OK;
}
-CAResult_t CARetransmissionStart(CARetransmission_t *context)
-{
- if (context == NULL)
- {
- OIC_LOG_V(DEBUG, TAG, "context is empty..");
- return CA_STATUS_FAILED;
- }
-
- if (context->threadPool == NULL)
- {
- OIC_LOG_V(DEBUG, TAG, "thread pool handle is empty..");
- return CA_STATUS_FAILED;
- }
-
- CAResult_t res = u_thread_pool_add_task(context->threadPool, CARetransmissionBaseRoutine,
- context);
-
- if (res != CA_STATUS_OK)
- {
- OIC_LOG_V(DEBUG, TAG, "thread pool add task error(send thread).");
- return res;
- }
-
- return res;
-}
-
CAResult_t CARetransmissionSentData(CARetransmission_t *context,
- const CARemoteEndpoint_t* endpoint,const void* pdu, uint32_t size)
+ const CAEndpoint_t *endpoint,
+ CADataType_t dataType,
+ const void *pdu, uint32_t size)
{
- if (context == NULL || endpoint == NULL || pdu == NULL)
+ if (NULL == context || NULL == endpoint || NULL == pdu)
{
- OIC_LOG_V(DEBUG, TAG, "invalid parameter..");
+ OIC_LOG(ERROR, TAG, "invalid parameter");
return CA_STATUS_INVALID_PARAM;
}
- // #0. check support connectivity type
- if (!(context->config.supportType & endpoint->connectivityType))
+ // #0. check support transport type
+ if (!(context->config.supportType & endpoint->adapter))
{
- OIC_LOG_V(DEBUG, TAG, "not supported connectivity type for retransmission..(%d)",
- endpoint->connectivityType);
- return CA_STATUS_OK;
+ OIC_LOG_V(DEBUG, TAG, "not supported transport type=%d", endpoint->adapter);
+ return CA_NOT_SUPPORTED;
}
// #1. check PDU method type and get message id.
CAMessageType_t type = CAGetMessageTypeFromPduBinaryData(pdu, size);
uint16_t messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
- OIC_LOG_V(DEBUG, TAG, "sent pdu, message type(%d), message id(%d)", type, messageId);
+ OIC_LOG_V(DEBUG, TAG, "sent pdu, msgtype=%d, msgid=%d", type, messageId);
- if (type != CA_MSG_CONFIRM)
+ if (CA_MSG_CONFIRM != type)
{
- return CA_STATUS_OK;
+ OIC_LOG(DEBUG, TAG, "not supported message type");
+ return CA_NOT_SUPPORTED;
}
// create retransmission data
- CARetransmissionData_t *retData = (CARetransmissionData_t *) OICMalloc(
- sizeof(CARetransmissionData_t));
+ CARetransmissionData_t *retData = (CARetransmissionData_t *) OICCalloc(
+ 1, sizeof(CARetransmissionData_t));
- if (retData == NULL)
+ if (NULL == retData)
{
- OIC_LOG_V(DEBUG, TAG, "memory error!!");
+ OIC_LOG(ERROR, TAG, "memory error");
return CA_MEMORY_ALLOC_FAILED;
}
- memset(retData, 0, sizeof(CARetransmissionData_t));
// copy PDU data
- void *pduData = (void *) OICMalloc(sizeof(int8_t) * size);
- if (pduData == NULL)
+ void *pduData = (void *) OICMalloc(size);
+ if (NULL == pduData)
{
OICFree(retData);
- OIC_LOG_V(DEBUG, TAG, "memory error!!");
+ OIC_LOG(ERROR, TAG, "memory error");
return CA_MEMORY_ALLOC_FAILED;
}
- memset(pduData, 0, sizeof(int8_t) * size);
- memcpy(pduData, pdu, sizeof(int8_t) * size);
+ memcpy(pduData, pdu, size);
// clone remote endpoint
- CARemoteEndpoint_t *remoteEndpoint = CACloneRemoteEndpoint(endpoint);
- if (remoteEndpoint == NULL)
+ CAEndpoint_t *remoteEndpoint = CACloneEndpoint(endpoint);
+ if (NULL == remoteEndpoint)
{
OICFree(retData);
OICFree(pduData);
- OIC_LOG_V(DEBUG, TAG, "memory error!!");
+ OIC_LOG(ERROR, TAG, "memory error");
return CA_MEMORY_ALLOC_FAILED;
}
// #2. add additional information. (time stamp, retransmission count...)
- retData->timeStamp = getCurrentTimeInMicroSeconds();
+ retData->timeStamp = OICGetCurrentTime(TIME_IN_US);
+#ifndef SINGLE_THREAD
retData->timeout = CAGetTimeoutValue();
+#endif
retData->triedCount = 0;
retData->messageId = messageId;
retData->endpoint = remoteEndpoint;
retData->pdu = pduData;
retData->size = size;
-
+ retData->dataType = dataType;
+#ifndef SINGLE_THREAD
// mutex lock
- u_mutex_lock(context->threadMutex);
+ oc_mutex_lock(context->threadMutex);
+
+ uint32_t i = 0;
+ uint32_t len = u_arraylist_length(context->dataList);
// #3. add data into list
- u_arraylist_add(context->dataList, (void *) retData);
+ for (i = 0; i < len; i++)
+ {
+ CARetransmissionData_t *currData = u_arraylist_get(context->dataList, i);
- // notity the thread
- u_cond_signal(context->threadCond);
+ if (NULL == currData)
+ {
+ continue;
+ }
+
+ // found index
+ if (NULL != currData->endpoint && currData->messageId == messageId
+ && (currData->endpoint->adapter == endpoint->adapter))
+ {
+ OIC_LOG(ERROR, TAG, "Duplicate message ID");
+
+ // mutex unlock
+ oc_mutex_unlock(context->threadMutex);
+
+ OICFree(retData);
+ OICFree(pduData);
+ OICFree(remoteEndpoint);
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ bool res = u_arraylist_add(context->dataList, (void *) retData);
+ if (!res)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+
+ oc_mutex_unlock(context->threadMutex);
+
+ OICFree(retData);
+ OICFree(pduData);
+ OICFree(remoteEndpoint);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ // notify the thread
+ oc_cond_signal(context->threadCond);
// mutex unlock
- u_mutex_unlock(context->threadMutex);
+ oc_mutex_unlock(context->threadMutex);
+#else
+ bool res = u_arraylist_add(context->dataList, (void *) retData);
+ if (!res)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+
+ oc_mutex_unlock(context->threadMutex);
+
+ OICFree(retData);
+ OICFree(pduData);
+ OICFree(remoteEndpoint);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ CACheckRetransmissionList(context);
+#endif
return CA_STATUS_OK;
}
CAResult_t CARetransmissionReceivedData(CARetransmission_t *context,
- const CARemoteEndpoint_t *endpoint, const void *pdu, uint32_t size)
+ const CAEndpoint_t *endpoint, const void *pdu,
+ uint32_t size, void **retransmissionPdu)
{
- if (context == NULL || endpoint == NULL || pdu == NULL)
+ OIC_LOG(DEBUG, TAG, "IN");
+ if (NULL == context || NULL == endpoint || NULL == pdu || NULL == retransmissionPdu)
{
- OIC_LOG_V(DEBUG, TAG, "invalid parameter..");
+ OIC_LOG(ERROR, TAG, "invalid parameter");
return CA_STATUS_INVALID_PARAM;
}
- // #0. check support connectivity type
- if (!(context->config.supportType & endpoint->connectivityType))
+ // #0. check support transport type
+ if (!(context->config.supportType & endpoint->adapter))
{
- OIC_LOG_V(DEBUG, TAG, "not supported connectivity type for retransmission..(%d)",
- endpoint->connectivityType);
+ OIC_LOG_V(DEBUG, TAG, "not supported transport type=%d", endpoint->adapter);
return CA_STATUS_OK;
}
// ACK, RST --> remove the CON data
CAMessageType_t type = CAGetMessageTypeFromPduBinaryData(pdu, size);
uint16_t messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
+ CAResponseResult_t code = CAGetCodeFromPduBinaryData(pdu, size);
- OIC_LOG_V(DEBUG, TAG, "received pdu, message type(%d), message id(%d)", type, messageId);
+ OIC_LOG_V(DEBUG, TAG, "received pdu, msgtype=%d, msgid=%d, code=%d",
+ type, messageId, code);
- if (type != CA_MSG_ACKNOWLEDGE && type != CA_MSG_RESET)
+ if (((CA_MSG_ACKNOWLEDGE != type) && (CA_MSG_RESET != type))
+ || (CA_MSG_RESET == type && CA_EMPTY != code))
{
return CA_STATUS_OK;
}
// mutex lock
- u_mutex_lock(context->threadMutex);
-
- uint32_t i = 0;
+ oc_mutex_lock(context->threadMutex);
uint32_t len = u_arraylist_length(context->dataList);
// find index
+ uint32_t i;
for (i = 0; i < len; i++)
{
- CARetransmissionData_t *retData = u_arraylist_get(context->dataList, i);
+ CARetransmissionData_t *retData = (CARetransmissionData_t *) u_arraylist_get(
+ context->dataList, i);
- if (retData == NULL)
+ if (NULL == retData)
+ {
continue;
+ }
// found index
- if ((retData->endpoint->connectivityType == endpoint->connectivityType)
- && retData->messageId == messageId)
+ if (NULL != retData->endpoint && retData->messageId == messageId
+ && (retData->endpoint->adapter == endpoint->adapter))
+ {
+ // get pdu data for getting token when CA_EMPTY(RST/ACK) is received from remote device
+ // if retransmission was finish..token will be unavailable.
+ if (CA_EMPTY == CAGetCodeFromPduBinaryData(pdu, size))
+ {
+ OIC_LOG(DEBUG, TAG, "code is CA_EMPTY");
+
+ if (NULL == retData->pdu)
+ {
+ OIC_LOG(ERROR, TAG, "retData->pdu is null");
+ OICFree(retData);
+ // mutex unlock
+ oc_mutex_unlock(context->threadMutex);
+
+ return CA_STATUS_FAILED;
+ }
+
+ // copy PDU data
+ (*retransmissionPdu) = (void *) OICCalloc(1, retData->size);
+ if ((*retransmissionPdu) == NULL)
+ {
+ OICFree(retData);
+ OIC_LOG(ERROR, TAG, "memory error");
+
+ // mutex unlock
+ oc_mutex_unlock(context->threadMutex);
+
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ memcpy((*retransmissionPdu), retData->pdu, retData->size);
+ }
+
+ // #2. remove data from list
+ CARetransmissionData_t *removedData = u_arraylist_remove(context->dataList, i);
+ if (NULL == removedData)
+ {
+ OIC_LOG(ERROR, TAG, "Removed data is NULL");
+
+ // mutex unlock
+ oc_mutex_unlock(context->threadMutex);
+
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "remove RTCON data!!, msgid=%d", messageId);
+
+ CAFreeEndpoint(removedData->endpoint);
+ OICFree(removedData->pdu);
+ OICFree(removedData);
+
break;
+ }
+ }
+
+ // mutex unlock
+ oc_mutex_unlock(context->threadMutex);
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CARetransmissionClearAdapterData(CARetransmission_t *context, CATransportAdapter_t type)
+{
+ if (NULL == context)
+ {
+ OIC_LOG(ERROR, TAG, "thread instance is empty..");
+ return CA_STATUS_INVALID_PARAM;
}
- // #2. remove data from list
- if (i < len)
+ OIC_LOG_V(DEBUG, TAG, "clear queue data for Adapter : %d ", type);
+
+ // mutex lock
+ oc_mutex_lock(context->threadMutex);
+
+ uint32_t len = u_arraylist_length(context->dataList);
+
+ // find index
+ uint32_t i;
+ for (i = 0; i < len; i++)
{
- CARetransmissionData_t *removedData = u_arraylist_remove(context->dataList, i);
+ // get data
+ CARetransmissionData_t *removedData = (CARetransmissionData_t *) u_arraylist_get(
+ context->dataList, i);
- if (removedData != NULL)
+ // free
+ if (NULL != removedData && NULL != removedData->endpoint &&
+ removedData->endpoint->adapter == type)
{
- OIC_LOG_V(DEBUG, TAG, "remove retransmission CON data!!, message id(%d)", messageId);
-
- CADestroyRemoteEndpointInternal(removedData->endpoint);
+ CAFreeEndpoint(removedData->endpoint);
OICFree(removedData->pdu);
-
OICFree(removedData);
}
}
// mutex unlock
- u_mutex_unlock(context->threadMutex);
+ oc_mutex_unlock(context->threadMutex);
return CA_STATUS_OK;
}
CAResult_t CARetransmissionStop(CARetransmission_t *context)
{
- if (context == NULL)
+ if (NULL == context)
{
- OIC_LOG_V(DEBUG, TAG, "context is empty..");
- return CA_STATUS_FAILED;
+ OIC_LOG(ERROR, TAG, "context is empty..");
+ return CA_STATUS_INVALID_PARAM;
}
- OIC_LOG_V(DEBUG, TAG, "retransmission stop request!!");
+ OIC_LOG(DEBUG, TAG, "retransmission stop request!!");
// mutex lock
- u_mutex_lock(context->threadMutex);
+ oc_mutex_lock(context->threadMutex);
// set stop flag
- context->isStop = CA_TRUE;
+ context->isStop = true;
- // notity the thread
- u_cond_signal(context->threadCond);
+ // notify the thread
+ oc_cond_signal(context->threadCond);
- u_cond_wait(context->threadCond, context->threadMutex);
+ oc_cond_wait(context->threadCond, context->threadMutex);
// mutex unlock
- u_mutex_unlock(context->threadMutex);
+ oc_mutex_unlock(context->threadMutex);
return CA_STATUS_OK;
}
CAResult_t CARetransmissionDestroy(CARetransmission_t *context)
{
- if (context == NULL)
+ if (NULL == context)
{
- OIC_LOG_V(DEBUG, TAG, "context is empty..");
- return CA_STATUS_FAILED;
+ OIC_LOG(ERROR, TAG, "context is empty..");
+ return CA_STATUS_INVALID_PARAM;
}
- OIC_LOG_V(DEBUG, TAG, "retransmission context destroy..");
+ OIC_LOG(DEBUG, TAG, "retransmission context destroy..");
- u_mutex_free(context->threadMutex);
+ oc_mutex_free(context->threadMutex);
context->threadMutex = NULL;
- u_cond_free(context->threadCond);
- u_arraylist_free(context->dataList);
+ oc_cond_free(context->threadCond);
+ u_arraylist_free(&context->dataList);
return CA_STATUS_OK;
}
-
-uint64_t getCurrentTimeInMicroSeconds()
-{
- uint64_t currentTime = 0;
-
-#ifdef __ANDROID__
- struct timespec getTs;
-
- memset(&getTs, 0, sizeof(getTs));
- clock_gettime(CLOCK_MONOTONIC, &getTs);
-
- currentTime = (getTs.tv_sec * (uint64_t)1000000000 + getTs.tv_nsec)/1000;
- OIC_LOG_V(DEBUG, TAG, "current time = %d", currentTime);
-#else
- currentTime = g_get_monotonic_time();
-#endif
- return currentTime;
-}