replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / cablockwisetransfer.c
index c93ca1c..94a642b 100644 (file)
 #include "caremotehandler.h"
 #include "cablockwisetransfer.h"
 #include "oic_malloc.h"
-#include "camutex.h"
+#include "oic_string.h"
+#include "octhread.h"
 #include "logger.h"
+#include "oic_time.h"
 
 #define TAG "OIC_CA_BWT"
 
@@ -52,6 +54,9 @@
 
 #define BLOCK_SIZE(arg) (1 << ((arg) + 4))
 
+#define BLOCK_DATA_TIMEOUT_SECONDS   (60 * 1)  // 1 minutes.
+static const uint64_t USECS_PER_SEC = 1000000;
+
 // context for block-wise transfer
 static CABlockWiseContext_t g_context = { .sendThreadFunc = NULL,
                                           .receivedThreadFunc = NULL,
@@ -112,6 +117,7 @@ CAResult_t CATerminateBlockWiseTransfer()
 
     if (g_context.dataList)
     {
+        CARemoveAllBlockDataFromList();
         u_arraylist_free(&g_context.dataList);
     }
 
@@ -124,20 +130,20 @@ CAResult_t CAInitBlockWiseMutexVariables()
 {
     if (!g_context.blockDataListMutex)
     {
-        g_context.blockDataListMutex = ca_mutex_new();
+        g_context.blockDataListMutex = oc_mutex_new();
         if (!g_context.blockDataListMutex)
         {
-            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
             return CA_STATUS_FAILED;
         }
     }
 
     if (!g_context.blockDataSenderMutex)
     {
-        g_context.blockDataSenderMutex = ca_mutex_new();
+        g_context.blockDataSenderMutex = oc_mutex_new();
         if (!g_context.blockDataSenderMutex)
         {
-            OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
             CATerminateBlockWiseMutexVariables();
             return CA_STATUS_FAILED;
         }
@@ -150,13 +156,13 @@ void CATerminateBlockWiseMutexVariables()
 {
     if (g_context.blockDataListMutex)
     {
-        ca_mutex_free(g_context.blockDataListMutex);
+        oc_mutex_free(g_context.blockDataListMutex);
         g_context.blockDataListMutex = NULL;
     }
 
     if (g_context.blockDataSenderMutex)
     {
-        ca_mutex_free(g_context.blockDataSenderMutex);
+        oc_mutex_free(g_context.blockDataSenderMutex);
         g_context.blockDataSenderMutex = NULL;
     }
 }
@@ -264,9 +270,9 @@ CAResult_t CAAddSendThreadQueue(const CAData_t *sendData, const CABlockDataID_t
 
     if (g_context.sendThreadFunc)
     {
-        ca_mutex_lock(g_context.blockDataSenderMutex);
+        oc_mutex_lock(g_context.blockDataSenderMutex);
         g_context.sendThreadFunc(cloneData);
-        ca_mutex_unlock(g_context.blockDataSenderMutex);
+        oc_mutex_unlock(g_context.blockDataSenderMutex);
     }
     else
     {
@@ -305,12 +311,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 +350,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 +396,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 +406,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 +497,26 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData
                 return CA_STATUS_FAILED;
             }
 
-            if (data->requestInfo)
-            {
-                data->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
-            }
-
             if (data->responseInfo)
             {
-                data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
-            }
+                data->responseInfo->info.type =
+                        (pdu->transport_hdr->udp.type == CA_MSG_CONFIRM) ?
+                                CA_MSG_ACKNOWLEDGE : CA_MSG_NONCONFIRM;
+                data->responseInfo->info.messageId = pdu->transport_hdr->udp.id;
 
-            res = CAAddSendThreadQueue(data, blockID);
-            if (CA_STATUS_OK != res)
-            {
-                OIC_LOG(ERROR, TAG, "add has failed");
-                return res;
+                res = CAAddSendThreadQueue(data, blockID);
+                if (CA_STATUS_OK != res)
+                {
+                    OIC_LOG(ERROR, TAG, "add has failed");
+                    return res;
+                }
             }
-
             break;
 
         case CA_OPTION1_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 +575,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 +589,27 @@ CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData
     return CA_STATUS_OK;
 }
 
+static CAResult_t CASendDirectEmptyResponse(const CAEndpoint_t *endpoint, uint16_t messageId)
+{
+    OIC_LOG(DEBUG, TAG, "Entering CASendDirectEmptyResponse");
+    CAResponseInfo_t respInfo = {
+        .result = CA_EMPTY
+    };
+    respInfo.info.type = CA_MSG_ACKNOWLEDGE;
+    respInfo.info.messageId = messageId;
+    respInfo.info.dataType = CA_RESPONSE_DATA;
+
+    CAResult_t caResult = CASendResponse(endpoint, &respInfo);
+
+    OIC_LOG(DEBUG, TAG, "Exit CASendDirectEmptyResponse");
+    return caResult;
+}
+
 CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType,
                               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 +633,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 +682,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
@@ -650,8 +693,21 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
         return CA_STATUS_FAILED;
     }
 
+    if (!data->sentData)
+    {
+        OIC_LOG(ERROR, TAG, "data has no sent-data");
+        return CA_STATUS_FAILED;
+    }
+
+    CAData_t *cloneData = CACloneCAData(data->sentData);
+    if (!cloneData)
+    {
+        OIC_LOG(ERROR, TAG, "clone has failed");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
     CAMessageType_t sentMsgType = CA_MSG_NONCONFIRM;
-    switch (pdu->hdr->coap_hdr_udp_t.type)
+    switch (pdu->transport_hdr->udp.type)
     {
         case CA_MSG_CONFIRM:
             sentMsgType = CA_MSG_ACKNOWLEDGE;
@@ -659,55 +715,44 @@ 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;
-    if (data->sentData)
+    if (cloneData->responseInfo)
+    {
+        cloneData->responseInfo->info.messageId = pdu->transport_hdr->udp.id;
+        cloneData->responseInfo->info.type = sentMsgType;
+        cloneData->responseInfo->result = responseResult;
+    }
+    else
     {
-        cloneData = CACloneCAData(data->sentData);
-        if (!cloneData)
+        CAInfo_t responseData = { .tokenLength = pdu->transport_hdr->udp.token_length };
+        responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
+        if (!responseData.token)
         {
-            OIC_LOG(ERROR, TAG, "clone has failed");
+            OIC_LOG(ERROR, TAG, "out of memory");
+            CADestroyDataSet(cloneData);
             return CA_MEMORY_ALLOC_FAILED;
         }
+        memcpy(responseData.token, pdu->transport_hdr->udp.token, responseData.tokenLength);
 
-        if (cloneData->responseInfo)
+        cloneData->responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
+        if (!cloneData->responseInfo)
         {
-            cloneData->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
-            cloneData->responseInfo->info.type = sentMsgType;
-            cloneData->responseInfo->result = responseResult;
+            OIC_LOG(ERROR, TAG, "out of memory");
+            CADestroyDataSet(cloneData);
+            OICFree(responseData.token);
+            return CA_MEMORY_ALLOC_FAILED;
         }
-        else
-        {
-            CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.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);
-
-            cloneData->responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
-            if (!cloneData->responseInfo)
-            {
-                OIC_LOG(ERROR, TAG, "out of memory");
-                OICFree(responseData.token);
-                return CA_MEMORY_ALLOC_FAILED;
-            }
 
-            cloneData->responseInfo->info = responseData;
-            cloneData->responseInfo->info.type = sentMsgType;
-            cloneData->responseInfo->result = responseResult;
-        }
-        OIC_LOG(DEBUG, TAG, "set response message to send error code");
-    }
-    else
-    {
-        OIC_LOG(ERROR, TAG, "data has no sent-data");
-        return CA_MEMORY_ALLOC_FAILED;
+        cloneData->responseInfo->info = responseData;
+        cloneData->responseInfo->info.type = sentMsgType;
+        cloneData->responseInfo->result = responseResult;
     }
 
+    OIC_LOG(DEBUG, TAG, "set response message to send error code");
+
     // if there is a requestInfo, remove it to send response message
     if (cloneData->requestInfo)
     {
@@ -718,9 +763,9 @@ CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
     // add data to send thread
     if (g_context.sendThreadFunc)
     {
-        ca_mutex_lock(g_context.blockDataSenderMutex);
+        oc_mutex_lock(g_context.blockDataSenderMutex);
         g_context.sendThreadFunc(cloneData);
-        ca_mutex_unlock(g_context.blockDataSenderMutex);
+        oc_mutex_unlock(g_context.blockDataSenderMutex);
     }
     else
     {
@@ -780,30 +825,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 +839,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 +847,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 +944,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 +1015,13 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
     OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
 
     VERIFY_NON_NULL(pdu, TAG, "pdu");
-    VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
+    VERIFY_NON_NULL(pdu->transport_hdr, TAG, "pdu->transport_hdr");
     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
     VERIFY_NON_NULL(receivedData, TAG, "receivedData");
 
     CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
-            (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
-            pdu->hdr->coap_hdr_udp_t.token_length,
+            (CAToken_t)pdu->transport_hdr->udp.token,
+            pdu->transport_hdr->udp.token_length,
             endpoint->port);
     if (NULL == blockDataID || blockDataID->idLength < 1)
     {
@@ -977,41 +1030,18 @@ CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
         return CA_STATUS_FAILED;
     }
 
-    // Get BlockData data. If does not exist, create a new data
-    CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
+    CAResult_t res = CA_STATUS_OK;
+    CABlockData_t *data = CACheckTheExistOfBlockData(blockDataID, pdu, endpoint,
+                                                     COAP_OPTION_BLOCK2);
     if (!data)
     {
-        OIC_LOG(DEBUG, TAG, "block data doesn't exist in list. create new one");
-
-        CAData_t *cadata = CACreateNewDataSet(pdu, endpoint);
-        if (!cadata)
-        {
-            OIC_LOG(ERROR, TAG, "data is null");
-            CADestroyBlockID(blockDataID);
-            return CA_STATUS_FAILED;
-        }
-
-        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 +1063,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 +1095,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 +1173,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 +1261,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 +1368,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 +1381,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 +1393,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 +1407,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 +1417,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");
@@ -1425,20 +1455,26 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
             {
                 OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
                           COAP_OPTION_DATA(*(coap_option *) opt->data));
-
                 OIC_LOG_V(DEBUG, TAG, "[%d] pdu length", (*pdu)->length);
-                coap_add_option(*pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
-                                COAP_OPTION_LENGTH(*(coap_option *) opt->data),
-                                COAP_OPTION_DATA(*(coap_option *) opt->data), coap_udp);
+
+                if (0 == coap_add_option(*pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
+                                         COAP_OPTION_LENGTH(*(coap_option *) opt->data),
+                                         COAP_OPTION_DATA(*(coap_option *) opt->data)))
+                {
+                    OIC_LOG(ERROR, TAG, "coap_add_option has failed");
+                    res = CA_STATUS_FAILED;
+                    goto exit;
+                }
             }
         }
-
         OIC_LOG_V(DEBUG, TAG, "[%d] pdu length after option", (*pdu)->length);
 
         // if response data is so large. it have to send as block transfer
         if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
         {
-            OIC_LOG(INFO, TAG, "it have to use block");
+            OIC_LOG(INFO, TAG, "it has to use block");
+            res = CA_STATUS_FAILED;
+            goto exit;
         }
         else
         {
@@ -1446,7 +1482,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,
@@ -1463,6 +1499,7 @@ CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
         }
     }
 
+    CAResetBlockDataTTL(blockDataID);
 exit:
     CADestroyBlockID(blockDataID);
     OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption");
@@ -1475,7 +1512,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 +1527,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 +1617,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 +1631,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 +1760,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 +1877,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 +2020,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 +2049,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,19 +2069,40 @@ 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);
+            OICFree(requestInfo);
+            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));
     if (!data)
     {
         OIC_LOG(ERROR, TAG, "out of memory");
-        OICFree(requestInfo);
-        OICFree(responseInfo);
+        if (NULL != requestInfo)
+        {
+            OICFree(requestInfo->info.resourceUri);
+            OICFree(requestInfo->info.token);
+            OICFree(requestInfo);
+        }
+        if (NULL != responseInfo)
+        {
+            OICFree(responseInfo->info.token);
+            OICFree(responseInfo);
+        }
         return NULL;
     }
 
@@ -2152,7 +2214,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,13 +2254,12 @@ CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType,
     return CA_STATUS_OK;
 }
 
-CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID,
-                                   uint8_t blockType)
+CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID, uint8_t blockType)
 {
     OIC_LOG(DEBUG, TAG, "IN-UpdateBlockOptionType");
     VERIFY_NON_NULL(blockID, TAG, "blockID");
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2207,12 +2268,12 @@ CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID,
         if (CABlockidMatches(currData, blockID))
         {
             currData->type = blockType;
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
             return CA_STATUS_OK;
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
     return CA_STATUS_FAILED;
@@ -2223,7 +2284,7 @@ uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID)
     OIC_LOG(DEBUG, TAG, "IN-GetBlockOptionType");
     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", 0);
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2231,12 +2292,12 @@ uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID)
         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
         if (CABlockidMatches(currData, blockID))
         {
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
             return currData->type;
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
     return 0;
@@ -2246,7 +2307,7 @@ CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID)
 {
     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2254,11 +2315,36 @@ CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID)
         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
         if (CABlockidMatches(currData, blockID))
         {
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             return currData->sentData;
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
+
+    return NULL;
+}
+
+CABlockData_t *CAUpdateDataSetFromBlockDataList(const CABlockDataID_t *blockID,
+                                                const CAData_t *sendData)
+{
+    VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
+    VERIFY_NON_NULL_RET(sendData, TAG, "sendData", NULL);
+
+    oc_mutex_lock(g_context.blockDataListMutex);
+
+    size_t len = u_arraylist_length(g_context.dataList);
+    for (size_t i = 0; i < len; i++)
+    {
+        CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
+        if (CABlockidMatches(currData, blockID))
+        {
+            CADestroyDataSet(currData->sentData);
+            currData->sentData = CACloneCAData(sendData);
+            oc_mutex_unlock(g_context.blockDataListMutex);
+            return currData;
+        }
+    }
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     return NULL;
 }
@@ -2271,7 +2357,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t
     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
     VERIFY_NON_NULL(responseInfo, TAG, "responseInfo");
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2284,7 +2370,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)
@@ -2295,13 +2381,13 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t
                     if (NULL == responseInfo->info.token)
                     {
                         OIC_LOG(ERROR, TAG, "out of memory");
-                        ca_mutex_unlock(g_context.blockDataListMutex);
+                        oc_mutex_unlock(g_context.blockDataListMutex);
                         return CA_MEMORY_ALLOC_FAILED;
                     }
                     memcpy(responseInfo->info.token, currData->sentData->requestInfo->info.token,
                            responseInfo->info.tokenLength);
 
-                    ca_mutex_unlock(g_context.blockDataListMutex);
+                    oc_mutex_unlock(g_context.blockDataListMutex);
                     OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
                     return CA_STATUS_OK;
                 }
@@ -2309,7 +2395,7 @@ CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t
         }
     }
 
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
     return CA_STATUS_FAILED;
@@ -2320,93 +2406,29 @@ CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t **
     VERIFY_NON_NULL(sendData, TAG, "sendData");
     VERIFY_NON_NULL(blockData, TAG, "blockData");
 
-    CABlockDataID_t* blockDataID;
-    if(sendData->requestInfo)
-    {
-        blockDataID = CACreateBlockDatablockId(
-                            (CAToken_t)sendData->requestInfo->info.token,
-                            sendData->requestInfo->info.tokenLength,
-                            sendData->remoteEndpoint->port);
-    }
-    else if(sendData->responseInfo)
-    {
-        blockDataID = CACreateBlockDatablockId(
-                            (CAToken_t)sendData->responseInfo->info.token,
-                            sendData->responseInfo->info.tokenLength,
-                            sendData->remoteEndpoint->port);
-    }
-    else
-    {
-        OIC_LOG(ERROR, TAG, "sendData doesn't have requestInfo or responseInfo");
-        return CA_STATUS_FAILED;
-    }
-
-    if (NULL == blockDataID || blockDataID->idLength < 1)
-    {
-        OIC_LOG(ERROR, TAG, "blockId is null");
-        CADestroyBlockID(blockDataID);
-        return CA_STATUS_FAILED;
-    }
-
-    ca_mutex_lock(g_context.blockDataListMutex);
-
-    size_t len = u_arraylist_length(g_context.dataList);
-    for (size_t i = 0; i < len; i++)
+    if (sendData->responseInfo)
     {
-        CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
-        if (!currData)
+        CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
+                (CAToken_t)sendData->responseInfo->info.token,
+                sendData->responseInfo->info.tokenLength,
+                sendData->remoteEndpoint->port);
+        if (NULL == blockDataID || blockDataID->idLength < 1)
         {
-            continue;
+            OIC_LOG(ERROR, TAG, "blockId is null");
+            CADestroyBlockID(blockDataID);
+            return CA_STATUS_FAILED;
         }
 
-        if (sendData->requestInfo) // sendData is requestMessage
-        {
-            OIC_LOG(DEBUG, TAG, "Send request");
-            if (NULL != currData->blockDataId
-                    && NULL != currData->blockDataId->id
-                    && currData->blockDataId->idLength > 0
-                    && NULL != sendData->requestInfo->info.token)
-            {
-                if (CABlockidMatches(currData, blockDataID))
-                {
-                    OIC_LOG(ERROR, TAG, "already sent");
-                    continue;
-                }
-            }
-        }
-        else if (sendData->responseInfo) // sendData is responseMessage
-        {
-            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
+        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);
-
-    CADestroyBlockID(blockDataID);
 
     return CA_STATUS_FAILED;
 }
@@ -2415,7 +2437,7 @@ CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID)
 {
     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2423,11 +2445,11 @@ CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID)
         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
         if (CABlockidMatches(currData, blockID))
         {
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             return currData;
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     return NULL;
 }
@@ -2437,7 +2459,7 @@ coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, uint16_t blockTyp
     OIC_LOG(DEBUG, TAG, "IN-GetBlockOption");
     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2445,7 +2467,7 @@ coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, uint16_t blockTyp
         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
         if (CABlockidMatches(currData, blockID))
         {
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
             if (COAP_OPTION_BLOCK2 == blockType)
             {
@@ -2457,7 +2479,7 @@ coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID, uint16_t blockTyp
             }
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
     return NULL;
@@ -2470,7 +2492,7 @@ CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID,
     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
     VERIFY_NON_NULL_RET(fullPayloadLen, TAG, "fullPayloadLen", NULL);
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2478,13 +2500,13 @@ CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID,
         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
         if (CABlockidMatches(currData, blockID))
         {
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             *fullPayloadLen = currData->receivedPayloadLen;
             OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
             return currData->payload;
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
     return NULL;
@@ -2546,8 +2568,10 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData)
         return NULL;
     }
     data->blockDataId = blockDataID;
+    uint64_t now = OICGetCurrentTime(TIME_IN_US);
+    data->ttl = now + (BLOCK_DATA_TIMEOUT_SECONDS * USECS_PER_SEC);
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     bool res = u_arraylist_add(g_context.dataList, (void *) data);
     if (!res)
@@ -2556,10 +2580,10 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData)
         CADestroyBlockID(data->blockDataId);
         CADestroyDataSet(data->sentData);
         OICFree(data);
-        ca_mutex_unlock(g_context.blockDataListMutex);
+        oc_mutex_unlock(g_context.blockDataListMutex);
         return NULL;
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     OIC_LOG(DEBUG, TAG, "OUT-CreateBlockData");
     return data;
@@ -2567,10 +2591,10 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData)
 
 CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
 {
-    OIC_LOG(DEBUG, TAG, "CARemoveBlockData");
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
     VERIFY_NON_NULL(blockID, TAG, "blockID");
 
-    ca_mutex_lock(g_context.blockDataListMutex);
+    oc_mutex_lock(g_context.blockDataListMutex);
 
     size_t len = u_arraylist_length(g_context.dataList);
     for (size_t i = 0; i < len; i++)
@@ -2582,20 +2606,51 @@ CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
             if (!removedData)
             {
                 OIC_LOG(ERROR, TAG, "data is NULL");
-                ca_mutex_unlock(g_context.blockDataListMutex);
+                oc_mutex_unlock(g_context.blockDataListMutex);
                 return CA_STATUS_FAILED;
             }
 
+            OIC_LOG(DEBUG, TAG, "Removed BlockID is ");
+            OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) removedData->blockDataId->id,
+                           removedData->blockDataId->idLength);
+
             // destroy memory
-            CADestroyDataSet(currData->sentData);
-            CADestroyBlockID(currData->blockDataId);
-            OICFree(currData->payload);
-            OICFree(currData);
-            ca_mutex_unlock(g_context.blockDataListMutex);
+            CADestroyDataSet(removedData->sentData);
+            CADestroyBlockID(removedData->blockDataId);
+            OICFree(removedData->payload);
+            OICFree(removedData);
+            oc_mutex_unlock(g_context.blockDataListMutex);
             return CA_STATUS_OK;
         }
     }
-    ca_mutex_unlock(g_context.blockDataListMutex);
+    oc_mutex_unlock(g_context.blockDataListMutex);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+    return CA_STATUS_OK;
+}
+
+CAResult_t CARemoveAllBlockDataFromList()
+{
+    OIC_LOG(DEBUG, TAG, "CARemoveAllBlockDataFromList");
+
+    oc_mutex_lock(g_context.blockDataListMutex);
+
+    size_t len = u_arraylist_length(g_context.dataList);
+    for (size_t i = len; i > 0; i--)
+    {
+        CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i - 1);
+        if (removedData)
+        {
+            // destroy memory
+            if (removedData->sentData)
+            {
+                CADestroyDataSet(removedData->sentData);
+            }
+            CADestroyBlockID(removedData->blockDataId);
+            OICFree(removedData->payload);
+            OICFree(removedData);
+        }
+    }
+    oc_mutex_unlock(g_context.blockDataListMutex);
 
     return CA_STATUS_OK;
 }
@@ -2604,9 +2659,21 @@ 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 +2748,78 @@ void CALogBlockInfo(coap_block_t *block)
 
     OIC_LOG_V(DEBUG, TAG, "block option-szx : %d", block->szx);
 }
+
+CAResult_t CARemoveBlockDataFromListWithSeed(const CAToken_t token, uint8_t tokenLength,
+                                             uint16_t portNumber)
+{
+    CABlockDataID_t* blockDataID = CACreateBlockDatablockId(token, tokenLength, portNumber);
+    if (NULL == blockDataID || blockDataID->idLength < 1)
+    {
+        OIC_LOG(ERROR, TAG, "blockId is null");
+        CADestroyBlockID(blockDataID);
+        return CA_STATUS_FAILED;
+    }
+
+    CAResult_t res = CARemoveBlockDataFromList(blockDataID);
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "CARemoveBlockDataFromList failed");
+    }
+
+    CADestroyBlockID(blockDataID);
+    return res;
+}
+
+void CAResetBlockDataTTL(const CABlockDataID_t *blockID)
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+    oc_mutex_lock(g_context.blockDataListMutex);
+    size_t len = u_arraylist_length(g_context.dataList);
+    for (size_t i = 0; i < len; i++)
+    {
+        CABlockData_t *blockData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
+        if (CABlockidMatches(blockData, blockID))
+        {
+            uint64_t now = OICGetCurrentTime(TIME_IN_US);
+            blockData->ttl = now + (BLOCK_DATA_TIMEOUT_SECONDS * USECS_PER_SEC);
+            oc_mutex_unlock(g_context.blockDataListMutex);
+            OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+            return;
+        }
+    }
+    oc_mutex_unlock(g_context.blockDataListMutex);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+
+void CACheckAndDeleteTimedOutBlockData()
+{
+    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+
+    uint64_t now = OICGetCurrentTime(TIME_IN_US);
+
+    oc_mutex_lock(g_context.blockDataListMutex);
+    for (size_t i = 0; i < u_arraylist_length(g_context.dataList); i++)
+    {
+        CABlockData_t *blockData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
+        if (blockData && blockData->ttl < now)
+        {
+            OIC_LOG(INFO, TAG, "Deleting timed-out BlockData");
+            OIC_LOG(DEBUG, TAG, "BlockID is ");
+            OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) blockData->blockDataId->id,
+                           blockData->blockDataId->idLength);
+
+            blockData = (CABlockData_t *) u_arraylist_remove(g_context.dataList, i);
+            if (blockData)
+            {
+                // destroy memory
+                CADestroyDataSet(blockData->sentData);
+                CADestroyBlockID(blockData->blockDataId);
+                OICFree(blockData->payload);
+                OICFree(blockData);
+            }
+        }
+    }
+    oc_mutex_unlock(g_context.blockDataListMutex);
+    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}