X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fcablockwisetransfer.c;h=0326f19de39d727c79bcf6d65fa318f63151c633;hb=03ae7cd73e2e10a8de75da40a0e476cc955b46b2;hp=edcb299a493e1e6c15bc202a43c800d580f2db03;hpb=00821d977c9d804fed5f6906c347e14d41564160;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/cablockwisetransfer.c b/resource/csdk/connectivity/src/cablockwisetransfer.c old mode 100644 new mode 100755 index edcb299..0326f19 --- a/resource/csdk/connectivity/src/cablockwisetransfer.c +++ b/resource/csdk/connectivity/src/cablockwisetransfer.c @@ -40,8 +40,10 @@ #include "caremotehandler.h" #include "cablockwisetransfer.h" #include "oic_malloc.h" -#include "camutex.h" +#include "oic_string.h" +#include "octhread.h" #include "logger.h" +#include "oic_time.h" #define TAG "OIC_CA_BWT" @@ -52,6 +54,9 @@ #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, @@ -77,7 +82,7 @@ static bool CACheckPayloadLength(const CAData_t *sendData) CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc, CAReceiveThreadFunc receivedThreadFunc) { - OIC_LOG(DEBUG, TAG, "initialize"); + OIC_LOG(DEBUG, TAG, "CAInitializeBlockWiseTransfer"); // set block-wise transfer context if (!g_context.sendThreadFunc) @@ -108,10 +113,11 @@ CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc, CAResult_t CATerminateBlockWiseTransfer() { - OIC_LOG(DEBUG, TAG, "terminate"); + OIC_LOG(DEBUG, TAG, "CATerminateBlockWiseTransfer"); if (g_context.dataList) { + CARemoveAllBlockDataFromList(); u_arraylist_free(&g_context.dataList); } @@ -124,20 +130,20 @@ CAResult_t CAInitBlockWiseMutexVariables() { 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; } @@ -150,13 +156,13 @@ void CATerminateBlockWiseMutexVariables() { 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; } } @@ -173,6 +179,16 @@ CAResult_t CASendBlockWiseData(const CAData_t *sendData) OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block"); return CA_NOT_SUPPORTED; } + + /* + * Other uses of the Block options in conjunction with multicast + * messages are for further study. + */ + if (sendData->requestInfo->isMulticast) + { + OIC_LOG(DEBUG, TAG, "multicast message can't be sent to the block"); + return CA_NOT_SUPPORTED; + } } else if (sendData->responseInfo) { @@ -181,6 +197,11 @@ CAResult_t CASendBlockWiseData(const CAData_t *sendData) OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block"); return CA_NOT_SUPPORTED; } + if (sendData->responseInfo->isMulticast) + { + OIC_LOG(DEBUG, TAG, "multicast message can't be sent to the block"); + return CA_NOT_SUPPORTED; + } } // #1. check if it is already included in block data list @@ -223,7 +244,7 @@ CAResult_t CASendBlockWiseData(const CAData_t *sendData) // #4. send block message OIC_LOG(DEBUG, TAG, "send first block msg"); res = CAAddSendThreadQueue(currData->sentData, - (const CABlockDataID_t *)&currData->blockDataId); + (const CABlockDataID_t *) &currData->blockDataId); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); @@ -249,9 +270,9 @@ CAResult_t CAAddSendThreadQueue(const CAData_t *sendData, const CABlockDataID_t 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 { @@ -290,21 +311,25 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, { OIC_LOG(DEBUG, TAG, "CAReceiveBlockWiseData"); VERIFY_NON_NULL(pdu, TAG, "pdu"); - VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); VERIFY_NON_NULL(endpoint, TAG, "endpoint"); VERIFY_NON_NULL(receivedData, TAG, "receivedData"); // check if received message type is CA_MSG_RESET - if (CA_EMPTY == pdu->hdr->coap_hdr_udp_t.code) + if (CA_EMPTY == pdu->transport_hdr->udp.code) { OIC_LOG(DEBUG, TAG, "code is CA_EMPTY.."); - // get token from block-wise transfer list when CA_EMPTY(RST/ACK) is received - CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint, receivedData->responseInfo); - if (CA_STATUS_OK != res) + if (!receivedData->responseInfo->info.token) { - OIC_LOG(ERROR, TAG, "fail to get token"); - return res; + // get token from block-wise transfer list when CA_EMPTY(RST/ACK) is received + CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint, + receivedData->responseInfo); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "fail to get token"); + return res; + } } CABlockDataID_t* blockDataID = CACreateBlockDatablockId( @@ -319,12 +344,20 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, OIC_LOG(INFO, TAG, "retransmission was stopped"); return CA_REQUEST_TIMEOUT; } - else - { - OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } + + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; + } + + // If we didn't send the last block message and received EMPTY message, + // we have to remain the block data from list. + CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); + if (data && (data->block1.m || data->block2.m)) + { + OIC_LOG(DEBUG, TAG, "this is normal EMPTY message for blockwise-transfer."); + CADestroyBlockID(blockDataID); + return CA_STATUS_OK; } CARemoveBlockDataFromList(blockDataID); @@ -333,7 +366,7 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, } // check if block option is set and get block data - coap_block_t block = {0, 0, 0}; + coap_block_t block = { 0, 0, 0 }; // get block1 option int isBlock1 = coap_get_block(pdu, COAP_OPTION_BLOCK1, &block); @@ -359,62 +392,53 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, } } - // check if there is error code + // if there is no block option in pdu, check if there is error code. if (!isBlock1 && !isBlock2) { - uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code); + CABlockDataID_t* blockDataID = CACreateBlockDatablockId( + (CAToken_t)pdu->transport_hdr->udp.token, + pdu->transport_hdr->udp.token_length, + endpoint->port); + if (NULL == blockDataID || blockDataID->idLength < 1) + { + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; + } + + uint32_t code = CA_RESPONSE_CODE(pdu->transport_hdr->udp.code); if (CA_REQUEST_ENTITY_INCOMPLETE == code) { - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)pdu->hdr->coap_hdr_udp_t.token, - pdu->hdr->coap_hdr_udp_t.token_length, - endpoint->port); - if (NULL == blockDataID || blockDataID->idLength < 1) + CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); + if (!data) { - OIC_LOG(ERROR, TAG, "blockId is null"); + OIC_LOG(ERROR, TAG, "getting has failed"); CADestroyBlockID(blockDataID); return CA_STATUS_FAILED; } - CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); - if (!data) + coap_block_t *block = CAGetBlockOption(blockDataID, data->type); + if (!block) { - OIC_LOG(ERROR, TAG, "getting has failed"); + OIC_LOG(ERROR, TAG, "block is null"); CADestroyBlockID(blockDataID); return CA_STATUS_FAILED; } + CAResult_t res = CA_STATUS_OK; if (COAP_OPTION_BLOCK2 == data->type) { - coap_block_t *block2 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK2); - if (!block2) - { - OIC_LOG(ERROR, TAG, "block is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, *block2, - dataLen); + res = CASetNextBlockOption2(pdu, endpoint, receivedData, *block, dataLen); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "setting has failed"); CADestroyBlockID(blockDataID); - return res; + return CA_STATUS_FAILED; } } else if (COAP_OPTION_BLOCK1 == data->type) { - coap_block_t *block1 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK1); - if (!block1) - { - OIC_LOG(ERROR, TAG, "block is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, *block1, - dataLen); + res = CASetNextBlockOption1(pdu, endpoint, receivedData, *block, dataLen); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "setting has failed"); @@ -422,11 +446,7 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, return res; } } - else - { - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } + CADestroyBlockID(blockDataID); } else { @@ -437,24 +457,12 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, // and sent data remain in block data list, remove block data if (receivedData->responseInfo) { - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)pdu->hdr->coap_hdr_udp_t.token, - pdu->hdr->coap_hdr_udp_t.token_length, - endpoint->port); - if (NULL == blockDataID || blockDataID->idLength < 1) - { - OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); } + CADestroyBlockID(blockDataID); return CA_NOT_SUPPORTED; } } - return CA_STATUS_OK; } @@ -480,7 +488,7 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData } break; - case CA_OPTION2_CON: + case CA_OPTION2_REQUEST: // add data to send thread data = CAGetDataSetFromBlockDataList(blockID); if (!data) @@ -489,30 +497,26 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData return CA_STATUS_FAILED; } - if (data->requestInfo) - { - data->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id; - } - if (data->responseInfo) { - data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id; - } + data->responseInfo->info.type = + (pdu->transport_hdr->udp.type == CA_MSG_CONFIRM) ? + CA_MSG_ACKNOWLEDGE : CA_MSG_NONCONFIRM; + data->responseInfo->info.messageId = pdu->transport_hdr->udp.id; - res = CAAddSendThreadQueue(data, blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "add has failed"); - return res; + res = CAAddSendThreadQueue(data, blockID); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "add has failed"); + return res; + } } - break; - case CA_OPTION1_ACK: - case CA_OPTION2_ACK: - case CA_SENT_PREVIOUS_NON_MSG: - res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus, - blockID); + case CA_OPTION1_RESPONSE: + case CA_OPTION2_RESPONSE: + case CA_OPTION1_REQUEST_BLOCK: + res = CASendBlockMessage(pdu, pdu->transport_hdr->udp.type, blockID); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "send has failed"); @@ -538,7 +542,7 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData } break; - case CA_OPTION1_NO_ACK_LAST_BLOCK: + case CA_OPTION1_REQUEST_LAST_BLOCK: // process last block and send upper layer res = CAReceiveLastBlock(blockID, receivedData); if (CA_STATUS_OK != res) @@ -546,53 +550,22 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData OIC_LOG(ERROR, TAG, "receive has failed"); return res; } - - if (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type) - { - // remove data from list - res = CARemoveBlockDataFromList(blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "remove has failed"); - return res; - } - } - break; - - case CA_OPTION1_NO_ACK_BLOCK: - if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type) - { - // add data to send thread - res = CASendBlockMessage(pdu, CA_MSG_ACKNOWLEDGE, blockWiseStatus, - blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "send has failed"); - return res; - } - } break; case CA_BLOCK_INCOMPLETE: - if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type || - CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type) + // add data to send thread + res = CASendErrorMessage(pdu, blockWiseStatus, CA_REQUEST_ENTITY_INCOMPLETE, blockID); + if (CA_STATUS_OK != res) { - // add data to send thread - res = CASendErrorMessage(pdu, blockWiseStatus, - CA_REQUEST_ENTITY_INCOMPLETE, - blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "send has failed"); - return res; - } + OIC_LOG(ERROR, TAG, "send has failed"); + return res; } break; case CA_BLOCK_TOO_LARGE: - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type) + if (receivedData->requestInfo) { - res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus, + res = CASendErrorMessage(pdu, blockWiseStatus, CA_REQUEST_ENTITY_TOO_LARGE, blockID); if (CA_STATUS_OK != res) { @@ -600,11 +573,9 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData return res; } } - else if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type) + else if (receivedData->responseInfo) { - res = CASendErrorMessage(pdu, blockWiseStatus, - CA_REQUEST_ENTITY_TOO_LARGE, - blockID); + res = CASendBlockMessage(pdu, pdu->transport_hdr->udp.type, blockID); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "send has failed"); @@ -618,11 +589,27 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData return CA_STATUS_OK; } +static CAResult_t CASendDirectEmptyResponse(const CAEndpoint_t *endpoint, uint16_t messageId) +{ + OIC_LOG(DEBUG, TAG, "Entering CASendDirectEmptyResponse"); + CAResponseInfo_t respInfo = { + .result = CA_EMPTY + }; + respInfo.info.type = CA_MSG_ACKNOWLEDGE; + respInfo.info.messageId = messageId; + respInfo.info.dataType = CA_RESPONSE_DATA; + + CAResult_t caResult = CASendResponse(endpoint, &respInfo); + + OIC_LOG(DEBUG, TAG, "Exit CASendDirectEmptyResponse"); + return caResult; +} + CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType, - uint8_t status, const CABlockDataID_t *blockID) + const CABlockDataID_t *blockID) { VERIFY_NON_NULL(pdu, TAG, "pdu"); - VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); VERIFY_NON_NULL(blockID, TAG, "blockID"); CAData_t *data = CAGetDataSetFromBlockDataList(blockID); @@ -632,34 +619,52 @@ CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType, return CA_STATUS_FAILED; } - if (CA_MSG_CONFIRM == msgType) + CAMessageType_t sentMsgType = CA_MSG_NONCONFIRM; + switch (msgType) { - OIC_LOG(DEBUG, TAG, "need new msgID"); - if (data->requestInfo) - { - data->requestInfo->info.messageId = 0; - } + case CA_MSG_CONFIRM: + sentMsgType = CA_MSG_ACKNOWLEDGE; + break; + case CA_MSG_ACKNOWLEDGE: + sentMsgType = CA_MSG_CONFIRM; + break; + default: + sentMsgType = CA_MSG_NONCONFIRM; + break; + } + uint32_t code = pdu->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) + { if (data->responseInfo) { - data->responseInfo->info.messageId = 0; + OIC_LOG(DEBUG, TAG, "set response info"); + data->responseInfo->info.messageId = pdu->transport_hdr->udp.id; + data->responseInfo->info.type = sentMsgType; + data->responseInfo->result = CA_CONTINUE; } } - else if (CA_MSG_ACKNOWLEDGE == msgType) + else { - if (data->responseInfo) + if (data->requestInfo) { - OIC_LOG(DEBUG, TAG, "set ACK message"); - data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id; - data->responseInfo->info.type = CA_MSG_ACKNOWLEDGE; - if (CA_OPTION1_NO_ACK_LAST_BLOCK == status) - { - data->responseInfo->result = CA_CHANGED; - } - else if (CA_OPTION1_NO_ACK_BLOCK == status) + // if the received response message type is CON, send empty message. + // and then, send next block request message with new messagId. + if (msgType == CA_MSG_CONFIRM) { - data->responseInfo->result = CA_CONTINUE; + CASendDirectEmptyResponse(data->remoteEndpoint, + data->requestInfo->info.messageId); + sentMsgType = CA_MSG_CONFIRM; } + + OIC_LOG(DEBUG, TAG, "need new msgID"); + data->requestInfo->info.messageId = 0; + data->requestInfo->info.type = sentMsgType; + } + else if (data->responseInfo) + { + data->responseInfo->info.messageId = pdu->transport_hdr->udp.id; + data->responseInfo->info.type = sentMsgType; } } @@ -674,11 +679,10 @@ CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType, } CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status, - CAResponseResult_t responseResult, - const CABlockDataID_t *blockID) + CAResponseResult_t responseResult, const CABlockDataID_t *blockID) { VERIFY_NON_NULL(pdu, TAG, "pdu"); - VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); VERIFY_NON_NULL(blockID, TAG, "blockID"); // create error responseInfo @@ -689,45 +693,79 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status, return CA_STATUS_FAILED; } - CAData_t *cloneData = NULL; - if (data->sentData && data->sentData->responseInfo) + if (!data->sentData) + { + OIC_LOG(ERROR, TAG, "data has no sent-data"); + return CA_STATUS_FAILED; + } + + CAData_t *cloneData = CACloneCAData(data->sentData); + if (!cloneData) { - data->sentData->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id; - data->sentData->responseInfo->info.type = CA_MSG_ACKNOWLEDGE; - data->sentData->responseInfo->result = responseResult; - 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) + { + case CA_MSG_CONFIRM: + sentMsgType = CA_MSG_ACKNOWLEDGE; + break; + case CA_MSG_ACKNOWLEDGE: + sentMsgType = CA_MSG_CONFIRM; + break; + default: + sentMsgType = CA_MSG_NONCONFIRM; + } + + if (cloneData->responseInfo) + { + cloneData->responseInfo->info.messageId = pdu->transport_hdr->udp.id; + cloneData->responseInfo->info.type = sentMsgType; + cloneData->responseInfo->result = responseResult; + } + 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, "clone has failed"); + OIC_LOG(ERROR, TAG, "out of memory"); + CADestroyDataSet(cloneData); return CA_MEMORY_ALLOC_FAILED; } - OIC_LOG(DEBUG, TAG, "set ACK message"); - } - else if (data->sentData) - { - cloneData = CACreateNewDataSet(pdu, data->sentData->remoteEndpoint); - if(!cloneData) + 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, PCF("CACreateNewDataSet failed")); + OIC_LOG(ERROR, TAG, "out of memory"); + CADestroyDataSet(cloneData); + OICFree(responseData.token); return CA_MEMORY_ALLOC_FAILED; } - cloneData->responseInfo->info.type = CA_MSG_CONFIRM; + cloneData->responseInfo->info = responseData; + cloneData->responseInfo->info.type = sentMsgType; cloneData->responseInfo->result = responseResult; - OIC_LOG(DEBUG, TAG, "set CON message"); } - else + + 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) { - OIC_LOG(ERROR, TAG, "data has no sent-data"); - return CA_MEMORY_ALLOC_FAILED; + CADestroyRequestInfoInternal(cloneData->requestInfo); + cloneData->requestInfo = NULL; } // 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 { @@ -748,8 +786,7 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status, return CA_STATUS_OK; } -CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID, - const CAData_t *receivedData) +CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID, const CAData_t *receivedData) { VERIFY_NON_NULL(blockID, TAG, "blockID"); VERIFY_NON_NULL(receivedData, TAG, "receivedData"); @@ -764,8 +801,7 @@ CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID, // update payload size_t fullPayloadLen = 0; - CAPayload_t fullPayload = CAGetPayloadFromBlockDataList(blockID, - &fullPayloadLen); + CAPayload_t fullPayload = CAGetPayloadFromBlockDataList(blockID, &fullPayloadLen); if (fullPayload) { CAResult_t res = CAUpdatePayloadToCAData(cloneData, fullPayload, fullPayloadLen); @@ -789,30 +825,10 @@ CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID, return CA_STATUS_OK; } -// TODO make pdu const after libcoap is updated to support that. -CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, - const CAData_t *receivedData, coap_block_t block, - size_t dataLen) +static CABlockData_t* CACheckTheExistOfBlockData(const CABlockDataID_t* blockDataID, + coap_pdu_t *pdu, const CAEndpoint_t *endpoint, + uint8_t blockType) { - OIC_LOG(INFO, TAG, "CASetNextBlockOption1"); - VERIFY_NON_NULL(pdu, TAG, "pdu"); - VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr"); - VERIFY_NON_NULL(endpoint, TAG, "endpoint"); - VERIFY_NON_NULL(receivedData, TAG, "receivedData"); - - OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx); - - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)pdu->hdr->coap_hdr_udp_t.token, - pdu->hdr->coap_hdr_udp_t.token_length, - endpoint->port); - if (NULL == blockDataID || blockDataID->idLength < 1) - { - OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - // Get BlockData data. If does not exist, create a new data CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); if (!data) @@ -823,91 +839,77 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (!cadata) { OIC_LOG(ERROR, TAG, "data is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; + return NULL; } - CABlockData_t *currData = CACreateNewBlockData(cadata); - if (!currData) + data = CACreateNewBlockData(cadata); + if (!data) { OIC_LOG(ERROR, TAG, "failed to create a new block data"); CADestroyDataSet(cadata); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; + return NULL; } CADestroyDataSet(cadata); } - // update BLOCK OPTION1 type - CAResult_t res = CAUpdateBlockOptionType(blockDataID, - COAP_OPTION_BLOCK1); + // update BLOCK OPTION type + CAResult_t res = CAUpdateBlockOptionType(blockDataID, blockType); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + return NULL; } - uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN; - // received type from remote device - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type) - { - uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code); - if (0 == block.m && - (CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code)) - { - int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block); - if (isBlock2) - { - OIC_LOG(INFO, TAG, "received data is combining block1 and block2"); - // initialize block number for response message - data->block1.num = 0; - } - else - { - OIC_LOG(INFO, TAG, "received data is not bulk data"); - CAReceiveLastBlock(blockDataID, receivedData); - CARemoveBlockDataFromList(blockDataID); - } + return data; +} - CADestroyBlockID(blockDataID); - return CA_STATUS_OK; - } +// TODO make pdu const after libcoap is updated to support that. +CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, + const CAData_t *receivedData, coap_block_t block, + size_t dataLen) +{ + OIC_LOG(INFO, TAG, "CASetNextBlockOption1"); + VERIFY_NON_NULL(pdu, TAG, "pdu"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); + VERIFY_NON_NULL(endpoint, TAG, "endpoint"); + VERIFY_NON_NULL(receivedData, TAG, "receivedData"); - blockWiseStatus = CA_OPTION1_ACK; - res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "update has failed"); - CADestroyBlockID(blockDataID); - return res; - } + OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx); - res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; - } + CABlockDataID_t* blockDataID = CACreateBlockDatablockId( + (CAToken_t)pdu->transport_hdr->udp.token, + pdu->transport_hdr->udp.token_length, + endpoint->port); + if (NULL == blockDataID || blockDataID->idLength < 1) + { + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; + } + + CAResult_t res = CA_STATUS_OK; + CABlockData_t *data = CACheckTheExistOfBlockData(blockDataID, pdu, endpoint, + COAP_OPTION_BLOCK1); + if (!data) + { + OIC_LOG(ERROR, TAG, "Failed to create or get block data"); + res = CA_STATUS_FAILED; + goto exit; } - else // CON or NON message + + uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN; + uint32_t code = pdu->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { + // received message type is request OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m); // check the size option - bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu, - COAP_OPTION_SIZE1, + bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu, COAP_OPTION_SIZE1, &(data->payloadLength)); - // check if received payload is exact - if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type) - { - blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData, - COAP_OPTION_BLOCK1, dataLen); - } + blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData, + COAP_OPTION_BLOCK1, dataLen); if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus) { @@ -917,9 +919,7 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, @@ -927,9 +927,7 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } // update block data @@ -937,37 +935,75 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } } // check the blcok-wise transfer status for next step if (CA_BLOCK_UNKNOWN == blockWiseStatus || CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus) { - if (0 == block.m) // Last block is received + OIC_LOG_V(DEBUG, TAG, "M bit is %d", block.m); + + blockWiseStatus = (0 == block.m) ? + CA_OPTION1_REQUEST_LAST_BLOCK : CA_OPTION1_REQUEST_BLOCK; + } + } + else + { + // received message type is response + uint32_t code = CA_RESPONSE_CODE(pdu->transport_hdr->udp.code); + if (0 == block.m && (CA_REQUEST_ENTITY_INCOMPLETE != code + && CA_REQUEST_ENTITY_TOO_LARGE != code)) + { + int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block); + if (isBlock2) { - OIC_LOG(DEBUG, TAG, "M bit is 0"); - blockWiseStatus = CA_OPTION1_NO_ACK_LAST_BLOCK; + OIC_LOG(INFO, TAG, "received data is combining block1 and block2"); + // initialize block number for response message + data->block1.num = 0; + CADestroyBlockID(blockDataID); + return CA_STATUS_OK; } else { - OIC_LOG(DEBUG, TAG, "M bit is 1"); - blockWiseStatus = CA_OPTION1_NO_ACK_BLOCK; + OIC_LOG(INFO, TAG, "received data is not bulk data"); + CAReceiveLastBlock(blockDataID, receivedData); + res = CA_STATUS_OK; + goto exit; } } + + blockWiseStatus = CA_OPTION1_RESPONSE; + res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "update has failed"); + CADestroyBlockID(blockDataID); + return res; + } + + res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "update has failed"); + goto exit; + } } res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "setting has failed"); - CARemoveBlockDataFromList(blockDataID); + goto exit; } CADestroyBlockID(blockDataID); return res; + +exit: + CARemoveBlockDataFromList(blockDataID); + CADestroyBlockID(blockDataID); + return res; } // TODO make pdu const after libcoap is updated to support that. @@ -979,13 +1015,13 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx); VERIFY_NON_NULL(pdu, TAG, "pdu"); - VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); VERIFY_NON_NULL(endpoint, TAG, "endpoint"); VERIFY_NON_NULL(receivedData, TAG, "receivedData"); CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)pdu->hdr->coap_hdr_udp_t.token, - pdu->hdr->coap_hdr_udp_t.token_length, + (CAToken_t)pdu->transport_hdr->udp.token, + pdu->transport_hdr->udp.token_length, endpoint->port); if (NULL == blockDataID || blockDataID->idLength < 1) { @@ -994,43 +1030,18 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, return CA_STATUS_FAILED; } - // Get BlockData data. If does not exist, create a new data - CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); + CAResult_t res = CA_STATUS_OK; + CABlockData_t *data = CACheckTheExistOfBlockData(blockDataID, pdu, endpoint, + COAP_OPTION_BLOCK2); if (!data) { - OIC_LOG(DEBUG, TAG, "block data doesn't exist in list. create new one"); - - CAData_t *cadata = CACreateNewDataSet(pdu, endpoint); - if (!cadata) - { - OIC_LOG(ERROR, TAG, "data is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - CABlockData_t *currData = CACreateNewBlockData(cadata); - if (!currData) - { - OIC_LOG(ERROR, TAG, "failed to create a new block data"); - CADestroyDataSet(cadata); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - CADestroyDataSet(cadata); - } - - // set Block Option Type - CAResult_t res = CAUpdateBlockOptionType(blockDataID, COAP_OPTION_BLOCK2); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + OIC_LOG(ERROR, TAG, "Failed to create or get block data"); + res = CA_STATUS_FAILED; + goto exit; } uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN; - if (0 == block.num && CA_GET == pdu->hdr->coap_hdr_udp_t.code && 0 == block.m) + if (0 == block.num && CA_GET == pdu->transport_hdr->udp.code && 0 == block.m) { OIC_LOG(INFO, TAG, "first block number"); @@ -1038,9 +1049,7 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } // first block data have to notify to Application @@ -1048,29 +1057,48 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } blockWiseStatus = CA_OPTION2_FIRST_BLOCK; } else { - // received type from remote device - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type || - (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type && - NULL != receivedData->responseInfo)) + uint32_t code = pdu->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { - OIC_LOG(DEBUG, TAG, "received ACK or NON"); + // received message type is request + OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m); + + blockWiseStatus = CA_OPTION2_REQUEST; + + res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "update has failed"); + goto exit; + } + + res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "update has failed"); + goto exit; + } + } + else + { + // received message type is response + OIC_LOG(DEBUG, TAG, "received response message with block option2"); // check the size option bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu, COAP_OPTION_SIZE2, &(data->payloadLength)); - // check if received payload is exact - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type) + uint32_t code = CA_RESPONSE_CODE(pdu->transport_hdr->udp.code); + if (CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code) { + // check if received payload is exact blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData, COAP_OPTION_BLOCK2, dataLen); } @@ -1083,9 +1111,7 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } } @@ -1094,21 +1120,17 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, OIC_LOG(DEBUG, TAG, "M bit is 0"); blockWiseStatus = CA_OPTION2_LAST_BLOCK; } + else if(CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)// If already received no need to update block option items. + { + OIC_LOG(DEBUG, TAG, "Already Received : M bit is 1"); + blockWiseStatus = CA_OPTION2_RESPONSE; + } else { - if (CA_BLOCK_UNKNOWN == blockWiseStatus || - CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus) + if (CA_BLOCK_UNKNOWN == blockWiseStatus) { OIC_LOG(DEBUG, TAG, "M bit is 1"); - - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type) - { - blockWiseStatus = CA_OPTION2_ACK; - } - else - { - blockWiseStatus = CA_OPTION2_NON; - } + blockWiseStatus = CA_OPTION2_RESPONSE; } res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, @@ -1116,58 +1138,33 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } } } - else // CON message and so on. - { - OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m); - - blockWiseStatus = CA_OPTION2_CON; - - res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; - } - - res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; - } - } } res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "setting has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } CADestroyBlockID(blockDataID); return CA_STATUS_OK; + +exit: + CARemoveBlockDataFromList(blockDataID); + CADestroyBlockID(blockDataID); + return res; } CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *pdu, @@ -1176,11 +1173,12 @@ CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *p { VERIFY_NON_NULL(currData, TAG, "currData"); VERIFY_NON_NULL(pdu, TAG, "pdu"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); VERIFY_NON_NULL(block, TAG, "block"); // update block data CAResult_t res = CA_STATUS_OK; - uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code); + uint32_t code = CA_RESPONSE_CODE(pdu->transport_hdr->udp.code); if (CA_REQUEST_ENTITY_INCOMPLETE == code || CA_REQUEST_ENTITY_TOO_LARGE == code) { @@ -1197,7 +1195,7 @@ CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *p // update block option items switch (status) { - case CA_OPTION1_ACK: + case CA_OPTION1_RESPONSE: if (currData->block1.num > block->num) { OIC_LOG(ERROR, TAG, "received incorrect block num"); @@ -1205,14 +1203,10 @@ CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *p } block->num++; break; - case CA_OPTION2_NON: - block->num++; - block->m = 0; - break; - case CA_OPTION2_CON: + case CA_OPTION2_REQUEST: block->m = 0; break; - case CA_OPTION2_ACK: + case CA_OPTION2_RESPONSE: if (currData->block2.num > block->num) { OIC_LOG(ERROR, TAG, "received incorrect block num"); @@ -1242,7 +1236,7 @@ CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *p if (CA_BLOCK_INCOMPLETE != status && CA_BLOCK_TOO_LARGE != status) { // negotiate block size - res = CANegotiateBlockSize(currData, block, pdu->hdr->coap_hdr_udp_t.type, blockType); + res = CANegotiateBlockSize(currData, block, pdu, blockType); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "negotiation has failed"); @@ -1257,8 +1251,7 @@ CAResult_t CASetMoreBitFromBlock(size_t payloadLen, coap_block_t *block) { VERIFY_NON_NULL(block, TAG, "block"); - if ((size_t)((block->num + 1) << (block->szx + BLOCK_NUMBER_IDX)) - < payloadLen) + if ((size_t) ((block->num + 1) << (block->szx + BLOCK_NUMBER_IDX)) < payloadLen) { OIC_LOG(DEBUG, TAG, "Set the M-bit(1)"); block->m = 1; @@ -1273,18 +1266,27 @@ CAResult_t CASetMoreBitFromBlock(size_t payloadLen, coap_block_t *block) } CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block, - CAMessageType_t msgType, uint16_t blockType) + const coap_pdu_t *pdu, uint16_t blockType) { OIC_LOG(DEBUG, TAG, "IN-NegotiateBlockSize"); VERIFY_NON_NULL(currData, TAG, "currData"); VERIFY_NON_NULL(block, TAG, "block"); + VERIFY_NON_NULL(pdu, TAG, "pdu"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); + + bool isReqMsg = false; + uint32_t code = pdu->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) + { + isReqMsg = true; + } // #1. check the block option type if (COAP_OPTION_BLOCK2 == blockType) { // #2. check the message type - if (CA_MSG_ACKNOWLEDGE == msgType) + if (!isReqMsg) { if (block->szx > currData->block2.szx) { @@ -1310,7 +1312,7 @@ CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block, } else if (COAP_OPTION_BLOCK1 == blockType) { - if (CA_MSG_ACKNOWLEDGE == msgType) + if (!isReqMsg) { if (block->szx < currData->block1.szx) { @@ -1371,22 +1373,20 @@ CAResult_t CAUpdateBlockData(CABlockData_t *currData, coap_block_t block, CAResult_t CAUpdateMessageId(coap_pdu_t *pdu, const CABlockDataID_t *blockID) { VERIFY_NON_NULL(pdu, TAG, "pdu"); + VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr"); VERIFY_NON_NULL(blockID, TAG, "blockID"); - // if CON message is sent, update messageId in block-wise transfer list - if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type) + // if message is sent, update messageId in block-wise transfer list + CAData_t * cadata = CAGetDataSetFromBlockDataList(blockID); + if (!cadata) { - CAData_t * cadata = CAGetDataSetFromBlockDataList(blockID); - if (!cadata) - { - OIC_LOG(ERROR, TAG, "CAData is unavailable"); - return CA_STATUS_FAILED; - } + OIC_LOG(ERROR, TAG, "CAData is unavailable"); + return CA_STATUS_FAILED; + } - if (cadata->requestInfo) - { - cadata->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id; - } + if (cadata->requestInfo) + { + cadata->requestInfo->info.messageId = pdu->transport_hdr->udp.id; } return CA_STATUS_OK; @@ -1398,11 +1398,12 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info, OIC_LOG(DEBUG, TAG, "IN-AddBlockOption"); VERIFY_NON_NULL(pdu, TAG, "pdu"); VERIFY_NON_NULL((*pdu), TAG, "(*pdu)"); - VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr"); + VERIFY_NON_NULL((*pdu)->transport_hdr, TAG, "(*pdu)->transport_hdr"); VERIFY_NON_NULL(info, TAG, "info"); VERIFY_NON_NULL(endpoint, TAG, "endpoint"); VERIFY_NON_NULL(options, TAG, "options"); + CAResult_t res = CA_STATUS_OK; size_t dataLength = 0; if (info->payload) { @@ -1410,19 +1411,9 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info, OIC_LOG_V(DEBUG, TAG, "dataLength - %zu", dataLength); } - OIC_LOG_V(DEBUG, TAG, "previous payload - %s", (*pdu)->data); - - CAResult_t res = CA_STATUS_OK; - uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->coap_hdr_udp_t.code); - if (CA_REQUEST_ENTITY_INCOMPLETE == code) - { - OIC_LOG(INFO, TAG, "don't use option"); - return res; - } - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)(*pdu)->hdr->coap_hdr_udp_t.token, - (*pdu)->hdr->coap_hdr_udp_t.token_length, + (CAToken_t)(*pdu)->transport_hdr->udp.token, + (*pdu)->transport_hdr->udp.token_length, endpoint->port); if (NULL == blockDataID || blockDataID->idLength < 1) { @@ -1431,6 +1422,14 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info, goto exit; } + uint32_t repCode = CA_RESPONSE_CODE((*pdu)->transport_hdr->udp.code); + if (CA_REQUEST_ENTITY_INCOMPLETE == repCode) + { + OIC_LOG(INFO, TAG, "don't use option"); + res = CA_STATUS_OK; + goto exit; + } + uint8_t blockType = CAGetBlockOptionType(blockDataID); if (COAP_OPTION_BLOCK2 == blockType) { @@ -1461,42 +1460,52 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info, { 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), coap_udp); + + 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; } else { OIC_LOG(INFO, TAG, "not Blockwise Transfer"); - goto exit; } } - // if received message type is RESET from remote device, - // we have to use the updated message id to find token. - res = CAUpdateMessageId(*pdu, blockDataID); - if (CA_STATUS_OK != res) + uint32_t code = (*pdu)->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { - OIC_LOG(ERROR, TAG, "fail to update CON message id "); - goto exit; + // if received message type is RESET from remote device, + // we have to use the updated message id of request message to find token. + CABlockData_t *blockData = CAGetBlockDataFromBlockDataList(blockDataID); + if (blockData) + { + res = CAUpdateMessageId(*pdu, blockDataID); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "fail to update message id"); + goto exit; + } + } } + CAResetBlockDataTTL(blockDataID); exit: - if (CA_ADAPTER_IP == endpoint->adapter && 0 == endpoint->port) - { - CARemoveBlockDataFromList(blockDataID); - } CADestroyBlockID(blockDataID); OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption"); return res; @@ -1508,7 +1517,7 @@ CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t data OIC_LOG(DEBUG, TAG, "IN-AddBlockOption2"); VERIFY_NON_NULL(pdu, TAG, "pdu"); VERIFY_NON_NULL((*pdu), TAG, "(*pdu)"); - VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr"); + VERIFY_NON_NULL((*pdu)->transport_hdr, TAG, "(*pdu)->transport_hdr"); VERIFY_NON_NULL(info, TAG, "info"); VERIFY_NON_NULL(blockID, TAG, "blockID"); VERIFY_NON_NULL(options, TAG, "options"); @@ -1522,33 +1531,28 @@ CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t data return CA_STATUS_FAILED; } - CALogBlockInfo(block2); - - if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type || - (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type && - CA_GET != (*pdu)->hdr->coap_hdr_udp_t.code)) + CAResult_t res = CA_STATUS_OK; + uint32_t code = (*pdu)->transport_hdr->udp.code; + if (CA_GET != code && CA_POST != code && CA_PUT != code && CA_DELETE != code) { CASetMoreBitFromBlock(dataLength, block2); - CALogBlockInfo(block2); // if block number is 0, add size2 option if (0 == block2->num) { - CAResult_t res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength, options); + res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } } - CAResult_t res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options); + res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } if (block1->num) @@ -1558,8 +1562,7 @@ CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t data if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } // initialize block number block1->num = 0; @@ -1569,8 +1572,7 @@ CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t data if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload, @@ -1580,51 +1582,38 @@ CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t data return CA_STATUS_FAILED; } + CALogBlockInfo(block2); + if (!block2->m) - { - // if sent message is last response block message, remove data - CARemoveBlockDataFromList(blockID); - } - else - { - if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type) - { - OIC_LOG(DEBUG, TAG, "NON, send next block.."); - // update block data - block2->num++; - CAResult_t res = CAProcessNextStep(*pdu, NULL, - CA_SENT_PREVIOUS_NON_MSG, - blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "failed to process next step"); - CARemoveBlockDataFromList(blockID); - return res; - } - } + { + // if sent message is last response block message, remove data + CARemoveBlockDataFromList(blockID); } } else { - OIC_LOG(DEBUG, TAG, "option2, not ACK msg"); - CAResult_t res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options); + OIC_LOG(DEBUG, TAG, "option2, not response msg"); + res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } res = CAAddOptionToPDU(*pdu, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } + CALogBlockInfo(block2); } return CA_STATUS_OK; + +exit: + CARemoveBlockDataFromList(blockID); + return res; } CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength, @@ -1633,7 +1622,7 @@ CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t data OIC_LOG(DEBUG, TAG, "IN-AddBlockOption1"); VERIFY_NON_NULL(pdu, TAG, "pdu"); VERIFY_NON_NULL((*pdu), TAG, "(*pdu)"); - VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr"); + VERIFY_NON_NULL((*pdu)->transport_hdr, TAG, "(*pdu)->transport_hdr"); VERIFY_NON_NULL(info, TAG, "info"); VERIFY_NON_NULL(blockID, TAG, "blockID"); VERIFY_NON_NULL(options, TAG, "options"); @@ -1646,115 +1635,96 @@ CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t data return CA_STATUS_FAILED; } - CALogBlockInfo(block1); - - if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type) + CAResult_t res = CA_STATUS_OK; + uint32_t code = (*pdu)->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { - OIC_LOG(DEBUG, TAG, "option1 and ACK msg.."); - CAResult_t res = CAAddBlockOptionImpl(block1, COAP_OPTION_BLOCK1, options); + CASetMoreBitFromBlock(dataLength, block1); + + // if block number is 0, add size1 option + if (0 == block1->num) + { + res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE1, dataLength, options); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "add has failed"); + goto exit; + } + } + + // add block option to option list. + res = CAAddBlockOptionImpl(block1, COAP_OPTION_BLOCK1, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } + // add option list to pdu. res = CAAddOptionToPDU(*pdu, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } - if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload)) + // add the payload data as the block size. + if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload, block1->num, + block1->szx)) { - OIC_LOG(ERROR, TAG, "failed to add payload"); + OIC_LOG(ERROR, TAG, "Data length is smaller than the start index"); return CA_STATUS_FAILED; } - - // reset block-list after write block - if (0 == block1->m) - { - // remove data from list - CAResult_t res = CARemoveBlockDataFromList(blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "remove has failed"); - return res; - } - } } else { - CASetMoreBitFromBlock(dataLength, block1); - - CAResult_t res = CA_STATUS_OK; - // if block number is 0, add size1 option - if (0 == block1->num) - { - res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE1, dataLength, options); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; - } - } + OIC_LOG(DEBUG, TAG, "received response message with block option1"); + // add block option to option list. res = CAAddBlockOptionImpl(block1, COAP_OPTION_BLOCK1, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } + // add option list to pdu. res = CAAddOptionToPDU(*pdu, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; + goto exit; } - CALogBlockInfo(block1); - - if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload, - block1->num, block1->szx)) + // add the payload data as the block size. + if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload)) { - OIC_LOG(ERROR, TAG, "Data length is smaller than the start index"); + OIC_LOG(ERROR, TAG, "failed to add payload"); return CA_STATUS_FAILED; } - // check the message type and if message type is NON, next block message will be sent - if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type) + // if it is last block message, remove block data from list. + if (0 == block1->m) { - if (block1->m) - { - OIC_LOG(DEBUG, TAG, "NON, send next block.."); - // update block data - block1->num++; - CAResult_t res = CAProcessNextStep(*pdu, NULL, - CA_SENT_PREVIOUS_NON_MSG, - blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "failed to process next step"); - CARemoveBlockDataFromList(blockID); - return res; - } - } - else + // remove data from list + res = CARemoveBlockDataFromList(blockID); + if (CA_STATUS_OK != res) { - CARemoveBlockDataFromList(blockID); + OIC_LOG(ERROR, TAG, "remove has failed"); + return res; } } } + CALogBlockInfo(block1); + OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption1"); return CA_STATUS_OK; + +exit: + CARemoveBlockDataFromList(blockID); + return res; } CAResult_t CAAddBlockOptionImpl(coap_block_t *block, uint8_t blockType, @@ -1795,7 +1765,7 @@ CAResult_t CAAddOptionToPDU(coap_pdu_t *pdu, coap_list_t **options) OIC_LOG_V(DEBUG, TAG, "[%d] pdu length", pdu->length); int ret = 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), coap_udp); + COAP_OPTION_DATA(*(coap_option *) opt->data)); if (!ret) { return CA_STATUS_FAILED; @@ -1889,8 +1859,7 @@ uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlo if (COAP_OPTION_BLOCK1 == blockType) { size_t prePayloadLen = currData->receivedPayloadLen; - if (prePayloadLen != (size_t)BLOCK_SIZE(receivedBlock->szx) - * receivedBlock->num) + if (prePayloadLen != (size_t) BLOCK_SIZE(receivedBlock->szx) * receivedBlock->num) { if (receivedBlock->num > currData->block1.num + 1) { @@ -1913,14 +1882,17 @@ uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlo OIC_LOG(ERROR, TAG, "it didn't order"); return CA_BLOCK_INCOMPLETE; } - return CA_BLOCK_RECEIVED_ALREADY; + else + { + OIC_LOG(ERROR, TAG, "already received this block"); + return CA_BLOCK_RECEIVED_ALREADY; + } } } // #3. check if error check logic is required size_t optionLen = dataLen - blockPayloadLen; - if (receivedBlock->m && blockPayloadLen != - (size_t)BLOCK_SIZE(receivedBlock->szx)) + if (receivedBlock->m && blockPayloadLen != (size_t) BLOCK_SIZE(receivedBlock->szx)) { // 413 Error handling of too large entity if (COAP_MAX_PDU_SIZE < BLOCK_SIZE(receivedBlock->szx) + optionLen) @@ -1935,14 +1907,8 @@ uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlo if (COAP_MAX_PDU_SIZE >= BLOCK_SIZE(size) + optionLen) { OIC_LOG_V(ERROR, TAG, "replace sze with %d", size); - if (COAP_OPTION_BLOCK2 == blockType) - { - currData->block2.szx = size; - } - else - { - currData->block1.szx = size; - } + currData->block2.szx = size; + currData->block1.szx = size; break; } } @@ -2059,36 +2025,93 @@ CAResult_t CAUpdatePayloadData(CABlockData_t *currData, const CAData_t *received CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint) { VERIFY_NON_NULL_RET(pdu, TAG, "pdu", NULL); - VERIFY_NON_NULL_RET(pdu->hdr, TAG, "pdu->hdr", NULL); + VERIFY_NON_NULL_RET(pdu->transport_hdr, TAG, "pdu->transport_hdr", NULL); VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL); - CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length }; - responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength); - if (!responseData.token) + CARequestInfo_t* requestInfo = NULL; + CAResponseInfo_t* responseInfo = NULL; + + uint32_t code = pdu->transport_hdr->udp.code; + if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { - OIC_LOG(ERROR, TAG, "out of memory"); - return NULL; - } - memcpy(responseData.token, pdu->hdr->coap_hdr_udp_t.token, responseData.tokenLength); + 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 NULL; + } + memcpy(responseData.token, pdu->transport_hdr->udp.token, responseData.tokenLength); - CAResponseInfo_t* responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t)); - if (!responseInfo) + responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t)); + if (!responseInfo) + { + OIC_LOG(ERROR, TAG, "out of memory"); + OICFree(responseData.token); + return NULL; + } + responseInfo->info = responseData; + } + else { - OIC_LOG(ERROR, TAG, "out of memory"); - OICFree(responseData.token); - return NULL; + CAInfo_t requestData = { .tokenLength = pdu->transport_hdr->udp.token_length }; + requestData.token = (CAToken_t) OICMalloc(requestData.tokenLength); + if (!requestData.token) + { + OIC_LOG(ERROR, TAG, "out of memory"); + return NULL; + } + memcpy(requestData.token, pdu->transport_hdr->udp.token, requestData.tokenLength); + + requestInfo = (CARequestInfo_t*) OICCalloc(1, sizeof(CARequestInfo_t)); + if (!requestInfo) + { + OIC_LOG(ERROR, TAG, "out of memory"); + OICFree(requestData.token); + return NULL; + } + requestInfo->info = requestData; + + // get resource uri information from received response message + // to send next request message to remote device + CAResponseInfo_t* resInfo = (CAResponseInfo_t*)OICCalloc(1, sizeof(*resInfo)); + if (!resInfo) + { + 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.resourceUri = OICStrdup(resInfo->info.resourceUri); + + // after copying the resource uri, destroy response info. + CADestroyResponseInfoInternal(resInfo); } - responseInfo->info = responseData; CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t)); if (!data) { OIC_LOG(ERROR, TAG, "out of memory"); - 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; } - data->requestInfo = NULL; + data->requestInfo = requestInfo; data->responseInfo = responseInfo; data->remoteEndpoint = CACloneEndpoint(endpoint); data->type = SEND_TYPE_UNICAST; @@ -2196,7 +2219,7 @@ CAPayload_t CAGetPayloadInfo(const CAData_t *data, size_t *payloadLen) return data->requestInfo->info.payload; } } - else + else if (data->responseInfo) { if (data->responseInfo->info.payload) { @@ -2236,13 +2259,12 @@ CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType, return CA_STATUS_OK; } -CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID, - uint8_t blockType) +CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID, uint8_t blockType) { 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++) @@ -2251,12 +2273,12 @@ CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID, 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; @@ -2267,7 +2289,7 @@ uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID) 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++) @@ -2275,12 +2297,12 @@ uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID) 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; @@ -2290,7 +2312,7 @@ CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID) { 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++) @@ -2298,11 +2320,36 @@ CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID) 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; } @@ -2315,7 +2362,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t 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++) @@ -2328,7 +2375,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t if (NULL != currData->sentData && NULL != currData->sentData->requestInfo) { - if (pdu->hdr->coap_hdr_udp_t.id == currData->sentData->requestInfo->info.messageId && + if (pdu->transport_hdr->udp.id == currData->sentData->requestInfo->info.messageId && endpoint->adapter == currData->sentData->remoteEndpoint->adapter) { if (NULL != currData->sentData->requestInfo->info.token) @@ -2339,13 +2386,13 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t 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; } @@ -2353,7 +2400,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t } } - ca_mutex_unlock(g_context.blockDataListMutex); + oc_mutex_unlock(g_context.blockDataListMutex); OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList"); return CA_STATUS_FAILED; @@ -2364,94 +2411,29 @@ CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t ** VERIFY_NON_NULL(sendData, TAG, "sendData"); VERIFY_NON_NULL(blockData, TAG, "blockData"); - CABlockDataID_t* blockDataID; - if(sendData->requestInfo) - { - blockDataID = CACreateBlockDatablockId( - (CAToken_t)sendData->requestInfo->info.token, - sendData->requestInfo->info.tokenLength, - sendData->remoteEndpoint->port); - } - else if(sendData->responseInfo) - { - blockDataID = CACreateBlockDatablockId( - (CAToken_t)sendData->responseInfo->info.token, - sendData->responseInfo->info.tokenLength, - sendData->remoteEndpoint->port); - } - else - { - OIC_LOG(ERROR, TAG, "sendData doesn't have requestInfo or responseInfo"); - return CA_STATUS_FAILED; - } - - if (NULL == blockDataID || blockDataID->idLength < 1) - { - OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - ca_mutex_lock(g_context.blockDataListMutex); - - size_t len = u_arraylist_length(g_context.dataList); - for (size_t i = 0; i < len; i++) + if (sendData->responseInfo) { - CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i); - - if (!currData) + CABlockDataID_t* blockDataID = CACreateBlockDatablockId( + (CAToken_t)sendData->responseInfo->info.token, + sendData->responseInfo->info.tokenLength, + sendData->remoteEndpoint->port); + if (NULL == blockDataID || blockDataID->idLength < 1) { - continue; + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; } - if (sendData->requestInfo) // sendData is requestMessage - { - OIC_LOG(DEBUG, TAG, "Send request"); - if (NULL != currData->blockDataId - && NULL != currData->blockDataId->id - && currData->blockDataId->idLength > 0 - && NULL != sendData->requestInfo->info.token) - { - if (CABlockidMatches(currData, blockDataID)) - { - OIC_LOG(ERROR, TAG, "already sent"); - continue; - } - } - } - else if (sendData->responseInfo) // sendData is responseMessage + CABlockData_t *updatedData = CAUpdateDataSetFromBlockDataList(blockDataID, sendData); + if (updatedData) { - OIC_LOG(DEBUG, TAG, "Send response"); - if (NULL != currData->blockDataId - && NULL != currData->blockDataId->id - && currData->blockDataId->idLength > 0 - && NULL != sendData->responseInfo->info.token) - { - if (CABlockidMatches(currData, blockDataID)) - { - // set sendData - if (NULL != currData->sentData) - { - OIC_LOG(DEBUG, TAG, "init block number"); - CADestroyDataSet(currData->sentData); - } - currData->sentData = CACloneCAData(sendData); - *blockData = currData; - ca_mutex_unlock(g_context.blockDataListMutex); - CADestroyBlockID(blockDataID); - return CA_STATUS_OK; - } - } - } - else - { - OIC_LOG(ERROR, TAG, "no CAInfo data"); - continue; + OIC_LOG(DEBUG, TAG, "Send response about the received block request."); + *blockData = updatedData; + CADestroyBlockID(blockDataID); + return CA_STATUS_OK; } + CADestroyBlockID(blockDataID); } - ca_mutex_unlock(g_context.blockDataListMutex); - - CADestroyBlockID(blockDataID); return CA_STATUS_FAILED; } @@ -2460,7 +2442,7 @@ CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID) { 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++) @@ -2468,22 +2450,21 @@ CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID) 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; } -coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, - uint16_t blockType) +coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, uint16_t blockType) { 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++) @@ -2491,19 +2472,19 @@ coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, 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) { return &currData->block2; } - else + else if (COAP_OPTION_BLOCK1 == blockType) { return &currData->block1; } } } - ca_mutex_unlock(g_context.blockDataListMutex); + oc_mutex_unlock(g_context.blockDataListMutex); OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption"); return NULL; @@ -2516,7 +2497,7 @@ CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID, 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++) @@ -2524,13 +2505,13 @@ CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID, 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; @@ -2552,7 +2533,7 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) data->block1.szx = CA_DEFAULT_BLOCK_SIZE; data->block2.szx = CA_DEFAULT_BLOCK_SIZE; data->sentData = CACloneCAData(sendData); - if(!data->sentData) + if (!data->sentData) { OIC_LOG(ERROR, TAG, PCF("memory alloc has failed")); OICFree(data); @@ -2567,7 +2548,7 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) tokenLength = data->sentData->requestInfo->info.tokenLength; token = data->sentData->requestInfo->info.token; } - else if(data->sentData->responseInfo) + else if (data->sentData->responseInfo) { tokenLength = data->sentData->responseInfo->info.tokenLength; token = data->sentData->responseInfo->info.token; @@ -2581,9 +2562,8 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) return NULL; } - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - token, tokenLength, - data->sentData->remoteEndpoint->port); + CABlockDataID_t* blockDataID = CACreateBlockDatablockId(token, tokenLength, + data->sentData->remoteEndpoint->port); if (NULL == blockDataID || blockDataID->idLength < 1) { OIC_LOG(ERROR, TAG, "blockId is null"); @@ -2593,8 +2573,10 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) 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) @@ -2603,10 +2585,10 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) 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; @@ -2614,10 +2596,10 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) 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++) @@ -2629,23 +2611,51 @@ CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID) 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(removedData->sentData); + CADestroyBlockID(removedData->blockDataId); + OICFree(removedData->payload); + OICFree(removedData); + oc_mutex_unlock(g_context.blockDataListMutex); + return CA_STATUS_OK; + } + } + oc_mutex_unlock(g_context.blockDataListMutex); + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + return CA_STATUS_OK; +} + +CAResult_t CARemoveAllBlockDataFromList() +{ + OIC_LOG(DEBUG, TAG, "CARemoveAllBlockDataFromList"); + + oc_mutex_lock(g_context.blockDataListMutex); + + size_t len = u_arraylist_length(g_context.dataList); + for (size_t i = len; i > 0; i--) + { + CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i - 1); + if (removedData) + { // destroy memory - if (currData->sentData) + if (removedData->sentData) { - CADestroyDataSet(currData->sentData); + CADestroyDataSet(removedData->sentData); } - CADestroyBlockID(currData->blockDataId); - OICFree(currData->payload); - OICFree(currData); - ca_mutex_unlock(g_context.blockDataListMutex); - return CA_STATUS_OK; + CADestroyBlockID(removedData->blockDataId); + OICFree(removedData->payload); + OICFree(removedData); } } - ca_mutex_unlock(g_context.blockDataListMutex); + oc_mutex_unlock(g_context.blockDataListMutex); return CA_STATUS_OK; } @@ -2654,18 +2664,30 @@ void CADestroyDataSet(CAData_t* data) { VERIFY_NON_NULL_VOID(data, TAG, "data"); - CAFreeEndpoint(data->remoteEndpoint); - CADestroyRequestInfoInternal(data->requestInfo); - CADestroyResponseInfoInternal(data->responseInfo); + 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); } CABlockDataID_t* CACreateBlockDatablockId(const CAToken_t token, uint8_t tokenLength, uint16_t portNumber) { - char port[PORT_LENGTH] = {0,}; - port[0] = (char)((portNumber>>8) & 0xFF); - port[1] = (char)(portNumber & 0xFF); + char port[PORT_LENGTH] = { 0, }; + port[0] = (char) ((portNumber >> 8) & 0xFF); + port[1] = (char) (portNumber & 0xFF); CABlockDataID_t* blockDataID = (CABlockDataID_t *) OICMalloc(sizeof(CABlockDataID_t)); if (!blockDataID) @@ -2731,3 +2753,78 @@ void CALogBlockInfo(coap_block_t *block) OIC_LOG_V(DEBUG, TAG, "block option-szx : %d", block->szx); } + +CAResult_t CARemoveBlockDataFromListWithSeed(const CAToken_t token, uint8_t tokenLength, + uint16_t portNumber) +{ + CABlockDataID_t* blockDataID = CACreateBlockDatablockId(token, tokenLength, portNumber); + if (NULL == blockDataID || blockDataID->idLength < 1) + { + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; + } + + CAResult_t res = CARemoveBlockDataFromList(blockDataID); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CARemoveBlockDataFromList failed"); + } + + CADestroyBlockID(blockDataID); + return res; +} + +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++) + { + CABlockData_t *blockData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i); + if (CABlockidMatches(blockData, blockID)) + { + 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__); +} + +void CACheckAndDeleteTimedOutBlockData() +{ + OIC_LOG_V(DEBUG, TAG, "In %s", __func__); + + 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__); +}