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