fixed the jira IOT-712 issue in blockwise-transfer
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / cablockwisetransfer.c
1 /* ****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 // Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
22 // definitions that may otherwise be skipped. Skipping can cause implicit
23 // declaration warnings and/or bugs and subtle problems in code execution.
24 // For glibc information on feature test macros,
25 // Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
26 //
27 // This file requires #define use due to random()
28 // For details on compatibility and glibc support,
29 // Refer http://www.gnu.org/software/libc/manual/html_node/BSD-Random.html
30 #define _DEFAULT_SOURCE
31 #define _BSD_SOURCE
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "caadapterutils.h"
38 #include "cainterface.h"
39 #include "camessagehandler.h"
40 #include "caremotehandler.h"
41 #include "cablockwisetransfer.h"
42 #include "oic_malloc.h"
43 #include "camutex.h"
44 #include "logger.h"
45
46 #define TAG "CA_BWT"
47
48 #define BLOCKWISE_OPTION_BUFFER    (sizeof(unsigned int))
49 #define BLOCK_NUMBER_IDX           4
50 #define BLOCK_M_BIT_IDX            3
51 #define PORT_LENGTH                2
52
53 #define BLOCK_SIZE(arg) (1 << ((arg) + 4))
54
55 // context for block-wise transfer
56 static CABlockWiseContext_t g_context = { 0 };
57
58 static bool CACheckPayloadLength(const CAData_t *sendData)
59 {
60     size_t payloadLen = 0;
61     CAGetPayloadInfo(sendData, &payloadLen);
62
63     // check if message has to be transfered to a block
64     size_t maxBlockSize = BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE);
65     OIC_LOG_V(DEBUG, TAG, "payloadLen=%d, maxBlockSize=%d", payloadLen, maxBlockSize);
66
67     if (payloadLen <= maxBlockSize)
68     {
69         return false;
70     }
71
72     return true;
73 }
74
75 CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc,
76                                          CAReceiveThreadFunc receivedThreadFunc)
77 {
78     OIC_LOG(DEBUG, TAG, "initialize");
79
80     // set block-wise transfer context
81     if (!g_context.sendThreadFunc)
82     {
83         g_context.sendThreadFunc = sendThreadFunc;
84     }
85
86     if (!g_context.receivedThreadFunc)
87     {
88         g_context.receivedThreadFunc = receivedThreadFunc;
89     }
90
91     if (!g_context.dataList)
92     {
93         g_context.dataList = u_arraylist_create();
94     }
95
96     CAResult_t res = CAInitBlockWiseMutexVariables();
97     if (CA_STATUS_OK != res)
98     {
99         OIC_LOG(ERROR, TAG, "init has failed");
100     }
101
102     return res;
103 }
104
105 CAResult_t CATerminateBlockWiseTransfer()
106 {
107     OIC_LOG(DEBUG, TAG, "terminate");
108
109     if (g_context.dataList)
110     {
111         u_arraylist_free(&g_context.dataList);
112     }
113
114     CATerminateBlockWiseMutexVariables();
115
116     return CA_STATUS_OK;
117 }
118
119 CAResult_t CAInitBlockWiseMutexVariables()
120 {
121     OIC_LOG(DEBUG, TAG, "IN");
122
123     if (!g_context.blockDataListMutex)
124     {
125         g_context.blockDataListMutex = ca_mutex_new();
126         if (!g_context.blockDataListMutex)
127         {
128             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
129             return CA_STATUS_FAILED;
130         }
131     }
132
133     if (!g_context.blockDataSenderMutex)
134     {
135         g_context.blockDataSenderMutex = ca_mutex_new();
136         if (!g_context.blockDataSenderMutex)
137         {
138             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
139             CATerminateBlockWiseMutexVariables();
140             return CA_STATUS_FAILED;
141         }
142     }
143
144     return CA_STATUS_OK;
145 }
146
147 void CATerminateBlockWiseMutexVariables()
148 {
149     OIC_LOG(DEBUG, TAG, "IN");
150
151     if (g_context.blockDataListMutex)
152     {
153         ca_mutex_free(g_context.blockDataListMutex);
154         g_context.blockDataListMutex = NULL;
155     }
156
157     if (g_context.blockDataSenderMutex)
158     {
159         ca_mutex_free(g_context.blockDataSenderMutex);
160         g_context.blockDataSenderMutex = NULL;
161     }
162 }
163
164 CAResult_t CASendBlockWiseData(const CAData_t *sendData)
165 {
166     VERIFY_NON_NULL(sendData, TAG, "sendData");
167
168     // check if message type is CA_MSG_RESET
169     if (sendData->requestInfo)
170     {
171         if (CA_MSG_RESET == sendData->requestInfo->info.type)
172         {
173             OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block");
174             return CA_NOT_SUPPORTED;
175         }
176     }
177     else if (sendData->responseInfo)
178     {
179         if (CA_MSG_RESET == sendData->responseInfo->info.type)
180         {
181             OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block");
182             return CA_NOT_SUPPORTED;
183         }
184     }
185
186     // #1. check if it is already included in block data list
187     CABlockData_t *currData = NULL;
188     CAResult_t res = CACheckBlockDataValidation(sendData, &currData);
189     if (CA_STATUS_OK != res)
190     {
191         // #2. if it is not included, add the data into list
192         if (!currData)
193         {
194             OIC_LOG(DEBUG, TAG, "There is no block data");
195
196             bool isBlock = CACheckPayloadLength(sendData);
197             if (!isBlock)
198             {
199                 if (sendData->requestInfo)
200                 {
201                     currData = CACreateNewBlockData(sendData);
202                     if (!currData)
203                     {
204                         OIC_LOG(ERROR, TAG, "failed to create block data");
205                         return CA_MEMORY_ALLOC_FAILED;
206                     }
207                 }
208                 return CA_NOT_SUPPORTED;
209             }
210             currData = CACreateNewBlockData(sendData);
211             if (!currData)
212             {
213                 OIC_LOG(ERROR, TAG, "failed to create block data");
214                 return CA_MEMORY_ALLOC_FAILED;
215             }
216         }
217     }
218
219     // #3. check request/response block option type and payload length
220     res = CACheckBlockOptionType(currData);
221     if (CA_STATUS_OK == res)
222     {
223         // #4. send block message
224         OIC_LOG(DEBUG, TAG, "send first block msg");
225         res = CAAddSendThreadQueue(currData->sentData,
226                                    (const CABlockDataID_t *)&currData->blockDataId);
227         if (CA_STATUS_OK != res)
228         {
229             OIC_LOG(ERROR, TAG, "add has failed");
230             return res;
231         }
232     }
233
234     return res;
235 }
236
237 CAResult_t CAAddSendThreadQueue(const CAData_t *sendData, const CABlockDataID_t *blockID)
238 {
239     VERIFY_NON_NULL(sendData, TAG, "sendData");
240     VERIFY_NON_NULL(blockID, TAG, "blockID");
241
242     CAData_t *cloneData = CACloneCAData(sendData);
243     if (!cloneData)
244     {
245         OIC_LOG(ERROR, TAG, "clone has failed");
246         CARemoveBlockDataFromList(blockID);
247         return CA_STATUS_FAILED;
248     }
249
250     if (g_context.sendThreadFunc)
251     {
252         ca_mutex_lock(g_context.blockDataSenderMutex);
253         g_context.sendThreadFunc(cloneData);
254         ca_mutex_unlock(g_context.blockDataSenderMutex);
255     }
256     else
257     {
258         CADestroyDataSet(cloneData);
259     }
260     return CA_STATUS_OK;
261 }
262
263 CAResult_t CACheckBlockOptionType(CABlockData_t *currData)
264 {
265     VERIFY_NON_NULL(currData, TAG, "currData");
266     VERIFY_NON_NULL(currData->sentData, TAG, "currData->sentData");
267
268     bool isBlock = CACheckPayloadLength(currData->sentData);
269     if (!isBlock)
270     {
271         return CA_NOT_SUPPORTED;
272     }
273
274     // set block option (COAP_OPTION_BLOCK2 or COAP_OPTION_BLOCK1)
275     if (currData->sentData->requestInfo) // request message
276     {
277         currData->type = COAP_OPTION_BLOCK1;
278     }
279     else // response message
280     {
281         currData->type = COAP_OPTION_BLOCK2;
282     }
283
284     return CA_STATUS_OK;
285 }
286
287 // TODO make pdu const after libcoap is updated to support that.
288 CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
289                                   const CAData_t *receivedData, size_t dataLen)
290 {
291     OIC_LOG(DEBUG, TAG, "CAReceiveBlockWiseData");
292     VERIFY_NON_NULL(pdu, TAG, "pdu");
293     VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
294     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
295     VERIFY_NON_NULL(receivedData, TAG, "receivedData");
296
297     // check if received message type is CA_MSG_RESET
298     if (CA_EMPTY == pdu->hdr->coap_hdr_udp_t.code)
299     {
300         OIC_LOG(DEBUG, TAG, "code is CA_EMPTY..");
301
302         // get token from block-wise transfer list when CA_EMPTY(RST/ACK) is received
303         CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint, receivedData->responseInfo);
304         if (CA_STATUS_OK != res)
305         {
306             OIC_LOG(ERROR, TAG, "fail to get token");
307             return res;
308         }
309
310         CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
311                 receivedData->responseInfo->info.token,
312                 receivedData->responseInfo->info.tokenLength,
313                 endpoint->port);
314         if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
315         {
316             OIC_LOG(ERROR, TAG, "blockId is null");
317             CADestroyBlockID(blockDataID);
318             return CA_STATUS_FAILED;
319         }
320
321         CARemoveBlockDataFromList(blockDataID);
322         CADestroyBlockID(blockDataID);
323         return CA_NOT_SUPPORTED;
324     }
325
326     // check if block option is set and get block data
327     coap_block_t block = {0, 0, 0};
328
329     // get block1 option
330     int isBlock1 = coap_get_block(pdu, COAP_OPTION_BLOCK1, &block);
331     if (isBlock1)
332     {
333         CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, block, dataLen);
334         if (CA_STATUS_OK != res)
335         {
336             OIC_LOG(ERROR, TAG, "setting has failed");
337             return res;
338         }
339     }
340
341     // get block2 option
342     int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block);
343     if (isBlock2)
344     {
345         CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, block, dataLen);
346         if (CA_STATUS_OK != res)
347         {
348             OIC_LOG(ERROR, TAG, "setting has failed");
349             return res;
350         }
351     }
352
353     // check if there is error code
354     if (!isBlock1 && !isBlock2)
355     {
356         uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
357         if (CA_REQUEST_ENTITY_INCOMPLETE == code)
358         {
359             CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
360                     (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
361                      pdu->hdr->coap_hdr_udp_t.token_length,
362                      endpoint->port);
363
364             if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
365             {
366                 OIC_LOG(ERROR, TAG, "blockId is null");
367                 CADestroyBlockID(blockDataID);
368                 return CA_STATUS_FAILED;
369             }
370
371             CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
372             if (!data)
373             {
374                 OIC_LOG(ERROR, TAG, "getting has failed");
375                 CADestroyBlockID(blockDataID);
376                 return CA_STATUS_FAILED;
377             }
378
379             if (COAP_OPTION_BLOCK2 == data->type)
380             {
381                 coap_block_t *block2 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK2);
382                 if (!block2)
383                 {
384                     OIC_LOG(ERROR, TAG, "block is null");
385                     CADestroyBlockID(blockDataID);
386                     return CA_STATUS_FAILED;
387                 }
388
389                 CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, *block2,
390                                                        dataLen);
391                 if (CA_STATUS_OK != res)
392                 {
393                     OIC_LOG(ERROR, TAG, "setting has failed");
394                     CADestroyBlockID(blockDataID);
395                     return res;
396                 }
397             }
398             else if (COAP_OPTION_BLOCK1 == data->type)
399             {
400                 coap_block_t *block1 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK1);
401                 if (!block1)
402                 {
403                     OIC_LOG(ERROR, TAG, "block is null");
404                     CADestroyBlockID(blockDataID);
405                     return CA_STATUS_FAILED;
406                 }
407
408                 CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, *block1,
409                                                        dataLen);
410                 if (CA_STATUS_OK != res)
411                 {
412                     OIC_LOG(ERROR, TAG, "setting has failed");
413                     CADestroyBlockID(blockDataID);
414                     return res;
415                 }
416             }
417         }
418         else
419         {
420             // normal pdu data
421             OIC_LOG(DEBUG, TAG, "it's normal pdu");
422
423             // if received data is response message
424             // and sent data remain in block data list, remove block data
425             if (receivedData->responseInfo)
426             {
427                 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
428                         (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
429                         pdu->hdr->coap_hdr_udp_t.token_length,
430                         endpoint->port);
431                 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
432                 {
433                     OIC_LOG(ERROR, TAG, "blockId is null");
434                     CADestroyBlockID(blockDataID);
435                     return CA_STATUS_FAILED;
436                 }
437
438                 CARemoveBlockDataFromList(blockDataID);
439                 CADestroyBlockID(blockDataID);
440             }
441             return CA_NOT_SUPPORTED;
442         }
443     }
444
445     return CA_STATUS_OK;
446 }
447
448 CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData,
449                              uint8_t blockWiseStatus, const CABlockDataID_t *blockID)
450 {
451     VERIFY_NON_NULL(pdu, TAG, "pdu");
452     VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
453     VERIFY_NON_NULL(blockID, TAG, "blockID");
454
455     CAResult_t res = CA_STATUS_OK;
456     CAData_t *data = NULL;
457
458     // process blockWiseStatus
459     switch (blockWiseStatus)
460     {
461         case CA_OPTION2_FIRST_BLOCK:
462             res = CAAddSendThreadQueue(receivedData, blockID);
463             if (CA_STATUS_OK != res)
464             {
465                 OIC_LOG(ERROR, TAG, "add has failed");
466                 return res;
467             }
468             break;
469
470         case CA_OPTION2_CON:
471             // add data to send thread
472             data = CAGetDataSetFromBlockDataList(blockID);
473             if (!data)
474             {
475                 OIC_LOG(ERROR, TAG, "it's unavailable");
476                 return CA_STATUS_FAILED;
477             }
478
479             if (data->requestInfo)
480             {
481                 data->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
482             }
483
484             if (data->responseInfo)
485             {
486                 data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
487             }
488
489             res = CAAddSendThreadQueue(data, blockID);
490             if (CA_STATUS_OK != res)
491             {
492                 OIC_LOG(ERROR, TAG, "add has failed");
493                 return res;
494             }
495
496             break;
497
498         case CA_OPTION1_ACK:
499         case CA_OPTION2_ACK:
500         case CA_SENT_PREVIOUS_NON_MSG:
501             res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
502                                      blockID);
503             if (CA_STATUS_OK != res)
504             {
505                 OIC_LOG(ERROR, TAG, "send has failed");
506                 return res;
507             }
508             break;
509
510         case CA_OPTION2_LAST_BLOCK:
511             // process last block and send upper layer
512             res = CAReceiveLastBlock(blockID, receivedData);
513             if (CA_STATUS_OK != res)
514             {
515                 OIC_LOG(ERROR, TAG, "receive has failed");
516                 return res;
517             }
518
519             // remove data from list
520             res = CARemoveBlockDataFromList(blockID);
521             if (CA_STATUS_OK != res)
522             {
523                 OIC_LOG(ERROR, TAG, "remove has failed");
524                 return res;
525             }
526             break;
527
528         case CA_OPTION1_NO_ACK_LAST_BLOCK:
529             // process last block and send upper layer
530             res = CAReceiveLastBlock(blockID, receivedData);
531             if (CA_STATUS_OK != res)
532             {
533                 OIC_LOG(ERROR, TAG, "receive has failed");
534                 return res;
535             }
536
537             if (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type)
538             {
539                 // remove data from list
540                 res = CARemoveBlockDataFromList(blockID);
541                 if (CA_STATUS_OK != res)
542                 {
543                     OIC_LOG(ERROR, TAG, "remove has failed");
544                     return res;
545                 }
546             }
547             break;
548
549         case CA_OPTION1_NO_ACK_BLOCK:
550             if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
551             {
552                 // add data to send thread
553                 res = CASendBlockMessage(pdu, CA_MSG_ACKNOWLEDGE, blockWiseStatus,
554                                          blockID);
555                 if (CA_STATUS_OK != res)
556                 {
557                     OIC_LOG(ERROR, TAG, "send has failed");
558                     return res;
559                 }
560             }
561             break;
562
563         case CA_BLOCK_INCOMPLETE:
564             if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type ||
565                     CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
566             {
567                 // add data to send thread
568                 res = CASendErrorMessage(pdu, blockWiseStatus,
569                                          CA_REQUEST_ENTITY_INCOMPLETE,
570                                          blockID);
571                 if (CA_STATUS_OK != res)
572                 {
573                     OIC_LOG(ERROR, TAG, "send has failed");
574                     return res;
575                 }
576             }
577             break;
578
579         case CA_BLOCK_TOO_LARGE:
580             if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
581             {
582                 res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
583                                          blockID);
584                 if (CA_STATUS_OK != res)
585                 {
586                     OIC_LOG(ERROR, TAG, "send has failed");
587                     return res;
588                 }
589             }
590             else if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
591             {
592                 res = CASendErrorMessage(pdu, blockWiseStatus,
593                                          CA_REQUEST_ENTITY_TOO_LARGE,
594                                          blockID);
595                 if (CA_STATUS_OK != res)
596                 {
597                     OIC_LOG(ERROR, TAG, "send has failed");
598                     return res;
599                 }
600             }
601             break;
602         default:
603             OIC_LOG_V(ERROR, TAG, "no logic [%d]", blockWiseStatus);
604     }
605     return CA_STATUS_OK;
606 }
607
608 CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType,
609                               uint8_t status, const CABlockDataID_t *blockID)
610 {
611     VERIFY_NON_NULL(pdu, TAG, "pdu");
612     VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
613     VERIFY_NON_NULL(blockID, TAG, "blockID");
614
615     CAData_t *data = CAGetDataSetFromBlockDataList(blockID);
616     if (!data)
617     {
618         OIC_LOG(ERROR, TAG, "CAData is unavailable");
619         return CA_STATUS_FAILED;
620     }
621
622     if (CA_MSG_CONFIRM == msgType)
623     {
624         OIC_LOG(DEBUG, TAG, "need new msgID");
625         if (data->requestInfo)
626         {
627             data->requestInfo->info.messageId = 0;
628         }
629
630         if (data->responseInfo)
631         {
632             data->responseInfo->info.messageId = 0;
633         }
634     }
635     else if (CA_MSG_ACKNOWLEDGE == msgType)
636     {
637         if (data->responseInfo)
638         {
639             OIC_LOG(DEBUG, TAG, "set ACK message");
640             data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
641             data->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
642             if (CA_OPTION1_NO_ACK_LAST_BLOCK == status)
643             {
644                 data->responseInfo->result = CA_CHANGED;
645             }
646             else if (CA_OPTION1_NO_ACK_BLOCK == status)
647             {
648                 data->responseInfo->result = CA_CONTINUE;
649             }
650         }
651     }
652
653     // add data to send thread
654     CAResult_t res = CAAddSendThreadQueue(data, blockID);
655     if (CA_STATUS_OK != res)
656     {
657         OIC_LOG(ERROR, TAG, "add has failed");
658     }
659
660     return res;
661 }
662
663 CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
664                               CAResponseResult_t responseResult,
665                               const CABlockDataID_t *blockID)
666 {
667     VERIFY_NON_NULL(pdu, TAG, "pdu");
668     VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
669     VERIFY_NON_NULL(blockID, TAG, "blockID");
670
671     // create error responseInfo
672     CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockID);
673     if (!data)
674     {
675         OIC_LOG(ERROR, TAG, "data is unavailable");
676         return CA_STATUS_FAILED;
677     }
678
679     CAData_t *cloneData = NULL;
680     if (data->sentData && data->sentData->responseInfo)
681     {
682         data->sentData->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
683         data->sentData->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
684         data->sentData->responseInfo->result = responseResult;
685         cloneData = CACloneCAData(data->sentData);
686         if (!cloneData)
687         {
688             OIC_LOG(ERROR, TAG, "clone has failed");
689             return CA_MEMORY_ALLOC_FAILED;
690         }
691         OIC_LOG(DEBUG, TAG, "set ACK message");
692     }
693     else if (data->sentData)
694     {
695         cloneData = CACreateNewDataSet(pdu, data->sentData->remoteEndpoint);
696         if(!cloneData)
697         {
698             OIC_LOG(ERROR, TAG, PCF("CACreateNewDataSet failed"));
699             return CA_MEMORY_ALLOC_FAILED;
700         }
701
702         cloneData->responseInfo->info.type = CA_MSG_CONFIRM;
703         cloneData->responseInfo->result = responseResult;
704         OIC_LOG(DEBUG, TAG, "set CON message");
705     }
706     else
707     {
708         OIC_LOG(ERROR, TAG, "data has no sent-data");
709         return CA_MEMORY_ALLOC_FAILED;
710     }
711
712     // add data to send thread
713     if (g_context.sendThreadFunc)
714     {
715         ca_mutex_lock(g_context.blockDataSenderMutex);
716         g_context.sendThreadFunc(cloneData);
717         ca_mutex_unlock(g_context.blockDataSenderMutex);
718     }
719     else
720     {
721         CADestroyDataSet(cloneData);
722     }
723
724     // if error code is 4.08, remove the stored payload and initialize block number
725     if (CA_BLOCK_INCOMPLETE == status)
726     {
727         OICFree(data->payload);
728         data->payload = NULL;
729         data->payloadLength = 0;
730         data->receivedPayloadLen = 0;
731         data->block1.num = 0;
732         data->block2.num = 0;
733     }
734
735     return CA_STATUS_OK;
736 }
737
738 CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID,
739                               const CAData_t *receivedData)
740 {
741     VERIFY_NON_NULL(blockID, TAG, "blockID");
742     VERIFY_NON_NULL(receivedData, TAG, "receivedData");
743
744     // total block data have to notify to Application
745     CAData_t *cloneData = CACloneCAData(receivedData);
746     if (!cloneData)
747     {
748         OIC_LOG(ERROR, TAG, "clone has failed");
749         return CA_MEMORY_ALLOC_FAILED;
750     }
751
752     // update payload
753     size_t fullPayloadLen = 0;
754     CAPayload_t fullPayload = CAGetPayloadFromBlockDataList(blockID,
755                                                             &fullPayloadLen);
756     if (fullPayload)
757     {
758         CAResult_t res = CAUpdatePayloadToCAData(cloneData, fullPayload, fullPayloadLen);
759         if (CA_STATUS_OK != res)
760         {
761             OIC_LOG(ERROR, TAG, "update has failed");
762             CADestroyDataSet(cloneData);
763             return res;
764         }
765     }
766
767     if (g_context.receivedThreadFunc)
768     {
769         g_context.receivedThreadFunc(cloneData);
770     }
771     else
772     {
773         CADestroyDataSet(cloneData);
774     }
775
776     return CA_STATUS_OK;
777 }
778
779 // TODO make pdu const after libcoap is updated to support that.
780 CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
781                                  const CAData_t *receivedData, coap_block_t block,
782                                  size_t dataLen)
783 {
784     OIC_LOG(INFO, TAG, "CASetNextBlockOption1");
785     VERIFY_NON_NULL(pdu, TAG, "pdu");
786     VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
787     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
788     VERIFY_NON_NULL(receivedData, TAG, "receivedData");
789
790     OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
791
792     CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
793             (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
794             pdu->hdr->coap_hdr_udp_t.token_length,
795             endpoint->port);
796
797     if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
798     {
799         OIC_LOG(ERROR, TAG, "blockId is null");
800         CADestroyBlockID(blockDataID);
801         return CA_STATUS_FAILED;
802     }
803
804     // BlockData data is created if it not existed
805     if (!CAIsBlockDataInList(blockDataID))
806     {
807         OIC_LOG(DEBUG, TAG, "no message in list");
808
809         CAData_t *data = CACreateNewDataSet(pdu, endpoint);
810         if (!data)
811         {
812             OIC_LOG(ERROR, TAG, "data is null");
813             CADestroyBlockID(blockDataID);
814             return CA_STATUS_FAILED;
815         }
816
817         CABlockData_t *currData = CACreateNewBlockData(data);
818         if (!currData)
819         {
820             OIC_LOG(ERROR, TAG, "currData is null");
821             CADestroyDataSet(data);
822             CADestroyBlockID(blockDataID);
823             return CA_STATUS_FAILED;
824         }
825         CADestroyDataSet(data);
826     }
827
828     // update BLOCK OPTION1 type
829     CAResult_t res = CAUpdateBlockOptionType(blockDataID,
830                                              COAP_OPTION_BLOCK1);
831     if (CA_STATUS_OK != res)
832     {
833         OIC_LOG(ERROR, TAG, "update has failed");
834         CARemoveBlockDataFromList(blockDataID);
835         CADestroyBlockID(blockDataID);
836         return res;
837     }
838
839     CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
840     if (!data)
841     {
842         OIC_LOG(ERROR, TAG, "getting has failed");
843         CADestroyBlockID(blockDataID);
844         return CA_STATUS_FAILED;
845     }
846
847     uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
848     // received type from remote device
849     if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
850     {
851         uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
852         if (0 == block.m &&
853                 (CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code))
854         {
855             int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block);
856             if (isBlock2)
857             {
858                 OIC_LOG(INFO, TAG, "received data is combining block1 and block2");
859                 // initialize block number for response message
860                 data->block1.num = 0;
861                 CADestroyBlockID(blockDataID);
862                 return CA_STATUS_OK;
863             }
864             else
865             {
866                 OIC_LOG(INFO, TAG, "received data is not bulk data");
867                 CAReceiveLastBlock(blockDataID, receivedData);
868                 CARemoveBlockDataFromList(blockDataID);
869                 CADestroyBlockID(blockDataID);
870                 return CA_STATUS_OK;
871             }
872         }
873
874         blockWiseStatus = CA_OPTION1_ACK;
875         res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus);
876         if (CA_STATUS_OK != res)
877         {
878             OIC_LOG(ERROR, TAG, "update has failed");
879             CADestroyBlockID(blockDataID);
880             return res;
881         }
882
883         res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1);
884         if (CA_STATUS_OK != res)
885         {
886             OIC_LOG(ERROR, TAG, "update has failed");
887             CARemoveBlockDataFromList(blockDataID);
888             CADestroyBlockID(blockDataID);
889             return res;
890         }
891     }
892     else // CON or NON message
893     {
894         OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m);
895
896         // check the size option
897         bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu,
898                                                                       COAP_OPTION_SIZE1,
899                                                                       &(data->payloadLength));
900
901         // check if received payload is exact
902         if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
903         {
904             blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
905                                                     COAP_OPTION_BLOCK1, dataLen);
906         }
907
908         if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus)
909         {
910             // store the received payload and merge
911             res = CAUpdatePayloadData(data, receivedData, blockWiseStatus,
912                                       isSizeOption, COAP_OPTION_BLOCK1);
913             if (CA_STATUS_OK != res)
914             {
915                 OIC_LOG(ERROR, TAG, "update has failed");
916                 CARemoveBlockDataFromList(blockDataID);
917                 CADestroyBlockID(blockDataID);
918                 return res;
919             }
920
921             res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus);
922             if (CA_STATUS_OK != res)
923             {
924                 OIC_LOG(ERROR, TAG, "update has failed");
925                 CARemoveBlockDataFromList(blockDataID);
926                 CADestroyBlockID(blockDataID);
927                 return res;
928             }
929
930             // update block data
931             res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1);
932             if (CA_STATUS_OK != res)
933             {
934                 OIC_LOG(ERROR, TAG, "update has failed");
935                 CARemoveBlockDataFromList(blockDataID);
936                 CADestroyBlockID(blockDataID);
937                 return res;
938             }
939         }
940
941         // check the blcok-wise transfer status for next step
942         if (CA_BLOCK_UNKNOWN == blockWiseStatus || CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)
943         {
944             if (0 == block.m) // Last block is received
945             {
946                 OIC_LOG(DEBUG, TAG, "M bit is 0");
947                 blockWiseStatus = CA_OPTION1_NO_ACK_LAST_BLOCK;
948             }
949             else
950             {
951                 OIC_LOG(DEBUG, TAG, "M bit is 1");
952                 blockWiseStatus = CA_OPTION1_NO_ACK_BLOCK;
953             }
954         }
955     }
956
957     res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID);
958     if (CA_STATUS_OK != res)
959     {
960         OIC_LOG(ERROR, TAG, "setting has failed");
961         CARemoveBlockDataFromList(blockDataID);
962     }
963
964     CADestroyBlockID(blockDataID);
965     return res;
966 }
967
968 // TODO make pdu const after libcoap is updated to support that.
969 CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
970                                  const CAData_t *receivedData, coap_block_t block,
971                                  size_t dataLen)
972 {
973     OIC_LOG(DEBUG, TAG, "CASetNextBlockOption2");
974     OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
975
976     VERIFY_NON_NULL(pdu, TAG, "pdu");
977     VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
978     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
979     VERIFY_NON_NULL(receivedData, TAG, "receivedData");
980
981     CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
982             (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
983             pdu->hdr->coap_hdr_udp_t.token_length,
984             endpoint->port);
985
986     if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
987     {
988         OIC_LOG(ERROR, TAG, "blockId is null");
989         CADestroyBlockID(blockDataID);
990         return CA_STATUS_FAILED;
991     }
992
993     // BlockData data is created if it not existed
994     if (!CAIsBlockDataInList(blockDataID))
995     {
996         OIC_LOG(DEBUG, TAG, "no msg in list.");
997
998         CAData_t *data = CACreateNewDataSet(pdu, endpoint);
999         if (!data)
1000         {
1001             OIC_LOG(ERROR, TAG, "data is null");
1002             CADestroyBlockID(blockDataID);
1003             return CA_STATUS_FAILED;
1004         }
1005
1006         CABlockData_t *currData = CACreateNewBlockData(data);
1007         if (!currData)
1008         {
1009             OIC_LOG(ERROR, TAG, "data is null");
1010             CADestroyDataSet(data);
1011             CADestroyBlockID(blockDataID);
1012             return CA_STATUS_FAILED;
1013         }
1014         CADestroyDataSet(data);
1015     }
1016
1017     // set Block Option Type
1018     CAResult_t res = CAUpdateBlockOptionType(blockDataID,
1019                                              COAP_OPTION_BLOCK2);
1020     if (CA_STATUS_OK != res)
1021     {
1022         OIC_LOG(ERROR, TAG, "update has failed");
1023         CARemoveBlockDataFromList(blockDataID);
1024         CADestroyBlockID(blockDataID);
1025         return res;
1026     }
1027
1028     CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
1029     if (!data)
1030     {
1031         OIC_LOG(ERROR, TAG, "getting has failed");
1032         CARemoveBlockDataFromList(blockDataID);
1033         CADestroyBlockID(blockDataID);
1034         return CA_STATUS_FAILED;
1035     }
1036
1037     uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
1038     if (0 == block.num && CA_GET == pdu->hdr->coap_hdr_udp_t.code && 0 == block.m)
1039     {
1040         OIC_LOG(INFO, TAG, "first block number");
1041
1042         res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus);
1043         if (CA_STATUS_OK != res)
1044         {
1045             OIC_LOG(ERROR, TAG, "update has failed");
1046             CARemoveBlockDataFromList(blockDataID);
1047             CADestroyBlockID(blockDataID);
1048             return res;
1049         }
1050
1051         // first block data have to notify to Application
1052         res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1053         if (CA_STATUS_OK != res)
1054         {
1055             OIC_LOG(ERROR, TAG, "update has failed");
1056             CARemoveBlockDataFromList(blockDataID);
1057             CADestroyBlockID(blockDataID);
1058             return res;
1059         }
1060         blockWiseStatus = CA_OPTION2_FIRST_BLOCK;
1061     }
1062     else
1063     {
1064         // received type from remote device
1065         if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type ||
1066                 (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type &&
1067                         NULL != receivedData->responseInfo))
1068         {
1069             OIC_LOG(DEBUG, TAG, "received ACK or NON");
1070
1071             // check the size option
1072             bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu,
1073                                                                           COAP_OPTION_SIZE2,
1074                                                                           &(data->payloadLength));
1075
1076             // check if received payload is exact
1077             if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
1078             {
1079                 blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
1080                                                         COAP_OPTION_BLOCK2, dataLen);
1081             }
1082
1083             if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus)
1084             {
1085                 // store the received payload and merge
1086                 res = CAUpdatePayloadData(data, receivedData, blockWiseStatus,
1087                                           isSizeOption, COAP_OPTION_BLOCK2);
1088                 if (CA_STATUS_OK != res)
1089                 {
1090                     OIC_LOG(ERROR, TAG, "update has failed");
1091                     CARemoveBlockDataFromList(blockDataID);
1092                     CADestroyBlockID(blockDataID);
1093                     return res;
1094                 }
1095             }
1096
1097             if (0 == block.m && CA_BLOCK_UNKNOWN == blockWiseStatus) // Last block is received
1098             {
1099                 OIC_LOG(DEBUG, TAG, "M bit is 0");
1100                 blockWiseStatus = CA_OPTION2_LAST_BLOCK;
1101             }
1102             else
1103             {
1104                 if (CA_BLOCK_UNKNOWN == blockWiseStatus ||
1105                         CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)
1106                 {
1107                     OIC_LOG(DEBUG, TAG, "M bit is 1");
1108
1109                     if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
1110                     {
1111                         blockWiseStatus = CA_OPTION2_ACK;
1112                     }
1113                     else
1114                     {
1115                         blockWiseStatus = CA_OPTION2_NON;
1116                     }
1117                 }
1118
1119                 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2,
1120                                                blockWiseStatus);
1121                 if (CA_STATUS_OK != res)
1122                 {
1123                     OIC_LOG(ERROR, TAG, "update has failed");
1124                     CARemoveBlockDataFromList(blockDataID);
1125                     CADestroyBlockID(blockDataID);
1126                     return res;
1127                 }
1128
1129                 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1130                 if (CA_STATUS_OK != res)
1131                 {
1132                     OIC_LOG(ERROR, TAG, "update has failed");
1133                     CARemoveBlockDataFromList(blockDataID);
1134                     CADestroyBlockID(blockDataID);
1135                     return res;
1136                 }
1137             }
1138         }
1139         else // CON message and so on.
1140         {
1141             OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m);
1142
1143             blockWiseStatus = CA_OPTION2_CON;
1144
1145             res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus);
1146             if (CA_STATUS_OK != res)
1147             {
1148                 OIC_LOG(ERROR, TAG, "update has failed");
1149                 CARemoveBlockDataFromList(blockDataID);
1150                 CADestroyBlockID(blockDataID);
1151                 return res;
1152             }
1153
1154             res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1155             if (CA_STATUS_OK != res)
1156             {
1157                 OIC_LOG(ERROR, TAG, "update has failed");
1158                 CARemoveBlockDataFromList(blockDataID);
1159                 CADestroyBlockID(blockDataID);
1160                 return res;
1161             }
1162         }
1163     }
1164
1165     res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID);
1166     if (CA_STATUS_OK != res)
1167     {
1168         OIC_LOG(ERROR, TAG, "setting has failed");
1169         CARemoveBlockDataFromList(blockDataID);
1170         CADestroyBlockID(blockDataID);
1171         return res;
1172     }
1173
1174     CADestroyBlockID(blockDataID);
1175     return CA_STATUS_OK;
1176 }
1177
1178 CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *pdu,
1179                                     coap_block_t *block, uint16_t blockType,
1180                                     uint32_t status)
1181 {
1182     VERIFY_NON_NULL(currData, TAG, "currData");
1183     VERIFY_NON_NULL(pdu, TAG, "pdu");
1184     VERIFY_NON_NULL(block, TAG, "block");
1185
1186     // update block data
1187     CAResult_t res = CA_STATUS_OK;
1188     uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
1189
1190     if (CA_REQUEST_ENTITY_INCOMPLETE == code || CA_REQUEST_ENTITY_TOO_LARGE == code)
1191     {
1192         // response error code of the received block message
1193         res = CAHandleBlockErrorResponse(block, blockType, code);
1194         if (CA_STATUS_OK != res)
1195         {
1196             OIC_LOG(ERROR, TAG, "error handle has failed");
1197             return res;
1198         }
1199     }
1200     else
1201     {
1202         // update block option items
1203         switch (status)
1204         {
1205             case CA_OPTION1_ACK:
1206                 if (currData->block1.num > block->num)
1207                 {
1208                     OIC_LOG(ERROR, TAG, "received incorrect block num");
1209                     return CA_STATUS_FAILED;
1210                 }
1211                 block->num++;
1212                 break;
1213             case CA_OPTION2_NON:
1214                 block->num++;
1215                 block->m = 0;
1216                 break;
1217             case CA_OPTION2_CON:
1218                 block->m = 0;
1219                 break;
1220             case CA_OPTION2_ACK:
1221                 if (currData->block2.num > block->num)
1222                 {
1223                     OIC_LOG(ERROR, TAG, "received incorrect block num");
1224                     return CA_STATUS_FAILED;
1225                 }
1226                 block->num++;
1227                 block->m = 0;
1228                 break;
1229             case CA_BLOCK_TOO_LARGE:
1230                 // if state of received block message is CA_BLOCK_TOO_LARGE or CA_BLOCK_INCOMPLETE
1231                 // we set the response error code appropriately and send
1232                 if (COAP_OPTION_BLOCK2 == blockType)
1233                 {
1234                     block->num++;
1235                     block->m = 0;
1236                     block->szx = currData->block2.szx;
1237                 }
1238                 else
1239                 {
1240                     block->szx = currData->block1.szx;
1241                 }
1242                 break;
1243             default:
1244                 OIC_LOG_V(ERROR, TAG, "no logic [%d]", status);
1245         }
1246
1247         if (CA_BLOCK_INCOMPLETE != status && CA_BLOCK_TOO_LARGE != status)
1248         {
1249             // negotiate block size
1250             res = CANegotiateBlockSize(currData, block, pdu->hdr->coap_hdr_udp_t.type, blockType);
1251             if (CA_STATUS_OK != res)
1252             {
1253                 OIC_LOG(ERROR, TAG, "negotiation has failed");
1254                 return res;
1255             }
1256         }
1257     }
1258     return res;
1259 }
1260
1261 CAResult_t CAGetMoreBitFromBlock(size_t payloadLen, coap_block_t *block)
1262 {
1263     VERIFY_NON_NULL(block, TAG, "block");
1264
1265     if ((size_t)((block->num + 1) << (block->szx + BLOCK_NUMBER_IDX))
1266         < payloadLen)
1267     {
1268         OIC_LOG(DEBUG, TAG, "Set the M-bit(1)");
1269         block->m = 1;
1270     }
1271     else
1272     {
1273         OIC_LOG(DEBUG, TAG, "Set the M-bit(0)");
1274         block->m = 0;
1275     }
1276
1277     return CA_STATUS_OK;
1278 }
1279
1280 CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block,
1281                                 CAMessageType_t msgType, uint16_t blockType)
1282 {
1283     OIC_LOG(DEBUG, TAG, "IN-NegotiateBlockSize");
1284
1285     VERIFY_NON_NULL(currData, TAG, "currData");
1286     VERIFY_NON_NULL(block, TAG, "block");
1287
1288     // #1. check the block option type
1289     if (COAP_OPTION_BLOCK2 == blockType)
1290     {
1291         // #2. check the message type
1292         if (CA_MSG_ACKNOWLEDGE == msgType)
1293         {
1294             if (block->szx > currData->block2.szx)
1295             {
1296                 OIC_LOG(DEBUG, TAG, "sze is big");
1297
1298                 // #3. calculate new block number from block size
1299                 unsigned int blockNum = BLOCK_SIZE(block->szx) /
1300                                         BLOCK_SIZE(currData->block2.szx) - 1;
1301                 OIC_LOG(DEBUG, TAG, "num is set as Negotiation");
1302                 block->num += blockNum;
1303                 block->szx = currData->block2.szx;
1304                 OIC_LOG_V(DEBUG, TAG, "updated block num: %d", block->num);
1305             }
1306         }
1307         else
1308         {
1309             if (block->szx > currData->block2.szx)
1310             {
1311                 OIC_LOG(DEBUG, TAG, "sze is big");
1312                 block->szx = currData->block2.szx;
1313             }
1314         }
1315     }
1316     else if (COAP_OPTION_BLOCK1 == blockType)
1317     {
1318         if (CA_MSG_ACKNOWLEDGE == msgType)
1319         {
1320             if (block->szx < currData->block1.szx)
1321             {
1322                 OIC_LOG(DEBUG, TAG, "sze is small");
1323
1324                 unsigned int blockNum = BLOCK_SIZE(currData->block1.szx) /
1325                                         BLOCK_SIZE(block->szx) - 1;
1326                 block->num += blockNum;
1327                 OIC_LOG_V(DEBUG, TAG, "updated block num: %d", block->num);
1328             }
1329         }
1330         else
1331         {
1332             if (block->szx > currData->block1.szx)
1333             {
1334                 OIC_LOG(DEBUG, TAG, "sze is big");
1335                 block->szx = currData->block1.szx;
1336             }
1337         }
1338     }
1339     else
1340     {
1341         OIC_LOG(DEBUG, TAG, "Invalid block option");
1342         return CA_STATUS_FAILED;
1343     }
1344
1345     OIC_LOG(DEBUG, TAG, "OUT-NegotiateBlockSize");
1346
1347     return CA_STATUS_OK;
1348 }
1349
1350 CAResult_t CAUpdateBlockData(CABlockData_t *currData, coap_block_t block,
1351                              uint16_t blockType)
1352 {
1353     VERIFY_NON_NULL(currData, TAG, "currData");
1354
1355     // check if block size is bigger than CABlockSize_t
1356     if (block.szx > CA_BLOCK_SIZE_1024_BYTE)
1357     {
1358         OIC_LOG(DEBUG, TAG, "invalid block szx");
1359         return CA_STATUS_FAILED;
1360     }
1361
1362     // update block option
1363     if (COAP_OPTION_BLOCK2 == blockType)
1364     {
1365         currData->block2 = block;
1366     }
1367     else
1368     {
1369         currData->block1 = block;
1370     }
1371
1372     OIC_LOG(DEBUG, TAG, "data has updated");
1373     return CA_STATUS_OK;
1374 }
1375
1376 CAResult_t CAUpdateMessageId(coap_pdu_t *pdu, const CABlockDataID_t *blockID)
1377 {
1378     VERIFY_NON_NULL(pdu, TAG, "pdu");
1379     VERIFY_NON_NULL(blockID, TAG, "blockID");
1380
1381     // if CON message is sent, update messageId in block-wise transfer list
1382     if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
1383     {
1384         CAData_t * cadata = CAGetDataSetFromBlockDataList(blockID);
1385         if (!cadata)
1386         {
1387             OIC_LOG(ERROR, TAG, "CAData is unavailable");
1388             return CA_STATUS_FAILED;
1389         }
1390
1391         if (cadata->requestInfo)
1392         {
1393             cadata->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
1394         }
1395     }
1396
1397     return CA_STATUS_OK;
1398 }
1399
1400 CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
1401                             const CAEndpoint_t *endpoint)
1402 {
1403     OIC_LOG(DEBUG, TAG, "IN-AddBlockOption");
1404     VERIFY_NON_NULL(pdu, TAG, "pdu");
1405     VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1406     VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1407     VERIFY_NON_NULL(info, TAG, "info");
1408     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
1409
1410     size_t dataLength = 0;
1411     if (info->payload)
1412     {
1413         dataLength = info->payloadSize;
1414         OIC_LOG_V(DEBUG, TAG, "dataLength - %d", dataLength);
1415     }
1416
1417     OIC_LOG_V(DEBUG, TAG, "previous payload - %s", (*pdu)->data);
1418
1419     CAResult_t res = CA_STATUS_OK;
1420     uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->coap_hdr_udp_t.code);
1421     if (CA_REQUEST_ENTITY_INCOMPLETE == code)
1422     {
1423         OIC_LOG(INFO, TAG, "don't use option");
1424         return res;
1425     }
1426
1427     CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
1428             (CAToken_t)(*pdu)->hdr->coap_hdr_udp_t.token,
1429             (*pdu)->hdr->coap_hdr_udp_t.token_length,
1430             endpoint->port);
1431
1432     if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
1433     {
1434         OIC_LOG(ERROR, TAG, "blockId is null");
1435         res = CA_STATUS_FAILED;
1436         goto exit;
1437     }
1438
1439     uint8_t blockType = CAGetBlockOptionType(blockDataID);
1440     if (COAP_OPTION_BLOCK2 == blockType)
1441     {
1442         res = CAAddBlockOption2(pdu, info, dataLength, blockDataID);
1443         if (CA_STATUS_OK != res)
1444         {
1445             OIC_LOG(ERROR, TAG, "add has failed");
1446             goto exit;
1447         }
1448     }
1449     else if (COAP_OPTION_BLOCK1 == blockType)
1450     {
1451         res = CAAddBlockOption1(pdu, info, dataLength, blockDataID);
1452         if (CA_STATUS_OK != res)
1453         {
1454             OIC_LOG(ERROR, TAG, "add has failed");
1455             goto exit;
1456         }
1457     }
1458     else
1459     {
1460         OIC_LOG(DEBUG, TAG, "no BLOCK option");
1461         // if response data is so large. it have to send as block transfer
1462         if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
1463         {
1464             OIC_LOG(INFO, TAG, "it have to use block");
1465         }
1466         else
1467         {
1468             OIC_LOG(INFO, TAG, "not Blockwise Transfer");
1469             goto exit;
1470         }
1471     }
1472
1473     // if received message type is RESET from remote device,
1474     // we have to use the updated message id to find token.
1475     res = CAUpdateMessageId(*pdu, blockDataID);
1476     if (CA_STATUS_OK != res)
1477     {
1478         OIC_LOG(ERROR, TAG, "fail to update CON message id ");
1479         goto exit;
1480     }
1481
1482 exit:
1483     if (0 == endpoint->port)
1484     {
1485         CARemoveBlockDataFromList(blockDataID);
1486     }
1487     CADestroyBlockID(blockDataID);
1488     OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption");
1489     return res;
1490 }
1491
1492 CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
1493                              const CABlockDataID_t *blockID)
1494 {
1495     OIC_LOG(DEBUG, TAG, "IN-AddBlockOption2");
1496     VERIFY_NON_NULL(pdu, TAG, "pdu");
1497     VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1498     VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1499     VERIFY_NON_NULL(info, TAG, "info");
1500     VERIFY_NON_NULL(blockID, TAG, "blockID");
1501
1502     // get set block data from CABlock list-set.
1503     coap_block_t *block1 = CAGetBlockOption(blockID,
1504                                             COAP_OPTION_BLOCK1);
1505     coap_block_t *block2 = CAGetBlockOption(blockID,
1506                                             COAP_OPTION_BLOCK2);
1507     if (!block1 || !block2)
1508     {
1509         OIC_LOG(ERROR, TAG, "getting has failed");
1510         return CA_STATUS_FAILED;
1511     }
1512
1513     CALogBlockInfo(block2);
1514
1515     uint8_t code = 0;
1516     if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type ||
1517             (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type &&
1518                     CA_GET != (*pdu)->hdr->coap_hdr_udp_t.code))
1519     {
1520         int32_t res = coap_write_block_opt(block2, COAP_OPTION_BLOCK2, *pdu, dataLength);
1521         switch (res)
1522         {
1523             case -2: /* illegal block */
1524                 code = COAP_RESPONSE_CODE(CA_BAD_REQ);
1525                 OIC_LOG(ERROR, TAG, "write block option : -2");
1526                 goto error;
1527             case -1: /* should really not happen */
1528                 OIC_LOG(ERROR, TAG, "write block option : -1");
1529                 break;
1530             case -3: /* cannot handle request */
1531                 code = COAP_RESPONSE_CODE(CA_INTERNAL_SERVER_ERROR);
1532                 OIC_LOG(ERROR, TAG, "write block option : -3");
1533                 goto error;
1534             default:
1535                 OIC_LOG(INFO, TAG, "success write block option");
1536         }
1537         CALogBlockInfo(block2);
1538
1539         if (block1->num)
1540         {
1541             OIC_LOG(DEBUG, TAG, "combining block1 and block2");
1542             CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
1543             if (CA_STATUS_OK != res)
1544             {
1545                 OIC_LOG(ERROR, TAG, "add has failed");
1546                 CARemoveBlockDataFromList(blockID);
1547                 return res;
1548             }
1549             // initialize block number
1550             block1->num = 0;
1551         }
1552
1553         // if block number is 0, add size2 option
1554         if (0 == block2->num)
1555         {
1556             res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength);
1557             if (CA_STATUS_OK != res)
1558             {
1559                 OIC_LOG(ERROR, TAG, "add has failed");
1560                 CARemoveBlockDataFromList(blockID);
1561                 return res;
1562             }
1563         }
1564
1565         if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload,
1566                             block2->num, block2->szx))
1567         {
1568             OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
1569             return CA_STATUS_FAILED;
1570         }
1571
1572         if (!block2->m)
1573         {
1574             // if sent message is last response block message, remove data
1575             CARemoveBlockDataFromList(blockID);
1576         }
1577         else
1578         {
1579             if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type)
1580             {
1581                 OIC_LOG(DEBUG, TAG, "NON, send next block..");
1582                 // update block data
1583                 block2->num++;
1584                 CAResult_t res = CAProcessNextStep(*pdu, NULL,
1585                                                    CA_SENT_PREVIOUS_NON_MSG,
1586                                                    blockID);
1587                 if (CA_STATUS_OK != res)
1588                 {
1589                     OIC_LOG(ERROR, TAG, "failed to process next step");
1590                     CARemoveBlockDataFromList(blockID);
1591                     return res;
1592                 }
1593             }
1594         }
1595     }
1596     else
1597     {
1598         OIC_LOG(DEBUG, TAG, "option2, not ACK msg");
1599         CAResult_t res = CAAddBlockOptionImpl(*pdu, block2, COAP_OPTION_BLOCK2);
1600         if (CA_STATUS_OK != res)
1601         {
1602             OIC_LOG(ERROR, TAG, "add has failed");
1603             CARemoveBlockDataFromList(blockID);
1604             return res;
1605         }
1606     }
1607
1608     return CA_STATUS_OK;
1609
1610 error:
1611     OIC_LOG_V(ERROR, TAG, "error : %d", code);
1612
1613     char* phrase = coap_response_phrase(code);
1614     if(phrase)
1615     {
1616         coap_add_data(*pdu, strlen(phrase),
1617                       (unsigned char *) phrase);
1618     }
1619     return CA_STATUS_FAILED;
1620 }
1621
1622 CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
1623                              const CABlockDataID_t *blockID)
1624 {
1625     OIC_LOG(DEBUG, TAG, "IN-AddBlockOption1");
1626     VERIFY_NON_NULL(pdu, TAG, "pdu");
1627     VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1628     VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1629     VERIFY_NON_NULL(info, TAG, "info");
1630     VERIFY_NON_NULL(blockID, TAG, "blockID");
1631
1632     // get set block data from CABlock list-set.
1633     coap_block_t *block1 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK1);
1634     if (!block1)
1635     {
1636         OIC_LOG(ERROR, TAG, "getting has failed");
1637         return CA_STATUS_FAILED;
1638     }
1639
1640     CALogBlockInfo(block1);
1641
1642     if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type)
1643     {
1644         OIC_LOG(DEBUG, TAG, "option1 and ACK msg..");
1645         CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
1646         if (CA_STATUS_OK != res)
1647         {
1648             OIC_LOG(ERROR, TAG, "add has failed");
1649             CARemoveBlockDataFromList(blockID);
1650             return res;
1651         }
1652
1653         if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
1654         {
1655             OIC_LOG(ERROR, TAG, "failed to add payload");
1656             return CA_STATUS_FAILED;
1657         }
1658
1659         // reset block-list after write block
1660         if (0 == block1->m)
1661         {
1662             // remove data from list
1663             CAResult_t res = CARemoveBlockDataFromList(blockID);
1664             if (CA_STATUS_OK != res)
1665             {
1666                 OIC_LOG(ERROR, TAG, "remove has failed");
1667                 return res;
1668             }
1669         }
1670     }
1671     else
1672     {
1673         CAGetMoreBitFromBlock(dataLength, block1);
1674         CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
1675         if (CA_STATUS_OK != res)
1676         {
1677             OIC_LOG(ERROR, TAG, "add has failed");
1678             CARemoveBlockDataFromList(blockID);
1679             return res;
1680         }
1681         CALogBlockInfo(block1);
1682
1683         // if block number is 0, add size1 option
1684         if (0 == block1->num)
1685         {
1686             res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE1, dataLength);
1687             if (CA_STATUS_OK != res)
1688             {
1689                 OIC_LOG(ERROR, TAG, "add has failed");
1690                 CARemoveBlockDataFromList(blockID);
1691                 return res;
1692             }
1693         }
1694
1695         if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload,
1696                             block1->num, block1->szx))
1697         {
1698             OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
1699             return CA_STATUS_FAILED;
1700         }
1701
1702         // check the message type and if message type is NON, next block message will be sent
1703         if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type)
1704         {
1705             if (block1->m)
1706             {
1707                 OIC_LOG(DEBUG, TAG, "NON, send next block..");
1708                 // update block data
1709                 block1->num++;
1710                 CAResult_t res = CAProcessNextStep(*pdu, NULL,
1711                                                    CA_SENT_PREVIOUS_NON_MSG,
1712                                                    blockID);
1713                 if (CA_STATUS_OK != res)
1714                 {
1715                     OIC_LOG(ERROR, TAG, "failed to process next step");
1716                     CARemoveBlockDataFromList(blockID);
1717                     return res;
1718                 }
1719             }
1720             else
1721             {
1722                 CARemoveBlockDataFromList(blockID);
1723             }
1724         }
1725     }
1726
1727     OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption1");
1728
1729     return CA_STATUS_OK;
1730 }
1731
1732 CAResult_t CAAddBlockOptionImpl(coap_pdu_t *pdu, coap_block_t *block, uint8_t blockType)
1733 {
1734     OIC_LOG(DEBUG, TAG, "IN-AddBlockOptionImpl");
1735     VERIFY_NON_NULL(pdu, TAG, "pdu");
1736     VERIFY_NON_NULL(block, TAG, "block");
1737
1738     coap_option *option = (coap_option *) OICMalloc(sizeof(coap_option));
1739     if (!option)
1740     {
1741         OIC_LOG(ERROR, TAG, "out of memory");
1742         return CA_MEMORY_ALLOC_FAILED;
1743     }
1744
1745     unsigned char buf[BLOCKWISE_OPTION_BUFFER] = { 0 };
1746     option->key = blockType;
1747     option->length = coap_encode_var_bytes(buf,
1748                                            ((block->num << BLOCK_NUMBER_IDX)
1749                                             | (block->m << BLOCK_M_BIT_IDX) | block->szx));
1750     if (!coap_add_option(pdu, option->key, option->length, buf, coap_udp))
1751     {
1752         OIC_LOG(ERROR, TAG, "coap_add_option has failed");
1753         OICFree(option);
1754         return CA_STATUS_FAILED;
1755     }
1756
1757     OICFree(option);
1758
1759     OIC_LOG(DEBUG, TAG, "OUT-AddBlockOptionImpl");
1760     return CA_STATUS_OK;
1761 }
1762
1763 CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataLength)
1764 {
1765     OIC_LOG(DEBUG, TAG, "IN-CAAddBlockSizeOption");
1766     VERIFY_NON_NULL(pdu, TAG, "pdu");
1767
1768     if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2)
1769     {
1770         OIC_LOG(ERROR, TAG, "unknown option type");
1771         return CA_STATUS_FAILED;
1772     }
1773
1774     unsigned char value[BLOCKWISE_OPTION_BUFFER] = { 0 };
1775     unsigned int optionLength = coap_encode_var_bytes(value, dataLength);
1776
1777     if (!coap_add_option(pdu, sizeType, optionLength, value, coap_udp))
1778     {
1779         OIC_LOG(ERROR, TAG, "failed to add size option");
1780         return CA_STATUS_FAILED;
1781     }
1782
1783     OIC_LOG(DEBUG, TAG, "OUT-CAAddBlockSizeOption");
1784
1785     return CA_STATUS_OK;
1786 }
1787
1788 // TODO make pdu const after libcoap is updated to support that.
1789 bool CAIsPayloadLengthInPduWithBlockSizeOption(coap_pdu_t *pdu,
1790                                                uint16_t sizeType,
1791                                                size_t *totalPayloadLen)
1792 {
1793     OIC_LOG(DEBUG, TAG, "IN-CAIsPayloadLengthInPduWithBlockSizeOption");
1794     VERIFY_NON_NULL(pdu, TAG, "pdu");
1795     VERIFY_NON_NULL(totalPayloadLen, TAG, "totalPayloadLen");
1796
1797     if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2)
1798     {
1799         OIC_LOG(ERROR, TAG, "unknown option type");
1800         return CA_STATUS_FAILED;
1801     }
1802
1803     coap_opt_iterator_t opt_iter;
1804     coap_opt_t *option = coap_check_option(pdu, sizeType, &opt_iter);
1805     if (option)
1806     {
1807         OIC_LOG(DEBUG, TAG, "get size option from pdu");
1808         *totalPayloadLen = coap_decode_var_bytes(COAP_OPT_VALUE(option),
1809                                                  COAP_OPT_LENGTH(option));
1810
1811         OIC_LOG_V(DEBUG, TAG, "the total payload length to be received is [%d]bytes",
1812                   *totalPayloadLen);
1813
1814         return true;
1815     }
1816
1817     OIC_LOG(DEBUG, TAG, "OUT-CAIsPayloadLengthInPduWithBlockSizeOption");
1818
1819     return false;
1820 }
1821
1822 uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlock,
1823                               const CAData_t *receivedData, uint16_t blockType,
1824                               size_t dataLen)
1825 {
1826     OIC_LOG(DEBUG, TAG, "IN-CheckBlockError");
1827
1828     VERIFY_NON_NULL(currData, TAG, "currData is NULL");
1829     VERIFY_NON_NULL(receivedBlock, TAG, "receivedBlock is NULL");
1830     VERIFY_NON_NULL(receivedData, TAG, "receivedData is NULL");
1831
1832     // #1. check the received payload length
1833     size_t blockPayloadLen = 0;
1834     CAGetPayloadInfo(receivedData, &blockPayloadLen);
1835
1836     // #2. check if the block sequence is right
1837     if (COAP_OPTION_BLOCK1 == blockType)
1838     {
1839         size_t prePayloadLen = currData->receivedPayloadLen;
1840         if (prePayloadLen != (size_t)BLOCK_SIZE(receivedBlock->szx)
1841             * receivedBlock->num)
1842         {
1843             if (receivedBlock->num > currData->block1.num + 1)
1844             {
1845                 // 408 Error handling of block loss
1846                 OIC_LOG(ERROR, TAG, "option1: error 4.08");
1847                 OIC_LOG(ERROR, TAG, "it didn't order");
1848                 return CA_BLOCK_INCOMPLETE;
1849             }
1850             return CA_BLOCK_RECEIVED_ALREADY;
1851         }
1852     }
1853     else if (COAP_OPTION_BLOCK2 == blockType)
1854     {
1855         if (receivedBlock->num != currData->block2.num)
1856         {
1857             if (receivedBlock->num > currData->block2.num)
1858             {
1859                 // 408 Error handling of block loss
1860                 OIC_LOG(ERROR, TAG, "option2: error 4.08");
1861                 OIC_LOG(ERROR, TAG, "it didn't order");
1862                 return CA_BLOCK_INCOMPLETE;
1863             }
1864             return CA_BLOCK_RECEIVED_ALREADY;
1865         }
1866     }
1867
1868     // #3. check if error check logic is required
1869     size_t optionLen = dataLen - blockPayloadLen;
1870     if (receivedBlock->m && blockPayloadLen !=
1871         (size_t)BLOCK_SIZE(receivedBlock->szx))
1872     {
1873         // 413 Error handling of too large entity
1874         if (COAP_MAX_PDU_SIZE < BLOCK_SIZE(receivedBlock->szx) + optionLen)
1875         {
1876             // buffer size is smaller than received block size
1877             OIC_LOG(ERROR, TAG, "error type 4.13");
1878             OIC_LOG(ERROR, TAG, "too large size");
1879
1880             // set the block size to be smaller than COAP_MAX_PDU_SIZE
1881             for (int32_t size = CA_DEFAULT_BLOCK_SIZE; size >= 0; size--)
1882             {
1883                 if (COAP_MAX_PDU_SIZE >= BLOCK_SIZE(size) + optionLen)
1884                 {
1885                     OIC_LOG_V(ERROR, TAG, "replace sze with %d", size);
1886                     if (COAP_OPTION_BLOCK2 == blockType)
1887                     {
1888                         currData->block2.szx = size;
1889                     }
1890                     else
1891                     {
1892                         currData->block1.szx = size;
1893                     }
1894                     break;
1895                 }
1896             }
1897             return CA_BLOCK_TOO_LARGE;
1898         }
1899         else
1900         {
1901             // 408 Error handling of payload loss
1902             OIC_LOG(ERROR, TAG, "error type 4.08");
1903             OIC_LOG(ERROR, TAG, "payload len != block sze");
1904             return CA_BLOCK_INCOMPLETE;
1905         }
1906     }
1907     else if (0 == receivedBlock->m && 0 != currData->payloadLength)
1908     {
1909         // if the received block is last block, check the total payload length
1910         size_t receivedPayloadLen = currData->receivedPayloadLen;
1911         receivedPayloadLen += blockPayloadLen;
1912
1913         if (receivedPayloadLen != currData->payloadLength)
1914         {
1915             OIC_LOG(ERROR, TAG, "error type 4.08");
1916             OIC_LOG(ERROR, TAG, "total payload length is wrong");
1917             return CA_BLOCK_INCOMPLETE;
1918         }
1919     }
1920
1921     OIC_LOG(DEBUG, TAG, "received all data normally");
1922
1923     OIC_LOG(DEBUG, TAG, "OUT-CheckBlockError");
1924
1925     return CA_BLOCK_UNKNOWN;
1926 }
1927
1928 CAResult_t CAUpdatePayloadData(CABlockData_t *currData, const CAData_t *receivedData,
1929                                uint8_t status, bool isSizeOption, uint16_t blockType)
1930 {
1931     OIC_LOG(DEBUG, TAG, "IN-UpdatePayloadData");
1932
1933     VERIFY_NON_NULL(currData, TAG, "currData");
1934     VERIFY_NON_NULL(receivedData, TAG, "receivedData");
1935
1936     // if error code is 4.08, do not update payload
1937     if (CA_BLOCK_INCOMPLETE == status)
1938     {
1939         OIC_LOG(ERROR, TAG, "no require to update");
1940         return CA_STATUS_OK;
1941     }
1942
1943     size_t blockPayloadLen = 0;
1944     CAPayload_t blockPayload = CAGetPayloadInfo(receivedData, &blockPayloadLen);
1945
1946     if (CA_BLOCK_TOO_LARGE == status)
1947     {
1948         blockPayloadLen = (COAP_OPTION_BLOCK2 == blockType) ?
1949                 BLOCK_SIZE(currData->block2.szx) : BLOCK_SIZE(currData->block1.szx);
1950     }
1951
1952     // memory allocation for the received block payload
1953     size_t prePayloadLen = currData->receivedPayloadLen;
1954     if (blockPayload)
1955     {
1956         if (currData->payloadLength)
1957         {
1958             // in case the block message has the size option
1959             // allocate the memory for the total payload
1960             if (isSizeOption)
1961             {
1962                 CAPayload_t prePayload = currData->payload;
1963
1964                 OIC_LOG(DEBUG, TAG, "allocate memory for the total payload");
1965                 currData->payload = (CAPayload_t) OICCalloc(1, currData->payloadLength);
1966                 if (NULL == currData->payload)
1967                 {
1968                     OIC_LOG(ERROR, TAG, "out of memory");
1969                     return CA_MEMORY_ALLOC_FAILED;
1970                 }
1971                 memcpy(currData->payload, prePayload, prePayloadLen);
1972                 OICFree(prePayload);
1973             }
1974
1975             // update the total payload
1976             memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
1977         }
1978         else
1979         {
1980             OIC_LOG(DEBUG, TAG, "allocate memory for the received block payload");
1981
1982             size_t totalPayloadLen = prePayloadLen + blockPayloadLen;
1983             CAPayload_t newPayload = OICRealloc(currData->payload, totalPayloadLen);
1984             if (NULL == newPayload)
1985             {
1986                 OIC_LOG(ERROR, TAG, "out of memory");
1987                 return CA_MEMORY_ALLOC_FAILED;
1988             }
1989
1990             // update the total payload
1991             memset(newPayload + prePayloadLen, 0, blockPayloadLen);
1992             currData->payload = newPayload;
1993             memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
1994         }
1995
1996         // update received payload length
1997         currData->receivedPayloadLen += blockPayloadLen;
1998
1999         OIC_LOG_V(DEBUG, TAG, "updated payload: %s, len: %d", currData->payload,
2000                   currData->receivedPayloadLen);
2001     }
2002
2003     OIC_LOG(DEBUG, TAG, "OUT-UpdatePayloadData");
2004     return CA_STATUS_OK;
2005 }
2006
2007 CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint)
2008 {
2009     VERIFY_NON_NULL_RET(pdu, TAG, "pdu", NULL);
2010     VERIFY_NON_NULL_RET(pdu->hdr, TAG, "pdu->hdr", NULL);
2011     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
2012
2013     CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length };
2014     responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
2015     if (!responseData.token)
2016     {
2017         OIC_LOG(ERROR, TAG, "out of memory");
2018         return NULL;
2019     }
2020     memcpy(responseData.token, pdu->hdr->coap_hdr_udp_t.token, responseData.tokenLength);
2021
2022     CAResponseInfo_t* responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
2023     if (!responseInfo)
2024     {
2025         OIC_LOG(ERROR, TAG, "out of memory");
2026         OICFree(responseData.token);
2027         return NULL;
2028     }
2029     responseInfo->info = responseData;
2030
2031     CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
2032     if (!data)
2033     {
2034         OIC_LOG(ERROR, TAG, "out of memory");
2035         OICFree(responseInfo);
2036         return NULL;
2037     }
2038
2039     data->requestInfo = NULL;
2040     data->responseInfo = responseInfo;
2041     data->remoteEndpoint = CACloneEndpoint(endpoint);
2042     data->type = SEND_TYPE_UNICAST;
2043
2044     return data;
2045 }
2046
2047 CAData_t *CACloneCAData(const CAData_t *data)
2048 {
2049     VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
2050
2051     CAData_t *clone = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
2052     if (!clone)
2053     {
2054         OIC_LOG(ERROR, TAG, "out of memory");
2055         return NULL;
2056     }
2057     *clone = *data;
2058
2059     if (data->requestInfo)
2060     {
2061         clone->requestInfo = CACloneRequestInfo(data->requestInfo);
2062     }
2063     else if (data->responseInfo)
2064     {
2065         clone->responseInfo = CACloneResponseInfo(data->responseInfo);
2066     }
2067
2068     if (data->remoteEndpoint)
2069     {
2070         clone->remoteEndpoint = CACloneEndpoint(data->remoteEndpoint);
2071     }
2072
2073     return clone;
2074 }
2075
2076 CAResult_t CAUpdatePayloadToCAData(CAData_t *data, const CAPayload_t payload,
2077                                    size_t payloadLen)
2078 {
2079     OIC_LOG(DEBUG, TAG, "IN-UpdatePayload");
2080
2081     VERIFY_NON_NULL(data, TAG, "data is NULL");
2082     VERIFY_NON_NULL(payload, TAG, "payload is NULL");
2083
2084     CAPayload_t newPayload = NULL;
2085     switch (data->dataType)
2086     {
2087         case CA_REQUEST_DATA:
2088             if (!data->requestInfo)
2089             {
2090                 OIC_LOG(ERROR, TAG, "request info is null");
2091                 return CA_STATUS_FAILED;
2092             }
2093             // allocate payload field
2094             newPayload = OICRealloc(data->requestInfo->info.payload, payloadLen);
2095             if (!newPayload)
2096             {
2097                 OIC_LOG(ERROR, TAG, "out of memory");
2098                 return CA_STATUS_FAILED;
2099             }
2100             data->requestInfo->info.payload = newPayload;
2101             memcpy(data->requestInfo->info.payload, payload, payloadLen);
2102             data->requestInfo->info.payloadSize = payloadLen;
2103             break;
2104
2105         case CA_RESPONSE_DATA:
2106             if (!data->responseInfo)
2107             {
2108                 OIC_LOG(ERROR, TAG, "response info is null");
2109                 return CA_STATUS_FAILED;
2110             }
2111             // allocate payload field
2112             newPayload = OICRealloc(data->responseInfo->info.payload, payloadLen);
2113             if (!newPayload)
2114             {
2115                 OIC_LOG(ERROR, TAG, "out of memory");
2116                 return CA_STATUS_FAILED;
2117             }
2118             data->responseInfo->info.payload = newPayload;
2119             memcpy(data->responseInfo->info.payload, payload, payloadLen);
2120             data->responseInfo->info.payloadSize = payloadLen;
2121             break;
2122
2123         default:
2124             // does not occur case
2125             OIC_LOG(ERROR, TAG, "not supported data type");
2126             return CA_NOT_SUPPORTED;
2127     }
2128
2129     OIC_LOG(DEBUG, TAG, "OUT-UpdatePayload");
2130
2131     return CA_STATUS_OK;
2132 }
2133
2134 CAPayload_t CAGetPayloadInfo(const CAData_t *data, size_t *payloadLen)
2135 {
2136     VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
2137     VERIFY_NON_NULL_RET(payloadLen, TAG, "payloadLen", NULL);
2138
2139     if (data->requestInfo)
2140     {
2141         if (data->requestInfo->info.payload)
2142         {
2143             *payloadLen = data->requestInfo->info.payloadSize;
2144             return data->requestInfo->info.payload;
2145         }
2146     }
2147     else
2148     {
2149         if (data->responseInfo->info.payload)
2150         {
2151             *payloadLen = data->responseInfo->info.payloadSize;
2152             return data->responseInfo->info.payload;
2153         }
2154     }
2155
2156     return NULL;
2157 }
2158
2159 CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType,
2160                                       uint32_t responseResult)
2161 {
2162     OIC_LOG(DEBUG, TAG, "IN-HandleBlockErrorRes");
2163     VERIFY_NON_NULL(block, TAG, "block is NULL");
2164
2165     // update block data
2166     switch (responseResult)
2167     {
2168         case CA_REQUEST_ENTITY_INCOMPLETE:
2169             block->num = 0;
2170             break;
2171         case CA_REQUEST_ENTITY_TOO_LARGE:
2172             if (COAP_OPTION_BLOCK1 == blockType)
2173             {
2174                 block->num++;
2175             }
2176             block->m = 0;
2177             break;
2178         default:
2179             OIC_LOG_V(ERROR, TAG, "there is no Error Code of BWT[%d]", responseResult);
2180     }
2181
2182     OIC_LOG(DEBUG, TAG, "OUT-HandleBlockErrorRes");
2183     return CA_STATUS_OK;
2184 }
2185
2186 CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID,
2187                                    uint8_t blockType)
2188 {
2189     OIC_LOG(DEBUG, TAG, "IN-UpdateBlockOptionType");
2190     VERIFY_NON_NULL(blockID, TAG, "blockID");
2191
2192     ca_mutex_lock(g_context.blockDataListMutex);
2193
2194     size_t len = u_arraylist_length(g_context.dataList);
2195     for (size_t i = 0; i < len; i++)
2196     {
2197         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2198         if (CABlockidMatches(currData, blockID))
2199         {
2200             currData->type = blockType;
2201             ca_mutex_unlock(g_context.blockDataListMutex);
2202             OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
2203             return CA_STATUS_OK;
2204         }
2205     }
2206     ca_mutex_unlock(g_context.blockDataListMutex);
2207
2208     OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
2209     return CA_STATUS_FAILED;
2210 }
2211
2212 uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID)
2213 {
2214     OIC_LOG(DEBUG, TAG, "IN-GetBlockOptionType");
2215     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", 0);
2216
2217     ca_mutex_lock(g_context.blockDataListMutex);
2218
2219     size_t len = u_arraylist_length(g_context.dataList);
2220     for (size_t i = 0; i < len; i++)
2221     {
2222         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2223         if (CABlockidMatches(currData, blockID))
2224         {
2225             ca_mutex_unlock(g_context.blockDataListMutex);
2226             OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
2227             return currData->type;
2228         }
2229     }
2230     ca_mutex_unlock(g_context.blockDataListMutex);
2231
2232     OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
2233     return 0;
2234 }
2235
2236 CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID)
2237 {
2238     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2239
2240     ca_mutex_lock(g_context.blockDataListMutex);
2241
2242     size_t len = u_arraylist_length(g_context.dataList);
2243     for (size_t i = 0; i < len; i++)
2244     {
2245         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2246         if (CABlockidMatches(currData, blockID))
2247         {
2248             ca_mutex_unlock(g_context.blockDataListMutex);
2249             return currData->sentData;
2250         }
2251     }
2252     ca_mutex_unlock(g_context.blockDataListMutex);
2253
2254     return NULL;
2255 }
2256
2257 CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
2258                                        CAResponseInfo_t *responseInfo)
2259 {
2260     OIC_LOG(DEBUG, TAG, "IN-CAGetTokenFromBlockDataList");
2261     VERIFY_NON_NULL(pdu, TAG, "pdu");
2262     VERIFY_NON_NULL(endpoint, TAG, "endpoint");
2263     VERIFY_NON_NULL(responseInfo, TAG, "responseInfo");
2264
2265     ca_mutex_lock(g_context.blockDataListMutex);
2266
2267     size_t len = u_arraylist_length(g_context.dataList);
2268     for (size_t i = 0; i < len; i++)
2269     {
2270         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2271         if (NULL == currData)
2272         {
2273             continue;
2274         }
2275
2276         if (NULL != currData->sentData && NULL != currData->sentData->requestInfo)
2277         {
2278             if (pdu->hdr->coap_hdr_udp_t.id == currData->sentData->requestInfo->info.messageId &&
2279                     endpoint->adapter == currData->sentData->remoteEndpoint->adapter)
2280             {
2281                 if (NULL != currData->sentData->requestInfo->info.token)
2282                 {
2283                     uint8_t length = currData->sentData->requestInfo->info.tokenLength;
2284                     responseInfo->info.tokenLength = length;
2285                     responseInfo->info.token = (char *) OICMalloc(length);
2286                     if (NULL == responseInfo->info.token)
2287                     {
2288                         OIC_LOG(ERROR, TAG, "out of memory");
2289                         ca_mutex_unlock(g_context.blockDataListMutex);
2290                         return CA_MEMORY_ALLOC_FAILED;
2291                     }
2292                     memcpy(responseInfo->info.token, currData->sentData->requestInfo->info.token,
2293                            responseInfo->info.tokenLength);
2294
2295                     ca_mutex_unlock(g_context.blockDataListMutex);
2296                     OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
2297                     return CA_STATUS_OK;
2298                 }
2299             }
2300         }
2301     }
2302
2303     ca_mutex_unlock(g_context.blockDataListMutex);
2304
2305     OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
2306     return CA_STATUS_OK;
2307 }
2308
2309 CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t **blockData)
2310 {
2311     VERIFY_NON_NULL(sendData, TAG, "sendData");
2312     VERIFY_NON_NULL(blockData, TAG, "blockData");
2313
2314     ca_mutex_lock(g_context.blockDataListMutex);
2315
2316     size_t len = u_arraylist_length(g_context.dataList);
2317     for (size_t i = 0; i < len; i++)
2318     {
2319         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2320
2321         if (!currData)
2322         {
2323             continue;
2324         }
2325
2326         if (sendData->requestInfo) // sendData is requestMessage
2327         {
2328             OIC_LOG(DEBUG, TAG, "Send request");
2329             if (NULL != currData->blockDataId
2330                     && NULL != currData->blockDataId->id
2331                     && currData->blockDataId->idLength > 0
2332                     && NULL != sendData->requestInfo->info.token)
2333             {
2334                 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2335                         (CAToken_t)sendData->requestInfo->info.token,
2336                         sendData->requestInfo->info.tokenLength,
2337                         sendData->remoteEndpoint->port);
2338
2339                 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2340                 {
2341                     OIC_LOG(ERROR, TAG, "blockId is null");
2342                     CADestroyBlockID(blockDataID);
2343                     return CA_STATUS_FAILED;
2344                 }
2345
2346                 if (CABlockidMatches(currData, blockDataID))
2347                 {
2348                     OIC_LOG(ERROR, TAG, "already sent");
2349                     CADestroyBlockID(blockDataID);
2350                     continue;
2351                 }
2352                 CADestroyBlockID(blockDataID);
2353             }
2354         }
2355         else if (sendData->responseInfo) // sendData is responseMessage
2356         {
2357             OIC_LOG(DEBUG, TAG, "Send response");
2358             if (NULL != currData->blockDataId
2359                     && NULL != currData->blockDataId->id
2360                     && currData->blockDataId->idLength > 0
2361                     && NULL != sendData->responseInfo->info.token)
2362             {
2363                 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2364                         (CAToken_t)sendData->responseInfo->info.token,
2365                         sendData->responseInfo->info.tokenLength,
2366                         sendData->remoteEndpoint->port);
2367
2368                 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2369                 {
2370                     OIC_LOG(ERROR, TAG, "blockId is null");
2371                     CADestroyBlockID(blockDataID);
2372                     return CA_STATUS_FAILED;
2373                 }
2374
2375                 if (CABlockidMatches(currData, blockDataID))
2376                 {
2377                     // set sendData
2378                     if (NULL != currData->sentData)
2379                     {
2380                         OIC_LOG(DEBUG, TAG, "init block number");
2381                         CADestroyDataSet(currData->sentData);
2382                     }
2383                     currData->sentData = CACloneCAData(sendData);
2384                     *blockData = currData;
2385                     CADestroyBlockID(blockDataID);
2386                     ca_mutex_unlock(g_context.blockDataListMutex);
2387                     return CA_STATUS_OK;
2388                 }
2389                 CADestroyBlockID(blockDataID);
2390             }
2391         }
2392         else
2393         {
2394             OIC_LOG(ERROR, TAG, "no CAInfo data");
2395             continue;
2396         }
2397     }
2398     ca_mutex_unlock(g_context.blockDataListMutex);
2399
2400     return CA_STATUS_FAILED;
2401 }
2402
2403 CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID)
2404 {
2405     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2406
2407     ca_mutex_lock(g_context.blockDataListMutex);
2408
2409     size_t len = u_arraylist_length(g_context.dataList);
2410     for (size_t i = 0; i < len; i++)
2411     {
2412         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2413         if (CABlockidMatches(currData, blockID))
2414         {
2415             ca_mutex_unlock(g_context.blockDataListMutex);
2416             return currData;
2417         }
2418     }
2419     ca_mutex_unlock(g_context.blockDataListMutex);
2420
2421     return NULL;
2422 }
2423
2424 coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID,
2425                                uint16_t blockType)
2426 {
2427     OIC_LOG(DEBUG, TAG, "IN-GetBlockOption");
2428     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2429
2430     ca_mutex_lock(g_context.blockDataListMutex);
2431
2432     size_t len = u_arraylist_length(g_context.dataList);
2433     for (size_t i = 0; i < len; i++)
2434     {
2435         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2436         if (CABlockidMatches(currData, blockID))
2437         {
2438             ca_mutex_unlock(g_context.blockDataListMutex);
2439             OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
2440             if (COAP_OPTION_BLOCK2 == blockType)
2441             {
2442                 return &currData->block2;
2443             }
2444             else
2445             {
2446                 return &currData->block1;
2447             }
2448         }
2449     }
2450     ca_mutex_unlock(g_context.blockDataListMutex);
2451
2452     OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
2453     return NULL;
2454 }
2455
2456 CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID,
2457                                           size_t *fullPayloadLen)
2458 {
2459     OIC_LOG(DEBUG, TAG, "IN-GetFullPayload");
2460     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2461     VERIFY_NON_NULL_RET(fullPayloadLen, TAG, "fullPayloadLen", NULL);
2462
2463     ca_mutex_lock(g_context.blockDataListMutex);
2464
2465     size_t len = u_arraylist_length(g_context.dataList);
2466     for (size_t i = 0; i < len; i++)
2467     {
2468         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2469         if (CABlockidMatches(currData, blockID))
2470         {
2471             ca_mutex_unlock(g_context.blockDataListMutex);
2472             *fullPayloadLen = currData->receivedPayloadLen;
2473             OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
2474             return currData->payload;
2475         }
2476     }
2477     ca_mutex_unlock(g_context.blockDataListMutex);
2478
2479     OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
2480     return NULL;
2481 }
2482
2483 CABlockData_t *CACreateNewBlockData(const CAData_t *sendData)
2484 {
2485     OIC_LOG(DEBUG, TAG, "IN-CACreateNewBlockData");
2486     VERIFY_NON_NULL_RET(sendData, TAG, "sendData", NULL);
2487
2488     // create block data
2489     CABlockData_t *data = (CABlockData_t *) OICCalloc(1, sizeof(CABlockData_t));
2490     if (!data)
2491     {
2492         OIC_LOG(ERROR, TAG, "memory alloc has failed");
2493         return NULL;
2494     }
2495
2496     data->block1.szx = CA_DEFAULT_BLOCK_SIZE;
2497     data->block2.szx = CA_DEFAULT_BLOCK_SIZE;
2498     data->sentData = CACloneCAData(sendData);
2499     if(!data->sentData)
2500     {
2501         OIC_LOG(ERROR, TAG, PCF("memory alloc has failed"));
2502         OICFree(data);
2503         return NULL;
2504     }
2505
2506     CAToken_t token = NULL;
2507     uint8_t tokenLength = 0;
2508     if (data->sentData->requestInfo)
2509     {
2510         // update token info
2511         tokenLength = data->sentData->requestInfo->info.tokenLength;
2512         token = data->sentData->requestInfo->info.token;
2513     }
2514     else if(data->sentData->responseInfo)
2515     {
2516         tokenLength = data->sentData->responseInfo->info.tokenLength;
2517         token = data->sentData->responseInfo->info.token;
2518     }
2519
2520     CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2521             token, tokenLength,
2522             data->sentData->remoteEndpoint->port);
2523     if (NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2524     {
2525         OIC_LOG(ERROR, TAG, "blockId is null");
2526         CADestroyBlockID(blockDataID);
2527         CADestroyDataSet(data->sentData);
2528         OICFree(data);
2529         return NULL;
2530     }
2531     data->blockDataId = blockDataID;
2532
2533     ca_mutex_lock(g_context.blockDataListMutex);
2534
2535     bool res = u_arraylist_add(g_context.dataList, (void *) data);
2536     if (!res)
2537     {
2538         OIC_LOG(ERROR, TAG, "add has failed");
2539         CADestroyBlockID(data->blockDataId);
2540         CADestroyDataSet(data->sentData);
2541         OICFree(data);
2542         ca_mutex_unlock(g_context.blockDataListMutex);
2543         return NULL;
2544     }
2545     ca_mutex_unlock(g_context.blockDataListMutex);
2546
2547     OIC_LOG(DEBUG, TAG, "OUT-CreateBlockData");
2548     return data;
2549 }
2550
2551 CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
2552 {
2553     OIC_LOG(DEBUG, TAG, "CARemoveBlockData");
2554     VERIFY_NON_NULL(blockID, TAG, "blockID");
2555
2556     ca_mutex_lock(g_context.blockDataListMutex);
2557
2558     size_t len = u_arraylist_length(g_context.dataList);
2559     for (size_t i = 0; i < len; i++)
2560     {
2561         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2562         if (CABlockidMatches(currData, blockID))
2563         {
2564             CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i);
2565             if (!removedData)
2566             {
2567                 OIC_LOG(ERROR, TAG, "data is NULL");
2568                 ca_mutex_unlock(g_context.blockDataListMutex);
2569                 return CA_STATUS_FAILED;
2570             }
2571
2572             // destroy memory
2573             if (currData->sentData)
2574             {
2575                 CADestroyDataSet(currData->sentData);
2576             }
2577             CADestroyBlockID(currData->blockDataId);
2578             OICFree(currData->payload);
2579             OICFree(currData);
2580             ca_mutex_unlock(g_context.blockDataListMutex);
2581             return CA_STATUS_OK;
2582         }
2583     }
2584     ca_mutex_unlock(g_context.blockDataListMutex);
2585
2586     return CA_STATUS_OK;
2587 }
2588
2589 bool CAIsBlockDataInList(const CABlockDataID_t *blockID)
2590 {
2591     OIC_LOG(DEBUG, TAG, "IN-IsBlockDataInList");
2592     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false);
2593
2594     ca_mutex_lock(g_context.blockDataListMutex);
2595
2596     size_t len = u_arraylist_length(g_context.dataList);
2597     for (size_t i = 0; i < len; i++)
2598     {
2599         CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2600         if (CABlockidMatches(currData, blockID))
2601         {
2602             OIC_LOG(DEBUG, TAG, "found block data");
2603             ca_mutex_unlock(g_context.blockDataListMutex);
2604             return true;
2605         }
2606     }
2607     ca_mutex_unlock(g_context.blockDataListMutex);
2608
2609     OIC_LOG(DEBUG, TAG, "OUT-IsBlockDataInList");
2610     return false;
2611 }
2612
2613 void CADestroyDataSet(CAData_t* data)
2614 {
2615     VERIFY_NON_NULL_VOID(data, TAG, "data");
2616
2617     CAFreeEndpoint(data->remoteEndpoint);
2618     CADestroyRequestInfoInternal(data->requestInfo);
2619     CADestroyResponseInfoInternal(data->responseInfo);
2620     OICFree(data);
2621 }
2622
2623 CABlockDataID_t* CACreateBlockDatablockId(const CAToken_t token, uint8_t tokenLength,
2624                                           uint16_t portNumber)
2625 {
2626     VERIFY_NON_NULL_RET(token, TAG, "token", NULL);
2627
2628     char port[PORT_LENGTH] = {0,};
2629     port[0] = (char)((portNumber>>8) & 0xFF);
2630     port[1] = (char)(portNumber & 0xFF);
2631
2632     CABlockDataID_t* blockDataID = (CABlockDataID_t *) OICMalloc(sizeof(CABlockDataID_t));
2633     if (!blockDataID)
2634     {
2635         OIC_LOG(ERROR, TAG, "memory alloc has failed");
2636         return NULL;
2637     }
2638     blockDataID->idLength = tokenLength + sizeof(port);
2639     blockDataID->id = (uint8_t *) OICMalloc(blockDataID->idLength);
2640     if (!blockDataID->id)
2641     {
2642         OIC_LOG(ERROR, TAG, "memory alloc has failed");
2643         OICFree(blockDataID);
2644         return NULL;
2645     }
2646
2647     memcpy(blockDataID->id, token, tokenLength);
2648     memcpy(blockDataID->id + tokenLength, port, sizeof(port));
2649
2650     OIC_LOG(DEBUG, TAG, "BlockID is ");
2651     OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)blockDataID->id, blockDataID->idLength);
2652
2653     return blockDataID;
2654 }
2655
2656 void CADestroyBlockID(CABlockDataID_t *blockID)
2657 {
2658     VERIFY_NON_NULL_VOID(blockID, TAG, "blockID");
2659     OICFree(blockID->id);
2660     OICFree(blockID);
2661     blockID = NULL;
2662 }
2663
2664 bool CABlockidMatches(const CABlockData_t *currData, const CABlockDataID_t *blockID)
2665 {
2666     VERIFY_NON_NULL_RET(currData, TAG, "currData", false);
2667     VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false);
2668     VERIFY_NON_NULL_RET(blockID->id, TAG, "blockID->id", false);
2669
2670     if ((currData->blockDataId)
2671         && (currData->blockDataId->id)
2672         && (currData->blockDataId->idLength == blockID->idLength)
2673         && !memcmp(currData->blockDataId->id, blockID->id, currData->blockDataId->idLength))
2674     {
2675         return true;
2676     }
2677     return false;
2678 }
2679
2680 void CALogBlockInfo(coap_block_t *block)
2681 {
2682     VERIFY_NON_NULL_VOID(block, TAG, "block");
2683
2684     OIC_LOG(DEBUG, TAG, "block option info");
2685
2686     OIC_LOG_V(DEBUG, TAG, "block option-num : %d", block->num);
2687
2688     OIC_LOG_V(DEBUG, TAG, "block option-m   : %d", block->m);
2689
2690     OIC_LOG_V(DEBUG, TAG, "block option-szx : %d", block->szx);
2691 }