X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fcablockwisetransfer.c;h=dd17fe9937dd9826558d05b08b02e14f7cf99784;hb=7d32081891bb0cb5d17184c5eca12262d119da8c;hp=edbcdb1cdafc4db2f224b13d0dc95fb84a6e7dca;hpb=7aa6219a4656ec0eaeaa43626f6872be5792b2ee;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/cablockwisetransfer.c b/resource/csdk/connectivity/src/cablockwisetransfer.c index edbcdb1..dd17fe9 100644 --- a/resource/csdk/connectivity/src/cablockwisetransfer.c +++ b/resource/csdk/connectivity/src/cablockwisetransfer.c @@ -40,10 +40,11 @@ #include "caremotehandler.h" #include "cablockwisetransfer.h" #include "oic_malloc.h" +#include "oic_string.h" #include "camutex.h" #include "logger.h" -#define TAG "CA_BWT" +#define TAG "OIC_CA_BWT" #define BLOCKWISE_OPTION_BUFFER (sizeof(unsigned int)) #define BLOCK_NUMBER_IDX 4 @@ -53,7 +54,9 @@ #define BLOCK_SIZE(arg) (1 << ((arg) + 4)) // context for block-wise transfer -static CABlockWiseContext_t g_context = { 0 }; +static CABlockWiseContext_t g_context = { .sendThreadFunc = NULL, + .receivedThreadFunc = NULL, + .dataList = NULL }; static bool CACheckPayloadLength(const CAData_t *sendData) { @@ -62,7 +65,7 @@ static bool CACheckPayloadLength(const CAData_t *sendData) // check if message has to be transfered to a block size_t maxBlockSize = BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE); - OIC_LOG_V(DEBUG, TAG, "payloadLen=%d, maxBlockSize=%d", payloadLen, maxBlockSize); + OIC_LOG_V(DEBUG, TAG, "payloadLen=%zu, maxBlockSize=%zu", payloadLen, maxBlockSize); if (payloadLen <= maxBlockSize) { @@ -75,7 +78,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) @@ -96,6 +99,8 @@ CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc, CAResult_t res = CAInitBlockWiseMutexVariables(); if (CA_STATUS_OK != res) { + u_arraylist_free(&g_context.dataList); + g_context.dataList = NULL; OIC_LOG(ERROR, TAG, "init has failed"); } @@ -104,10 +109,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); } @@ -118,8 +124,6 @@ CAResult_t CATerminateBlockWiseTransfer() CAResult_t CAInitBlockWiseMutexVariables() { - OIC_LOG(DEBUG, TAG, "IN"); - if (!g_context.blockDataListMutex) { g_context.blockDataListMutex = ca_mutex_new(); @@ -146,8 +150,6 @@ CAResult_t CAInitBlockWiseMutexVariables() void CATerminateBlockWiseMutexVariables() { - OIC_LOG(DEBUG, TAG, "IN"); - if (g_context.blockDataListMutex) { ca_mutex_free(g_context.blockDataListMutex); @@ -166,13 +168,36 @@ CAResult_t CASendBlockWiseData(const CAData_t *sendData) VERIFY_NON_NULL(sendData, TAG, "sendData"); // check if message type is CA_MSG_RESET - if (sendData->responseInfo) + if (sendData->requestInfo) + { + if (CA_MSG_RESET == sendData->requestInfo->info.type) + { + 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) { if (CA_MSG_RESET == sendData->responseInfo->info.type) { 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 @@ -215,7 +240,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"); @@ -282,41 +307,62 @@ 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->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( receivedData->responseInfo->info.token, receivedData->responseInfo->info.tokenLength, endpoint->port); - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) + if (NULL == blockDataID || blockDataID->idLength < 1) { + // if retransmission is timeout, callback msg will be send without token. + if (NULL == blockDataID && !receivedData->responseInfo->info.token) + { + OIC_LOG(INFO, TAG, "retransmission was stopped"); + return CA_REQUEST_TIMEOUT; + } + 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); CADestroyBlockID(blockDataID); return CA_NOT_SUPPORTED; } // 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); @@ -342,63 +388,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->code); - if (CA_REQUEST_ENTITY_INCOMPLETE == 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) { - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)pdu->hdr->token, - pdu->hdr->token_length, - endpoint->port); + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; + } - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) + uint32_t code = CA_RESPONSE_CODE(pdu->transport_hdr->udp.code); + if (CA_REQUEST_ENTITY_INCOMPLETE == code) + { + 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"); @@ -406,6 +442,7 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, return res; } } + CADestroyBlockID(blockDataID); } else { @@ -416,24 +453,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->token, - pdu->hdr->token_length, - endpoint->port); - if(NULL == blockDataID || NULL == blockDataID->id || 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; } @@ -459,7 +484,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) @@ -468,30 +493,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->id; - } - if (data->responseInfo) { - data->responseInfo->info.messageId = pdu->hdr->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"); @@ -517,7 +538,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) @@ -525,52 +546,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->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->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->type || CA_MSG_ACKNOWLEDGE == pdu->hdr->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->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) { @@ -578,11 +569,9 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData return res; } } - else if (CA_MSG_CONFIRM == pdu->hdr->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"); @@ -596,11 +585,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); @@ -610,34 +615,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->id; - data->responseInfo->info.type = CA_MSG_ACKNOWLEDGE; - if (CA_OPTION1_NO_ACK_LAST_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_CHANGED; - } - else if (CA_OPTION1_NO_ACK_BLOCK == status) - { - 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; } } @@ -652,11 +675,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 @@ -667,32 +689,59 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status, return CA_STATUS_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; + } + CAData_t *cloneData = NULL; - if (data->sentData && data->sentData->responseInfo) + if (data->sentData) { - data->sentData->responseInfo->info.messageId = pdu->hdr->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; } - OIC_LOG(DEBUG, TAG, "set ACK message"); - } - else if (data->sentData) - { - cloneData = CACreateNewDataSet(pdu, data->sentData->remoteEndpoint); - if(!cloneData) + + if (cloneData->responseInfo) { - OIC_LOG(ERROR, TAG, PCF("CACreateNewDataSet failed")); - return CA_MEMORY_ALLOC_FAILED; + 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, "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.type = CA_MSG_CONFIRM; - cloneData->responseInfo->result = responseResult; - OIC_LOG(DEBUG, TAG, "set CON message"); + 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 { @@ -700,6 +749,13 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status, return CA_MEMORY_ALLOC_FAILED; } + // if there is a requestInfo, remove it to send response message + if (cloneData->requestInfo) + { + CADestroyRequestInfoInternal(cloneData->requestInfo); + cloneData->requestInfo = NULL; + } + // add data to send thread if (g_context.sendThreadFunc) { @@ -726,8 +782,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"); @@ -742,8 +797,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); @@ -767,6 +821,44 @@ CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID, return CA_STATUS_OK; } +static CABlockData_t* CACheckTheExistOfBlockData(const CABlockDataID_t* blockDataID, + coap_pdu_t *pdu, const CAEndpoint_t *endpoint, + uint8_t blockType) +{ + // Get BlockData data. If does not exist, create a new data + CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); + 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"); + return NULL; + } + + data = CACreateNewBlockData(cadata); + if (!data) + { + OIC_LOG(ERROR, TAG, "failed to create a new block data"); + CADestroyDataSet(cadata); + return NULL; + } + CADestroyDataSet(cadata); + } + + // update BLOCK OPTION type + CAResult_t res = CAUpdateBlockOptionType(blockDataID, blockType); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "update has failed"); + return NULL; + } + + return data; +} + // 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, @@ -774,115 +866,46 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, { OIC_LOG(INFO, TAG, "CASetNextBlockOption1"); 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"); 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->token, - pdu->hdr->token_length, + (CAToken_t)pdu->transport_hdr->udp.token, + pdu->transport_hdr->udp.token_length, endpoint->port); - - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) + if (NULL == blockDataID || blockDataID->idLength < 1) { OIC_LOG(ERROR, TAG, "blockId is null"); CADestroyBlockID(blockDataID); return CA_STATUS_FAILED; } - // BlockData data is created if it not existed - if (!CAIsBlockDataInList(blockDataID)) - { - OIC_LOG(DEBUG, TAG, "no message in list"); - - CAData_t *data = CACreateNewDataSet(pdu, endpoint); - if (!data) - { - OIC_LOG(ERROR, TAG, "data is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - CABlockData_t *currData = CACreateNewBlockData(data); - if (!currData) - { - OIC_LOG(ERROR, TAG, "currData is null"); - CADestroyDataSet(data); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - CADestroyDataSet(data); - } - - // update BLOCK OPTION1 type - CAResult_t res = CAUpdateBlockOptionType(blockDataID, - COAP_OPTION_BLOCK1); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; - } - - CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID); + CAResult_t res = CA_STATUS_OK; + CABlockData_t *data = CACheckTheExistOfBlockData(blockDataID, pdu, endpoint, + COAP_OPTION_BLOCK1); if (!data) { - OIC_LOG(ERROR, TAG, "getting has failed"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; + OIC_LOG(ERROR, TAG, "Failed to create or get block data"); + res = CA_STATUS_FAILED; + goto exit; } uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN; - // received type from remote device - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type) - { - uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code); - if (0 == block.m && - (CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code)) - { - OIC_LOG(INFO, TAG, "Data has sent"); - // initialize block number for response message - data->block1.num = 0; - CADestroyBlockID(blockDataID); - return CA_STATUS_OK; - } - - 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; - } - - 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; - } - } - else // CON or NON message + 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->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) { @@ -892,18 +915,15 @@ 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, blockWiseStatus); + res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, + blockWiseStatus); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "update has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return res; + goto exit; } // update block data @@ -911,37 +931,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. @@ -953,68 +1011,33 @@ 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->token, - pdu->hdr->token_length, + (CAToken_t)pdu->transport_hdr->udp.token, + pdu->transport_hdr->udp.token_length, endpoint->port); - - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) + if (NULL == blockDataID || blockDataID->idLength < 1) { OIC_LOG(ERROR, TAG, "blockId is null"); CADestroyBlockID(blockDataID); return CA_STATUS_FAILED; } - // BlockData data is created if it not existed - if (!CAIsBlockDataInList(blockDataID)) - { - OIC_LOG(DEBUG, TAG, "no msg in list."); - - CAData_t *data = CACreateNewDataSet(pdu, endpoint); - if (!data) - { - OIC_LOG(ERROR, TAG, "data is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - CABlockData_t *currData = CACreateNewBlockData(data); - if (!currData) - { - OIC_LOG(ERROR, TAG, "data is null"); - CADestroyDataSet(data); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - CADestroyDataSet(data); - } - - // 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; - } - - 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(ERROR, TAG, "getting has failed"); - CARemoveBlockDataFromList(blockDataID); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; + 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->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"); @@ -1022,9 +1045,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 @@ -1032,28 +1053,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->type || - (CA_MSG_NONCONFIRM == pdu->hdr->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) + { + // 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 { - OIC_LOG(DEBUG, TAG, "received ACK or NON"); + // 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->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); } @@ -1066,9 +1107,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; } } @@ -1083,15 +1122,7 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint, CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus) { OIC_LOG(DEBUG, TAG, "M bit is 1"); - - if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type) - { - blockWiseStatus = CA_OPTION2_ACK; - } - else - { - blockWiseStatus = CA_OPTION2_NON; - } + blockWiseStatus = CA_OPTION2_RESPONSE; } res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, @@ -1099,58 +1130,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, @@ -1163,7 +1169,7 @@ CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *p // update block data CAResult_t res = CA_STATUS_OK; - uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code); + uint32_t code = CA_RESPONSE_CODE(pdu->transport_hdr->udp.code); if (CA_REQUEST_ENTITY_INCOMPLETE == code || CA_REQUEST_ENTITY_TOO_LARGE == code) { @@ -1180,7 +1186,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"); @@ -1188,14 +1194,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"); @@ -1225,7 +1227,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->type, blockType); + res = CANegotiateBlockSize(currData, block, pdu, blockType); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "negotiation has failed"); @@ -1236,12 +1238,11 @@ CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *p return res; } -CAResult_t CAGetMoreBitFromBlock(size_t payloadLen, coap_block_t *block) +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; @@ -1256,18 +1257,27 @@ CAResult_t CAGetMoreBitFromBlock(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) { @@ -1293,7 +1303,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) { @@ -1354,252 +1364,254 @@ 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->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->id; - } + if (cadata->requestInfo) + { + cadata->requestInfo->info.messageId = pdu->transport_hdr->udp.id; } return CA_STATUS_OK; } -CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t info, - const CAEndpoint_t *endpoint) +CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info, + const CAEndpoint_t *endpoint, coap_list_t **options) { 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) + if (info->payload) { - dataLength = info.payloadSize; - OIC_LOG_V(DEBUG, TAG, "dataLength - %d", dataLength); - } - - OIC_LOG_V(DEBUG, TAG, "previous payload - %s", (*pdu)->data); - - uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->code); - if (CA_REQUEST_ENTITY_INCOMPLETE == code) - { - OIC_LOG(INFO, TAG, "don't use option"); - return CA_STATUS_OK; + dataLength = info->payloadSize; + OIC_LOG_V(DEBUG, TAG, "dataLength - %zu", dataLength); } CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)(*pdu)->hdr->token, - (*pdu)->hdr->token_length, + (CAToken_t)(*pdu)->transport_hdr->udp.token, + (*pdu)->transport_hdr->udp.token_length, endpoint->port); - - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) + if (NULL == blockDataID || blockDataID->idLength < 1) { OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; + res = CA_STATUS_FAILED; + 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) { - CAResult_t res = CAAddBlockOption2(pdu, info, dataLength, - blockDataID); + res = CAAddBlockOption2(pdu, info, dataLength, blockDataID, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CADestroyBlockID(blockDataID); - return res; + goto exit; } } else if (COAP_OPTION_BLOCK1 == blockType) { - CAResult_t res = CAAddBlockOption1(pdu, info, dataLength, - blockDataID); + res = CAAddBlockOption1(pdu, info, dataLength, blockDataID, options); if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "add has failed"); - CADestroyBlockID(blockDataID); - return res; + goto exit; } } else { OIC_LOG(DEBUG, TAG, "no BLOCK option"); + + // in case it is not large data, add option list to pdu. + if (*options) + { + for (coap_list_t *opt = *options; opt; opt = opt->next) + { + 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)); + } + } + + 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)) + if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload)) { OIC_LOG(INFO, TAG, "it have to use block"); + res = CA_STATUS_FAILED; + goto exit; } else { OIC_LOG(INFO, TAG, "not Blockwise Transfer"); - CADestroyBlockID(blockDataID); - return CA_STATUS_OK; } } - CAResult_t 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 "); - CADestroyBlockID(blockDataID); - return res; + // 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; + } + } } +exit: CADestroyBlockID(blockDataID); OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption"); - return CA_STATUS_OK; + return res; } -CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength, - const CABlockDataID_t *blockID) +CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength, + const CABlockDataID_t *blockID, coap_list_t **options) { 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"); // get set block data from CABlock list-set. - coap_block_t *block1 = CAGetBlockOption(blockID, - COAP_OPTION_BLOCK1); - coap_block_t *block2 = CAGetBlockOption(blockID, - COAP_OPTION_BLOCK2); + coap_block_t *block1 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK1); + coap_block_t *block2 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK2); if (!block1 || !block2) { OIC_LOG(ERROR, TAG, "getting has failed"); return CA_STATUS_FAILED; } - CALogBlockInfo(block2); - - uint8_t code = 0; - if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->type || - (CA_MSG_NONCONFIRM == (*pdu)->hdr->type && CA_GET != (*pdu)->hdr->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) { - int32_t res = coap_write_block_opt(block2, COAP_OPTION_BLOCK2, *pdu, dataLength); - switch (res) + CASetMoreBitFromBlock(dataLength, block2); + + // if block number is 0, add size2 option + if (0 == block2->num) { - case -2: /* illegal block */ - code = COAP_RESPONSE_CODE(CA_BAD_REQ); - OIC_LOG(ERROR, TAG, "write block option : -2"); - goto error; - case -1: /* should really not happen */ - OIC_LOG(ERROR, TAG, "write block option : -1"); - break; - case -3: /* cannot handle request */ - code = COAP_RESPONSE_CODE(CA_INTERNAL_SERVER_ERROR); - OIC_LOG(ERROR, TAG, "write block option : -3"); - goto error; - default: - OIC_LOG(INFO, TAG, "success write block option"); + res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength, options); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "add has failed"); + goto exit; + } + } + + res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "add has failed"); + goto exit; } - CALogBlockInfo(block2); if (block1->num) { OIC_LOG(DEBUG, TAG, "combining block1 and block2"); - CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1); + 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; } // initialize block number block1->num = 0; } - // if block number is 0, add size2 option - if (0 == block2->num) + res = CAAddOptionToPDU(*pdu, options); + if (CA_STATUS_OK != res) { - res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; - } + OIC_LOG(ERROR, TAG, "add has failed"); + goto exit; } - if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info.payload, + if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload, block2->num, block2->szx)) { OIC_LOG(ERROR, TAG, "Data length is smaller than the start index"); 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->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; - } - } - } } else { - OIC_LOG(DEBUG, TAG, "option2, not ACK msg"); - CAResult_t res = CAAddBlockOptionImpl(*pdu, block2, COAP_OPTION_BLOCK2); + 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"); + goto exit; + } + CALogBlockInfo(block2); } return CA_STATUS_OK; -error: - OIC_LOG_V(ERROR, TAG, "error : %d", code); - - char* phrase = coap_response_phrase(code); - if(phrase) - { - coap_add_data(*pdu, strlen(phrase), - (unsigned char *) phrase); - } - return CA_STATUS_FAILED; +exit: + CARemoveBlockDataFromList(blockID); + return res; } -CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength, - const CABlockDataID_t *blockID) +CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength, + const CABlockDataID_t *blockID, coap_list_t **options) { 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"); // get set block data from CABlock list-set. coap_block_t *block1 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK1); @@ -1607,129 +1619,157 @@ CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t info, size_t dataL { OIC_LOG(ERROR, TAG, "getting has failed"); return CA_STATUS_FAILED; - } - - CALogBlockInfo(block1); + } - if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->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(*pdu, block1, COAP_OPTION_BLOCK1); + 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; } - // reset block-list after write block - if (0 == block1->m) + // add option list to pdu. + res = CAAddOptionToPDU(*pdu, options); + if (CA_STATUS_OK != res) { - // remove data from list - CAResult_t res = CARemoveBlockDataFromList(blockID); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "remove has failed"); - return res; - } + OIC_LOG(ERROR, TAG, "add has failed"); + goto exit; + } + + // 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, "Data length is smaller than the start index"); + return CA_STATUS_FAILED; } } else { - CAGetMoreBitFromBlock(dataLength, block1); - CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1); + 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; } - CALogBlockInfo(block1); - // if block number is 0, add size1 option - if (0 == block1->num) + // add option list to pdu. + res = CAAddOptionToPDU(*pdu, options); + if (CA_STATUS_OK != res) { - res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE1, dataLength); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "add has failed"); - CARemoveBlockDataFromList(blockID); - return res; - } + OIC_LOG(ERROR, TAG, "add has failed"); + goto exit; } - 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->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_pdu_t *pdu, coap_block_t *block, uint8_t blockType) +CAResult_t CAAddBlockOptionImpl(coap_block_t *block, uint8_t blockType, + coap_list_t **options) { OIC_LOG(DEBUG, TAG, "IN-AddBlockOptionImpl"); - VERIFY_NON_NULL(pdu, TAG, "pdu"); VERIFY_NON_NULL(block, TAG, "block"); + VERIFY_NON_NULL(options, TAG, "options"); + + unsigned char buf[BLOCKWISE_OPTION_BUFFER] = { 0 }; + unsigned int optionLength = coap_encode_var_bytes(buf, + ((block->num << BLOCK_NUMBER_IDX) + | (block->m << BLOCK_M_BIT_IDX) + | block->szx)); - coap_option *option = (coap_option *) OICMalloc(sizeof(coap_option)); - if (!option) + int ret = coap_insert(options, + CACreateNewOptionNode(blockType, optionLength, (char *) buf), + CAOrderOpts); + if (ret <= 0) { - OIC_LOG(ERROR, TAG, "out of memory"); - return CA_MEMORY_ALLOC_FAILED; + return CA_STATUS_INVALID_PARAM; } - unsigned char buf[BLOCKWISE_OPTION_BUFFER] = { 0 }; - option->key = blockType; - option->length = coap_encode_var_bytes(buf, - ((block->num << BLOCK_NUMBER_IDX) - | (block->m << BLOCK_M_BIT_IDX) | block->szx)); - if (!coap_add_option(pdu, option->key, option->length, buf)) - { - OIC_LOG(ERROR, TAG, "coap_add_option has failed"); - OICFree(option); - return CA_STATUS_FAILED; + OIC_LOG(DEBUG, TAG, "OUT-AddBlockOptionImpl"); + return CA_STATUS_OK; +} + +CAResult_t CAAddOptionToPDU(coap_pdu_t *pdu, coap_list_t **options) +{ + // after adding the block option to option list, add option list to pdu. + if (*options) + { + for (coap_list_t *opt = *options; opt; opt = opt->next) + { + 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); + 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)); + if (!ret) + { + return CA_STATUS_FAILED; + } + } } - OICFree(option); + OIC_LOG_V(DEBUG, TAG, "[%d] pdu length after option", pdu->length); - OIC_LOG(DEBUG, TAG, "OUT-AddBlockOptionImpl"); return CA_STATUS_OK; } -CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataLength) +CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataLength, + coap_list_t **options) { OIC_LOG(DEBUG, TAG, "IN-CAAddBlockSizeOption"); VERIFY_NON_NULL(pdu, TAG, "pdu"); + VERIFY_NON_NULL(options, TAG, "options"); if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2) { @@ -1740,10 +1780,12 @@ CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataL unsigned char value[BLOCKWISE_OPTION_BUFFER] = { 0 }; unsigned int optionLength = coap_encode_var_bytes(value, dataLength); - if (!coap_add_option(pdu, sizeType, optionLength, value)) + int ret = coap_insert(options, + CACreateNewOptionNode(sizeType, optionLength, (char *) value), + CAOrderOpts); + if (ret <= 0) { - OIC_LOG(ERROR, TAG, "failed to add size option"); - return CA_STATUS_FAILED; + return CA_STATUS_INVALID_PARAM; } OIC_LOG(DEBUG, TAG, "OUT-CAAddBlockSizeOption"); @@ -1774,7 +1816,7 @@ bool CAIsPayloadLengthInPduWithBlockSizeOption(coap_pdu_t *pdu, *totalPayloadLen = coap_decode_var_bytes(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option)); - OIC_LOG_V(DEBUG, TAG, "the total payload length to be received is [%d]bytes", + OIC_LOG_V(DEBUG, TAG, "the total payload length to be received is [%zu]bytes", *totalPayloadLen); return true; @@ -1803,8 +1845,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) { @@ -1827,14 +1868,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) @@ -1849,14 +1893,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; } } @@ -1962,7 +2000,7 @@ CAResult_t CAUpdatePayloadData(CABlockData_t *currData, const CAData_t *received // update received payload length currData->receivedPayloadLen += blockPayloadLen; - OIC_LOG_V(DEBUG, TAG, "updated payload: %s, len: %d", currData->payload, + OIC_LOG_V(DEBUG, TAG, "updated payload: %s, len: %zu", currData->payload, currData->receivedPayloadLen); } @@ -1973,36 +2011,82 @@ 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->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->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); + 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(requestInfo); OICFree(responseInfo); return NULL; } - data->requestInfo = NULL; + data->requestInfo = requestInfo; data->responseInfo = responseInfo; data->remoteEndpoint = CACloneEndpoint(endpoint); data->type = SEND_TYPE_UNICAST; @@ -2026,8 +2110,7 @@ CAData_t *CACloneCAData(const CAData_t *data) { clone->requestInfo = CACloneRequestInfo(data->requestInfo); } - - if (data->responseInfo) + else if (data->responseInfo) { clone->responseInfo = CACloneResponseInfo(data->responseInfo); } @@ -2048,44 +2131,49 @@ CAResult_t CAUpdatePayloadToCAData(CAData_t *data, const CAPayload_t payload, VERIFY_NON_NULL(data, TAG, "data is NULL"); VERIFY_NON_NULL(payload, TAG, "payload is NULL"); - if (data->requestInfo) + CAPayload_t newPayload = NULL; + switch (data->dataType) { - // allocate payload field - if (data->requestInfo->info.payload) - { - char *temp = (char *) OICCalloc(payloadLen, sizeof(char)); - if (!temp) + case CA_REQUEST_DATA: + if (!data->requestInfo) + { + OIC_LOG(ERROR, TAG, "request info is null"); + return CA_STATUS_FAILED; + } + // allocate payload field + newPayload = OICRealloc(data->requestInfo->info.payload, payloadLen); + if (!newPayload) { OIC_LOG(ERROR, TAG, "out of memory"); return CA_STATUS_FAILED; } - memcpy(temp, payload, payloadLen); - - // save the full payload - OICFree(data->requestInfo->info.payload); - data->requestInfo->info.payload = (CAPayload_t) temp; - } - data->requestInfo->info.payloadSize = payloadLen; - } + data->requestInfo->info.payload = newPayload; + memcpy(data->requestInfo->info.payload, payload, payloadLen); + data->requestInfo->info.payloadSize = payloadLen; + break; - if (data->responseInfo) - { - // allocate payload field - if (data->responseInfo->info.payload) - { - char *temp = (char *) OICCalloc(payloadLen, sizeof(char)); - if (!temp) + case CA_RESPONSE_DATA: + if (!data->responseInfo) + { + OIC_LOG(ERROR, TAG, "response info is null"); + return CA_STATUS_FAILED; + } + // allocate payload field + newPayload = OICRealloc(data->responseInfo->info.payload, payloadLen); + if (!newPayload) { OIC_LOG(ERROR, TAG, "out of memory"); return CA_STATUS_FAILED; } - memcpy(temp, payload, payloadLen); + data->responseInfo->info.payload = newPayload; + memcpy(data->responseInfo->info.payload, payload, payloadLen); + data->responseInfo->info.payloadSize = payloadLen; + break; - // save the full payload - OICFree(data->responseInfo->info.payload); - data->responseInfo->info.payload = (CAPayload_t) temp; - } - data->responseInfo->info.payloadSize = payloadLen; + default: + // does not occur case + OIC_LOG(ERROR, TAG, "not supported data type"); + return CA_NOT_SUPPORTED; } OIC_LOG(DEBUG, TAG, "OUT-UpdatePayload"); @@ -2106,7 +2194,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) { @@ -2139,14 +2227,14 @@ CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType, break; default: OIC_LOG_V(ERROR, TAG, "there is no Error Code of BWT[%d]", responseResult); + return CA_STATUS_FAILED; } OIC_LOG(DEBUG, TAG, "OUT-HandleBlockErrorRes"); 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"); @@ -2216,6 +2304,31 @@ CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID) 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); + + ca_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); + ca_mutex_unlock(g_context.blockDataListMutex); + return currData; + } + } + ca_mutex_unlock(g_context.blockDataListMutex); + + return NULL; +} + CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint, CAResponseInfo_t *responseInfo) { @@ -2237,7 +2350,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t if (NULL != currData->sentData && NULL != currData->sentData->requestInfo) { - if (pdu->hdr->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) @@ -2265,7 +2378,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t ca_mutex_unlock(g_context.blockDataListMutex); OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList"); - return CA_STATUS_OK; + return CA_STATUS_FAILED; } CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t **blockData) @@ -2273,91 +2386,29 @@ CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t ** VERIFY_NON_NULL(sendData, TAG, "sendData"); VERIFY_NON_NULL(blockData, TAG, "blockData"); - 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) - { - continue; - } - - if (sendData->requestInfo) // sendData is requestMessage + CABlockDataID_t* blockDataID = CACreateBlockDatablockId( + (CAToken_t)sendData->responseInfo->info.token, + sendData->responseInfo->info.tokenLength, + sendData->remoteEndpoint->port); + if (NULL == blockDataID || blockDataID->idLength < 1) { - OIC_LOG(DEBUG, TAG, "Send request"); - if (NULL != currData->blockDataId - && NULL != currData->blockDataId->id - && currData->blockDataId->idLength > 0 - && NULL != sendData->requestInfo->info.token) - { - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)sendData->requestInfo->info.token, - sendData->requestInfo->info.tokenLength, - sendData->remoteEndpoint->port); - - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) - { - OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - - if (CABlockidMatches(currData, blockDataID)) - { - OIC_LOG(ERROR, TAG, "already sent"); - CADestroyBlockID(blockDataID); - continue; - } - CADestroyBlockID(blockDataID); - } + OIC_LOG(ERROR, TAG, "blockId is null"); + CADestroyBlockID(blockDataID); + return CA_STATUS_FAILED; } - else if (sendData->responseInfo) // sendData is responseMessage - { - OIC_LOG(DEBUG, TAG, "Send response"); - if (NULL != currData->blockDataId - && NULL != currData->blockDataId->id - && currData->blockDataId->idLength > 0 - && NULL != sendData->responseInfo->info.token) - { - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - (CAToken_t)sendData->responseInfo->info.token, - sendData->responseInfo->info.tokenLength, - sendData->remoteEndpoint->port); - - if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) - { - OIC_LOG(ERROR, TAG, "blockId is null"); - CADestroyBlockID(blockDataID); - return CA_STATUS_FAILED; - } - 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; - CADestroyBlockID(blockDataID); - ca_mutex_unlock(g_context.blockDataListMutex); - return CA_STATUS_OK; - } - CADestroyBlockID(blockDataID); - } - } - else + CABlockData_t *updatedData = CAUpdateDataSetFromBlockDataList(blockDataID, sendData); + if (updatedData) { - 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); return CA_STATUS_FAILED; } @@ -2383,8 +2434,7 @@ CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID) 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); @@ -2403,7 +2453,7 @@ coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, { return &currData->block2; } - else + else if (COAP_OPTION_BLOCK1 == blockType) { return &currData->block1; } @@ -2458,7 +2508,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); @@ -2473,16 +2523,23 @@ 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; } - CABlockDataID_t* blockDataID = CACreateBlockDatablockId( - token, tokenLength, - data->sentData->remoteEndpoint->port); - if (NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1) + if (!data->sentData->remoteEndpoint) + { + OIC_LOG(ERROR, TAG, "remoteEndpoint is null"); + CADestroyDataSet(data->sentData); + OICFree(data); + return NULL; + } + + CABlockDataID_t* blockDataID = CACreateBlockDatablockId(token, tokenLength, + data->sentData->remoteEndpoint->port); + if (NULL == blockDataID || blockDataID->idLength < 1) { OIC_LOG(ERROR, TAG, "blockId is null"); CADestroyBlockID(blockDataID); @@ -2532,13 +2589,10 @@ CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID) } // destroy memory - if (currData->sentData) - { - CADestroyDataSet(currData->sentData); - } - CADestroyBlockID(currData->blockDataId); - OICFree(currData->payload); - OICFree(currData); + CADestroyDataSet(removedData->sentData); + CADestroyBlockID(removedData->blockDataId); + OICFree(removedData->payload); + OICFree(removedData); ca_mutex_unlock(g_context.blockDataListMutex); return CA_STATUS_OK; } @@ -2548,48 +2602,61 @@ CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID) return CA_STATUS_OK; } -bool CAIsBlockDataInList(const CABlockDataID_t *blockID) +CAResult_t CARemoveAllBlockDataFromList() { - OIC_LOG(DEBUG, TAG, "IN-IsBlockDataInList"); - VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false); + OIC_LOG(DEBUG, TAG, "CARemoveAllBlockDataFromList"); ca_mutex_lock(g_context.blockDataListMutex); size_t len = u_arraylist_length(g_context.dataList); - for (size_t i = 0; i < len; i++) + for (size_t i = len; i > 0; i--) { - CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i); - if (CABlockidMatches(currData, blockID)) + CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i - 1); + if (removedData) { - OIC_LOG(DEBUG, TAG, "found block data"); - ca_mutex_unlock(g_context.blockDataListMutex); - return true; + // destroy memory + if (removedData->sentData) + { + CADestroyDataSet(removedData->sentData); + } + CADestroyBlockID(removedData->blockDataId); + OICFree(removedData->payload); + OICFree(removedData); } } ca_mutex_unlock(g_context.blockDataListMutex); - OIC_LOG(DEBUG, TAG, "OUT-IsBlockDataInList"); - return false; + return CA_STATUS_OK; } 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) { - VERIFY_NON_NULL_RET(token, TAG, "token", NULL); - - 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) @@ -2606,7 +2673,11 @@ CABlockDataID_t* CACreateBlockDatablockId(const CAToken_t token, uint8_t tokenLe return NULL; } - memcpy(blockDataID->id, token, tokenLength); + if (token) + { + memcpy(blockDataID->id, token, tokenLength); + } + memcpy(blockDataID->id + tokenLength, port, sizeof(port)); OIC_LOG(DEBUG, TAG, "BlockID is "); @@ -2651,3 +2722,24 @@ 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; +}