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