replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / caretransmission.c
index e6a8dae..611ee5d 100644 (file)
  *
  ******************************************************************/
 
+// 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 "coap.h"
+
 #include "caretransmission.h"
 #include "caremotehandler.h"
 #include "caprotocolmessage.h"
 #include "oic_malloc.h"
+#include "oic_time.h"
+#include "ocrandom.h"
 #include "logger.h"
 
-#define TAG PCF("CA")
+#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;
+    }
+
+    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 CA_FALSE;
+    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);
@@ -111,19 +197,22 @@ static void CACheckRetransmissionList(CARetransmission_t *context)
     {
         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.
@@ -135,271 +224,313 @@ static void CACheckRetransmissionList(CARetransmission_t *context)
         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);
+
+        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;
+    }
 
-    // notity the thread
-    u_cond_signal(context->threadCond);
+    // 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,
-                                        void **retransmissionPdu)
+                                        const CAEndpoint_t *endpoint, const void *pdu,
+                                        uint32_t size, void **retransmissionPdu)
 {
-    OIC_LOG_V(DEBUG, TAG, "IN - CARetransmissionReceivedData");
-    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;
     }
 
@@ -407,141 +538,177 @@ CAResult_t CARetransmissionReceivedData(CARetransmission_t *context,
     // 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))
+            if (CA_EMPTY == CAGetCodeFromPduBinaryData(pdu, size))
             {
-                OIC_LOG_V(DEBUG, TAG, "code is CA_EMPTY..");
+                OIC_LOG(DEBUG, TAG, "code is CA_EMPTY");
 
-                if(NULL == retData->pdu)
+                if (NULL == retData->pdu)
                 {
-                    OIC_LOG_V(DEBUG, TAG, "retData->pdu is null");
+                    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 *) OICMalloc(sizeof(int8_t) * retData->size);
+                (*retransmissionPdu) = (void *) OICCalloc(1, retData->size);
                 if ((*retransmissionPdu) == NULL)
                 {
                     OICFree(retData);
-                    OIC_LOG_V(DEBUG, TAG, "memory error!!");
+                    OIC_LOG(ERROR, TAG, "memory error");
+
+                    // mutex unlock
+                    oc_mutex_unlock(context->threadMutex);
+
                     return CA_MEMORY_ALLOC_FAILED;
                 }
-                memset((*retransmissionPdu), 0, sizeof(int8_t) * retData->size);
-                memcpy((*retransmissionPdu), retData->pdu, sizeof(int8_t) * retData->size);
+                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;
         }
     }
 
-    // #2. remove data from list
-    if (i < len)
+    // 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;
+    }
+
+    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);
 
-    OIC_LOG_V(DEBUG, TAG, "OUT - CARetransmissionReceivedData");
     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);
+    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;
-}