X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fcaretransmission.c;h=611ee5d4e75879f796800eaa1ef35c95aeae9095;hb=refs%2Ftags%2Fsubmit%2Ftizen_4.0%2F20171010.021147;hp=ca302ee7c4454de3b43f071b040e1da815b141c0;hpb=ece439f7727bd7de66f850726f8ce9d4856d39c2;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/caretransmission.c b/resource/csdk/connectivity/src/caretransmission.c index ca302ee..611ee5d 100644 --- a/resource/csdk/connectivity/src/caretransmission.c +++ b/resource/csdk/connectivity/src/caretransmission.c @@ -18,13 +18,57 @@ * ******************************************************************/ +// 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 +#endif + +#include "iotivity_config.h" #include #include #include +#ifdef TB_LOG +#include +#endif + +#ifndef SINGLE_THREAD +#ifdef HAVE_UNISTD_H #include -#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIMEB_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#endif -#ifdef __ANDROID__ +#if defined(__ANDROID__) #include #endif @@ -32,77 +76,119 @@ #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); @@ -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,268 +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); - // 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; } @@ -404,115 +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)) + { + 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); + 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; -}