Fixed double free issue when destroying endpoint
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / cablockwisetransfer.c
index c93ca1c..dd17fe9 100644 (file)
@@ -40,6 +40,7 @@
 #include "caremotehandler.h"
 #include "cablockwisetransfer.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 #include "camutex.h"
 #include "logger.h"
 
@@ -112,6 +113,7 @@ CAResult_t CATerminateBlockWiseTransfer()
 
     if (g_context.dataList)
     {
+        CARemoveAllBlockDataFromList();
         u_arraylist_free(&g_context.dataList);
     }
 
@@ -305,12 +307,12 @@ 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..");
 
@@ -344,6 +346,16 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
             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;
@@ -380,8 +392,8 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
     if (!isBlock1 && !isBlock2)
     {
         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)
         {
@@ -390,7 +402,7 @@ CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
             return CA_STATUS_FAILED;
         }
 
-        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)
         {
             CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
@@ -481,29 +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->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_RESPONSE:
         case CA_OPTION2_RESPONSE:
         case CA_OPTION1_REQUEST_BLOCK:
-            res = CASendBlockMessage(pdu, pdu->hdr->coap_hdr_udp_t.type, blockID);
+            res = CASendBlockMessage(pdu, pdu->transport_hdr->udp.type, blockID);
             if (CA_STATUS_OK != res)
             {
                 OIC_LOG(ERROR, TAG, "send has failed");
@@ -562,7 +571,7 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData
             }
             else if (receivedData->responseInfo)
             {
-                res = CASendBlockMessage(pdu, pdu->hdr->coap_hdr_udp_t.type, blockID);
+                res = CASendBlockMessage(pdu, pdu->transport_hdr->udp.type, blockID);
                 if (CA_STATUS_OK != res)
                 {
                     OIC_LOG(ERROR, TAG, "send has failed");
@@ -576,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,
                               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);
@@ -604,25 +629,39 @@ CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType,
             break;
     }
 
-    uint32_t code = pdu->hdr->coap_hdr_udp_t.code;
+    uint32_t code = pdu->transport_hdr->udp.code;
     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
     {
         if (data->responseInfo)
         {
             OIC_LOG(DEBUG, TAG, "set response info");
-            data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
+            data->responseInfo->info.messageId = pdu->transport_hdr->udp.id;
             data->responseInfo->info.type = sentMsgType;
             data->responseInfo->result = CA_CONTINUE;
         }
     }
     else
     {
-        OIC_LOG(DEBUG, TAG, "need new msgID");
         if (data->requestInfo)
         {
+            // 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)
+            {
+                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;
+        }
     }
 
     // add data to send thread
@@ -639,7 +678,7 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
                               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
@@ -651,7 +690,7 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
     }
 
     CAMessageType_t sentMsgType = CA_MSG_NONCONFIRM;
-    switch (pdu->hdr->coap_hdr_udp_t.type)
+    switch (pdu->transport_hdr->udp.type)
     {
         case CA_MSG_CONFIRM:
             sentMsgType = CA_MSG_ACKNOWLEDGE;
@@ -659,6 +698,8 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
         case CA_MSG_ACKNOWLEDGE:
             sentMsgType = CA_MSG_CONFIRM;
             break;
+        default:
+            sentMsgType = CA_MSG_NONCONFIRM;
     }
 
     CAData_t *cloneData = NULL;
@@ -673,20 +714,20 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
 
         if (cloneData->responseInfo)
         {
-            cloneData->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
+            cloneData->responseInfo->info.messageId = pdu->transport_hdr->udp.id;
             cloneData->responseInfo->info.type = sentMsgType;
             cloneData->responseInfo->result = responseResult;
         }
         else
         {
-            CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length };
+            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->hdr->coap_hdr_udp_t.token, responseData.tokenLength);
+            memcpy(responseData.token, pdu->transport_hdr->udp.token, responseData.tokenLength);
 
             cloneData->responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
             if (!cloneData->responseInfo)
@@ -780,30 +821,10 @@ CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID, const CAData_t *re
     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)
@@ -814,8 +835,7 @@ 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;
         }
 
         data = CACreateNewBlockData(cadata);
@@ -823,22 +843,58 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
         {
             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");
+        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,
+                                 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");
+
+    OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
+
+    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;
     }
 
     uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
-    uint32_t code = pdu->hdr->coap_hdr_udp_t.code;
+    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
@@ -884,21 +940,14 @@ CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
         {
             OIC_LOG_V(DEBUG, TAG, "M bit is %d", block.m);
 
-            if (0 == block.m)
-            {
-                // Last block is received
-                blockWiseStatus = CA_OPTION1_REQUEST_LAST_BLOCK;
-            }
-            else
-            {
-                blockWiseStatus = CA_OPTION1_REQUEST_BLOCK;
-            }
+            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->hdr->coap_hdr_udp_t.code);
+        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))
         {
@@ -962,13 +1011,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)
     {
@@ -977,41 +1026,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;
-        }
-
-        data = CACreateNewBlockData(cadata);
-        if (!data)
-        {
-            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");
+        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");
 
@@ -1033,7 +1059,7 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
     }
     else
     {
-        uint32_t code = pdu->hdr->coap_hdr_udp_t.code;
+        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
@@ -1065,7 +1091,7 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
                                                                           COAP_OPTION_SIZE2,
                                                                           &(data->payloadLength));
 
-            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)
             {
                 // check if received payload is exact
@@ -1143,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->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)
     {
@@ -1231,17 +1257,17 @@ CAResult_t CASetMoreBitFromBlock(size_t payloadLen, coap_block_t *block)
 }
 
 CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block,
-                                coap_pdu_t *pdu, 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->hdr, TAG, "pdu->hdr");
+    VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr");
 
     bool isReqMsg = false;
-    uint32_t code = pdu->hdr->coap_hdr_udp_t.code;
+    uint32_t code = pdu->transport_hdr->udp.code;
     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
     {
         isReqMsg = true;
@@ -1338,7 +1364,7 @@ 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->hdr, TAG, "pdu->hdr");
+    VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr");
     VERIFY_NON_NULL(blockID, TAG, "blockID");
 
     // if message is sent, update messageId in block-wise transfer list
@@ -1351,7 +1377,7 @@ CAResult_t CAUpdateMessageId(coap_pdu_t *pdu, const CABlockDataID_t *blockID)
 
     if (cadata->requestInfo)
     {
-        cadata->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
+        cadata->requestInfo->info.messageId = pdu->transport_hdr->udp.id;
     }
 
     return CA_STATUS_OK;
@@ -1363,7 +1389,7 @@ 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");
@@ -1377,8 +1403,8 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
     }
 
     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)
     {
@@ -1387,7 +1413,7 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
         goto exit;
     }
 
-    uint32_t repCode = CA_RESPONSE_CODE((*pdu)->hdr->coap_hdr_udp_t.code);
+    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");
@@ -1429,7 +1455,7 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
                 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);
+                                COAP_OPTION_DATA(*(coap_option *) opt->data));
             }
         }
 
@@ -1439,6 +1465,8 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
         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
         {
@@ -1446,7 +1474,7 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
         }
     }
 
-    uint32_t code = (*pdu)->hdr->coap_hdr_udp_t.code;
+    uint32_t code = (*pdu)->transport_hdr->udp.code;
     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
     {
         // if received message type is RESET from remote device,
@@ -1475,7 +1503,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");
@@ -1490,7 +1518,7 @@ CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t data
     }
 
     CAResult_t res = CA_STATUS_OK;
-    uint32_t code = (*pdu)->hdr->coap_hdr_udp_t.code;
+    uint32_t code = (*pdu)->transport_hdr->udp.code;
     if (CA_GET != code && CA_POST != code && CA_PUT != code && CA_DELETE != code)
     {
         CASetMoreBitFromBlock(dataLength, block2);
@@ -1580,7 +1608,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");
@@ -1594,7 +1622,7 @@ CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t data
     }
 
     CAResult_t res = CA_STATUS_OK;
-    uint32_t code = (*pdu)->hdr->coap_hdr_udp_t.code;
+    uint32_t code = (*pdu)->transport_hdr->udp.code;
     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
     {
         CASetMoreBitFromBlock(dataLength, block1);
@@ -1723,7 +1751,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;
@@ -1840,7 +1868,11 @@ 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;
+            }
         }
     }
 
@@ -1979,23 +2011,23 @@ 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);
 
     CARequestInfo_t* requestInfo = NULL;
     CAResponseInfo_t* responseInfo = NULL;
 
-    uint32_t code = pdu->hdr->coap_hdr_udp_t.code;
+    uint32_t code = pdu->transport_hdr->udp.code;
     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
     {
-        CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length };
+        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->hdr->coap_hdr_udp_t.token, responseData.tokenLength);
+        memcpy(responseData.token, pdu->transport_hdr->udp.token, responseData.tokenLength);
 
         responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
         if (!responseInfo)
@@ -2008,14 +2040,14 @@ CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint
     }
     else
     {
-        CAInfo_t requestData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length };
+        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->hdr->coap_hdr_udp_t.token, requestData.tokenLength);
+        memcpy(requestData.token, pdu->transport_hdr->udp.token, requestData.tokenLength);
 
         requestInfo = (CARequestInfo_t*) OICCalloc(1, sizeof(CARequestInfo_t));
         if (!requestInfo)
@@ -2028,11 +2060,21 @@ CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint
 
         // get resource uri information from received response message
         // to send next request message to remote device
-        CAResponseInfo_t resInfo = { 0 };
-        CAGetResponseInfoFromPDU(pdu, &resInfo, endpoint);
+        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.resourceUri = resInfo.info.resourceUri;
+        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);
     }
 
     CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
@@ -2152,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)
         {
@@ -2192,8 +2234,7 @@ 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");
@@ -2263,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)
 {
@@ -2284,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->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)
@@ -2320,93 +2386,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)
+    if (sendData->responseInfo)
     {
-        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++)
-    {
-        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
+        CABlockData_t *updatedData = CAUpdateDataSetFromBlockDataList(blockDataID, sendData);
+        if (updatedData)
         {
-            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
-        {
-            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;
 }
@@ -2587,10 +2589,10 @@ CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
             }
 
             // destroy memory
-            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;
         }
@@ -2600,13 +2602,52 @@ CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
     return CA_STATUS_OK;
 }
 
+CAResult_t CARemoveAllBlockDataFromList()
+{
+    OIC_LOG(DEBUG, TAG, "CARemoveAllBlockDataFromList");
+
+    ca_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 (removedData->sentData)
+            {
+                CADestroyDataSet(removedData->sentData);
+            }
+            CADestroyBlockID(removedData->blockDataId);
+            OICFree(removedData->payload);
+            OICFree(removedData);
+        }
+    }
+    ca_mutex_unlock(g_context.blockDataListMutex);
+
+    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);
 }
 
@@ -2681,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;
+}