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