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