1 /* ****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
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
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
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"
48 #define BLOCKWISE_OPTION_BUFFER (sizeof(unsigned int))
49 #define BLOCK_NUMBER_IDX 4
50 #define BLOCK_M_BIT_IDX 3
53 #define BLOCK_SIZE(arg) (1 << ((arg) + 4))
55 // context for block-wise transfer
56 static CABlockWiseContext_t g_context = { 0 };
58 CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc,
59 CAReceiveThreadFunc receivedThreadFunc)
61 OIC_LOG(DEBUG, TAG, "initialize");
63 // set block-wise transfer context
64 if (!g_context.sendThreadFunc)
66 g_context.sendThreadFunc = sendThreadFunc;
69 if (!g_context.receivedThreadFunc)
71 g_context.receivedThreadFunc = receivedThreadFunc;
74 if (!g_context.dataList)
76 g_context.dataList = u_arraylist_create();
79 CAResult_t res = CAInitBlockWiseMutexVariables();
80 if (CA_STATUS_OK != res)
82 OIC_LOG(ERROR, TAG, "init has failed");
88 CAResult_t CATerminateBlockWiseTransfer()
90 OIC_LOG(DEBUG, TAG, "terminate");
92 if (g_context.dataList)
94 u_arraylist_free(&g_context.dataList);
97 CATerminateBlockWiseMutexVariables();
102 CAResult_t CAInitBlockWiseMutexVariables()
104 OIC_LOG(DEBUG, TAG, "IN");
106 if (NULL == g_context.blockDataListMutex)
108 g_context.blockDataListMutex = ca_mutex_new();
109 if (NULL == g_context.blockDataListMutex)
111 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
112 return CA_STATUS_FAILED;
116 if (NULL == g_context.blockDataSenderMutex)
118 g_context.blockDataSenderMutex = ca_mutex_new();
119 if (NULL == g_context.blockDataSenderMutex)
121 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
122 CATerminateBlockWiseMutexVariables();
123 return CA_STATUS_FAILED;
130 void CATerminateBlockWiseMutexVariables()
132 OIC_LOG(DEBUG, TAG, "IN");
134 if (g_context.blockDataListMutex)
136 ca_mutex_free(g_context.blockDataListMutex);
137 g_context.blockDataListMutex = NULL;
140 if (g_context.blockDataSenderMutex)
142 ca_mutex_free(g_context.blockDataSenderMutex);
143 g_context.blockDataSenderMutex = NULL;
147 CAResult_t CASendBlockWiseData(const CAData_t *sendData)
149 VERIFY_NON_NULL(sendData, TAG, "sendData");
151 // check if message type is CA_MSG_RESET
152 if (NULL != sendData->responseInfo)
154 if (CA_MSG_RESET == sendData->responseInfo->info.type)
156 OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block");
157 return CA_NOT_SUPPORTED;
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)
166 // #2. if it is not included, add the data into list
167 if (NULL == currData)
169 OIC_LOG(DEBUG, TAG, "There is no block data");
170 currData = CACreateNewBlockData(sendData);
171 if (NULL == currData)
173 OIC_LOG(ERROR, TAG, "failed to create block data");
174 return CA_MEMORY_ALLOC_FAILED;
179 // #3. check request/response block option type and payload length
180 res = CACheckBlockOptionType(currData);
181 if (CA_STATUS_OK == res)
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)
188 OIC_LOG(ERROR, TAG, "add has failed");
196 CAResult_t CAAddSendThreadQueue(const CAData_t *sendData, const CABlockDataID_t *blockID)
198 VERIFY_NON_NULL(sendData, TAG, "sendData");
199 VERIFY_NON_NULL(blockID, TAG, "blockID");
201 CAData_t *cloneData = CACloneCAData(sendData);
202 if (NULL == cloneData)
204 OIC_LOG(ERROR, TAG, "clone has failed");
205 CARemoveBlockDataFromList(blockID);
206 return CA_STATUS_FAILED;
209 if (g_context.sendThreadFunc)
211 ca_mutex_lock(g_context.blockDataSenderMutex);
212 g_context.sendThreadFunc(cloneData);
213 ca_mutex_unlock(g_context.blockDataSenderMutex);
217 CADestroyDataSet(cloneData);
222 CAResult_t CACheckBlockOptionType(CABlockData_t *currData)
224 VERIFY_NON_NULL(currData, TAG, "currData");
225 VERIFY_NON_NULL(currData->sentData, TAG, "currData->sentData");
227 size_t payloadLen = 0;
228 CAGetPayloadInfo(currData->sentData, &payloadLen);
230 // check if message has to be transfered to a block
231 size_t maxBlockSize = BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE);
232 if (payloadLen <= maxBlockSize)
234 OIC_LOG_V(DEBUG, TAG, "payloadLen=%d, maxBlockSize=%d", payloadLen, maxBlockSize);
235 return CA_NOT_SUPPORTED;
238 // set block option (COAP_OPTION_BLOCK2 or COAP_OPTION_BLOCK1)
239 if (NULL != currData->sentData->requestInfo) // request message
241 currData->type = COAP_OPTION_BLOCK1;
243 else // response message
245 currData->type = COAP_OPTION_BLOCK2;
251 // TODO make pdu const after libcoap is updated to support that.
252 CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
253 const CAData_t *receivedData, size_t dataLen)
255 OIC_LOG(DEBUG, TAG, "CAReceiveBlockWiseData");
256 VERIFY_NON_NULL(pdu, TAG, "pdu");
257 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
258 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
259 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
261 // check if received message type is CA_MSG_RESET
262 if (CA_EMPTY == pdu->hdr->code)
264 OIC_LOG(DEBUG, TAG, "code is CA_EMPTY..");
266 // get token from block-wise transfer list when CA_EMPTY(RST/ACK) is received
267 CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint, receivedData->responseInfo);
268 if (CA_STATUS_OK != res)
270 OIC_LOG(ERROR, TAG, "fail to get token");
274 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
275 receivedData->responseInfo->info.token,
276 receivedData->responseInfo->info.tokenLength,
278 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
280 OIC_LOG(ERROR, TAG, "blockId is null");
281 CADestroyBlockID(blockDataID);
282 return CA_STATUS_FAILED;
285 CARemoveBlockDataFromList(blockDataID);
286 CADestroyBlockID(blockDataID);
287 return CA_NOT_SUPPORTED;
290 // check if block option is set and get block data
291 coap_block_t block = {0, 0, 0};
294 int isBlock1 = coap_get_block(pdu, COAP_OPTION_BLOCK1, &block);
297 CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, block, dataLen);
298 if (CA_STATUS_OK != res)
300 OIC_LOG(ERROR, TAG, "setting has failed");
306 int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block);
309 CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, block, dataLen);
310 if (CA_STATUS_OK != res)
312 OIC_LOG(ERROR, TAG, "setting has failed");
317 // check if there is error code
318 if (!isBlock1 && !isBlock2)
320 uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code);
321 if (CA_REQUEST_ENTITY_INCOMPLETE == code)
323 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
324 (CAToken_t)pdu->hdr->token,
325 pdu->hdr->token_length,
328 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
330 OIC_LOG(ERROR, TAG, "blockId is null");
331 CADestroyBlockID(blockDataID);
332 return CA_STATUS_FAILED;
335 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
338 OIC_LOG(ERROR, TAG, "getting has failed");
339 CADestroyBlockID(blockDataID);
340 return CA_STATUS_FAILED;
343 if (COAP_OPTION_BLOCK2 == data->type)
345 coap_block_t *block2 = CAGetBlockOption(blockDataID,
349 OIC_LOG(ERROR, TAG, "block is null");
350 CADestroyBlockID(blockDataID);
351 return CA_STATUS_FAILED;
354 CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, *block2,
356 if (CA_STATUS_OK != res)
358 OIC_LOG(ERROR, TAG, "setting has failed");
359 CADestroyBlockID(blockDataID);
363 else if (COAP_OPTION_BLOCK1 == data->type)
365 coap_block_t *block1 = CAGetBlockOption(blockDataID,
369 OIC_LOG(ERROR, TAG, "block is null");
370 CADestroyBlockID(blockDataID);
371 return CA_STATUS_FAILED;
374 CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, *block1,
376 if (CA_STATUS_OK != res)
378 OIC_LOG(ERROR, TAG, "setting has failed");
379 CADestroyBlockID(blockDataID);
387 OIC_LOG(DEBUG, TAG, "it's normal pdu");
389 // if received data is response message
390 // and sent data remain in block data list, remove block data
391 if (receivedData->responseInfo)
393 CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint,
394 receivedData->responseInfo);
395 if (CA_STATUS_OK != res)
397 OIC_LOG(ERROR, TAG, "fail to get token");
401 return CA_NOT_SUPPORTED;
408 CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData,
409 uint8_t blockWiseStatus, const CABlockDataID_t *blockID)
411 VERIFY_NON_NULL(pdu, TAG, "pdu");
412 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
413 VERIFY_NON_NULL(blockID, TAG, "blockID");
415 CAResult_t res = CA_STATUS_OK;
416 CAData_t *data = NULL;
418 // process blockWiseStatus
419 switch (blockWiseStatus)
421 case CA_OPTION2_FIRST_BLOCK:
422 res = CAAddSendThreadQueue(receivedData, blockID);
423 if (CA_STATUS_OK != res)
425 OIC_LOG(ERROR, TAG, "add has failed");
431 // add data to send thread
432 data = CAGetDataSetFromBlockDataList(blockID);
435 OIC_LOG(ERROR, TAG, "it's unavailable");
436 return CA_STATUS_FAILED;
439 if (data->requestInfo)
441 data->requestInfo->info.messageId = pdu->hdr->id;
444 if (data->responseInfo)
446 data->responseInfo->info.messageId = pdu->hdr->id;
449 res = CAAddSendThreadQueue(data, blockID);
450 if (CA_STATUS_OK != res)
452 OIC_LOG(ERROR, TAG, "add has failed");
460 case CA_SENT_PREVIOUS_NON_MSG:
461 res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
463 if (CA_STATUS_OK != res)
465 OIC_LOG(ERROR, TAG, "send has failed");
470 case CA_OPTION2_LAST_BLOCK:
471 // process last block and send upper layer
472 res = CAReceiveLastBlock(blockID, receivedData);
473 if (CA_STATUS_OK != res)
475 OIC_LOG(ERROR, TAG, "receive has failed");
479 // remove data from list
480 res = CARemoveBlockDataFromList(blockID);
481 if (CA_STATUS_OK != res)
483 OIC_LOG(ERROR, TAG, "remove has failed");
488 case CA_OPTION1_NO_ACK_LAST_BLOCK:
489 // process last block and send upper layer
490 res = CAReceiveLastBlock(blockID, receivedData);
491 if (CA_STATUS_OK != res)
493 OIC_LOG(ERROR, TAG, "receive has failed");
497 if (CA_MSG_NONCONFIRM == pdu->hdr->type)
499 // remove data from list
500 res = CARemoveBlockDataFromList(blockID);
501 if (CA_STATUS_OK != res)
503 OIC_LOG(ERROR, TAG, "remove has failed");
509 case CA_OPTION1_NO_ACK_BLOCK:
510 if (CA_MSG_CONFIRM == pdu->hdr->type)
512 // add data to send thread
513 res = CASendBlockMessage(pdu, CA_MSG_ACKNOWLEDGE, blockWiseStatus,
515 if (CA_STATUS_OK != res)
517 OIC_LOG(ERROR, TAG, "send has failed");
523 case CA_BLOCK_INCOMPLETE:
524 if (CA_MSG_CONFIRM == pdu->hdr->type || CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
526 // add data to send thread
527 res = CASendErrorMessage(pdu, blockWiseStatus,
528 CA_REQUEST_ENTITY_INCOMPLETE,
530 if (CA_STATUS_OK != res)
532 OIC_LOG(ERROR, TAG, "send has failed");
538 case CA_BLOCK_TOO_LARGE:
539 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
541 res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
543 if (CA_STATUS_OK != res)
545 OIC_LOG(ERROR, TAG, "send has failed");
549 else if (CA_MSG_CONFIRM == pdu->hdr->type)
551 res = CASendErrorMessage(pdu, blockWiseStatus,
552 CA_REQUEST_ENTITY_TOO_LARGE,
554 if (CA_STATUS_OK != res)
556 OIC_LOG(ERROR, TAG, "send has failed");
562 OIC_LOG_V(ERROR, TAG, "no logic [%d]", blockWiseStatus);
567 CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType,
568 uint8_t status, const CABlockDataID_t *blockID)
570 VERIFY_NON_NULL(pdu, TAG, "pdu");
571 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
572 VERIFY_NON_NULL(blockID, TAG, "blockID");
574 CAData_t *data = CAGetDataSetFromBlockDataList(blockID);
577 OIC_LOG(ERROR, TAG, "CAData is unavailable");
578 return CA_STATUS_FAILED;
581 if (CA_MSG_CONFIRM == msgType)
583 OIC_LOG(DEBUG, TAG, "need new msgID");
584 if (data->requestInfo)
586 data->requestInfo->info.messageId = 0;
589 if (data->responseInfo)
591 data->responseInfo->info.messageId = 0;
594 else if (CA_MSG_ACKNOWLEDGE == msgType)
596 if (data->responseInfo)
598 OIC_LOG(DEBUG, TAG, "set ACK message");
599 data->responseInfo->info.messageId = pdu->hdr->id;
600 data->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
601 if (CA_OPTION1_NO_ACK_LAST_BLOCK == status)
603 data->responseInfo->result = CA_CHANGED;
605 else if (CA_OPTION1_NO_ACK_BLOCK == status)
607 data->responseInfo->result = CA_CONTINUE;
612 // add data to send thread
613 CAResult_t res = CAAddSendThreadQueue(data, blockID);
614 if (CA_STATUS_OK != res)
616 OIC_LOG(ERROR, TAG, "add has failed");
622 CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
623 CAResponseResult_t responseResult,
624 const CABlockDataID_t *blockID)
626 VERIFY_NON_NULL(pdu, TAG, "pdu");
627 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
628 VERIFY_NON_NULL(blockID, TAG, "blockID");
630 // create error responseInfo
631 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockID);
634 OIC_LOG(ERROR, TAG, "data is unavailable");
635 return CA_STATUS_FAILED;
638 CAData_t *cloneData = NULL;
639 if (data->sentData && data->sentData->responseInfo)
641 data->sentData->responseInfo->info.messageId = pdu->hdr->id;
642 data->sentData->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
643 data->sentData->responseInfo->result = responseResult;
644 cloneData = CACloneCAData(data->sentData);
645 if (NULL == cloneData)
647 OIC_LOG(ERROR, TAG, "clone has failed");
648 return CA_MEMORY_ALLOC_FAILED;
650 OIC_LOG(DEBUG, TAG, "set ACK message");
652 else if (data->sentData)
654 cloneData = CACreateNewDataSet(pdu, data->sentData->remoteEndpoint);
658 OIC_LOG(ERROR, TAG, PCF("CACreateNewDataSet failed"));
659 return CA_MEMORY_ALLOC_FAILED;
662 cloneData->responseInfo->info.type = CA_MSG_CONFIRM;
663 cloneData->responseInfo->result = responseResult;
664 OIC_LOG(DEBUG, TAG, "set CON message");
668 OIC_LOG(ERROR, TAG, "data has no sent-data");
669 return CA_MEMORY_ALLOC_FAILED;
672 // add data to send thread
673 if (g_context.sendThreadFunc)
675 ca_mutex_lock(g_context.blockDataSenderMutex);
676 g_context.sendThreadFunc(cloneData);
677 ca_mutex_unlock(g_context.blockDataSenderMutex);
681 CADestroyDataSet(cloneData);
684 // if error code is 4.08, remove the stored payload and initialize block number
685 if (CA_BLOCK_INCOMPLETE == status)
687 OICFree(data->payload);
688 data->payload = NULL;
689 data->payloadLength = 0;
690 data->receivedPayloadLen = 0;
691 data->block1.num = 0;
692 data->block2.num = 0;
698 CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID,
699 const CAData_t *receivedData)
701 VERIFY_NON_NULL(blockID, TAG, "blockID");
702 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
704 // total block data have to notify to Application
705 CAData_t *cloneData = CACloneCAData(receivedData);
706 if (NULL == cloneData)
708 OIC_LOG(ERROR, TAG, "clone has failed");
709 return CA_MEMORY_ALLOC_FAILED;
713 size_t fullPayloadLen = 0;
714 CAPayload_t fullPayload = CAGetPayloadFromBlockDataList(blockID,
716 if (NULL != fullPayload)
718 CAResult_t res = CAUpdatePayloadToCAData(cloneData, fullPayload, fullPayloadLen);
719 if (CA_STATUS_OK != res)
721 OIC_LOG(ERROR, TAG, "update has failed");
722 CADestroyDataSet(cloneData);
723 return CA_STATUS_FAILED;
727 if (g_context.receivedThreadFunc)
729 g_context.receivedThreadFunc(cloneData);
733 CADestroyDataSet(cloneData);
739 // TODO make pdu const after libcoap is updated to support that.
740 CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
741 const CAData_t *receivedData, coap_block_t block,
744 OIC_LOG(INFO, TAG, "CASetNextBlockOption1");
745 VERIFY_NON_NULL(pdu, TAG, "pdu");
746 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
747 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
748 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
750 OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
752 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
753 (CAToken_t)pdu->hdr->token,
754 pdu->hdr->token_length,
757 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
759 OIC_LOG(ERROR, TAG, "blockId is null");
760 CADestroyBlockID(blockDataID);
761 return CA_STATUS_FAILED;
764 // BlockData data is created if it not existed
765 if (!CAIsBlockDataInList(blockDataID))
767 OIC_LOG(DEBUG, TAG, "no message in list");
769 CAData_t *data = CACreateNewDataSet(pdu, endpoint);
772 OIC_LOG(ERROR, TAG, "data is null");
773 CADestroyBlockID(blockDataID);
774 return CA_STATUS_FAILED;
777 CABlockData_t *currData = CACreateNewBlockData(data);
778 if (NULL == currData)
780 OIC_LOG(ERROR, TAG, "currData is null");
781 CADestroyDataSet(data);
782 CADestroyBlockID(blockDataID);
783 return CA_STATUS_FAILED;
787 // update BLOCK OPTION1 type
788 CAResult_t res = CAUpdateBlockOptionType(blockDataID,
790 if (CA_STATUS_OK != res)
792 OIC_LOG(ERROR, TAG, "update has failed");
793 CARemoveBlockDataFromList(blockDataID);
794 CADestroyBlockID(blockDataID);
798 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
801 OIC_LOG(ERROR, TAG, "getting has failed");
802 CADestroyBlockID(blockDataID);
803 return CA_STATUS_FAILED;
806 uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
807 // received type from remote device
808 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
810 uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code);
812 (CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code))
814 OIC_LOG(INFO, TAG, "Data has sent");
815 // initialize block number for response message
816 data->block1.num = 0;
817 CADestroyBlockID(blockDataID);
821 blockWiseStatus = CA_OPTION1_ACK;
822 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus);
823 if (CA_STATUS_OK != res)
825 OIC_LOG(ERROR, TAG, "update has failed");
826 CADestroyBlockID(blockDataID);
830 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1);
831 if (CA_STATUS_OK != res)
833 OIC_LOG(ERROR, TAG, "update has failed");
834 CARemoveBlockDataFromList(blockDataID);
835 CADestroyBlockID(blockDataID);
839 else // CON or NON message
841 OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m);
843 // check the size option
844 bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu,
846 &(data->payloadLength));
848 // check if received payload is exact
849 if (CA_MSG_CONFIRM == pdu->hdr->type)
851 blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
852 COAP_OPTION_BLOCK1, dataLen);
855 if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus)
857 // store the received payload and merge
858 res = CAUpdatePayloadData(data, receivedData, blockWiseStatus,
859 isSizeOption, COAP_OPTION_BLOCK1);
860 if (CA_STATUS_OK != res)
862 OIC_LOG(ERROR, TAG, "update has failed");
863 CARemoveBlockDataFromList(blockDataID);
864 CADestroyBlockID(blockDataID);
868 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus);
869 if (CA_STATUS_OK != res)
871 OIC_LOG(ERROR, TAG, "update has failed");
872 CARemoveBlockDataFromList(blockDataID);
873 CADestroyBlockID(blockDataID);
878 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1);
879 if (CA_STATUS_OK != res)
881 OIC_LOG(ERROR, TAG, "update has failed");
882 CARemoveBlockDataFromList(blockDataID);
883 CADestroyBlockID(blockDataID);
888 // check the blcok-wise transfer status for next step
889 if (CA_BLOCK_UNKNOWN == blockWiseStatus || CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)
891 if (0 == block.m) // Last block is received
893 OIC_LOG(DEBUG, TAG, "M bit is 0");
894 blockWiseStatus = CA_OPTION1_NO_ACK_LAST_BLOCK;
898 OIC_LOG(DEBUG, TAG, "M bit is 1");
899 blockWiseStatus = CA_OPTION1_NO_ACK_BLOCK;
904 res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID);
905 if (CA_STATUS_OK != res)
907 OIC_LOG(ERROR, TAG, "setting has failed");
908 CARemoveBlockDataFromList(blockDataID);
911 CADestroyBlockID(blockDataID);
915 // TODO make pdu const after libcoap is updated to support that.
916 CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
917 const CAData_t *receivedData, coap_block_t block,
920 OIC_LOG(DEBUG, TAG, "CASetNextBlockOption2");
921 OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
923 VERIFY_NON_NULL(pdu, TAG, "pdu");
924 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
925 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
926 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
928 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
929 (CAToken_t)pdu->hdr->token,
930 pdu->hdr->token_length,
933 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
935 OIC_LOG(ERROR, TAG, "blockId is null");
936 CADestroyBlockID(blockDataID);
937 return CA_STATUS_FAILED;
940 // BlockData data is created if it not existed
941 if (!CAIsBlockDataInList(blockDataID))
943 OIC_LOG(DEBUG, TAG, "no msg in list.");
945 CAData_t *data = CACreateNewDataSet(pdu, endpoint);
948 OIC_LOG(ERROR, TAG, "data is null");
949 CADestroyBlockID(blockDataID);
950 return CA_STATUS_FAILED;
953 CABlockData_t *currData = CACreateNewBlockData(data);
954 if (NULL == currData)
956 OIC_LOG(ERROR, TAG, "data is null");
957 CADestroyDataSet(data);
958 CADestroyBlockID(blockDataID);
959 return CA_STATUS_FAILED;
963 // set Block Option Type
964 CAResult_t res = CAUpdateBlockOptionType(blockDataID,
966 if (CA_STATUS_OK != res)
968 OIC_LOG(ERROR, TAG, "update has failed");
969 CARemoveBlockDataFromList(blockDataID);
970 CADestroyBlockID(blockDataID);
974 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
977 OIC_LOG(ERROR, TAG, "getting has failed");
978 CARemoveBlockDataFromList(blockDataID);
979 CADestroyBlockID(blockDataID);
980 return CA_STATUS_FAILED;
983 uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
984 if (0 == block.num && CA_GET == pdu->hdr->code && 0 == block.m)
986 OIC_LOG(INFO, TAG, "first block number");
988 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus);
989 if (CA_STATUS_OK != res)
991 OIC_LOG(ERROR, TAG, "update has failed");
992 CARemoveBlockDataFromList(blockDataID);
993 CADestroyBlockID(blockDataID);
997 // first block data have to notify to Application
998 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
999 if (CA_STATUS_OK != res)
1001 OIC_LOG(ERROR, TAG, "update has failed");
1002 CARemoveBlockDataFromList(blockDataID);
1003 CADestroyBlockID(blockDataID);
1006 blockWiseStatus = CA_OPTION2_FIRST_BLOCK;
1010 // received type from remote device
1011 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type ||
1012 (CA_MSG_NONCONFIRM == pdu->hdr->type && NULL != receivedData->responseInfo))
1014 OIC_LOG(DEBUG, TAG, "received ACK or NON");
1016 // check the size option
1017 bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu,
1019 &(data->payloadLength));
1021 // check if received payload is exact
1022 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
1024 blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
1025 COAP_OPTION_BLOCK2, dataLen);
1028 if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus)
1030 // store the received payload and merge
1031 res = CAUpdatePayloadData(data, receivedData, blockWiseStatus,
1032 isSizeOption, COAP_OPTION_BLOCK2);
1033 if (CA_STATUS_OK != res)
1035 OIC_LOG(ERROR, TAG, "update has failed");
1036 CARemoveBlockDataFromList(blockDataID);
1037 CADestroyBlockID(blockDataID);
1042 if (0 == block.m && CA_BLOCK_UNKNOWN == blockWiseStatus) // Last block is received
1044 OIC_LOG(DEBUG, TAG, "M bit is 0");
1045 blockWiseStatus = CA_OPTION2_LAST_BLOCK;
1049 if (CA_BLOCK_UNKNOWN == blockWiseStatus ||
1050 CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)
1052 OIC_LOG(DEBUG, TAG, "M bit is 1");
1054 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
1056 blockWiseStatus = CA_OPTION2_ACK;
1060 blockWiseStatus = CA_OPTION2_NON;
1064 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2,
1066 if (CA_STATUS_OK != res)
1068 OIC_LOG(ERROR, TAG, "update has failed");
1069 CARemoveBlockDataFromList(blockDataID);
1070 CADestroyBlockID(blockDataID);
1074 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1075 if (CA_STATUS_OK != res)
1077 OIC_LOG(ERROR, TAG, "update has failed");
1078 CARemoveBlockDataFromList(blockDataID);
1079 CADestroyBlockID(blockDataID);
1084 else // CON message and so on.
1086 OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m);
1088 blockWiseStatus = CA_OPTION2_CON;
1090 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus);
1091 if (CA_STATUS_OK != res)
1093 OIC_LOG(ERROR, TAG, "update has failed");
1094 CARemoveBlockDataFromList(blockDataID);
1095 CADestroyBlockID(blockDataID);
1099 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1100 if (CA_STATUS_OK != res)
1102 OIC_LOG(ERROR, TAG, "update has failed");
1103 CARemoveBlockDataFromList(blockDataID);
1104 CADestroyBlockID(blockDataID);
1110 res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID);
1111 if (CA_STATUS_OK != res)
1113 OIC_LOG(ERROR, TAG, "setting has failed");
1114 CARemoveBlockDataFromList(blockDataID);
1115 CADestroyBlockID(blockDataID);
1119 CADestroyBlockID(blockDataID);
1120 return CA_STATUS_OK;
1123 CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *pdu,
1124 coap_block_t *block, uint16_t blockType,
1127 VERIFY_NON_NULL(currData, TAG, "currData");
1128 VERIFY_NON_NULL(pdu, TAG, "pdu");
1129 VERIFY_NON_NULL(block, TAG, "block");
1131 // update block data
1132 CAResult_t res = CA_STATUS_OK;
1133 uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code);
1135 if (CA_REQUEST_ENTITY_INCOMPLETE == code || CA_REQUEST_ENTITY_TOO_LARGE == code)
1137 // response error code of the received block message
1138 res = CAHandleBlockErrorResponse(block, blockType, code);
1139 if (CA_STATUS_OK != res)
1141 OIC_LOG(ERROR, TAG, "error handle has failed");
1147 // update block option items
1150 case CA_OPTION1_ACK:
1151 if (currData->block1.num > block->num)
1153 OIC_LOG(ERROR, TAG, "received incorrect block num");
1154 return CA_STATUS_FAILED;
1158 case CA_OPTION2_NON:
1162 case CA_OPTION2_CON:
1165 case CA_OPTION2_ACK:
1166 if (currData->block2.num > block->num)
1168 OIC_LOG(ERROR, TAG, "received incorrect block num");
1169 return CA_STATUS_FAILED;
1174 case CA_BLOCK_TOO_LARGE:
1175 // if state of received block message is CA_BLOCK_TOO_LARGE or CA_BLOCK_INCOMPLETE
1176 // we set the response error code appropriately and send
1177 if (COAP_OPTION_BLOCK2 == blockType)
1181 block->szx = currData->block2.szx;
1185 block->szx = currData->block1.szx;
1189 OIC_LOG_V(ERROR, TAG, "no logic [%d]", status);
1192 if (CA_BLOCK_INCOMPLETE != status && CA_BLOCK_TOO_LARGE != status)
1194 // negotiate block size
1195 res = CANegotiateBlockSize(currData, block, pdu->hdr->type, blockType);
1196 if (CA_STATUS_OK != res)
1198 OIC_LOG(ERROR, TAG, "negotiation has failed");
1206 CAResult_t CAGetMoreBitFromBlock(size_t payloadLen, coap_block_t *block)
1208 VERIFY_NON_NULL(block, TAG, "block");
1210 if ((size_t)((block->num + 1) << (block->szx + BLOCK_NUMBER_IDX))
1213 OIC_LOG(DEBUG, TAG, "Set the M-bit(1)");
1218 OIC_LOG(DEBUG, TAG, "Set the M-bit(0)");
1222 return CA_STATUS_OK;
1225 CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block,
1226 CAMessageType_t msgType, uint16_t blockType)
1228 OIC_LOG(DEBUG, TAG, "IN-NegotiateBlockSize");
1230 VERIFY_NON_NULL(currData, TAG, "currData");
1231 VERIFY_NON_NULL(block, TAG, "block");
1233 // #1. check the block option type
1234 if (COAP_OPTION_BLOCK2 == blockType)
1236 // #2. check the message type
1237 if (CA_MSG_ACKNOWLEDGE == msgType)
1239 if (block->szx > currData->block2.szx)
1241 OIC_LOG(DEBUG, TAG, "sze is big");
1243 // #3. calculate new block number from block size
1244 unsigned int blockNum = BLOCK_SIZE(block->szx) /
1245 BLOCK_SIZE(currData->block2.szx) - 1;
1246 OIC_LOG(DEBUG, TAG, "num is set as Negotiation");
1247 block->num += blockNum;
1248 block->szx = currData->block2.szx;
1249 OIC_LOG_V(DEBUG, TAG, "updated block num: %d", block->num);
1254 if (block->szx > currData->block2.szx)
1256 OIC_LOG(DEBUG, TAG, "sze is big");
1257 block->szx = currData->block2.szx;
1261 else if (COAP_OPTION_BLOCK1 == blockType)
1263 if (CA_MSG_ACKNOWLEDGE == msgType)
1265 if (block->szx < currData->block1.szx)
1267 OIC_LOG(DEBUG, TAG, "sze is small");
1269 unsigned int blockNum = BLOCK_SIZE(currData->block1.szx) /
1270 BLOCK_SIZE(block->szx) - 1;
1271 block->num += blockNum;
1272 OIC_LOG_V(DEBUG, TAG, "updated block num: %d", block->num);
1277 if (block->szx > currData->block1.szx)
1279 OIC_LOG(DEBUG, TAG, "sze is big");
1280 block->szx = currData->block1.szx;
1286 OIC_LOG(DEBUG, TAG, "Invalid block option");
1287 return CA_STATUS_FAILED;
1290 OIC_LOG(DEBUG, TAG, "OUT-NegotiateBlockSize");
1292 return CA_STATUS_OK;
1295 CAResult_t CAUpdateBlockData(CABlockData_t *currData, coap_block_t block,
1298 VERIFY_NON_NULL(currData, TAG, "currData");
1300 // check if block size is bigger than CABlockSize_t
1301 if (block.szx > CA_BLOCK_SIZE_1024_BYTE)
1303 OIC_LOG(DEBUG, TAG, "invalid block szx");
1304 return CA_STATUS_FAILED;
1307 // update block option
1308 if (COAP_OPTION_BLOCK2 == blockType)
1310 currData->block2 = block;
1314 currData->block1 = block;
1317 OIC_LOG(DEBUG, TAG, "data has updated");
1318 return CA_STATUS_OK;
1321 CAResult_t CAUpdateMessageId(coap_pdu_t *pdu, const CABlockDataID_t *blockID)
1323 VERIFY_NON_NULL(pdu, TAG, "pdu");
1324 VERIFY_NON_NULL(blockID, TAG, "blockID");
1326 // if CON message is sent, update messageId in block-wise transfer list
1327 if (CA_MSG_CONFIRM == pdu->hdr->type)
1329 CAData_t * cadata = CAGetDataSetFromBlockDataList(blockID);
1332 OIC_LOG(ERROR, TAG, "CAData is unavailable");
1333 return CA_STATUS_FAILED;
1336 if (NULL != cadata->requestInfo)
1338 cadata->requestInfo->info.messageId = pdu->hdr->id;
1342 return CA_STATUS_OK;
1345 CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t info,
1346 const CAEndpoint_t *endpoint)
1348 OIC_LOG(DEBUG, TAG, "IN-AddBlockOption");
1349 VERIFY_NON_NULL(pdu, TAG, "pdu");
1350 VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1351 VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1352 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
1354 size_t dataLength = 0;
1357 dataLength = info.payloadSize;
1358 OIC_LOG_V(DEBUG, TAG, "dataLength - %d", dataLength);
1361 OIC_LOG_V(DEBUG, TAG, "previous payload - %s", (*pdu)->data);
1363 uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->code);
1364 if (CA_REQUEST_ENTITY_INCOMPLETE == code)
1366 OIC_LOG(INFO, TAG, "don't use option");
1367 return CA_STATUS_OK;
1370 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
1371 (CAToken_t)(*pdu)->hdr->token,
1372 (*pdu)->hdr->token_length,
1375 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
1377 OIC_LOG(ERROR, TAG, "blockId is null");
1378 CADestroyBlockID(blockDataID);
1379 return CA_STATUS_FAILED;
1382 uint8_t blockType = CAGetBlockOptionType(blockDataID);
1383 if (COAP_OPTION_BLOCK2 == blockType)
1385 CAResult_t res = CAAddBlockOption2(pdu, info, dataLength,
1387 if (CA_STATUS_OK != res)
1389 OIC_LOG(ERROR, TAG, "add has failed");
1390 CADestroyBlockID(blockDataID);
1394 else if (COAP_OPTION_BLOCK1 == blockType)
1396 CAResult_t res = CAAddBlockOption1(pdu, info, dataLength,
1398 if (CA_STATUS_OK != res)
1400 OIC_LOG(ERROR, TAG, "add has failed");
1401 CADestroyBlockID(blockDataID);
1407 OIC_LOG(DEBUG, TAG, "no BLOCK option");
1408 // if response data is so large. it have to send as block transfer
1409 if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info.payload))
1411 OIC_LOG(INFO, TAG, "it have to use block");
1415 OIC_LOG(INFO, TAG, "not Blockwise Transfer");
1419 CAResult_t res = CAUpdateMessageId(*pdu, blockDataID);
1420 if (CA_STATUS_OK != res)
1422 OIC_LOG(ERROR, TAG, "fail to update CON message id ");
1423 CADestroyBlockID(blockDataID);
1427 CADestroyBlockID(blockDataID);
1428 OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption");
1429 return CA_STATUS_OK;
1432 CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength,
1433 const CABlockDataID_t *blockID)
1435 OIC_LOG(DEBUG, TAG, "IN-AddBlockOption2");
1436 VERIFY_NON_NULL(pdu, TAG, "pdu");
1437 VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1438 VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1439 VERIFY_NON_NULL(blockID, TAG, "blockID");
1441 // get set block data from CABlock list-set.
1442 coap_block_t *block1 = CAGetBlockOption(blockID,
1443 COAP_OPTION_BLOCK1);
1444 coap_block_t *block2 = CAGetBlockOption(blockID,
1445 COAP_OPTION_BLOCK2);
1446 if (!block1 || !block2)
1448 OIC_LOG(ERROR, TAG, "getting has failed");
1449 return CA_STATUS_FAILED;
1452 CALogBlockInfo(block2);
1455 if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->type ||
1456 (CA_MSG_NONCONFIRM == (*pdu)->hdr->type && CA_GET != (*pdu)->hdr->code))
1458 int32_t res = coap_write_block_opt(block2, COAP_OPTION_BLOCK2, *pdu, dataLength);
1461 case -2: /* illegal block */
1462 code = COAP_RESPONSE_CODE(CA_BAD_REQ);
1463 OIC_LOG(ERROR, TAG, "write block option : -2");
1465 case -1: /* should really not happen */
1466 OIC_LOG(ERROR, TAG, "write block option : -1");
1468 case -3: /* cannot handle request */
1469 code = COAP_RESPONSE_CODE(CA_INTERNAL_SERVER_ERROR);
1470 OIC_LOG(ERROR, TAG, "write block option : -3");
1473 OIC_LOG(INFO, TAG, "success write block option");
1475 CALogBlockInfo(block2);
1479 OIC_LOG(DEBUG, TAG, "combining block1 and block2");
1480 CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
1481 if (CA_STATUS_OK != res)
1483 OIC_LOG(ERROR, TAG, "add has failed");
1484 CARemoveBlockDataFromList(blockID);
1487 // initialize block number
1491 // if block number is 0, add size2 option
1492 if (0 == block2->num)
1494 res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength);
1495 if (CA_STATUS_OK != res)
1497 OIC_LOG(ERROR, TAG, "add has failed");
1498 CARemoveBlockDataFromList(blockID);
1503 if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info.payload,
1504 block2->num, block2->szx))
1506 OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
1507 return CA_STATUS_FAILED;
1512 // if sent message is last response block message, remove data
1513 CARemoveBlockDataFromList(blockID);
1517 if (CA_MSG_NONCONFIRM == (*pdu)->hdr->type)
1519 OIC_LOG(DEBUG, TAG, "NON, send next block..");
1520 // update block data
1522 CAResult_t res = CAProcessNextStep(*pdu, NULL,
1523 CA_SENT_PREVIOUS_NON_MSG,
1525 if (CA_STATUS_OK != res)
1527 OIC_LOG(ERROR, TAG, "failed to process next step");
1528 CARemoveBlockDataFromList(blockID);
1536 OIC_LOG(DEBUG, TAG, "option2, not ACK msg");
1537 CAResult_t res = CAAddBlockOptionImpl(*pdu, block2, COAP_OPTION_BLOCK2);
1538 if (CA_STATUS_OK != res)
1540 OIC_LOG(ERROR, TAG, "add has failed");
1541 CARemoveBlockDataFromList(blockID);
1546 return CA_STATUS_OK;
1549 OIC_LOG_V(ERROR, TAG, "error : %d", code);
1551 char* phrase = coap_response_phrase(code);
1554 coap_add_data(*pdu, strlen(phrase),
1555 (unsigned char *) phrase);
1557 return CA_STATUS_FAILED;
1560 CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength,
1561 const CABlockDataID_t *blockID)
1563 OIC_LOG(DEBUG, TAG, "IN-AddBlockOption1");
1564 VERIFY_NON_NULL(pdu, TAG, "pdu");
1565 VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1566 VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1567 VERIFY_NON_NULL(blockID, TAG, "blockID");
1569 // get set block data from CABlock list-set.
1570 coap_block_t *block1 = CAGetBlockOption(blockID,
1571 COAP_OPTION_BLOCK1);
1574 OIC_LOG(ERROR, TAG, "getting has failed");
1575 return CA_STATUS_FAILED;
1578 CALogBlockInfo(block1);
1580 if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->type)
1582 OIC_LOG(DEBUG, TAG, "option1 and ACK msg..");
1583 CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
1584 if (CA_STATUS_OK != res)
1586 OIC_LOG(ERROR, TAG, "add has failed");
1587 CARemoveBlockDataFromList(blockID);
1591 // reset block-list after write block
1594 // remove data from list
1595 CAResult_t res = CARemoveBlockDataFromList(blockID);
1596 if (CA_STATUS_OK != res)
1598 OIC_LOG(ERROR, TAG, "remove has failed");
1605 CAGetMoreBitFromBlock(dataLength, block1);
1606 CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
1607 if (CA_STATUS_OK != res)
1609 OIC_LOG(ERROR, TAG, "add has failed");
1610 CARemoveBlockDataFromList(blockID);
1613 CALogBlockInfo(block1);
1615 // if block number is 0, add size1 option
1616 if (0 == block1->num)
1618 res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE1, dataLength);
1619 if (CA_STATUS_OK != res)
1621 OIC_LOG(ERROR, TAG, "add has failed");
1622 CARemoveBlockDataFromList(blockID);
1627 if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info.payload,
1628 block1->num, block1->szx))
1630 OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
1631 return CA_STATUS_FAILED;
1634 // check the message type and if message type is NON, next block message will be sent
1635 if (CA_MSG_NONCONFIRM == (*pdu)->hdr->type)
1639 OIC_LOG(DEBUG, TAG, "NON, send next block..");
1640 // update block data
1642 CAResult_t res = CAProcessNextStep(*pdu, NULL,
1643 CA_SENT_PREVIOUS_NON_MSG,
1645 if (CA_STATUS_OK != res)
1647 OIC_LOG(ERROR, TAG, "failed to process next step");
1648 CARemoveBlockDataFromList(blockID);
1654 CARemoveBlockDataFromList(blockID);
1659 OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption1");
1661 return CA_STATUS_OK;
1664 CAResult_t CAAddBlockOptionImpl(coap_pdu_t *pdu, coap_block_t *block, uint8_t blockType)
1666 OIC_LOG(DEBUG, TAG, "IN-AddBlockOptionImpl");
1667 VERIFY_NON_NULL(pdu, TAG, "pdu");
1668 VERIFY_NON_NULL(block, TAG, "block");
1670 coap_option *option = (coap_option *) OICMalloc(sizeof(coap_option));
1673 OIC_LOG(ERROR, TAG, "out of memory");
1674 return CA_MEMORY_ALLOC_FAILED;
1677 unsigned char buf[BLOCKWISE_OPTION_BUFFER] = { 0 };
1678 option->key = blockType;
1679 option->length = coap_encode_var_bytes(buf,
1680 ((block->num << BLOCK_NUMBER_IDX)
1681 | (block->m << BLOCK_M_BIT_IDX) | block->szx));
1682 if (!coap_add_option(pdu, option->key, option->length, buf))
1684 OIC_LOG(ERROR, TAG, "coap_add_option has failed");
1686 return CA_STATUS_FAILED;
1691 OIC_LOG(DEBUG, TAG, "OUT-AddBlockOptionImpl");
1692 return CA_STATUS_OK;
1695 CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataLength)
1697 OIC_LOG(DEBUG, TAG, "IN-CAAddBlockSizeOption");
1698 VERIFY_NON_NULL(pdu, TAG, "pdu");
1700 if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2)
1702 OIC_LOG(ERROR, TAG, "unknown option type");
1703 return CA_STATUS_FAILED;
1706 unsigned char value[BLOCKWISE_OPTION_BUFFER] = { 0 };
1707 unsigned int optionLength = coap_encode_var_bytes(value, dataLength);
1709 if (!coap_add_option(pdu, sizeType, optionLength, value))
1711 OIC_LOG(ERROR, TAG, "failed to add size option");
1712 return CA_STATUS_FAILED;
1715 OIC_LOG(DEBUG, TAG, "OUT-CAAddBlockSizeOption");
1717 return CA_STATUS_OK;
1720 // TODO make pdu const after libcoap is updated to support that.
1721 bool CAIsPayloadLengthInPduWithBlockSizeOption(coap_pdu_t *pdu,
1723 size_t *totalPayloadLen)
1725 OIC_LOG(DEBUG, TAG, "IN-CAIsPayloadLengthInPduWithBlockSizeOption");
1726 VERIFY_NON_NULL(pdu, TAG, "pdu");
1727 VERIFY_NON_NULL(totalPayloadLen, TAG, "totalPayloadLen");
1729 if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2)
1731 OIC_LOG(ERROR, TAG, "unknown option type");
1732 return CA_STATUS_FAILED;
1735 coap_opt_iterator_t opt_iter;
1736 coap_opt_t *option = coap_check_option(pdu, sizeType, &opt_iter);
1739 OIC_LOG(DEBUG, TAG, "get size option from pdu");
1740 *totalPayloadLen = coap_decode_var_bytes(COAP_OPT_VALUE(option),
1741 COAP_OPT_LENGTH(option));
1743 OIC_LOG_V(DEBUG, TAG, "the total payload length to be received is [%d]bytes",
1749 OIC_LOG(DEBUG, TAG, "OUT-CAIsPayloadLengthInPduWithBlockSizeOption");
1754 uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlock,
1755 const CAData_t *receivedData, uint16_t blockType,
1758 OIC_LOG(DEBUG, TAG, "IN-CheckBlockError");
1760 VERIFY_NON_NULL(currData, TAG, "currData is NULL");
1761 VERIFY_NON_NULL(receivedBlock, TAG, "receivedBlock is NULL");
1762 VERIFY_NON_NULL(receivedData, TAG, "receivedData is NULL");
1764 // #1. check the received payload length
1765 size_t blockPayloadLen = 0;
1766 CAGetPayloadInfo(receivedData, &blockPayloadLen);
1768 // #2. check if the block sequence is right
1769 if (COAP_OPTION_BLOCK1 == blockType)
1771 size_t prePayloadLen = currData->receivedPayloadLen;
1772 if (prePayloadLen != (size_t)BLOCK_SIZE(receivedBlock->szx)
1773 * receivedBlock->num)
1775 if (receivedBlock->num > currData->block1.num + 1)
1777 // 408 Error handling of block loss
1778 OIC_LOG(ERROR, TAG, "option1: error 4.08");
1779 OIC_LOG(ERROR, TAG, "it didn't order");
1780 return CA_BLOCK_INCOMPLETE;
1782 return CA_BLOCK_RECEIVED_ALREADY;
1785 else if (COAP_OPTION_BLOCK2 == blockType)
1787 if (receivedBlock->num != currData->block2.num)
1789 if (receivedBlock->num > currData->block2.num)
1791 // 408 Error handling of block loss
1792 OIC_LOG(ERROR, TAG, "option2: error 4.08");
1793 OIC_LOG(ERROR, TAG, "it didn't order");
1794 return CA_BLOCK_INCOMPLETE;
1796 return CA_BLOCK_RECEIVED_ALREADY;
1800 // #3. check if error check logic is required
1801 size_t optionLen = dataLen - blockPayloadLen;
1802 if (receivedBlock->m && blockPayloadLen !=
1803 (size_t)BLOCK_SIZE(receivedBlock->szx))
1805 // 413 Error handling of too large entity
1806 if (COAP_MAX_PDU_SIZE < BLOCK_SIZE(receivedBlock->szx) + optionLen)
1808 // buffer size is smaller than received block size
1809 OIC_LOG(ERROR, TAG, "error type 4.13");
1810 OIC_LOG(ERROR, TAG, "too large size");
1812 // set the block size to be smaller than COAP_MAX_PDU_SIZE
1813 for (int32_t size = CA_DEFAULT_BLOCK_SIZE; size >= 0; size--)
1815 if (COAP_MAX_PDU_SIZE >= BLOCK_SIZE(size) + optionLen)
1817 OIC_LOG_V(ERROR, TAG, "replace sze with %d", size);
1818 if (COAP_OPTION_BLOCK2 == blockType)
1820 currData->block2.szx = size;
1824 currData->block1.szx = size;
1829 return CA_BLOCK_TOO_LARGE;
1833 // 408 Error handling of payload loss
1834 OIC_LOG(ERROR, TAG, "error type 4.08");
1835 OIC_LOG(ERROR, TAG, "payload len != block sze");
1836 return CA_BLOCK_INCOMPLETE;
1839 else if (0 == receivedBlock->m && 0 != currData->payloadLength)
1841 // if the received block is last block, check the total payload length
1842 size_t receivedPayloadLen = currData->receivedPayloadLen;
1843 receivedPayloadLen += blockPayloadLen;
1845 if (receivedPayloadLen != currData->payloadLength)
1847 OIC_LOG(ERROR, TAG, "error type 4.08");
1848 OIC_LOG(ERROR, TAG, "total payload length is wrong");
1849 return CA_BLOCK_INCOMPLETE;
1853 OIC_LOG(DEBUG, TAG, "received all data normally");
1855 OIC_LOG(DEBUG, TAG, "OUT-CheckBlockError");
1857 return CA_BLOCK_UNKNOWN;
1860 CAResult_t CAUpdatePayloadData(CABlockData_t *currData, const CAData_t *receivedData,
1861 uint8_t status, bool isSizeOption, uint16_t blockType)
1863 OIC_LOG(DEBUG, TAG, "IN-UpdatePayloadData");
1865 VERIFY_NON_NULL(currData, TAG, "currData");
1866 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
1868 // if error code is 4.08, do not update payload
1869 if (CA_BLOCK_INCOMPLETE == status)
1871 OIC_LOG(ERROR, TAG, "no require to update");
1872 return CA_STATUS_OK;
1875 size_t blockPayloadLen = 0;
1876 CAPayload_t blockPayload = CAGetPayloadInfo(receivedData, &blockPayloadLen);
1878 if (CA_BLOCK_TOO_LARGE == status)
1880 blockPayloadLen = (COAP_OPTION_BLOCK2 == blockType) ?
1881 BLOCK_SIZE(currData->block2.szx) : BLOCK_SIZE(currData->block1.szx);
1884 // memory allocation for the received block payload
1885 size_t prePayloadLen = currData->receivedPayloadLen;
1886 if (NULL != blockPayload)
1888 if (0 != currData->payloadLength)
1890 // in case the block message has the size option
1891 // allocate the memory for the total payload
1892 if (true == isSizeOption)
1894 CAPayload_t prePayload = currData->payload;
1896 OIC_LOG(DEBUG, TAG, "allocate memory for the total payload");
1897 currData->payload = (CAPayload_t) OICCalloc(currData->payloadLength + 1,
1899 if (NULL == currData->payload)
1901 OIC_LOG(ERROR, TAG, "out of memory");
1902 return CA_MEMORY_ALLOC_FAILED;
1904 memcpy(currData->payload, prePayload, prePayloadLen);
1905 OICFree(prePayload);
1908 // update the total payload
1909 memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
1913 OIC_LOG(DEBUG, TAG, "allocate memory for the received block payload");
1915 size_t totalPayloadLen = prePayloadLen + blockPayloadLen + 1;
1916 CAPayload_t newPayload = OICRealloc(currData->payload, totalPayloadLen);
1917 if (NULL == newPayload)
1919 OIC_LOG(ERROR, TAG, "out of memory");
1920 return CA_MEMORY_ALLOC_FAILED;
1923 // update the total payload
1924 memset(newPayload + prePayloadLen, 0, blockPayloadLen + 1);
1925 currData->payload = newPayload;
1926 memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
1929 // update received payload length
1930 currData->receivedPayloadLen += blockPayloadLen;
1932 OIC_LOG_V(DEBUG, TAG, "updated payload: %s, len: %d", currData->payload,
1933 currData->receivedPayloadLen);
1936 OIC_LOG(DEBUG, TAG, "OUT-UpdatePayloadData");
1937 return CA_STATUS_OK;
1940 CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint)
1942 VERIFY_NON_NULL_RET(pdu, TAG, "pdu", NULL);
1943 VERIFY_NON_NULL_RET(pdu->hdr, TAG, "pdu->hdr", NULL);
1944 VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
1946 CAInfo_t responseData = { .tokenLength = pdu->hdr->token_length };
1947 responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
1948 if (NULL == responseData.token)
1950 OIC_LOG(ERROR, TAG, "out of memory");
1953 memcpy(responseData.token, pdu->hdr->token, responseData.tokenLength);
1955 CAResponseInfo_t* responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
1956 if (NULL == responseInfo)
1958 OIC_LOG(ERROR, TAG, "out of memory");
1959 OICFree(responseData.token);
1962 responseInfo->info = responseData;
1964 CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
1967 OIC_LOG(ERROR, TAG, "out of memory");
1968 OICFree(responseInfo);
1972 data->requestInfo = NULL;
1973 data->responseInfo = responseInfo;
1974 data->remoteEndpoint = CACloneEndpoint(endpoint);
1975 data->type = SEND_TYPE_UNICAST;
1980 CAData_t *CACloneCAData(const CAData_t *data)
1982 VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
1984 CAData_t *clone = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
1987 OIC_LOG(ERROR, TAG, "out of memory");
1992 if (data->requestInfo)
1994 clone->requestInfo = CACloneRequestInfo(data->requestInfo);
1997 if (data->responseInfo)
1999 clone->responseInfo = CACloneResponseInfo(data->responseInfo);
2002 if (data->remoteEndpoint)
2004 clone->remoteEndpoint = CACloneEndpoint(data->remoteEndpoint);
2010 CAResult_t CAUpdatePayloadToCAData(CAData_t *data, const CAPayload_t payload,
2013 OIC_LOG(DEBUG, TAG, "IN-UpdatePayload");
2015 VERIFY_NON_NULL(data, TAG, "data is NULL");
2016 VERIFY_NON_NULL(payload, TAG, "payload is NULL");
2018 if (NULL != data->requestInfo)
2020 // allocate payload field
2021 if (NULL != data->requestInfo->info.payload)
2023 char *temp = (char *) OICCalloc(payloadLen, sizeof(char));
2026 OIC_LOG(ERROR, TAG, "out of memory");
2027 return CA_STATUS_FAILED;
2029 memcpy(temp, payload, payloadLen);
2031 // save the full payload
2032 OICFree(data->requestInfo->info.payload);
2033 data->requestInfo->info.payload = (CAPayload_t) temp;
2035 data->requestInfo->info.payloadSize = payloadLen;
2038 if (NULL != data->responseInfo)
2040 // allocate payload field
2041 if (NULL != data->responseInfo->info.payload)
2043 char *temp = (char *) OICCalloc(payloadLen, sizeof(char));
2046 OIC_LOG(ERROR, TAG, "out of memory");
2047 return CA_STATUS_FAILED;
2049 memcpy(temp, payload, payloadLen);
2051 // save the full payload
2052 OICFree(data->responseInfo->info.payload);
2053 data->responseInfo->info.payload = (CAPayload_t) temp;
2055 data->responseInfo->info.payloadSize = payloadLen;
2058 OIC_LOG(DEBUG, TAG, "OUT-UpdatePayload");
2060 return CA_STATUS_OK;
2063 CAPayload_t CAGetPayloadInfo(const CAData_t *data, size_t *payloadLen)
2065 VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
2066 VERIFY_NON_NULL_RET(payloadLen, TAG, "payloadLen", NULL);
2068 if (NULL != data->requestInfo)
2070 if (NULL != data->requestInfo->info.payload)
2072 *payloadLen = data->requestInfo->info.payloadSize;
2073 return data->requestInfo->info.payload;
2078 if (NULL != data->responseInfo->info.payload)
2080 *payloadLen = data->responseInfo->info.payloadSize;
2081 return data->responseInfo->info.payload;
2088 CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType,
2089 uint32_t responseResult)
2091 OIC_LOG(DEBUG, TAG, "IN-HandleBlockErrorRes");
2092 VERIFY_NON_NULL(block, TAG, "block is NULL");
2094 // update block data
2095 switch (responseResult)
2097 case CA_REQUEST_ENTITY_INCOMPLETE:
2100 case CA_REQUEST_ENTITY_TOO_LARGE:
2101 if (COAP_OPTION_BLOCK1 == blockType)
2108 OIC_LOG_V(ERROR, TAG, "there is no Error Code of BWT[%d]", responseResult);
2111 OIC_LOG(DEBUG, TAG, "OUT-HandleBlockErrorRes");
2112 return CA_STATUS_OK;
2115 CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID,
2118 OIC_LOG(DEBUG, TAG, "IN-UpdateBlockOptionType");
2119 VERIFY_NON_NULL(blockID, TAG, "blockID");
2121 ca_mutex_lock(g_context.blockDataListMutex);
2123 size_t len = u_arraylist_length(g_context.dataList);
2124 for (size_t i = 0; i < len; i++)
2126 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2127 if (CABlockidMatches(currData, blockID))
2129 currData->type = blockType;
2130 ca_mutex_unlock(g_context.blockDataListMutex);
2131 OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
2132 return CA_STATUS_OK;
2135 ca_mutex_unlock(g_context.blockDataListMutex);
2137 OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
2138 return CA_STATUS_FAILED;
2141 uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID)
2143 OIC_LOG(DEBUG, TAG, "IN-GetBlockOptionType");
2144 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", 0);
2146 ca_mutex_lock(g_context.blockDataListMutex);
2148 size_t len = u_arraylist_length(g_context.dataList);
2149 for (size_t i = 0; i < len; i++)
2151 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2152 if (CABlockidMatches(currData, blockID))
2154 ca_mutex_unlock(g_context.blockDataListMutex);
2155 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
2156 return currData->type;
2159 ca_mutex_unlock(g_context.blockDataListMutex);
2161 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
2165 CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID)
2167 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2169 ca_mutex_lock(g_context.blockDataListMutex);
2171 size_t len = u_arraylist_length(g_context.dataList);
2172 for (size_t i = 0; i < len; i++)
2174 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2175 if (CABlockidMatches(currData, blockID))
2177 ca_mutex_unlock(g_context.blockDataListMutex);
2178 return currData->sentData;
2181 ca_mutex_unlock(g_context.blockDataListMutex);
2186 CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
2187 CAResponseInfo_t *responseInfo)
2189 OIC_LOG(DEBUG, TAG, "IN-CAGetTokenFromBlockDataList");
2190 VERIFY_NON_NULL(pdu, TAG, "pdu");
2191 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
2192 VERIFY_NON_NULL(responseInfo, TAG, "responseInfo");
2194 ca_mutex_lock(g_context.blockDataListMutex);
2196 size_t len = u_arraylist_length(g_context.dataList);
2197 for (size_t i = 0; i < len; i++)
2199 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2200 if (NULL == currData)
2205 if (NULL != currData->sentData && NULL != currData->sentData->requestInfo)
2207 if (pdu->hdr->id == currData->sentData->requestInfo->info.messageId &&
2208 endpoint->adapter == currData->sentData->remoteEndpoint->adapter)
2210 if (NULL != currData->sentData->requestInfo->info.token)
2212 uint8_t length = currData->sentData->requestInfo->info.tokenLength;
2213 responseInfo->info.tokenLength = length;
2214 responseInfo->info.token = (char *) OICMalloc(length);
2215 if (NULL == responseInfo->info.token)
2217 OIC_LOG(ERROR, TAG, "out of memory");
2218 ca_mutex_unlock(g_context.blockDataListMutex);
2219 return CA_MEMORY_ALLOC_FAILED;
2221 memcpy(responseInfo->info.token, currData->sentData->requestInfo->info.token,
2222 responseInfo->info.tokenLength);
2224 ca_mutex_unlock(g_context.blockDataListMutex);
2225 OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
2226 return CA_STATUS_OK;
2232 ca_mutex_unlock(g_context.blockDataListMutex);
2234 OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
2235 return CA_STATUS_OK;
2238 CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t **blockData)
2240 VERIFY_NON_NULL(sendData, TAG, "sendData");
2241 VERIFY_NON_NULL(blockData, TAG, "blockData");
2243 ca_mutex_lock(g_context.blockDataListMutex);
2245 size_t len = u_arraylist_length(g_context.dataList);
2246 for (size_t i = 0; i < len; i++)
2248 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2250 if (NULL == currData)
2255 if (NULL != sendData->requestInfo) // sendData is requestMessage
2257 OIC_LOG(DEBUG, TAG, "Send request");
2258 if (NULL != currData->blockDataId
2259 && NULL != currData->blockDataId->id
2260 && currData->blockDataId->idLength > 0
2261 && NULL != sendData->requestInfo->info.token)
2263 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2264 (CAToken_t)sendData->requestInfo->info.token,
2265 sendData->requestInfo->info.tokenLength,
2266 sendData->remoteEndpoint->port);
2268 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2270 OIC_LOG(ERROR, TAG, "blockId is null");
2271 CADestroyBlockID(blockDataID);
2272 return CA_STATUS_FAILED;
2275 if (CABlockidMatches(currData, blockDataID))
2277 OIC_LOG(ERROR, TAG, "already sent");
2278 CADestroyBlockID(blockDataID);
2281 CADestroyBlockID(blockDataID);
2284 else if (NULL != sendData->responseInfo) // sendData is responseMessage
2286 OIC_LOG(DEBUG, TAG, "Send response");
2287 if (NULL != currData->blockDataId
2288 && NULL != currData->blockDataId->id
2289 && currData->blockDataId->idLength > 0
2290 && NULL != sendData->responseInfo->info.token)
2292 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2293 (CAToken_t)sendData->responseInfo->info.token,
2294 sendData->responseInfo->info.tokenLength,
2295 sendData->remoteEndpoint->port);
2297 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2299 OIC_LOG(ERROR, TAG, "blockId is null");
2300 CADestroyBlockID(blockDataID);
2301 return CA_STATUS_FAILED;
2304 if (CABlockidMatches(currData, blockDataID))
2307 if (NULL != currData->sentData)
2309 OIC_LOG(DEBUG, TAG, "init block number");
2310 CADestroyDataSet(currData->sentData);
2312 currData->sentData = CACloneCAData(sendData);
2313 *blockData = currData;
2314 CADestroyBlockID(blockDataID);
2315 ca_mutex_unlock(g_context.blockDataListMutex);
2316 return CA_STATUS_OK;
2318 CADestroyBlockID(blockDataID);
2323 OIC_LOG(ERROR, TAG, "no CAInfo data");
2327 ca_mutex_unlock(g_context.blockDataListMutex);
2329 return CA_STATUS_FAILED;
2332 CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID)
2334 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2336 ca_mutex_lock(g_context.blockDataListMutex);
2338 size_t len = u_arraylist_length(g_context.dataList);
2339 for (size_t i = 0; i < len; i++)
2341 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2342 if (CABlockidMatches(currData, blockID))
2344 ca_mutex_unlock(g_context.blockDataListMutex);
2348 ca_mutex_unlock(g_context.blockDataListMutex);
2353 coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID,
2356 OIC_LOG(DEBUG, TAG, "IN-GetBlockOption");
2357 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2359 ca_mutex_lock(g_context.blockDataListMutex);
2361 size_t len = u_arraylist_length(g_context.dataList);
2362 for (size_t i = 0; i < len; i++)
2364 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2365 if (CABlockidMatches(currData, blockID))
2367 ca_mutex_unlock(g_context.blockDataListMutex);
2368 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
2369 if (COAP_OPTION_BLOCK2 == blockType)
2371 return &currData->block2;
2375 return &currData->block1;
2379 ca_mutex_unlock(g_context.blockDataListMutex);
2381 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
2385 CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID,
2386 size_t *fullPayloadLen)
2388 OIC_LOG(DEBUG, TAG, "IN-GetFullPayload");
2389 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2390 VERIFY_NON_NULL_RET(fullPayloadLen, TAG, "fullPayloadLen", NULL);
2392 ca_mutex_lock(g_context.blockDataListMutex);
2394 size_t len = u_arraylist_length(g_context.dataList);
2395 for (size_t i = 0; i < len; i++)
2397 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2398 if (CABlockidMatches(currData, blockID))
2400 ca_mutex_unlock(g_context.blockDataListMutex);
2401 *fullPayloadLen = currData->receivedPayloadLen;
2402 OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
2403 return currData->payload;
2406 ca_mutex_unlock(g_context.blockDataListMutex);
2408 OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
2412 CABlockData_t *CACreateNewBlockData(const CAData_t *sendData)
2414 OIC_LOG(DEBUG, TAG, "IN-CACreateNewBlockData");
2415 VERIFY_NON_NULL_RET(sendData, TAG, "sendData", NULL);
2417 // create block data
2418 CABlockData_t *data = (CABlockData_t *) OICCalloc(1, sizeof(CABlockData_t));
2421 OIC_LOG(ERROR, TAG, "memory alloc has failed");
2425 data->block1.szx = CA_DEFAULT_BLOCK_SIZE;
2426 data->block2.szx = CA_DEFAULT_BLOCK_SIZE;
2427 data->sentData = CACloneCAData(sendData);
2430 OIC_LOG(ERROR, TAG, PCF("memory alloc has failed"));
2435 CAToken_t token = NULL;
2436 uint8_t tokenLength = 0;
2437 if (data->sentData->requestInfo)
2439 // update token info
2440 tokenLength = data->sentData->requestInfo->info.tokenLength;
2441 token = data->sentData->requestInfo->info.token;
2443 else if(data->sentData->responseInfo)
2445 tokenLength = data->sentData->responseInfo->info.tokenLength;
2446 token = data->sentData->responseInfo->info.token;
2449 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2451 data->sentData->remoteEndpoint->port);
2452 if (NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2454 OIC_LOG(ERROR, TAG, "blockId is null");
2455 CADestroyBlockID(blockDataID);
2458 data->blockDataId = blockDataID;
2460 ca_mutex_lock(g_context.blockDataListMutex);
2462 bool res = u_arraylist_add(g_context.dataList, (void *) data);
2465 OIC_LOG(ERROR, TAG, "add has failed");
2466 CADestroyBlockID(data->blockDataId);
2468 ca_mutex_unlock(g_context.blockDataListMutex);
2471 ca_mutex_unlock(g_context.blockDataListMutex);
2473 OIC_LOG(DEBUG, TAG, "OUT-CreateBlockData");
2477 CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
2479 OIC_LOG(DEBUG, TAG, "CARemoveBlockData");
2480 VERIFY_NON_NULL(blockID, TAG, "blockID");
2482 ca_mutex_lock(g_context.blockDataListMutex);
2484 size_t len = u_arraylist_length(g_context.dataList);
2485 for (size_t i = 0; i < len; i++)
2487 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2488 if (CABlockidMatches(currData, blockID))
2490 CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i);
2491 if (NULL == removedData)
2493 OIC_LOG(ERROR, TAG, "data is NULL");
2494 ca_mutex_unlock(g_context.blockDataListMutex);
2495 return CA_STATUS_FAILED;
2499 if (currData->sentData)
2501 CADestroyDataSet(currData->sentData);
2503 OICFree(currData->payload);
2504 CADestroyBlockID(currData->blockDataId);
2505 ca_mutex_unlock(g_context.blockDataListMutex);
2506 return CA_STATUS_OK;
2509 ca_mutex_unlock(g_context.blockDataListMutex);
2511 return CA_STATUS_OK;
2514 bool CAIsBlockDataInList(const CABlockDataID_t *blockID)
2516 OIC_LOG(DEBUG, TAG, "IN-IsBlockDataInList");
2517 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false);
2519 ca_mutex_lock(g_context.blockDataListMutex);
2521 size_t len = u_arraylist_length(g_context.dataList);
2522 for (size_t i = 0; i < len; i++)
2524 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2525 if (CABlockidMatches(currData, blockID))
2527 OIC_LOG(DEBUG, TAG, "found block data");
2528 ca_mutex_unlock(g_context.blockDataListMutex);
2532 ca_mutex_unlock(g_context.blockDataListMutex);
2534 OIC_LOG(DEBUG, TAG, "OUT-IsBlockDataInList");
2538 void CADestroyDataSet(CAData_t* data)
2540 VERIFY_NON_NULL_VOID(data, TAG, "data");
2542 CAFreeEndpoint(data->remoteEndpoint);
2543 CADestroyRequestInfoInternal(data->requestInfo);
2544 CADestroyResponseInfoInternal(data->responseInfo);
2548 CABlockDataID_t* CACreateBlockDatablockId(const CAToken_t token, uint8_t tokenLength,
2549 uint16_t portNumber)
2551 VERIFY_NON_NULL_RET(token, TAG, "token", NULL);
2553 char port[PORT_LENGTH] = {0,};
2554 port[0] = (char)((portNumber>>8) & 0xFF);
2555 port[1] = (char)(portNumber & 0xFF);
2557 CABlockDataID_t* blockDataID = (CABlockDataID_t *) OICMalloc(sizeof(CABlockDataID_t));
2558 blockDataID->idLength = tokenLength + sizeof(port);
2559 blockDataID->id = (uint8_t *) OICMalloc(blockDataID->idLength);
2560 if (!blockDataID->id)
2562 OIC_LOG(ERROR, TAG, "memory alloc has failed");
2563 OICFree(blockDataID);
2567 memcpy(blockDataID->id, token, tokenLength);
2568 memcpy(blockDataID->id + tokenLength, port, sizeof(port));
2570 OIC_LOG(DEBUG, TAG, "BlockID is ");
2571 OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)blockDataID->id, blockDataID->idLength);
2576 void CADestroyBlockID(CABlockDataID_t *blockID)
2578 VERIFY_NON_NULL_VOID(blockID, TAG, "blockID");
2579 OICFree(blockID->id);
2584 bool CABlockidMatches(const CABlockData_t *currData, const CABlockDataID_t *blockID)
2586 VERIFY_NON_NULL_RET(currData, TAG, "currData", false);
2587 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false);
2588 VERIFY_NON_NULL_RET(blockID->id, TAG, "blockID->id", false);
2590 if ((currData->blockDataId)
2591 && (currData->blockDataId->id)
2592 && (currData->blockDataId->idLength == blockID->idLength)
2593 && !memcmp(currData->blockDataId->id, blockID->id, currData->blockDataId->idLength))
2600 void CALogBlockInfo(coap_block_t *block)
2602 VERIFY_NON_NULL_VOID(block, TAG, "block");
2604 OIC_LOG(DEBUG, TAG, "block option info");
2606 OIC_LOG_V(DEBUG, TAG, "block option-num : %d", block->num);
2608 OIC_LOG_V(DEBUG, TAG, "block option-m : %d", block->m);
2610 OIC_LOG_V(DEBUG, TAG, "block option-szx : %d", block->szx);