#include "cablockwisetransfer.h"
#include "oic_malloc.h"
#include "oic_string.h"
-#include "camutex.h"
+#include "octhread.h"
#include "logger.h"
+#include "oic_time.h"
#define TAG "OIC_CA_BWT"
#define BLOCK_SIZE(arg) (1 << ((arg) + 4))
+#define BLOCK_DATA_TIMEOUT_SECONDS (60 * 1) // 1 minutes.
+static const uint64_t USECS_PER_SEC = 1000000;
+
// context for block-wise transfer
static CABlockWiseContext_t g_context = { .sendThreadFunc = NULL,
.receivedThreadFunc = NULL,
{
if (!g_context.blockDataListMutex)
{
- g_context.blockDataListMutex = ca_mutex_new();
+ g_context.blockDataListMutex = oc_mutex_new();
if (!g_context.blockDataListMutex)
{
- OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+ OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
return CA_STATUS_FAILED;
}
}
if (!g_context.blockDataSenderMutex)
{
- g_context.blockDataSenderMutex = ca_mutex_new();
+ g_context.blockDataSenderMutex = oc_mutex_new();
if (!g_context.blockDataSenderMutex)
{
- OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+ OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
CATerminateBlockWiseMutexVariables();
return CA_STATUS_FAILED;
}
{
if (g_context.blockDataListMutex)
{
- ca_mutex_free(g_context.blockDataListMutex);
+ oc_mutex_free(g_context.blockDataListMutex);
g_context.blockDataListMutex = NULL;
}
if (g_context.blockDataSenderMutex)
{
- ca_mutex_free(g_context.blockDataSenderMutex);
+ oc_mutex_free(g_context.blockDataSenderMutex);
g_context.blockDataSenderMutex = NULL;
}
}
if (g_context.sendThreadFunc)
{
- ca_mutex_lock(g_context.blockDataSenderMutex);
+ oc_mutex_lock(g_context.blockDataSenderMutex);
g_context.sendThreadFunc(cloneData);
- ca_mutex_unlock(g_context.blockDataSenderMutex);
+ oc_mutex_unlock(g_context.blockDataSenderMutex);
}
else
{
return CA_STATUS_FAILED;
}
+ if (!data->sentData)
+ {
+ OIC_LOG(ERROR, TAG, "data has no sent-data");
+ return CA_STATUS_FAILED;
+ }
+
+ CAData_t *cloneData = CACloneCAData(data->sentData);
+ if (!cloneData)
+ {
+ OIC_LOG(ERROR, TAG, "clone has failed");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
CAMessageType_t sentMsgType = CA_MSG_NONCONFIRM;
switch (pdu->transport_hdr->udp.type)
{
sentMsgType = CA_MSG_NONCONFIRM;
}
- CAData_t *cloneData = NULL;
- if (data->sentData)
+ if (cloneData->responseInfo)
+ {
+ cloneData->responseInfo->info.messageId = pdu->transport_hdr->udp.id;
+ cloneData->responseInfo->info.type = sentMsgType;
+ cloneData->responseInfo->result = responseResult;
+ }
+ else
{
- cloneData = CACloneCAData(data->sentData);
- if (!cloneData)
+ CAInfo_t responseData = { .tokenLength = pdu->transport_hdr->udp.token_length };
+ responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
+ if (!responseData.token)
{
- OIC_LOG(ERROR, TAG, "clone has failed");
+ OIC_LOG(ERROR, TAG, "out of memory");
+ CADestroyDataSet(cloneData);
return CA_MEMORY_ALLOC_FAILED;
}
+ memcpy(responseData.token, pdu->transport_hdr->udp.token, responseData.tokenLength);
- if (cloneData->responseInfo)
+ cloneData->responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
+ if (!cloneData->responseInfo)
{
- cloneData->responseInfo->info.messageId = pdu->transport_hdr->udp.id;
- cloneData->responseInfo->info.type = sentMsgType;
- cloneData->responseInfo->result = responseResult;
+ OIC_LOG(ERROR, TAG, "out of memory");
+ CADestroyDataSet(cloneData);
+ OICFree(responseData.token);
+ return CA_MEMORY_ALLOC_FAILED;
}
- else
- {
- CAInfo_t responseData = { .tokenLength = pdu->transport_hdr->udp.token_length };
- responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
- if (!responseData.token)
- {
- OIC_LOG(ERROR, TAG, "out of memory");
- return CA_MEMORY_ALLOC_FAILED;
- }
- memcpy(responseData.token, pdu->transport_hdr->udp.token, responseData.tokenLength);
-
- cloneData->responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
- if (!cloneData->responseInfo)
- {
- OIC_LOG(ERROR, TAG, "out of memory");
- OICFree(responseData.token);
- return CA_MEMORY_ALLOC_FAILED;
- }
- cloneData->responseInfo->info = responseData;
- cloneData->responseInfo->info.type = sentMsgType;
- cloneData->responseInfo->result = responseResult;
- }
- OIC_LOG(DEBUG, TAG, "set response message to send error code");
- }
- else
- {
- OIC_LOG(ERROR, TAG, "data has no sent-data");
- return CA_MEMORY_ALLOC_FAILED;
+ cloneData->responseInfo->info = responseData;
+ cloneData->responseInfo->info.type = sentMsgType;
+ cloneData->responseInfo->result = responseResult;
}
+ OIC_LOG(DEBUG, TAG, "set response message to send error code");
+
// if there is a requestInfo, remove it to send response message
if (cloneData->requestInfo)
{
// add data to send thread
if (g_context.sendThreadFunc)
{
- ca_mutex_lock(g_context.blockDataSenderMutex);
+ oc_mutex_lock(g_context.blockDataSenderMutex);
g_context.sendThreadFunc(cloneData);
- ca_mutex_unlock(g_context.blockDataSenderMutex);
+ oc_mutex_unlock(g_context.blockDataSenderMutex);
}
else
{
{
OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
COAP_OPTION_DATA(*(coap_option *) opt->data));
-
OIC_LOG_V(DEBUG, TAG, "[%d] pdu length", (*pdu)->length);
- coap_add_option(*pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
- COAP_OPTION_LENGTH(*(coap_option *) opt->data),
- COAP_OPTION_DATA(*(coap_option *) opt->data));
+
+ if (0 == coap_add_option(*pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
+ COAP_OPTION_LENGTH(*(coap_option *) opt->data),
+ COAP_OPTION_DATA(*(coap_option *) opt->data)))
+ {
+ OIC_LOG(ERROR, TAG, "coap_add_option has failed");
+ res = CA_STATUS_FAILED;
+ goto exit;
+ }
}
}
-
OIC_LOG_V(DEBUG, TAG, "[%d] pdu length after option", (*pdu)->length);
// if response data is so large. it have to send as block transfer
if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
{
- OIC_LOG(INFO, TAG, "it have to use block");
+ OIC_LOG(INFO, TAG, "it has to use block");
res = CA_STATUS_FAILED;
goto exit;
}
}
}
+ CAResetBlockDataTTL(blockDataID);
exit:
CADestroyBlockID(blockDataID);
OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption");
{
OIC_LOG(ERROR, TAG, "memory allocation failed");
OICFree(requestData.token);
+ OICFree(requestInfo);
return NULL;
}
CAGetResponseInfoFromPDU(pdu, resInfo, endpoint);
requestInfo->method = CA_GET;
- requestInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu->transport_hdr, pdu->length);
+ requestInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu->transport_hdr,
+ pdu->length);
requestInfo->info.resourceUri = OICStrdup(resInfo->info.resourceUri);
// after copying the resource uri, destroy response info.
if (!data)
{
OIC_LOG(ERROR, TAG, "out of memory");
- OICFree(requestInfo);
- OICFree(responseInfo);
+ if (NULL != requestInfo)
+ {
+ OICFree(requestInfo->info.resourceUri);
+ OICFree(requestInfo->info.token);
+ OICFree(requestInfo);
+ }
+ if (NULL != responseInfo)
+ {
+ OICFree(responseInfo->info.token);
+ OICFree(responseInfo);
+ }
return NULL;
}
return data->requestInfo->info.payload;
}
}
- else
+ else if (data->responseInfo)
{
if (data->responseInfo->info.payload)
{
OIC_LOG(DEBUG, TAG, "IN-UpdateBlockOptionType");
VERIFY_NON_NULL(blockID, TAG, "blockID");
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
if (CABlockidMatches(currData, blockID))
{
currData->type = blockType;
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
return CA_STATUS_OK;
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
return CA_STATUS_FAILED;
OIC_LOG(DEBUG, TAG, "IN-GetBlockOptionType");
VERIFY_NON_NULL_RET(blockID, TAG, "blockID", 0);
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
if (CABlockidMatches(currData, blockID))
{
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
return currData->type;
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
return 0;
{
VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
if (CABlockidMatches(currData, blockID))
{
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return currData->sentData;
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
+
+ return NULL;
+}
+
+CABlockData_t *CAUpdateDataSetFromBlockDataList(const CABlockDataID_t *blockID,
+ const CAData_t *sendData)
+{
+ VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
+ VERIFY_NON_NULL_RET(sendData, TAG, "sendData", NULL);
+
+ oc_mutex_lock(g_context.blockDataListMutex);
+
+ size_t len = u_arraylist_length(g_context.dataList);
+ for (size_t i = 0; i < len; i++)
+ {
+ CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
+ if (CABlockidMatches(currData, blockID))
+ {
+ CADestroyDataSet(currData->sentData);
+ currData->sentData = CACloneCAData(sendData);
+ oc_mutex_unlock(g_context.blockDataListMutex);
+ return currData;
+ }
+ }
+ oc_mutex_unlock(g_context.blockDataListMutex);
return NULL;
}
VERIFY_NON_NULL(endpoint, TAG, "endpoint");
VERIFY_NON_NULL(responseInfo, TAG, "responseInfo");
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
if (NULL == responseInfo->info.token)
{
OIC_LOG(ERROR, TAG, "out of memory");
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return CA_MEMORY_ALLOC_FAILED;
}
memcpy(responseInfo->info.token, currData->sentData->requestInfo->info.token,
responseInfo->info.tokenLength);
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
return CA_STATUS_OK;
}
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
return CA_STATUS_FAILED;
return CA_STATUS_FAILED;
}
- CABlockData_t *storedData = CAGetBlockDataFromBlockDataList(blockDataID);
- if (storedData)
+ CABlockData_t *updatedData = CAUpdateDataSetFromBlockDataList(blockDataID, sendData);
+ if (updatedData)
{
OIC_LOG(DEBUG, TAG, "Send response about the received block request.");
- if (storedData->sentData)
- {
- OIC_LOG(DEBUG, TAG, "init block number");
- CADestroyDataSet(storedData->sentData);
- }
- storedData->sentData = CACloneCAData(sendData);
- *blockData = storedData;
+ *blockData = updatedData;
CADestroyBlockID(blockDataID);
return CA_STATUS_OK;
}
{
VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
if (CABlockidMatches(currData, blockID))
{
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return currData;
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return NULL;
}
OIC_LOG(DEBUG, TAG, "IN-GetBlockOption");
VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
if (CABlockidMatches(currData, blockID))
{
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
if (COAP_OPTION_BLOCK2 == blockType)
{
}
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
return NULL;
VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
VERIFY_NON_NULL_RET(fullPayloadLen, TAG, "fullPayloadLen", NULL);
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
if (CABlockidMatches(currData, blockID))
{
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
*fullPayloadLen = currData->receivedPayloadLen;
OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
return currData->payload;
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
return NULL;
return NULL;
}
data->blockDataId = blockDataID;
+ uint64_t now = OICGetCurrentTime(TIME_IN_US);
+ data->ttl = now + (BLOCK_DATA_TIMEOUT_SECONDS * USECS_PER_SEC);
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
bool res = u_arraylist_add(g_context.dataList, (void *) data);
if (!res)
CADestroyBlockID(data->blockDataId);
CADestroyDataSet(data->sentData);
OICFree(data);
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return NULL;
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
OIC_LOG(DEBUG, TAG, "OUT-CreateBlockData");
return data;
CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
{
- OIC_LOG(DEBUG, TAG, "CARemoveBlockData");
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
VERIFY_NON_NULL(blockID, TAG, "blockID");
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = 0; i < len; i++)
if (!removedData)
{
OIC_LOG(ERROR, TAG, "data is NULL");
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return CA_STATUS_FAILED;
}
+ OIC_LOG(DEBUG, TAG, "Removed BlockID is ");
+ OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) removedData->blockDataId->id,
+ removedData->blockDataId->idLength);
+
// destroy memory
- CADestroyDataSet(currData->sentData);
- CADestroyBlockID(currData->blockDataId);
- OICFree(currData->payload);
- OICFree(currData);
- ca_mutex_unlock(g_context.blockDataListMutex);
+ CADestroyDataSet(removedData->sentData);
+ CADestroyBlockID(removedData->blockDataId);
+ OICFree(removedData->payload);
+ OICFree(removedData);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return CA_STATUS_OK;
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
-
+ oc_mutex_unlock(g_context.blockDataListMutex);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
return CA_STATUS_OK;
}
{
OIC_LOG(DEBUG, TAG, "CARemoveAllBlockDataFromList");
- ca_mutex_lock(g_context.blockDataListMutex);
+ oc_mutex_lock(g_context.blockDataListMutex);
size_t len = u_arraylist_length(g_context.dataList);
for (size_t i = len; i > 0; i--)
OICFree(removedData);
}
}
- ca_mutex_unlock(g_context.blockDataListMutex);
+ oc_mutex_unlock(g_context.blockDataListMutex);
return CA_STATUS_OK;
}
{
VERIFY_NON_NULL_VOID(data, TAG, "data");
- CAFreeEndpoint(data->remoteEndpoint);
+ if (data->remoteEndpoint)
+ {
+ CAFreeEndpoint(data->remoteEndpoint);
+ data->remoteEndpoint = NULL;
+ }
if (data->requestInfo)
{
CADestroyRequestInfoInternal(data->requestInfo);
+ data->requestInfo = NULL;
}
if (data->responseInfo)
{
CADestroyResponseInfoInternal(data->responseInfo);
+ data->responseInfo = NULL;
}
OICFree(data);
}
return CA_STATUS_FAILED;
}
- CAResult_t res = CA_STATUS_OK;
+ CAResult_t res = CARemoveBlockDataFromList(blockDataID);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CARemoveBlockDataFromList failed");
+ }
+
+ CADestroyBlockID(blockDataID);
+ return res;
+}
- if (NULL != CAGetBlockDataFromBlockDataList(blockDataID))
+void CAResetBlockDataTTL(const CABlockDataID_t *blockID)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+ oc_mutex_lock(g_context.blockDataListMutex);
+ size_t len = u_arraylist_length(g_context.dataList);
+ for (size_t i = 0; i < len; i++)
{
- res = CARemoveBlockDataFromList(blockDataID);
- if (CA_STATUS_OK != res)
+ CABlockData_t *blockData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
+ if (CABlockidMatches(blockData, blockID))
{
- OIC_LOG(ERROR, TAG, "CARemoveBlockDataFromList failed");
+ uint64_t now = OICGetCurrentTime(TIME_IN_US);
+ blockData->ttl = now + (BLOCK_DATA_TIMEOUT_SECONDS * USECS_PER_SEC);
+ oc_mutex_unlock(g_context.blockDataListMutex);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return;
}
}
+ oc_mutex_unlock(g_context.blockDataListMutex);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
- CADestroyBlockID(blockDataID);
+void CACheckAndDeleteTimedOutBlockData()
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
- return res;
+ uint64_t now = OICGetCurrentTime(TIME_IN_US);
+
+ oc_mutex_lock(g_context.blockDataListMutex);
+ for (size_t i = 0; i < u_arraylist_length(g_context.dataList); i++)
+ {
+ CABlockData_t *blockData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
+ if (blockData && blockData->ttl < now)
+ {
+ OIC_LOG(INFO, TAG, "Deleting timed-out BlockData");
+ OIC_LOG(DEBUG, TAG, "BlockID is ");
+ OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) blockData->blockDataId->id,
+ blockData->blockDataId->idLength);
+
+ blockData = (CABlockData_t *) u_arraylist_remove(g_context.dataList, i);
+ if (blockData)
+ {
+ // destroy memory
+ CADestroyDataSet(blockData->sentData);
+ CADestroyBlockID(blockData->blockDataId);
+ OICFree(blockData->payload);
+ OICFree(blockData);
+ }
+ }
+ }
+ oc_mutex_unlock(g_context.blockDataListMutex);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
}