#define DEFAULT_ACK_TIMEOUT_SEC 2
/** default max retransmission trying count is 4.(CoAP) **/
-#define DEFAULT_MAX_RETRANSMIT 4
+#define DEFAULT_RETRANSMISSION_COUNT 4
/** check period is 1 sec. **/
#define RETRANSMISSION_CHECK_PERIOD_SEC 1
* if NULL is coming, it will set default values.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
*/
-CAResult_t CARetransmissionInitialize(CARetransmission_t *context, ca_thread_pool_t handle,
+CAResult_t CARetransmissionInitialize(CARetransmission_t *context,
+ ca_thread_pool_t handle,
CADataSendMethod_t retransmissionSendMethod,
CATimeoutCallback_t timeoutCallback,
CARetransmissionConfig_t* config);
*/
CAResult_t CARetransmissionDestroy(CARetransmission_t *context);
+/**
+ * @brief Invoke Retransmission according to TimedAction Response
+ * @param threadValue [IN] context for retransmission
+ */
+void CARetransmissionBaseRoutine(void *threadValue);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-
-/**
- * @file caretransmission_singlethread.h
- * @brief This file contains common function for retransmission messages.
- */
-
-#ifndef CA_RETRANSMISSION_SINGLETHREAD_H_
-#define CA_RETRANSMISSION_SINGLETHREAD_H_
-
-#include <stdint.h>
-
-#include "uarraylist.h"
-#include "cacommon.h"
-
-/** CA_IPV4, CA_LE **/
-#define DEFAULT_RETRANSMISSION_TYPE (CA_ADAPTER_IP | CA_ADAPTER_GATT_BTLE)
-
-/** default retransmission trying count is 4. **/
-#define DEFAULT_RETRANSMISSION_COUNT 4
-
-/** check period is 1 sec. **/
-#define RETRANSMISSION_CHECK_PERIOD_SEC 1
-
-/** retransmission data send method type**/
-typedef CAResult_t (*CADataSendMethod_t)(const CAEndpoint_t *endpoint, const void *pdu,
- uint32_t size);
-
-/** retransmission timeout callback type**/
-typedef void (*CATimeoutCallback_t)(const CAEndpoint_t *endpoint, const void *pdu,
- uint32_t size);
-
-typedef struct
-{
- /** retransmission support transport type **/
- CATransportAdapter_t supportType;
-
- /** retransmission trying count **/
- uint8_t tryingCount;
-
-} CARetransmissionConfig_t;
-
-typedef struct
-{
- /** send method for retransmission data **/
- CADataSendMethod_t dataSendMethod;
-
- /** callback function for retransmit timeout **/
- CATimeoutCallback_t timeoutCallback;
-
- /** retransmission configure data **/
- CARetransmissionConfig_t config;
-
- /** Variable to inform the thread to stop **/
- bool isStop;
-
- /** array list on which the thread is operating. **/
- u_arraylist_t *dataList;
-
-} CARetransmission_t;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * @brief Initializes the retransmission context
- * @param context [IN] context for retransmission
- * @param retransmissionSendMethod [IN] function to be called for retransmission
- * @param timeoutCallback [IN] callback for retransmit timeout
- * @param config [IN] configuration for retransmission.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
- */
-CAResult_t CARetransmissionInitialize(CARetransmission_t *context,
- CADataSendMethod_t retransmissionSendMethod,
- CATimeoutCallback_t timeoutCallback,
- CARetransmissionConfig_t *config);
-
-/**
- * @brief Pass the sent pdu data. if retransmission process need, internal thread will wake up
- * and process the retransmission data.
- * @param context [IN] context for retransmission
- * @param endpoint [IN] endpoint information
- * @param pdu [IN] sent pdu binary data
- * @param size [IN] sent pdu binary data size
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
- */
-CAResult_t CARetransmissionSentData(CARetransmission_t *context,
- const CAEndpoint_t *endpoint,
- const void *pdu, uint32_t size);
-
-/**
- * @brief Paas the received pdu data. if received pdu is ACK data for the retransmission CON data,
- * the specified CON data will remove on retransmission list.
- * @param context [IN] context for retransmission
- * @param endpoint [IN] endpoint information
- * @param pdu [IN] received pdu binary data
- * @param size [IN] received pdu binary data size
- * @param retransmissionPdu [OUT] pdu data of the request for reset and ack
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
- */
-CAResult_t CARetransmissionReceivedData(CARetransmission_t *context,
- const CAEndpoint_t *endpoint, const void *pdu,
- uint32_t size, void **retransmissionPdu);
-
-/**
- * @brief Stopping the retransmission context
- * @param context [IN] context for retransmission
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
- */
-CAResult_t CARetransmissionStop(CARetransmission_t *context);
-
-/**
- * @brief Terminating the retransmission context
- * @param context [IN] context for retransmission
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
- */
-CAResult_t CARetransmissionDestroy(CARetransmission_t *context);
-
-/**
- * @brief Retransmitting the request/response for CONFIRMABLE type
- */
-void CACheckRetransmissionList();
-
-/**
- * @brief Invoke Retransmission according to TimedAction Response
- * @param threadValue [IN] context for retransmission
- */
-void CARetransmissionBaseRoutine(void *threadValue);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* CA_RETRANSMISSION_SINGLETHREAD_H_ */
-
env.AppendUnique(CPPDEFINES = ['SINGLE_THREAD'])
env.AppendUnique(CPPDEFINES = ['WITH_ARDUINO'])
print "setting WITH_ARDUINO"
- ca_common_src = [
- 'caconnectivitymanager_singlethread.c',
+ ca_common_src = [
+ 'caconnectivitymanager_singlethread.c',
'cainterfacecontroller_singlethread.c',
'camessagehandler_singlethread.c',
'canetworkconfigurator.c',
'caprotocolmessage.c',
- 'caretransmission_singlethread.c',
+ 'caretransmission.c',
]
else:
env.AppendUnique(CPPDEFINES = ['MULTI_THREAD'])
#include "caremotehandler.h"
#include "cainterfacecontroller_singlethread.h"
#include "caprotocolmessage.h"
-#include "caretransmission_singlethread.h"
+#include "caretransmission.h"
#include "logger.h"
#include "config.h" /* for coap protocol */
#include "oic_malloc.h"
CASetNetworkChangeCallback(CANetworkChangedCallback);
// retransmission initialize
- CARetransmissionInitialize(&g_retransmissionContext, CASendUnicastData,
+ CARetransmissionInitialize(&g_retransmissionContext, NULL, CASendUnicastData,
CATimeoutCallback, NULL);
CAInitializeAdapters();
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#ifndef SINGLE_THREAD
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
+#endif
#if defined(__ANDROID__)
#include <linux/time.h>
#include "oic_malloc.h"
#include "logger.h"
-#define TAG PCF("CA")
+#define TAG "CA"
typedef struct
{
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 */
CAEndpoint_t *endpoint; /**< remote endpoint */
*/
uint64_t getCurrentTimeInMicroSeconds();
+#ifndef SINGLE_THREAD
+/**
+ * @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 uint64_t CAGetTimeoutValue()
+{
+ return ((DEFAULT_ACK_TIMEOUT_SEC * 1000) + ((1000 * (random() & 0xFF)) >> 8)) *
+ (uint64_t) 1000;
+}
+
+CAResult_t CARetransmissionStart(CARetransmission_t *context)
+{
+ if (NULL == context)
+ {
+ 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;
+ }
+
+ CAResult_t res = ca_thread_pool_add_task(context->threadPool, CARetransmissionBaseRoutine,
+ context);
+
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "thread pool add task error(send thread).");
+ return res;
+ }
+
+ return res;
+}
+#endif
+
/**
* @brief check timeout routine
* @param currentTime [IN]microseconds
- * @param timeStamp [IN]microseconds
- * @param timeoutValue [IN]microseconds
- * @param triedCount [IN]Number of retransmission tried
+ * @param retData [IN]retransmission data
* @return true if the timeout period has elapsed, false otherwise
*/
-static bool CACheckTimeout(uint64_t currentTime, uint64_t timeStamp, uint64_t timeoutValue,
- uint8_t triedCount)
+static bool CACheckTimeout(uint64_t currentTime, CARetransmissionData_t *retData)
{
+#ifndef SINGLE_THREAD
// #1. calculate timeout
- uint32_t milliTimeoutValue = timeoutValue * 0.001;
- uint64_t timeout = (milliTimeoutValue << triedCount) * (uint64_t) 1000;
+ uint32_t milliTimeoutValue = retData->timeout * 0.001;
+ uint64_t timeout = (milliTimeoutValue << retData->triedCount) * (uint64_t) 1000;
- if (currentTime >= timeStamp + timeout)
+ if (currentTime >= retData->timeStamp + timeout)
{
- OIC_LOG_V(DEBUG, TAG, "%d microseconds time out!!, tried count(%ld)", timeout, triedCount);
+ OIC_LOG_V(DEBUG, TAG, "%d microseconds time out!!, tried count(%ld)",
+ timeout, retData->triedCount);
return true;
}
+#else
+ // #1. calculate timeout
+ uint64_t timeOut = (2 << retData->triedCount) * 1000000;
+ 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;
}
-/**
- * @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 uint64_t CAGetTimeoutValue()
-{
- return ((DEFAULT_ACK_TIMEOUT_SEC * 1000) + ((1000 * (random() & 0xFF)) >> 8)) *
- (uint64_t) 1000;
-}
-
static void CACheckRetransmissionList(CARetransmission_t *context)
{
if (NULL == context)
{
- OIC_LOG(ERROR, TAG, "context is null..");
+ OIC_LOG(ERROR, TAG, "context is null");
return;
}
uint64_t currentTime = getCurrentTimeInMicroSeconds();
- if (CACheckTimeout(currentTime, retData->timeStamp, retData->timeout, retData->triedCount))
+ if (CACheckTimeout(currentTime, retData))
{
// #2. if time's up, send the data.
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);
}
if (retData->triedCount >= context->config.tryingCount)
{
CARetransmissionData_t *removedData = u_arraylist_remove(context->dataList, i);
-
- if (NULL != removedData)
+ 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 (NULL != context->timeoutCallback)
- {
- 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;
+ OIC_LOG(ERROR, TAG, "Removed data is NULL");
+ // mutex unlock
+ ca_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(ERROR, 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;
}
}
ca_mutex_unlock(context->threadMutex);
}
-static void CARetransmissionBaseRoutine(void *threadValue)
+void CARetransmissionBaseRoutine(void *threadValue)
{
- OIC_LOG(DEBUG, TAG, "retransmission main thread start..");
+ OIC_LOG(DEBUG, TAG, "retransmission main thread start");
CARetransmission_t *context = (CARetransmission_t *) threadValue;
if (NULL == context)
{
- OIC_LOG(ERROR, 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)
{
ca_cond_signal(context->threadCond);
ca_mutex_unlock(context->threadMutex);
- OIC_LOG(DEBUG, TAG, "retransmission main thread end..");
+#endif
+ OIC_LOG(DEBUG, TAG, "retransmission main thread end");
}
-CAResult_t CARetransmissionInitialize(CARetransmission_t *context, ca_thread_pool_t handle,
+CAResult_t CARetransmissionInitialize(CARetransmission_t *context,
+ ca_thread_pool_t handle,
CADataSendMethod_t retransmissionSendMethod,
CATimeoutCallback_t timeoutCallback,
CARetransmissionConfig_t* config)
{
if (NULL == context)
{
- OIC_LOG(ERROR, TAG, "thread instance is empty..");
+ OIC_LOG(ERROR, TAG, "thread instance is empty");
return CA_STATUS_INVALID_PARAM;
}
-
+#ifndef SINGLE_THREAD
if (NULL == handle)
{
- OIC_LOG(ERROR, TAG, "thread pool handle is empty..");
+ OIC_LOG(ERROR, TAG, "thread pool handle is empty");
return CA_STATUS_INVALID_PARAM;
}
-
- OIC_LOG(DEBUG, TAG, "thread initialize..");
+#endif
+ OIC_LOG(DEBUG, TAG, "thread initialize");
memset(context, 0, sizeof(CARetransmission_t));
{
// setDefault
cfg.supportType = DEFAULT_RETRANSMISSION_TYPE;
- cfg.tryingCount = DEFAULT_MAX_RETRANSMIT;
+ cfg.tryingCount = DEFAULT_RETRANSMISSION_COUNT;
}
else
{
return CA_STATUS_OK;
}
-CAResult_t CARetransmissionStart(CARetransmission_t *context)
-{
- if (NULL == context)
- {
- 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;
- }
-
- CAResult_t res = ca_thread_pool_add_task(context->threadPool, CARetransmissionBaseRoutine,
- context);
-
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "thread pool add task error(send thread).");
- return res;
- }
-
- return res;
-}
-
CAResult_t CARetransmissionSentData(CARetransmission_t *context,
const CAEndpoint_t *endpoint,
const void *pdu, uint32_t size)
{
if (NULL == context || NULL == endpoint || NULL == pdu)
{
- OIC_LOG(ERROR, TAG, "invalid parameter..");
+ OIC_LOG(ERROR, TAG, "invalid parameter");
return CA_STATUS_INVALID_PARAM;
}
// #0. check support transport type
if (!(context->config.supportType & endpoint->adapter))
{
- OIC_LOG_V(DEBUG, TAG, "not supported transport type for retransmission..(%d)",
- endpoint->adapter);
+ OIC_LOG_V(DEBUG, TAG, "not supported transport type=%d", endpoint->adapter);
return CA_NOT_SUPPORTED;
}
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 (CA_MSG_CONFIRM != type)
{
- OIC_LOG(DEBUG, TAG, "not supported message type for retransmission..");
+ OIC_LOG(DEBUG, TAG, "not supported message type");
return CA_NOT_SUPPORTED;
}
if (NULL == retData)
{
- OIC_LOG(ERROR, TAG, "memory error!!");
+ OIC_LOG(ERROR, TAG, "memory error");
return CA_MEMORY_ALLOC_FAILED;
}
if (NULL == pduData)
{
OICFree(retData);
- OIC_LOG(ERROR, TAG, "memory error!!");
+ OIC_LOG(ERROR, TAG, "memory error");
return CA_MEMORY_ALLOC_FAILED;
}
memcpy(pduData, pdu, size);
{
OICFree(retData);
OICFree(pduData);
- OIC_LOG(ERROR, 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();
+#ifndef SINGLE_THREAD
retData->timeout = CAGetTimeoutValue();
+#endif
retData->triedCount = 0;
retData->messageId = messageId;
retData->endpoint = remoteEndpoint;
retData->pdu = pduData;
retData->size = size;
-
+#ifndef SINGLE_THREAD
// mutex lock
ca_mutex_lock(context->threadMutex);
// mutex unlock
ca_mutex_unlock(context->threadMutex);
+#else
+ u_arraylist_add(context->dataList, (void *) retData);
+
+ CACheckRetransmissionList(context);
+#endif
return CA_STATUS_OK;
}
const CAEndpoint_t *endpoint, const void *pdu,
uint32_t size, void **retransmissionPdu)
{
- OIC_LOG(DEBUG, TAG, "IN - CARetransmissionReceivedData");
+ OIC_LOG(DEBUG, TAG, "IN");
if (NULL == context || NULL == endpoint || NULL == pdu || NULL == retransmissionPdu)
{
- OIC_LOG(ERROR, TAG, "invalid parameter..");
+ OIC_LOG(ERROR, TAG, "invalid parameter");
return CA_STATUS_INVALID_PARAM;
}
// #0. check support transport type
if (!(context->config.supportType & endpoint->adapter))
{
- OIC_LOG_V(DEBUG, TAG, "not supported transport type for retransmission..(%d)",
- endpoint->adapter);
+ OIC_LOG_V(DEBUG, TAG, "not supported transport type=%d", endpoint->adapter);
return CA_STATUS_OK;
}
CAMessageType_t type = CAGetMessageTypeFromPduBinaryData(pdu, size);
uint16_t messageId = CAGetMessageIdFromPduBinaryData(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", type, messageId);
if ((CA_MSG_ACKNOWLEDGE != type) && (CA_MSG_RESET != type))
{
// if retransmission was finish..token will be unavailable.
if (CA_EMPTY == CAGetCodeFromPduBinaryData(pdu, size))
{
- OIC_LOG(DEBUG, TAG, "code is CA_EMPTY..");
+ OIC_LOG(DEBUG, TAG, "code is CA_EMPTY");
if (NULL == retData->pdu)
{
if ((*retransmissionPdu) == NULL)
{
OICFree(retData);
- OIC_LOG(ERROR, TAG, "memory error!!");
+ OIC_LOG(ERROR, TAG, "memory error");
// mutex unlock
ca_mutex_unlock(context->threadMutex);
return CA_STATUS_FAILED;
}
- OIC_LOG_V(DEBUG, TAG, "remove retransmission CON data!!, message id(%d)",
- messageId);
+ OIC_LOG_V(DEBUG, TAG, "remove RTCON data!!, msgid=%d", messageId);
CAFreeEndpoint(removedData->endpoint);
OICFree(removedData->pdu);
// mutex unlock
ca_mutex_unlock(context->threadMutex);
- OIC_LOG(DEBUG, TAG, "OUT - CARetransmissionReceivedData");
+ OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
currentTime = (getTs.tv_sec * (uint64_t)1000000000 + getTs.tv_nsec)/1000;
OIC_LOG_V(DEBUG, TAG, "current time = %ld", currentTime);
+#elif defined __ARDUINO__
+ currentTime = millis() * 1000;
+ OIC_LOG_V(DEBUG, TAG, "currtime=%lu", currentTime);
#else
#if _POSIX_TIMERS > 0
struct timespec ts;
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-#include "caretransmission_singlethread.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "caremotehandler.h"
-#include "caprotocolmessage.h"
-#include "oic_malloc.h"
-#include "logger.h"
-
-#ifndef __ARDUINO__
-#include <sys/time.h>
-#endif
-
-#define TAG "RT"
-
-typedef struct
-{
- /** last sent time. microseconds **/
- uint64_t timeStamp;
-
- /** retransmission count **/
- uint8_t triedCount;
-
- /** coap PDU message id **/
- uint16_t messageId;
-
- /** remote endpoint **/
- CAEndpoint_t *endpoint;
-
- /** coap PDU **/
- void *pdu;
-
- /** coap PDU size**/
- uint32_t size;
-
-} CARetransmissionData_t;
-
-static CARetransmission_t *g_retransmissionPtr = NULL;
-
-/**
- * getCurrent monotonic time.
- *
- * @return current time in microseconds.
- */
-uint64_t getCurrentTimeInMicroSeconds();
-
-/**
- * @brief check timeout routine
- * @param currentTime [IN]microseconds
- * @param timeStamp [IN]microseconds
- * @param triedCount [IN]Number of retransmission tried.
- * @return true if the timeout period has elapsed, false otherwise.
- */
-static bool CACheckTimeout(uint64_t currentTime, uint64_t timeStamp, uint8_t triedCount)
-{
- OIC_LOG(DEBUG, TAG, "IN");
- // #1. calculate timeout
- uint64_t timeOut = (2 << triedCount) * 1000000;
-
- if (currentTime >= timeStamp + timeOut)
- {
- OIC_LOG_V(DEBUG, TAG, "timeout=%d, tried cnt=%d", (2 << triedCount), triedCount);
- return true;
- }
-
- OIC_LOG(DEBUG, TAG, "OUT");
- return false;
-}
-
-void CACheckRetransmissionList()
-{
- uint32_t len = u_arraylist_length(g_retransmissionPtr->dataList);
-
- OIC_LOG_V(DEBUG, TAG, "len=%d", len);
- for (uint32_t i = 0; i < len; i++)
- {
- CARetransmissionData_t *retData =
- (CARetransmissionData_t *) u_arraylist_get(g_retransmissionPtr->dataList, i);
-
- if (NULL == retData)
- {
- continue;
- }
-
- uint64_t currentTime = getCurrentTimeInMicroSeconds();
-
- OIC_LOG_V(DEBUG, TAG, "currtime=%lu", currentTime);
- if (CACheckTimeout(currentTime, retData->timeStamp, retData->triedCount))
- {
-
- OIC_LOG(DEBUG, TAG, "RTdata-Success");
- // #2. if time's up, send the data.
- if (NULL != g_retransmissionPtr->dataSendMethod)
- {
- OIC_LOG_V(DEBUG, TAG, "retry CON data-msgid=%d", retData->messageId);
- g_retransmissionPtr->dataSendMethod(retData->endpoint, retData->pdu, retData->size);
- }
-
- // #3. increase the retransmission count and update timestamp.
- retData->timeStamp = currentTime;
- retData->triedCount++;
- }
-
- // #4. if tried count is max, remove the retransmission data from list.
- if (retData->triedCount >= g_retransmissionPtr->config.tryingCount)
- {
- CARetransmissionData_t *removedData = (CARetransmissionData_t *) u_arraylist_remove(
- g_retransmissionPtr->dataList, i);
- if (NULL == removedData)
- {
- OIC_LOG(ERROR, TAG, "Removed data is NULL");
- return;
- }
-
- OIC_LOG(DEBUG, TAG, "max trycount rchd");
-
- OIC_LOG_V(DEBUG, TAG, "max trycount, remove retransmission CON data!!, messageid=%d",
- removedData->messageId);
-
- // callback for retransmit timeout
- if (NULL != g_retransmissionPtr->timeoutCallback)
- {
- g_retransmissionPtr->timeoutCallback(removedData->endpoint, removedData->pdu,
- removedData->size);
- }
-
- CAFreeEndpoint(removedData->endpoint);
- OICFree(removedData->pdu);
-
- OICFree(removedData);
-
- // modify loop value.
- len = u_arraylist_length(g_retransmissionPtr->dataList);
- --i;
- }
- }
-}
-
-void CARetransmissionBaseRoutine(void *threadValue)
-{
- CARetransmission_t *context = (CARetransmission_t *) threadValue;
-
- if (NULL == context)
- {
- OIC_LOG(ERROR, TAG, "cnxt null");
- return;
- }
-
- if (true == context->isStop)
- {
- OIC_LOG(DEBUG, TAG, "thread stopped");
- return;
- }
- g_retransmissionPtr = context;
- CACheckRetransmissionList();
-}
-
-CAResult_t CARetransmissionInitialize(CARetransmission_t *context,
- CADataSendMethod_t retransmissionSendMethod,
- CATimeoutCallback_t timeoutCallback,
- CARetransmissionConfig_t *config)
-{
- OIC_LOG(DEBUG, TAG, "IN");
- if (NULL == context)
- {
- OIC_LOG(ERROR, TAG, "cnxt null");
- return CA_STATUS_INVALID_PARAM;
- }
-
- memset(context, 0, sizeof(CARetransmission_t));
-
- CARetransmissionConfig_t cfg = {};
-
- if (NULL == config)
- {
- // setDefault
- cfg.supportType = (CATransportAdapter_t) DEFAULT_RETRANSMISSION_TYPE;
- cfg.tryingCount = DEFAULT_RETRANSMISSION_COUNT;
- }
- else
- {
- cfg = *config;
- }
-
- // set send thread data
- context->dataSendMethod = retransmissionSendMethod;
- context->timeoutCallback = timeoutCallback;
- context->config = cfg;
- context->isStop = false;
- context->dataList = u_arraylist_create();
-
- // Enable TimedAction for CACheckRetransmissionList API
- g_retransmissionPtr = context;
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CARetransmissionSentData(CARetransmission_t *context, const CAEndpoint_t *endpoint,
- const void *pdu, uint32_t size)
-{
- OIC_LOG(DEBUG, TAG, "IN");
- if (NULL == context || NULL == endpoint || NULL == pdu)
- {
- OIC_LOG(ERROR, TAG, "error");
- return CA_STATUS_INVALID_PARAM;
- }
-
- // #0. check support connectivity type
- if (!(context->config.supportType & endpoint->adapter))
- {
- OIC_LOG(ERROR, TAG, "error");
- OIC_LOG_V(ERROR, TAG, "not supported conntype=%d", context->config.supportType);
- 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, msgtype=%d,msgid=%d", type, messageId);
-
- if (CA_MSG_CONFIRM != type)
- {
- OIC_LOG(DEBUG, TAG, "not supported message type");
- return CA_NOT_SUPPORTED;
- }
-
- // create retransmission data
- CARetransmissionData_t *retData = (CARetransmissionData_t *) OICCalloc(
- 1, sizeof(CARetransmissionData_t));
-
- if (NULL == retData)
- {
- OIC_LOG(ERROR, TAG, "error");
- return CA_MEMORY_ALLOC_FAILED;
- }
-
- // copy PDU data
- void *pduData = (void *) OICMalloc(size);
- if (NULL == pduData)
- {
- OICFree(retData);
- OIC_LOG(ERROR, TAG, "error");
- return CA_MEMORY_ALLOC_FAILED;
- }
- memcpy(pduData, pdu, size);
-
- // clone remote endpoint
- CAEndpoint_t *remoteEndpoint = CACloneEndpoint(endpoint);
- if (NULL == remoteEndpoint)
- {
- OICFree(retData);
- OICFree(pduData);
- OIC_LOG(ERROR, TAG, "error");
- return CA_MEMORY_ALLOC_FAILED;
- }
-
- // #2. add additional information. (time stamp, retransmission count...)
- retData->timeStamp = getCurrentTimeInMicroSeconds();
- retData->triedCount = 0;
- retData->messageId = messageId;
- retData->endpoint = remoteEndpoint;
- retData->pdu = pduData;
- retData->size = size;
-
- // #3. add data into list
- u_arraylist_add(context->dataList, (void *) retData);
-
- // #4. Initiate Re-transmission for added entry
- g_retransmissionPtr = context;
- CACheckRetransmissionList();
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CARetransmissionReceivedData(CARetransmission_t *context,
- const CAEndpoint_t *endpoint, const void *pdu,
- uint32_t size, void **retransmissionPdu)
-{
- OIC_LOG(DEBUG, TAG, "IN");
- if (NULL == context || NULL == endpoint || NULL == pdu || NULL == retransmissionPdu)
- {
- OIC_LOG(ERROR, TAG, "error");
- return CA_STATUS_INVALID_PARAM;
- }
-
- // #0. check support connectivity type
- if (!(context->config.supportType & endpoint->adapter))
- {
- OIC_LOG_V(DEBUG, TAG, "not supp conntype=%d", endpoint->adapter);
- return CA_STATUS_OK;
- }
-
- // #1. check PDU method type and get message id.
- // ACK, RST --> remove the CON data
- CAMessageType_t type = CAGetMessageTypeFromPduBinaryData(pdu, size);
- uint16_t messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
-
- OIC_LOG_V(DEBUG, TAG, "recv pdu, msgtype=%d,msgid=%d", type, messageId);
-
- if (CA_MSG_ACKNOWLEDGE != type && CA_MSG_RESET != type)
- {
- return CA_STATUS_OK;
- }
-
- uint32_t len = u_arraylist_length(context->dataList);
-
- // find index
- for (uint32_t i = 0; i < len; i++)
- {
- CARetransmissionData_t *retData = (CARetransmissionData_t *) u_arraylist_get(
- context->dataList, i);
-
- if (NULL == retData)
- {
- continue;
- }
-
- // found index
- 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, "CA_EMPTY");
-
- if (NULL == retData->pdu)
- {
- OIC_LOG(ERROR, TAG, "retData->pdu is null");
- OICFree(retData);
- return CA_STATUS_FAILED;
- }
-
- // copy PDU data
- (*retransmissionPdu) = (void *) OICCalloc(1, retData->size);
- if (NULL == (*retransmissionPdu))
- {
- OICFree(retData);
- OIC_LOG(ERROR, TAG, "error");
- return CA_MEMORY_ALLOC_FAILED;
- }
- memcpy((*retransmissionPdu), retData->pdu, retData->size);
- }
-
- // #2. remove data from list
- CARetransmissionData_t *removedData = (CARetransmissionData_t *) u_arraylist_remove(
- context->dataList, i);
- if (NULL == removedData)
- {
- OIC_LOG(ERROR, TAG, "Removed data is NULL");
- return CA_STATUS_FAILED;
- }
-
- OIC_LOG_V(DEBUG, TAG, "remove RTCON data, msgid=%d", messageId);
-
- CAFreeEndpoint(removedData->endpoint);
- OICFree(removedData->pdu);
-
- OICFree(removedData);
-
- break;
- }
- }
-
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CARetransmissionStop(CARetransmission_t *context)
-{
- OIC_LOG(DEBUG, TAG, "IN");
- if (NULL == context)
- {
- OIC_LOG(ERROR, TAG, "error");
- return CA_STATUS_INVALID_PARAM;
- }
-
- // set stop flag
- context->isStop = true;
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-CAResult_t CARetransmissionDestroy(CARetransmission_t *context)
-{
- OIC_LOG(DEBUG, TAG, "IN");
- if (NULL == context)
- {
- OIC_LOG(ERROR, TAG, "error");
- return CA_STATUS_INVALID_PARAM;
- }
-
- u_arraylist_free(&context->dataList);
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
-}
-
-uint64_t getCurrentTimeInMicroSeconds()
-{
- OIC_LOG(DEBUG, TAG, "IN");
- uint64_t currentTime = 0;
-
-#ifdef __ARDUINO__
- currentTime = millis() * 1000;
-
- OIC_LOG_V(DEBUG, TAG, "currtime=%lu", currentTime);
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- currentTime = tv.tv_sec * USECS_PER_SEC + tv.tv_usec;
-#endif
-
- OIC_LOG(DEBUG, TAG, "OUT");
- return currentTime;
-}
-