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"
46 #define TAG "OIC_CA_BWT"
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 = { .sendThreadFunc = NULL,
57 .receivedThreadFunc = NULL,
60 static bool CACheckPayloadLength(const CAData_t *sendData)
62 size_t payloadLen = 0;
63 CAGetPayloadInfo(sendData, &payloadLen);
65 // check if message has to be transfered to a block
66 size_t maxBlockSize = BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE);
67 OIC_LOG_V(DEBUG, TAG, "payloadLen=%zu, maxBlockSize=%zu", payloadLen, maxBlockSize);
69 if (payloadLen <= maxBlockSize)
77 CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc,
78 CAReceiveThreadFunc receivedThreadFunc)
80 OIC_LOG(DEBUG, TAG, "initialize");
82 // set block-wise transfer context
83 if (!g_context.sendThreadFunc)
85 g_context.sendThreadFunc = sendThreadFunc;
88 if (!g_context.receivedThreadFunc)
90 g_context.receivedThreadFunc = receivedThreadFunc;
93 if (!g_context.dataList)
95 g_context.dataList = u_arraylist_create();
98 CAResult_t res = CAInitBlockWiseMutexVariables();
99 if (CA_STATUS_OK != res)
101 OIC_LOG(ERROR, TAG, "init has failed");
107 CAResult_t CATerminateBlockWiseTransfer()
109 OIC_LOG(DEBUG, TAG, "terminate");
111 if (g_context.dataList)
113 u_arraylist_free(&g_context.dataList);
116 CATerminateBlockWiseMutexVariables();
121 CAResult_t CAInitBlockWiseMutexVariables()
123 if (!g_context.blockDataListMutex)
125 g_context.blockDataListMutex = ca_mutex_new();
126 if (!g_context.blockDataListMutex)
128 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
129 return CA_STATUS_FAILED;
133 if (!g_context.blockDataSenderMutex)
135 g_context.blockDataSenderMutex = ca_mutex_new();
136 if (!g_context.blockDataSenderMutex)
138 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
139 CATerminateBlockWiseMutexVariables();
140 return CA_STATUS_FAILED;
147 void CATerminateBlockWiseMutexVariables()
149 if (g_context.blockDataListMutex)
151 ca_mutex_free(g_context.blockDataListMutex);
152 g_context.blockDataListMutex = NULL;
155 if (g_context.blockDataSenderMutex)
157 ca_mutex_free(g_context.blockDataSenderMutex);
158 g_context.blockDataSenderMutex = NULL;
162 CAResult_t CASendBlockWiseData(const CAData_t *sendData)
164 VERIFY_NON_NULL(sendData, TAG, "sendData");
166 // check if message type is CA_MSG_RESET
167 if (sendData->requestInfo)
169 if (CA_MSG_RESET == sendData->requestInfo->info.type)
171 OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block");
172 return CA_NOT_SUPPORTED;
175 else if (sendData->responseInfo)
177 if (CA_MSG_RESET == sendData->responseInfo->info.type)
179 OIC_LOG(DEBUG, TAG, "reset message can't be sent to the block");
180 return CA_NOT_SUPPORTED;
184 // #1. check if it is already included in block data list
185 CABlockData_t *currData = NULL;
186 CAResult_t res = CACheckBlockDataValidation(sendData, &currData);
187 if (CA_STATUS_OK != res)
189 // #2. if it is not included, add the data into list
192 OIC_LOG(DEBUG, TAG, "There is no block data");
194 bool isBlock = CACheckPayloadLength(sendData);
197 if (sendData->requestInfo)
199 currData = CACreateNewBlockData(sendData);
202 OIC_LOG(ERROR, TAG, "failed to create block data");
203 return CA_MEMORY_ALLOC_FAILED;
206 return CA_NOT_SUPPORTED;
208 currData = CACreateNewBlockData(sendData);
211 OIC_LOG(ERROR, TAG, "failed to create block data");
212 return CA_MEMORY_ALLOC_FAILED;
217 // #3. check request/response block option type and payload length
218 res = CACheckBlockOptionType(currData);
219 if (CA_STATUS_OK == res)
221 // #4. send block message
222 OIC_LOG(DEBUG, TAG, "send first block msg");
223 res = CAAddSendThreadQueue(currData->sentData,
224 (const CABlockDataID_t *)&currData->blockDataId);
225 if (CA_STATUS_OK != res)
227 OIC_LOG(ERROR, TAG, "add has failed");
235 CAResult_t CAAddSendThreadQueue(const CAData_t *sendData, const CABlockDataID_t *blockID)
237 VERIFY_NON_NULL(sendData, TAG, "sendData");
238 VERIFY_NON_NULL(blockID, TAG, "blockID");
240 CAData_t *cloneData = CACloneCAData(sendData);
243 OIC_LOG(ERROR, TAG, "clone has failed");
244 CARemoveBlockDataFromList(blockID);
245 return CA_STATUS_FAILED;
248 if (g_context.sendThreadFunc)
250 ca_mutex_lock(g_context.blockDataSenderMutex);
251 g_context.sendThreadFunc(cloneData);
252 ca_mutex_unlock(g_context.blockDataSenderMutex);
256 CADestroyDataSet(cloneData);
261 CAResult_t CACheckBlockOptionType(CABlockData_t *currData)
263 VERIFY_NON_NULL(currData, TAG, "currData");
264 VERIFY_NON_NULL(currData->sentData, TAG, "currData->sentData");
266 bool isBlock = CACheckPayloadLength(currData->sentData);
269 return CA_NOT_SUPPORTED;
272 // set block option (COAP_OPTION_BLOCK2 or COAP_OPTION_BLOCK1)
273 if (currData->sentData->requestInfo) // request message
275 currData->type = COAP_OPTION_BLOCK1;
277 else // response message
279 currData->type = COAP_OPTION_BLOCK2;
285 // TODO make pdu const after libcoap is updated to support that.
286 CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
287 const CAData_t *receivedData, size_t dataLen)
289 OIC_LOG(DEBUG, TAG, "CAReceiveBlockWiseData");
290 VERIFY_NON_NULL(pdu, TAG, "pdu");
291 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
292 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
293 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
295 // check if received message type is CA_MSG_RESET
296 if (CA_EMPTY == pdu->hdr->coap_hdr_udp_t.code)
298 OIC_LOG(DEBUG, TAG, "code is CA_EMPTY..");
300 // get token from block-wise transfer list when CA_EMPTY(RST/ACK) is received
301 CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint, receivedData->responseInfo);
302 if (CA_STATUS_OK != res)
304 OIC_LOG(ERROR, TAG, "fail to get token");
308 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
309 receivedData->responseInfo->info.token,
310 receivedData->responseInfo->info.tokenLength,
312 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
314 // if retransmission is timeout, callback msg will be send without token.
315 if (NULL == blockDataID && !receivedData->responseInfo->info.token)
317 OIC_LOG(INFO, TAG, "retransmission was stopped");
318 return CA_REQUEST_TIMEOUT;
322 OIC_LOG(ERROR, TAG, "blockId is null");
323 CADestroyBlockID(blockDataID);
324 return CA_STATUS_FAILED;
328 CARemoveBlockDataFromList(blockDataID);
329 CADestroyBlockID(blockDataID);
330 return CA_NOT_SUPPORTED;
333 // check if block option is set and get block data
334 coap_block_t block = {0, 0, 0};
337 int isBlock1 = coap_get_block(pdu, COAP_OPTION_BLOCK1, &block);
340 CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, block, dataLen);
341 if (CA_STATUS_OK != res)
343 OIC_LOG(ERROR, TAG, "setting has failed");
349 int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block);
352 CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, block, dataLen);
353 if (CA_STATUS_OK != res)
355 OIC_LOG(ERROR, TAG, "setting has failed");
360 // check if there is error code
361 if (!isBlock1 && !isBlock2)
363 uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
364 if (CA_REQUEST_ENTITY_INCOMPLETE == code)
366 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
367 (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
368 pdu->hdr->coap_hdr_udp_t.token_length,
371 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
373 OIC_LOG(ERROR, TAG, "blockId is null");
374 CADestroyBlockID(blockDataID);
375 return CA_STATUS_FAILED;
378 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
381 OIC_LOG(ERROR, TAG, "getting has failed");
382 CADestroyBlockID(blockDataID);
383 return CA_STATUS_FAILED;
386 if (COAP_OPTION_BLOCK2 == data->type)
388 coap_block_t *block2 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK2);
391 OIC_LOG(ERROR, TAG, "block is null");
392 CADestroyBlockID(blockDataID);
393 return CA_STATUS_FAILED;
396 CAResult_t res = CASetNextBlockOption2(pdu, endpoint, receivedData, *block2,
398 if (CA_STATUS_OK != res)
400 OIC_LOG(ERROR, TAG, "setting has failed");
401 CADestroyBlockID(blockDataID);
405 else if (COAP_OPTION_BLOCK1 == data->type)
407 coap_block_t *block1 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK1);
410 OIC_LOG(ERROR, TAG, "block is null");
411 CADestroyBlockID(blockDataID);
412 return CA_STATUS_FAILED;
415 CAResult_t res = CASetNextBlockOption1(pdu, endpoint, receivedData, *block1,
417 if (CA_STATUS_OK != res)
419 OIC_LOG(ERROR, TAG, "setting has failed");
420 CADestroyBlockID(blockDataID);
428 OIC_LOG(DEBUG, TAG, "it's normal pdu");
430 // if received data is response message
431 // and sent data remain in block data list, remove block data
432 if (receivedData->responseInfo)
434 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
435 (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
436 pdu->hdr->coap_hdr_udp_t.token_length,
438 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
440 OIC_LOG(ERROR, TAG, "blockId is null");
441 CADestroyBlockID(blockDataID);
442 return CA_STATUS_FAILED;
445 CARemoveBlockDataFromList(blockDataID);
446 CADestroyBlockID(blockDataID);
448 return CA_NOT_SUPPORTED;
455 CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData,
456 uint8_t blockWiseStatus, const CABlockDataID_t *blockID)
458 VERIFY_NON_NULL(pdu, TAG, "pdu");
459 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
460 VERIFY_NON_NULL(blockID, TAG, "blockID");
462 CAResult_t res = CA_STATUS_OK;
463 CAData_t *data = NULL;
465 // process blockWiseStatus
466 switch (blockWiseStatus)
468 case CA_OPTION2_FIRST_BLOCK:
469 res = CAAddSendThreadQueue(receivedData, blockID);
470 if (CA_STATUS_OK != res)
472 OIC_LOG(ERROR, TAG, "add has failed");
478 // add data to send thread
479 data = CAGetDataSetFromBlockDataList(blockID);
482 OIC_LOG(ERROR, TAG, "it's unavailable");
483 return CA_STATUS_FAILED;
486 if (data->requestInfo)
488 data->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
491 if (data->responseInfo)
493 data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
496 res = CAAddSendThreadQueue(data, blockID);
497 if (CA_STATUS_OK != res)
499 OIC_LOG(ERROR, TAG, "add has failed");
507 case CA_SENT_PREVIOUS_NON_MSG:
508 res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
510 if (CA_STATUS_OK != res)
512 OIC_LOG(ERROR, TAG, "send has failed");
517 case CA_OPTION2_LAST_BLOCK:
518 // process last block and send upper layer
519 res = CAReceiveLastBlock(blockID, receivedData);
520 if (CA_STATUS_OK != res)
522 OIC_LOG(ERROR, TAG, "receive has failed");
526 // remove data from list
527 res = CARemoveBlockDataFromList(blockID);
528 if (CA_STATUS_OK != res)
530 OIC_LOG(ERROR, TAG, "remove has failed");
535 case CA_OPTION1_NO_ACK_LAST_BLOCK:
536 // process last block and send upper layer
537 res = CAReceiveLastBlock(blockID, receivedData);
538 if (CA_STATUS_OK != res)
540 OIC_LOG(ERROR, TAG, "receive has failed");
544 if (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type)
546 // remove data from list
547 res = CARemoveBlockDataFromList(blockID);
548 if (CA_STATUS_OK != res)
550 OIC_LOG(ERROR, TAG, "remove has failed");
556 case CA_OPTION1_NO_ACK_BLOCK:
557 if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
559 // add data to send thread
560 res = CASendBlockMessage(pdu, CA_MSG_ACKNOWLEDGE, blockWiseStatus,
562 if (CA_STATUS_OK != res)
564 OIC_LOG(ERROR, TAG, "send has failed");
570 case CA_BLOCK_INCOMPLETE:
571 if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type ||
572 CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
574 // add data to send thread
575 res = CASendErrorMessage(pdu, blockWiseStatus,
576 CA_REQUEST_ENTITY_INCOMPLETE,
578 if (CA_STATUS_OK != res)
580 OIC_LOG(ERROR, TAG, "send has failed");
586 case CA_BLOCK_TOO_LARGE:
587 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
589 res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
591 if (CA_STATUS_OK != res)
593 OIC_LOG(ERROR, TAG, "send has failed");
597 else if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
599 res = CASendErrorMessage(pdu, blockWiseStatus,
600 CA_REQUEST_ENTITY_TOO_LARGE,
602 if (CA_STATUS_OK != res)
604 OIC_LOG(ERROR, TAG, "send has failed");
610 OIC_LOG_V(ERROR, TAG, "no logic [%d]", blockWiseStatus);
615 CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType,
616 uint8_t status, const CABlockDataID_t *blockID)
618 VERIFY_NON_NULL(pdu, TAG, "pdu");
619 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
620 VERIFY_NON_NULL(blockID, TAG, "blockID");
622 CAData_t *data = CAGetDataSetFromBlockDataList(blockID);
625 OIC_LOG(ERROR, TAG, "CAData is unavailable");
626 return CA_STATUS_FAILED;
629 if (CA_MSG_CONFIRM == msgType)
631 OIC_LOG(DEBUG, TAG, "need new msgID");
632 if (data->requestInfo)
634 data->requestInfo->info.messageId = 0;
637 if (data->responseInfo)
639 data->responseInfo->info.messageId = 0;
642 else if (CA_MSG_ACKNOWLEDGE == msgType)
644 if (data->responseInfo)
646 OIC_LOG(DEBUG, TAG, "set ACK message");
647 data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
648 data->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
649 if (CA_OPTION1_NO_ACK_LAST_BLOCK == status)
651 data->responseInfo->result = CA_CHANGED;
653 else if (CA_OPTION1_NO_ACK_BLOCK == status)
655 data->responseInfo->result = CA_CONTINUE;
660 // add data to send thread
661 CAResult_t res = CAAddSendThreadQueue(data, blockID);
662 if (CA_STATUS_OK != res)
664 OIC_LOG(ERROR, TAG, "add has failed");
670 CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
671 CAResponseResult_t responseResult,
672 const CABlockDataID_t *blockID)
674 VERIFY_NON_NULL(pdu, TAG, "pdu");
675 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
676 VERIFY_NON_NULL(blockID, TAG, "blockID");
678 // create error responseInfo
679 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockID);
682 OIC_LOG(ERROR, TAG, "data is unavailable");
683 return CA_STATUS_FAILED;
686 CAData_t *cloneData = NULL;
687 if (data->sentData && data->sentData->responseInfo)
689 data->sentData->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
690 data->sentData->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
691 data->sentData->responseInfo->result = responseResult;
692 cloneData = CACloneCAData(data->sentData);
695 OIC_LOG(ERROR, TAG, "clone has failed");
696 return CA_MEMORY_ALLOC_FAILED;
698 OIC_LOG(DEBUG, TAG, "set ACK message");
700 else if (data->sentData)
702 cloneData = CACreateNewDataSet(pdu, data->sentData->remoteEndpoint);
705 OIC_LOG(ERROR, TAG, PCF("CACreateNewDataSet failed"));
706 return CA_MEMORY_ALLOC_FAILED;
709 cloneData->responseInfo->info.type = CA_MSG_CONFIRM;
710 cloneData->responseInfo->result = responseResult;
711 OIC_LOG(DEBUG, TAG, "set CON message");
715 OIC_LOG(ERROR, TAG, "data has no sent-data");
716 return CA_MEMORY_ALLOC_FAILED;
719 // add data to send thread
720 if (g_context.sendThreadFunc)
722 ca_mutex_lock(g_context.blockDataSenderMutex);
723 g_context.sendThreadFunc(cloneData);
724 ca_mutex_unlock(g_context.blockDataSenderMutex);
728 CADestroyDataSet(cloneData);
731 // if error code is 4.08, remove the stored payload and initialize block number
732 if (CA_BLOCK_INCOMPLETE == status)
734 OICFree(data->payload);
735 data->payload = NULL;
736 data->payloadLength = 0;
737 data->receivedPayloadLen = 0;
738 data->block1.num = 0;
739 data->block2.num = 0;
745 CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID,
746 const CAData_t *receivedData)
748 VERIFY_NON_NULL(blockID, TAG, "blockID");
749 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
751 // total block data have to notify to Application
752 CAData_t *cloneData = CACloneCAData(receivedData);
755 OIC_LOG(ERROR, TAG, "clone has failed");
756 return CA_MEMORY_ALLOC_FAILED;
760 size_t fullPayloadLen = 0;
761 CAPayload_t fullPayload = CAGetPayloadFromBlockDataList(blockID,
765 CAResult_t res = CAUpdatePayloadToCAData(cloneData, fullPayload, fullPayloadLen);
766 if (CA_STATUS_OK != res)
768 OIC_LOG(ERROR, TAG, "update has failed");
769 CADestroyDataSet(cloneData);
774 if (g_context.receivedThreadFunc)
776 g_context.receivedThreadFunc(cloneData);
780 CADestroyDataSet(cloneData);
786 // TODO make pdu const after libcoap is updated to support that.
787 CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
788 const CAData_t *receivedData, coap_block_t block,
791 OIC_LOG(INFO, TAG, "CASetNextBlockOption1");
792 VERIFY_NON_NULL(pdu, TAG, "pdu");
793 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
794 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
795 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
797 OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
799 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
800 (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
801 pdu->hdr->coap_hdr_udp_t.token_length,
804 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
806 OIC_LOG(ERROR, TAG, "blockId is null");
807 CADestroyBlockID(blockDataID);
808 return CA_STATUS_FAILED;
811 // BlockData data is created if it not existed
812 if (!CAIsBlockDataInList(blockDataID))
814 OIC_LOG(DEBUG, TAG, "no message in list");
816 CAData_t *data = CACreateNewDataSet(pdu, endpoint);
819 OIC_LOG(ERROR, TAG, "data is null");
820 CADestroyBlockID(blockDataID);
821 return CA_STATUS_FAILED;
824 CABlockData_t *currData = CACreateNewBlockData(data);
827 OIC_LOG(ERROR, TAG, "currData is null");
828 CADestroyDataSet(data);
829 CADestroyBlockID(blockDataID);
830 return CA_STATUS_FAILED;
832 CADestroyDataSet(data);
835 // update BLOCK OPTION1 type
836 CAResult_t res = CAUpdateBlockOptionType(blockDataID,
838 if (CA_STATUS_OK != res)
840 OIC_LOG(ERROR, TAG, "update has failed");
841 CARemoveBlockDataFromList(blockDataID);
842 CADestroyBlockID(blockDataID);
846 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
849 OIC_LOG(ERROR, TAG, "getting has failed");
850 CADestroyBlockID(blockDataID);
851 return CA_STATUS_FAILED;
854 uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
855 // received type from remote device
856 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
858 uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
860 (CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code))
862 int isBlock2 = coap_get_block(pdu, COAP_OPTION_BLOCK2, &block);
865 OIC_LOG(INFO, TAG, "received data is combining block1 and block2");
866 // initialize block number for response message
867 data->block1.num = 0;
868 CADestroyBlockID(blockDataID);
873 OIC_LOG(INFO, TAG, "received data is not bulk data");
874 CAReceiveLastBlock(blockDataID, receivedData);
875 CARemoveBlockDataFromList(blockDataID);
876 CADestroyBlockID(blockDataID);
881 blockWiseStatus = CA_OPTION1_ACK;
882 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1, blockWiseStatus);
883 if (CA_STATUS_OK != res)
885 OIC_LOG(ERROR, TAG, "update has failed");
886 CADestroyBlockID(blockDataID);
890 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1);
891 if (CA_STATUS_OK != res)
893 OIC_LOG(ERROR, TAG, "update has failed");
894 CARemoveBlockDataFromList(blockDataID);
895 CADestroyBlockID(blockDataID);
899 else // CON or NON message
901 OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m);
903 // check the size option
904 bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu,
906 &(data->payloadLength));
908 // check if received payload is exact
909 if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
911 blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
912 COAP_OPTION_BLOCK1, dataLen);
915 if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus)
917 // store the received payload and merge
918 res = CAUpdatePayloadData(data, receivedData, blockWiseStatus,
919 isSizeOption, COAP_OPTION_BLOCK1);
920 if (CA_STATUS_OK != res)
922 OIC_LOG(ERROR, TAG, "update has failed");
923 CARemoveBlockDataFromList(blockDataID);
924 CADestroyBlockID(blockDataID);
928 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK1,
930 if (CA_STATUS_OK != res)
932 OIC_LOG(ERROR, TAG, "update has failed");
933 CARemoveBlockDataFromList(blockDataID);
934 CADestroyBlockID(blockDataID);
939 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK1);
940 if (CA_STATUS_OK != res)
942 OIC_LOG(ERROR, TAG, "update has failed");
943 CARemoveBlockDataFromList(blockDataID);
944 CADestroyBlockID(blockDataID);
949 // check the blcok-wise transfer status for next step
950 if (CA_BLOCK_UNKNOWN == blockWiseStatus || CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)
952 if (0 == block.m) // Last block is received
954 OIC_LOG(DEBUG, TAG, "M bit is 0");
955 blockWiseStatus = CA_OPTION1_NO_ACK_LAST_BLOCK;
959 OIC_LOG(DEBUG, TAG, "M bit is 1");
960 blockWiseStatus = CA_OPTION1_NO_ACK_BLOCK;
965 res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID);
966 if (CA_STATUS_OK != res)
968 OIC_LOG(ERROR, TAG, "setting has failed");
969 CARemoveBlockDataFromList(blockDataID);
972 CADestroyBlockID(blockDataID);
976 // TODO make pdu const after libcoap is updated to support that.
977 CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
978 const CAData_t *receivedData, coap_block_t block,
981 OIC_LOG(DEBUG, TAG, "CASetNextBlockOption2");
982 OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
984 VERIFY_NON_NULL(pdu, TAG, "pdu");
985 VERIFY_NON_NULL(pdu->hdr, TAG, "pdu->hdr");
986 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
987 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
989 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
990 (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
991 pdu->hdr->coap_hdr_udp_t.token_length,
994 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
996 OIC_LOG(ERROR, TAG, "blockId is null");
997 CADestroyBlockID(blockDataID);
998 return CA_STATUS_FAILED;
1001 // BlockData data is created if it not existed
1002 if (!CAIsBlockDataInList(blockDataID))
1004 OIC_LOG(DEBUG, TAG, "no msg in list.");
1006 CAData_t *data = CACreateNewDataSet(pdu, endpoint);
1009 OIC_LOG(ERROR, TAG, "data is null");
1010 CADestroyBlockID(blockDataID);
1011 return CA_STATUS_FAILED;
1014 CABlockData_t *currData = CACreateNewBlockData(data);
1017 OIC_LOG(ERROR, TAG, "data is null");
1018 CADestroyDataSet(data);
1019 CADestroyBlockID(blockDataID);
1020 return CA_STATUS_FAILED;
1022 CADestroyDataSet(data);
1025 // set Block Option Type
1026 CAResult_t res = CAUpdateBlockOptionType(blockDataID, COAP_OPTION_BLOCK2);
1027 if (CA_STATUS_OK != res)
1029 OIC_LOG(ERROR, TAG, "update has failed");
1030 CARemoveBlockDataFromList(blockDataID);
1031 CADestroyBlockID(blockDataID);
1035 CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
1038 OIC_LOG(ERROR, TAG, "getting has failed");
1039 CARemoveBlockDataFromList(blockDataID);
1040 CADestroyBlockID(blockDataID);
1041 return CA_STATUS_FAILED;
1044 uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
1045 if (0 == block.num && CA_GET == pdu->hdr->coap_hdr_udp_t.code && 0 == block.m)
1047 OIC_LOG(INFO, TAG, "first block number");
1049 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus);
1050 if (CA_STATUS_OK != res)
1052 OIC_LOG(ERROR, TAG, "update has failed");
1053 CARemoveBlockDataFromList(blockDataID);
1054 CADestroyBlockID(blockDataID);
1058 // first block data have to notify to Application
1059 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1060 if (CA_STATUS_OK != res)
1062 OIC_LOG(ERROR, TAG, "update has failed");
1063 CARemoveBlockDataFromList(blockDataID);
1064 CADestroyBlockID(blockDataID);
1067 blockWiseStatus = CA_OPTION2_FIRST_BLOCK;
1071 // received type from remote device
1072 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type ||
1073 (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type &&
1074 NULL != receivedData->responseInfo))
1076 OIC_LOG(DEBUG, TAG, "received ACK or NON");
1078 // check the size option
1079 bool isSizeOption = CAIsPayloadLengthInPduWithBlockSizeOption(pdu,
1081 &(data->payloadLength));
1083 // check if received payload is exact
1084 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
1086 blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
1087 COAP_OPTION_BLOCK2, dataLen);
1090 if (CA_BLOCK_RECEIVED_ALREADY != blockWiseStatus)
1092 // store the received payload and merge
1093 res = CAUpdatePayloadData(data, receivedData, blockWiseStatus,
1094 isSizeOption, COAP_OPTION_BLOCK2);
1095 if (CA_STATUS_OK != res)
1097 OIC_LOG(ERROR, TAG, "update has failed");
1098 CARemoveBlockDataFromList(blockDataID);
1099 CADestroyBlockID(blockDataID);
1104 if (0 == block.m && CA_BLOCK_UNKNOWN == blockWiseStatus) // Last block is received
1106 OIC_LOG(DEBUG, TAG, "M bit is 0");
1107 blockWiseStatus = CA_OPTION2_LAST_BLOCK;
1111 if (CA_BLOCK_UNKNOWN == blockWiseStatus ||
1112 CA_BLOCK_RECEIVED_ALREADY == blockWiseStatus)
1114 OIC_LOG(DEBUG, TAG, "M bit is 1");
1116 if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
1118 blockWiseStatus = CA_OPTION2_ACK;
1122 blockWiseStatus = CA_OPTION2_NON;
1126 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2,
1128 if (CA_STATUS_OK != res)
1130 OIC_LOG(ERROR, TAG, "update has failed");
1131 CARemoveBlockDataFromList(blockDataID);
1132 CADestroyBlockID(blockDataID);
1136 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1137 if (CA_STATUS_OK != res)
1139 OIC_LOG(ERROR, TAG, "update has failed");
1140 CARemoveBlockDataFromList(blockDataID);
1141 CADestroyBlockID(blockDataID);
1146 else // CON message and so on.
1148 OIC_LOG_V(INFO, TAG, "num:%d, M:%d", block.num, block.m);
1150 blockWiseStatus = CA_OPTION2_CON;
1152 res = CAUpdateBlockOptionItems(data, pdu, &block, COAP_OPTION_BLOCK2, blockWiseStatus);
1153 if (CA_STATUS_OK != res)
1155 OIC_LOG(ERROR, TAG, "update has failed");
1156 CARemoveBlockDataFromList(blockDataID);
1157 CADestroyBlockID(blockDataID);
1161 res = CAUpdateBlockData(data, block, COAP_OPTION_BLOCK2);
1162 if (CA_STATUS_OK != res)
1164 OIC_LOG(ERROR, TAG, "update has failed");
1165 CARemoveBlockDataFromList(blockDataID);
1166 CADestroyBlockID(blockDataID);
1172 res = CAProcessNextStep(pdu, receivedData, blockWiseStatus, blockDataID);
1173 if (CA_STATUS_OK != res)
1175 OIC_LOG(ERROR, TAG, "setting has failed");
1176 CARemoveBlockDataFromList(blockDataID);
1177 CADestroyBlockID(blockDataID);
1181 CADestroyBlockID(blockDataID);
1182 return CA_STATUS_OK;
1185 CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *pdu,
1186 coap_block_t *block, uint16_t blockType,
1189 VERIFY_NON_NULL(currData, TAG, "currData");
1190 VERIFY_NON_NULL(pdu, TAG, "pdu");
1191 VERIFY_NON_NULL(block, TAG, "block");
1193 // update block data
1194 CAResult_t res = CA_STATUS_OK;
1195 uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
1197 if (CA_REQUEST_ENTITY_INCOMPLETE == code || CA_REQUEST_ENTITY_TOO_LARGE == code)
1199 // response error code of the received block message
1200 res = CAHandleBlockErrorResponse(block, blockType, code);
1201 if (CA_STATUS_OK != res)
1203 OIC_LOG(ERROR, TAG, "error handle has failed");
1209 // update block option items
1212 case CA_OPTION1_ACK:
1213 if (currData->block1.num > block->num)
1215 OIC_LOG(ERROR, TAG, "received incorrect block num");
1216 return CA_STATUS_FAILED;
1220 case CA_OPTION2_NON:
1224 case CA_OPTION2_CON:
1227 case CA_OPTION2_ACK:
1228 if (currData->block2.num > block->num)
1230 OIC_LOG(ERROR, TAG, "received incorrect block num");
1231 return CA_STATUS_FAILED;
1236 case CA_BLOCK_TOO_LARGE:
1237 // if state of received block message is CA_BLOCK_TOO_LARGE or CA_BLOCK_INCOMPLETE
1238 // we set the response error code appropriately and send
1239 if (COAP_OPTION_BLOCK2 == blockType)
1243 block->szx = currData->block2.szx;
1247 block->szx = currData->block1.szx;
1251 OIC_LOG_V(ERROR, TAG, "no logic [%d]", status);
1254 if (CA_BLOCK_INCOMPLETE != status && CA_BLOCK_TOO_LARGE != status)
1256 // negotiate block size
1257 res = CANegotiateBlockSize(currData, block, pdu->hdr->coap_hdr_udp_t.type, blockType);
1258 if (CA_STATUS_OK != res)
1260 OIC_LOG(ERROR, TAG, "negotiation has failed");
1268 CAResult_t CAGetMoreBitFromBlock(size_t payloadLen, coap_block_t *block)
1270 VERIFY_NON_NULL(block, TAG, "block");
1272 if ((size_t)((block->num + 1) << (block->szx + BLOCK_NUMBER_IDX))
1275 OIC_LOG(DEBUG, TAG, "Set the M-bit(1)");
1280 OIC_LOG(DEBUG, TAG, "Set the M-bit(0)");
1284 return CA_STATUS_OK;
1287 CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block,
1288 CAMessageType_t msgType, uint16_t blockType)
1290 OIC_LOG(DEBUG, TAG, "IN-NegotiateBlockSize");
1292 VERIFY_NON_NULL(currData, TAG, "currData");
1293 VERIFY_NON_NULL(block, TAG, "block");
1295 // #1. check the block option type
1296 if (COAP_OPTION_BLOCK2 == blockType)
1298 // #2. check the message type
1299 if (CA_MSG_ACKNOWLEDGE == msgType)
1301 if (block->szx > currData->block2.szx)
1303 OIC_LOG(DEBUG, TAG, "sze is big");
1305 // #3. calculate new block number from block size
1306 unsigned int blockNum = BLOCK_SIZE(block->szx) /
1307 BLOCK_SIZE(currData->block2.szx) - 1;
1308 OIC_LOG(DEBUG, TAG, "num is set as Negotiation");
1309 block->num += blockNum;
1310 block->szx = currData->block2.szx;
1311 OIC_LOG_V(DEBUG, TAG, "updated block num: %d", block->num);
1316 if (block->szx > currData->block2.szx)
1318 OIC_LOG(DEBUG, TAG, "sze is big");
1319 block->szx = currData->block2.szx;
1323 else if (COAP_OPTION_BLOCK1 == blockType)
1325 if (CA_MSG_ACKNOWLEDGE == msgType)
1327 if (block->szx < currData->block1.szx)
1329 OIC_LOG(DEBUG, TAG, "sze is small");
1331 unsigned int blockNum = BLOCK_SIZE(currData->block1.szx) /
1332 BLOCK_SIZE(block->szx) - 1;
1333 block->num += blockNum;
1334 OIC_LOG_V(DEBUG, TAG, "updated block num: %d", block->num);
1339 if (block->szx > currData->block1.szx)
1341 OIC_LOG(DEBUG, TAG, "sze is big");
1342 block->szx = currData->block1.szx;
1348 OIC_LOG(DEBUG, TAG, "Invalid block option");
1349 return CA_STATUS_FAILED;
1352 OIC_LOG(DEBUG, TAG, "OUT-NegotiateBlockSize");
1354 return CA_STATUS_OK;
1357 CAResult_t CAUpdateBlockData(CABlockData_t *currData, coap_block_t block,
1360 VERIFY_NON_NULL(currData, TAG, "currData");
1362 // check if block size is bigger than CABlockSize_t
1363 if (block.szx > CA_BLOCK_SIZE_1024_BYTE)
1365 OIC_LOG(DEBUG, TAG, "invalid block szx");
1366 return CA_STATUS_FAILED;
1369 // update block option
1370 if (COAP_OPTION_BLOCK2 == blockType)
1372 currData->block2 = block;
1376 currData->block1 = block;
1379 OIC_LOG(DEBUG, TAG, "data has updated");
1380 return CA_STATUS_OK;
1383 CAResult_t CAUpdateMessageId(coap_pdu_t *pdu, const CABlockDataID_t *blockID)
1385 VERIFY_NON_NULL(pdu, TAG, "pdu");
1386 VERIFY_NON_NULL(blockID, TAG, "blockID");
1388 // if CON message is sent, update messageId in block-wise transfer list
1389 if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
1391 CAData_t * cadata = CAGetDataSetFromBlockDataList(blockID);
1394 OIC_LOG(ERROR, TAG, "CAData is unavailable");
1395 return CA_STATUS_FAILED;
1398 if (cadata->requestInfo)
1400 cadata->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
1404 return CA_STATUS_OK;
1407 CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
1408 const CAEndpoint_t *endpoint, coap_list_t **options)
1410 OIC_LOG(DEBUG, TAG, "IN-AddBlockOption");
1411 VERIFY_NON_NULL(pdu, TAG, "pdu");
1412 VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1413 VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1414 VERIFY_NON_NULL(info, TAG, "info");
1415 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
1416 VERIFY_NON_NULL(options, TAG, "options");
1418 size_t dataLength = 0;
1421 dataLength = info->payloadSize;
1422 OIC_LOG_V(DEBUG, TAG, "dataLength - %zu", dataLength);
1425 OIC_LOG_V(DEBUG, TAG, "previous payload - %s", (*pdu)->data);
1427 CAResult_t res = CA_STATUS_OK;
1428 uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->coap_hdr_udp_t.code);
1429 if (CA_REQUEST_ENTITY_INCOMPLETE == code)
1431 OIC_LOG(INFO, TAG, "don't use option");
1435 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
1436 (CAToken_t)(*pdu)->hdr->coap_hdr_udp_t.token,
1437 (*pdu)->hdr->coap_hdr_udp_t.token_length,
1440 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
1442 OIC_LOG(ERROR, TAG, "blockId is null");
1443 res = CA_STATUS_FAILED;
1447 uint8_t blockType = CAGetBlockOptionType(blockDataID);
1448 if (COAP_OPTION_BLOCK2 == blockType)
1450 res = CAAddBlockOption2(pdu, info, dataLength, blockDataID, options);
1451 if (CA_STATUS_OK != res)
1453 OIC_LOG(ERROR, TAG, "add has failed");
1457 else if (COAP_OPTION_BLOCK1 == blockType)
1459 res = CAAddBlockOption1(pdu, info, dataLength, blockDataID, options);
1460 if (CA_STATUS_OK != res)
1462 OIC_LOG(ERROR, TAG, "add has failed");
1468 OIC_LOG(DEBUG, TAG, "no BLOCK option");
1470 // in case it is not large data, add option list to pdu.
1473 for (coap_list_t *opt = *options; opt; opt = opt->next)
1475 OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
1476 COAP_OPTION_DATA(*(coap_option *) opt->data));
1478 OIC_LOG_V(DEBUG, TAG, "[%d] pdu length", (*pdu)->length);
1479 coap_add_option(*pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
1480 COAP_OPTION_LENGTH(*(coap_option *) opt->data),
1481 COAP_OPTION_DATA(*(coap_option *) opt->data), coap_udp);
1485 OIC_LOG_V(DEBUG, TAG, "[%d] pdu length after option", (*pdu)->length);
1487 // if response data is so large. it have to send as block transfer
1488 if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
1490 OIC_LOG(INFO, TAG, "it have to use block");
1494 OIC_LOG(INFO, TAG, "not Blockwise Transfer");
1499 // if received message type is RESET from remote device,
1500 // we have to use the updated message id to find token.
1501 res = CAUpdateMessageId(*pdu, blockDataID);
1502 if (CA_STATUS_OK != res)
1504 OIC_LOG(ERROR, TAG, "fail to update CON message id ");
1509 if (CA_ADAPTER_IP == endpoint->adapter && 0 == endpoint->port)
1511 CARemoveBlockDataFromList(blockDataID);
1513 CADestroyBlockID(blockDataID);
1514 OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption");
1518 CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
1519 const CABlockDataID_t *blockID, coap_list_t **options)
1521 OIC_LOG(DEBUG, TAG, "IN-AddBlockOption2");
1522 VERIFY_NON_NULL(pdu, TAG, "pdu");
1523 VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1524 VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1525 VERIFY_NON_NULL(info, TAG, "info");
1526 VERIFY_NON_NULL(blockID, TAG, "blockID");
1527 VERIFY_NON_NULL(options, TAG, "options");
1529 // get set block data from CABlock list-set.
1530 coap_block_t *block1 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK1);
1531 coap_block_t *block2 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK2);
1532 if (!block1 || !block2)
1534 OIC_LOG(ERROR, TAG, "getting has failed");
1535 return CA_STATUS_FAILED;
1538 CALogBlockInfo(block2);
1540 if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type ||
1541 (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type &&
1542 CA_GET != (*pdu)->hdr->coap_hdr_udp_t.code))
1544 CAGetMoreBitFromBlock(dataLength, block2);
1545 CALogBlockInfo(block2);
1547 // if block number is 0, add size2 option
1548 if (0 == block2->num)
1550 CAResult_t res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE2, dataLength, options);
1551 if (CA_STATUS_OK != res)
1553 OIC_LOG(ERROR, TAG, "add has failed");
1554 CARemoveBlockDataFromList(blockID);
1559 CAResult_t res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options);
1560 if (CA_STATUS_OK != res)
1562 OIC_LOG(ERROR, TAG, "add has failed");
1563 CARemoveBlockDataFromList(blockID);
1569 OIC_LOG(DEBUG, TAG, "combining block1 and block2");
1570 res = CAAddBlockOptionImpl(block1, COAP_OPTION_BLOCK1, options);
1571 if (CA_STATUS_OK != res)
1573 OIC_LOG(ERROR, TAG, "add has failed");
1574 CARemoveBlockDataFromList(blockID);
1577 // initialize block number
1581 res = CAAddOptionToPDU(*pdu, options);
1582 if (CA_STATUS_OK != res)
1584 OIC_LOG(ERROR, TAG, "add has failed");
1585 CARemoveBlockDataFromList(blockID);
1589 if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload,
1590 block2->num, block2->szx))
1592 OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
1593 return CA_STATUS_FAILED;
1598 // if sent message is last response block message, remove data
1599 CARemoveBlockDataFromList(blockID);
1603 if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type)
1605 OIC_LOG(DEBUG, TAG, "NON, send next block..");
1606 // update block data
1608 CAResult_t res = CAProcessNextStep(*pdu, NULL,
1609 CA_SENT_PREVIOUS_NON_MSG,
1611 if (CA_STATUS_OK != res)
1613 OIC_LOG(ERROR, TAG, "failed to process next step");
1614 CARemoveBlockDataFromList(blockID);
1622 OIC_LOG(DEBUG, TAG, "option2, not ACK msg");
1623 CAResult_t res = CAAddBlockOptionImpl(block2, COAP_OPTION_BLOCK2, options);
1624 if (CA_STATUS_OK != res)
1626 OIC_LOG(ERROR, TAG, "add has failed");
1627 CARemoveBlockDataFromList(blockID);
1631 res = CAAddOptionToPDU(*pdu, options);
1632 if (CA_STATUS_OK != res)
1634 OIC_LOG(ERROR, TAG, "add has failed");
1635 CARemoveBlockDataFromList(blockID);
1640 return CA_STATUS_OK;
1643 CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
1644 const CABlockDataID_t *blockID, coap_list_t **options)
1646 OIC_LOG(DEBUG, TAG, "IN-AddBlockOption1");
1647 VERIFY_NON_NULL(pdu, TAG, "pdu");
1648 VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
1649 VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
1650 VERIFY_NON_NULL(info, TAG, "info");
1651 VERIFY_NON_NULL(blockID, TAG, "blockID");
1652 VERIFY_NON_NULL(options, TAG, "options");
1654 // get set block data from CABlock list-set.
1655 coap_block_t *block1 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK1);
1658 OIC_LOG(ERROR, TAG, "getting has failed");
1659 return CA_STATUS_FAILED;
1662 CALogBlockInfo(block1);
1664 if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type)
1666 OIC_LOG(DEBUG, TAG, "option1 and ACK msg..");
1667 CAResult_t res = CAAddBlockOptionImpl(block1, COAP_OPTION_BLOCK1, options);
1668 if (CA_STATUS_OK != res)
1670 OIC_LOG(ERROR, TAG, "add has failed");
1671 CARemoveBlockDataFromList(blockID);
1675 res = CAAddOptionToPDU(*pdu, options);
1676 if (CA_STATUS_OK != res)
1678 OIC_LOG(ERROR, TAG, "add has failed");
1679 CARemoveBlockDataFromList(blockID);
1683 if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
1685 OIC_LOG(ERROR, TAG, "failed to add payload");
1686 return CA_STATUS_FAILED;
1689 // reset block-list after write block
1692 // remove data from list
1693 CAResult_t res = CARemoveBlockDataFromList(blockID);
1694 if (CA_STATUS_OK != res)
1696 OIC_LOG(ERROR, TAG, "remove has failed");
1703 CAGetMoreBitFromBlock(dataLength, block1);
1705 CAResult_t res = CA_STATUS_OK;
1706 // if block number is 0, add size1 option
1707 if (0 == block1->num)
1709 res = CAAddBlockSizeOption(*pdu, COAP_OPTION_SIZE1, dataLength, options);
1710 if (CA_STATUS_OK != res)
1712 OIC_LOG(ERROR, TAG, "add has failed");
1713 CARemoveBlockDataFromList(blockID);
1718 res = CAAddBlockOptionImpl(block1, COAP_OPTION_BLOCK1, options);
1719 if (CA_STATUS_OK != res)
1721 OIC_LOG(ERROR, TAG, "add has failed");
1722 CARemoveBlockDataFromList(blockID);
1726 res = CAAddOptionToPDU(*pdu, options);
1727 if (CA_STATUS_OK != res)
1729 OIC_LOG(ERROR, TAG, "add has failed");
1730 CARemoveBlockDataFromList(blockID);
1734 CALogBlockInfo(block1);
1736 if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload,
1737 block1->num, block1->szx))
1739 OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
1740 return CA_STATUS_FAILED;
1743 // check the message type and if message type is NON, next block message will be sent
1744 if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type)
1748 OIC_LOG(DEBUG, TAG, "NON, send next block..");
1749 // update block data
1751 CAResult_t res = CAProcessNextStep(*pdu, NULL,
1752 CA_SENT_PREVIOUS_NON_MSG,
1754 if (CA_STATUS_OK != res)
1756 OIC_LOG(ERROR, TAG, "failed to process next step");
1757 CARemoveBlockDataFromList(blockID);
1763 CARemoveBlockDataFromList(blockID);
1768 OIC_LOG(DEBUG, TAG, "OUT-AddBlockOption1");
1770 return CA_STATUS_OK;
1773 CAResult_t CAAddBlockOptionImpl(coap_block_t *block, uint8_t blockType,
1774 coap_list_t **options)
1776 OIC_LOG(DEBUG, TAG, "IN-AddBlockOptionImpl");
1777 VERIFY_NON_NULL(block, TAG, "block");
1778 VERIFY_NON_NULL(options, TAG, "options");
1780 unsigned char buf[BLOCKWISE_OPTION_BUFFER] = { 0 };
1781 unsigned int optionLength = coap_encode_var_bytes(buf,
1782 ((block->num << BLOCK_NUMBER_IDX)
1783 | (block->m << BLOCK_M_BIT_IDX)
1786 int ret = coap_insert(options,
1787 CACreateNewOptionNode(blockType, optionLength, (char *) buf),
1791 return CA_STATUS_INVALID_PARAM;
1794 OIC_LOG(DEBUG, TAG, "OUT-AddBlockOptionImpl");
1795 return CA_STATUS_OK;
1798 CAResult_t CAAddOptionToPDU(coap_pdu_t *pdu, coap_list_t **options)
1800 // after adding the block option to option list, add option list to pdu.
1803 for (coap_list_t *opt = *options; opt; opt = opt->next)
1805 OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
1806 COAP_OPTION_DATA(*(coap_option *) opt->data));
1808 OIC_LOG_V(DEBUG, TAG, "[%d] pdu length", pdu->length);
1809 int ret = coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
1810 COAP_OPTION_LENGTH(*(coap_option *) opt->data),
1811 COAP_OPTION_DATA(*(coap_option *) opt->data), coap_udp);
1814 return CA_STATUS_FAILED;
1819 OIC_LOG_V(DEBUG, TAG, "[%d] pdu length after option", pdu->length);
1821 return CA_STATUS_OK;
1824 CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataLength,
1825 coap_list_t **options)
1827 OIC_LOG(DEBUG, TAG, "IN-CAAddBlockSizeOption");
1828 VERIFY_NON_NULL(pdu, TAG, "pdu");
1829 VERIFY_NON_NULL(options, TAG, "options");
1831 if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2)
1833 OIC_LOG(ERROR, TAG, "unknown option type");
1834 return CA_STATUS_FAILED;
1837 unsigned char value[BLOCKWISE_OPTION_BUFFER] = { 0 };
1838 unsigned int optionLength = coap_encode_var_bytes(value, dataLength);
1840 int ret = coap_insert(options,
1841 CACreateNewOptionNode(sizeType, optionLength, (char *) value),
1845 return CA_STATUS_INVALID_PARAM;
1848 OIC_LOG(DEBUG, TAG, "OUT-CAAddBlockSizeOption");
1850 return CA_STATUS_OK;
1853 // TODO make pdu const after libcoap is updated to support that.
1854 bool CAIsPayloadLengthInPduWithBlockSizeOption(coap_pdu_t *pdu,
1856 size_t *totalPayloadLen)
1858 OIC_LOG(DEBUG, TAG, "IN-CAIsPayloadLengthInPduWithBlockSizeOption");
1859 VERIFY_NON_NULL(pdu, TAG, "pdu");
1860 VERIFY_NON_NULL(totalPayloadLen, TAG, "totalPayloadLen");
1862 if (sizeType != COAP_OPTION_SIZE1 && sizeType != COAP_OPTION_SIZE2)
1864 OIC_LOG(ERROR, TAG, "unknown option type");
1865 return CA_STATUS_FAILED;
1868 coap_opt_iterator_t opt_iter;
1869 coap_opt_t *option = coap_check_option(pdu, sizeType, &opt_iter);
1872 OIC_LOG(DEBUG, TAG, "get size option from pdu");
1873 *totalPayloadLen = coap_decode_var_bytes(COAP_OPT_VALUE(option),
1874 COAP_OPT_LENGTH(option));
1876 OIC_LOG_V(DEBUG, TAG, "the total payload length to be received is [%zu]bytes",
1882 OIC_LOG(DEBUG, TAG, "OUT-CAIsPayloadLengthInPduWithBlockSizeOption");
1887 uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlock,
1888 const CAData_t *receivedData, uint16_t blockType,
1891 OIC_LOG(DEBUG, TAG, "IN-CheckBlockError");
1893 VERIFY_NON_NULL(currData, TAG, "currData is NULL");
1894 VERIFY_NON_NULL(receivedBlock, TAG, "receivedBlock is NULL");
1895 VERIFY_NON_NULL(receivedData, TAG, "receivedData is NULL");
1897 // #1. check the received payload length
1898 size_t blockPayloadLen = 0;
1899 CAGetPayloadInfo(receivedData, &blockPayloadLen);
1901 // #2. check if the block sequence is right
1902 if (COAP_OPTION_BLOCK1 == blockType)
1904 size_t prePayloadLen = currData->receivedPayloadLen;
1905 if (prePayloadLen != (size_t)BLOCK_SIZE(receivedBlock->szx)
1906 * receivedBlock->num)
1908 if (receivedBlock->num > currData->block1.num + 1)
1910 // 408 Error handling of block loss
1911 OIC_LOG(ERROR, TAG, "option1: error 4.08");
1912 OIC_LOG(ERROR, TAG, "it didn't order");
1913 return CA_BLOCK_INCOMPLETE;
1915 return CA_BLOCK_RECEIVED_ALREADY;
1918 else if (COAP_OPTION_BLOCK2 == blockType)
1920 if (receivedBlock->num != currData->block2.num)
1922 if (receivedBlock->num > currData->block2.num)
1924 // 408 Error handling of block loss
1925 OIC_LOG(ERROR, TAG, "option2: error 4.08");
1926 OIC_LOG(ERROR, TAG, "it didn't order");
1927 return CA_BLOCK_INCOMPLETE;
1929 return CA_BLOCK_RECEIVED_ALREADY;
1933 // #3. check if error check logic is required
1934 size_t optionLen = dataLen - blockPayloadLen;
1935 if (receivedBlock->m && blockPayloadLen !=
1936 (size_t)BLOCK_SIZE(receivedBlock->szx))
1938 // 413 Error handling of too large entity
1939 if (COAP_MAX_PDU_SIZE < BLOCK_SIZE(receivedBlock->szx) + optionLen)
1941 // buffer size is smaller than received block size
1942 OIC_LOG(ERROR, TAG, "error type 4.13");
1943 OIC_LOG(ERROR, TAG, "too large size");
1945 // set the block size to be smaller than COAP_MAX_PDU_SIZE
1946 for (int32_t size = CA_DEFAULT_BLOCK_SIZE; size >= 0; size--)
1948 if (COAP_MAX_PDU_SIZE >= BLOCK_SIZE(size) + optionLen)
1950 OIC_LOG_V(ERROR, TAG, "replace sze with %d", size);
1951 if (COAP_OPTION_BLOCK2 == blockType)
1953 currData->block2.szx = size;
1957 currData->block1.szx = size;
1962 return CA_BLOCK_TOO_LARGE;
1966 // 408 Error handling of payload loss
1967 OIC_LOG(ERROR, TAG, "error type 4.08");
1968 OIC_LOG(ERROR, TAG, "payload len != block sze");
1969 return CA_BLOCK_INCOMPLETE;
1972 else if (0 == receivedBlock->m && 0 != currData->payloadLength)
1974 // if the received block is last block, check the total payload length
1975 size_t receivedPayloadLen = currData->receivedPayloadLen;
1976 receivedPayloadLen += blockPayloadLen;
1978 if (receivedPayloadLen != currData->payloadLength)
1980 OIC_LOG(ERROR, TAG, "error type 4.08");
1981 OIC_LOG(ERROR, TAG, "total payload length is wrong");
1982 return CA_BLOCK_INCOMPLETE;
1986 OIC_LOG(DEBUG, TAG, "received all data normally");
1988 OIC_LOG(DEBUG, TAG, "OUT-CheckBlockError");
1990 return CA_BLOCK_UNKNOWN;
1993 CAResult_t CAUpdatePayloadData(CABlockData_t *currData, const CAData_t *receivedData,
1994 uint8_t status, bool isSizeOption, uint16_t blockType)
1996 OIC_LOG(DEBUG, TAG, "IN-UpdatePayloadData");
1998 VERIFY_NON_NULL(currData, TAG, "currData");
1999 VERIFY_NON_NULL(receivedData, TAG, "receivedData");
2001 // if error code is 4.08, do not update payload
2002 if (CA_BLOCK_INCOMPLETE == status)
2004 OIC_LOG(ERROR, TAG, "no require to update");
2005 return CA_STATUS_OK;
2008 size_t blockPayloadLen = 0;
2009 CAPayload_t blockPayload = CAGetPayloadInfo(receivedData, &blockPayloadLen);
2011 if (CA_BLOCK_TOO_LARGE == status)
2013 blockPayloadLen = (COAP_OPTION_BLOCK2 == blockType) ?
2014 BLOCK_SIZE(currData->block2.szx) : BLOCK_SIZE(currData->block1.szx);
2017 // memory allocation for the received block payload
2018 size_t prePayloadLen = currData->receivedPayloadLen;
2021 if (currData->payloadLength)
2023 // in case the block message has the size option
2024 // allocate the memory for the total payload
2027 CAPayload_t prePayload = currData->payload;
2029 OIC_LOG(DEBUG, TAG, "allocate memory for the total payload");
2030 currData->payload = (CAPayload_t) OICCalloc(1, currData->payloadLength);
2031 if (NULL == currData->payload)
2033 OIC_LOG(ERROR, TAG, "out of memory");
2034 return CA_MEMORY_ALLOC_FAILED;
2036 memcpy(currData->payload, prePayload, prePayloadLen);
2037 OICFree(prePayload);
2040 // update the total payload
2041 memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
2045 OIC_LOG(DEBUG, TAG, "allocate memory for the received block payload");
2047 size_t totalPayloadLen = prePayloadLen + blockPayloadLen;
2048 CAPayload_t newPayload = OICRealloc(currData->payload, totalPayloadLen);
2049 if (NULL == newPayload)
2051 OIC_LOG(ERROR, TAG, "out of memory");
2052 return CA_MEMORY_ALLOC_FAILED;
2055 // update the total payload
2056 memset(newPayload + prePayloadLen, 0, blockPayloadLen);
2057 currData->payload = newPayload;
2058 memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
2061 // update received payload length
2062 currData->receivedPayloadLen += blockPayloadLen;
2064 OIC_LOG_V(DEBUG, TAG, "updated payload: %s, len: %zu", currData->payload,
2065 currData->receivedPayloadLen);
2068 OIC_LOG(DEBUG, TAG, "OUT-UpdatePayloadData");
2069 return CA_STATUS_OK;
2072 CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint)
2074 VERIFY_NON_NULL_RET(pdu, TAG, "pdu", NULL);
2075 VERIFY_NON_NULL_RET(pdu->hdr, TAG, "pdu->hdr", NULL);
2076 VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
2078 CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length };
2079 responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
2080 if (!responseData.token)
2082 OIC_LOG(ERROR, TAG, "out of memory");
2085 memcpy(responseData.token, pdu->hdr->coap_hdr_udp_t.token, responseData.tokenLength);
2087 CAResponseInfo_t* responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
2090 OIC_LOG(ERROR, TAG, "out of memory");
2091 OICFree(responseData.token);
2094 responseInfo->info = responseData;
2096 CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
2099 OIC_LOG(ERROR, TAG, "out of memory");
2100 OICFree(responseInfo);
2104 data->requestInfo = NULL;
2105 data->responseInfo = responseInfo;
2106 data->remoteEndpoint = CACloneEndpoint(endpoint);
2107 data->type = SEND_TYPE_UNICAST;
2112 CAData_t *CACloneCAData(const CAData_t *data)
2114 VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
2116 CAData_t *clone = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
2119 OIC_LOG(ERROR, TAG, "out of memory");
2124 if (data->requestInfo)
2126 clone->requestInfo = CACloneRequestInfo(data->requestInfo);
2128 else if (data->responseInfo)
2130 clone->responseInfo = CACloneResponseInfo(data->responseInfo);
2133 if (data->remoteEndpoint)
2135 clone->remoteEndpoint = CACloneEndpoint(data->remoteEndpoint);
2141 CAResult_t CAUpdatePayloadToCAData(CAData_t *data, const CAPayload_t payload,
2144 OIC_LOG(DEBUG, TAG, "IN-UpdatePayload");
2146 VERIFY_NON_NULL(data, TAG, "data is NULL");
2147 VERIFY_NON_NULL(payload, TAG, "payload is NULL");
2149 CAPayload_t newPayload = NULL;
2150 switch (data->dataType)
2152 case CA_REQUEST_DATA:
2153 if (!data->requestInfo)
2155 OIC_LOG(ERROR, TAG, "request info is null");
2156 return CA_STATUS_FAILED;
2158 // allocate payload field
2159 newPayload = OICRealloc(data->requestInfo->info.payload, payloadLen);
2162 OIC_LOG(ERROR, TAG, "out of memory");
2163 return CA_STATUS_FAILED;
2165 data->requestInfo->info.payload = newPayload;
2166 memcpy(data->requestInfo->info.payload, payload, payloadLen);
2167 data->requestInfo->info.payloadSize = payloadLen;
2170 case CA_RESPONSE_DATA:
2171 if (!data->responseInfo)
2173 OIC_LOG(ERROR, TAG, "response info is null");
2174 return CA_STATUS_FAILED;
2176 // allocate payload field
2177 newPayload = OICRealloc(data->responseInfo->info.payload, payloadLen);
2180 OIC_LOG(ERROR, TAG, "out of memory");
2181 return CA_STATUS_FAILED;
2183 data->responseInfo->info.payload = newPayload;
2184 memcpy(data->responseInfo->info.payload, payload, payloadLen);
2185 data->responseInfo->info.payloadSize = payloadLen;
2189 // does not occur case
2190 OIC_LOG(ERROR, TAG, "not supported data type");
2191 return CA_NOT_SUPPORTED;
2194 OIC_LOG(DEBUG, TAG, "OUT-UpdatePayload");
2196 return CA_STATUS_OK;
2199 CAPayload_t CAGetPayloadInfo(const CAData_t *data, size_t *payloadLen)
2201 VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
2202 VERIFY_NON_NULL_RET(payloadLen, TAG, "payloadLen", NULL);
2204 if (data->requestInfo)
2206 if (data->requestInfo->info.payload)
2208 *payloadLen = data->requestInfo->info.payloadSize;
2209 return data->requestInfo->info.payload;
2214 if (data->responseInfo->info.payload)
2216 *payloadLen = data->responseInfo->info.payloadSize;
2217 return data->responseInfo->info.payload;
2224 CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType,
2225 uint32_t responseResult)
2227 OIC_LOG(DEBUG, TAG, "IN-HandleBlockErrorRes");
2228 VERIFY_NON_NULL(block, TAG, "block is NULL");
2230 // update block data
2231 switch (responseResult)
2233 case CA_REQUEST_ENTITY_INCOMPLETE:
2236 case CA_REQUEST_ENTITY_TOO_LARGE:
2237 if (COAP_OPTION_BLOCK1 == blockType)
2244 OIC_LOG_V(ERROR, TAG, "there is no Error Code of BWT[%d]", responseResult);
2247 OIC_LOG(DEBUG, TAG, "OUT-HandleBlockErrorRes");
2248 return CA_STATUS_OK;
2251 CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID,
2254 OIC_LOG(DEBUG, TAG, "IN-UpdateBlockOptionType");
2255 VERIFY_NON_NULL(blockID, TAG, "blockID");
2257 ca_mutex_lock(g_context.blockDataListMutex);
2259 size_t len = u_arraylist_length(g_context.dataList);
2260 for (size_t i = 0; i < len; i++)
2262 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2263 if (CABlockidMatches(currData, blockID))
2265 currData->type = blockType;
2266 ca_mutex_unlock(g_context.blockDataListMutex);
2267 OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
2268 return CA_STATUS_OK;
2271 ca_mutex_unlock(g_context.blockDataListMutex);
2273 OIC_LOG(DEBUG, TAG, "OUT-UpdateBlockOptionType");
2274 return CA_STATUS_FAILED;
2277 uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID)
2279 OIC_LOG(DEBUG, TAG, "IN-GetBlockOptionType");
2280 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", 0);
2282 ca_mutex_lock(g_context.blockDataListMutex);
2284 size_t len = u_arraylist_length(g_context.dataList);
2285 for (size_t i = 0; i < len; i++)
2287 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2288 if (CABlockidMatches(currData, blockID))
2290 ca_mutex_unlock(g_context.blockDataListMutex);
2291 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
2292 return currData->type;
2295 ca_mutex_unlock(g_context.blockDataListMutex);
2297 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOptionType");
2301 CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID)
2303 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2305 ca_mutex_lock(g_context.blockDataListMutex);
2307 size_t len = u_arraylist_length(g_context.dataList);
2308 for (size_t i = 0; i < len; i++)
2310 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2311 if (CABlockidMatches(currData, blockID))
2313 ca_mutex_unlock(g_context.blockDataListMutex);
2314 return currData->sentData;
2317 ca_mutex_unlock(g_context.blockDataListMutex);
2322 CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
2323 CAResponseInfo_t *responseInfo)
2325 OIC_LOG(DEBUG, TAG, "IN-CAGetTokenFromBlockDataList");
2326 VERIFY_NON_NULL(pdu, TAG, "pdu");
2327 VERIFY_NON_NULL(endpoint, TAG, "endpoint");
2328 VERIFY_NON_NULL(responseInfo, TAG, "responseInfo");
2330 ca_mutex_lock(g_context.blockDataListMutex);
2332 size_t len = u_arraylist_length(g_context.dataList);
2333 for (size_t i = 0; i < len; i++)
2335 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2336 if (NULL == currData)
2341 if (NULL != currData->sentData && NULL != currData->sentData->requestInfo)
2343 if (pdu->hdr->coap_hdr_udp_t.id == currData->sentData->requestInfo->info.messageId &&
2344 endpoint->adapter == currData->sentData->remoteEndpoint->adapter)
2346 if (NULL != currData->sentData->requestInfo->info.token)
2348 uint8_t length = currData->sentData->requestInfo->info.tokenLength;
2349 responseInfo->info.tokenLength = length;
2350 responseInfo->info.token = (char *) OICMalloc(length);
2351 if (NULL == responseInfo->info.token)
2353 OIC_LOG(ERROR, TAG, "out of memory");
2354 ca_mutex_unlock(g_context.blockDataListMutex);
2355 return CA_MEMORY_ALLOC_FAILED;
2357 memcpy(responseInfo->info.token, currData->sentData->requestInfo->info.token,
2358 responseInfo->info.tokenLength);
2360 ca_mutex_unlock(g_context.blockDataListMutex);
2361 OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
2362 return CA_STATUS_OK;
2368 ca_mutex_unlock(g_context.blockDataListMutex);
2370 OIC_LOG(DEBUG, TAG, "OUT-CAGetTokenFromBlockDataList");
2371 return CA_STATUS_OK;
2374 CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t **blockData)
2376 VERIFY_NON_NULL(sendData, TAG, "sendData");
2377 VERIFY_NON_NULL(blockData, TAG, "blockData");
2379 ca_mutex_lock(g_context.blockDataListMutex);
2381 size_t len = u_arraylist_length(g_context.dataList);
2382 for (size_t i = 0; i < len; i++)
2384 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2391 if (sendData->requestInfo) // sendData is requestMessage
2393 OIC_LOG(DEBUG, TAG, "Send request");
2394 if (NULL != currData->blockDataId
2395 && NULL != currData->blockDataId->id
2396 && currData->blockDataId->idLength > 0
2397 && NULL != sendData->requestInfo->info.token)
2399 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2400 (CAToken_t)sendData->requestInfo->info.token,
2401 sendData->requestInfo->info.tokenLength,
2402 sendData->remoteEndpoint->port);
2404 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2406 OIC_LOG(ERROR, TAG, "blockId is null");
2407 CADestroyBlockID(blockDataID);
2408 return CA_STATUS_FAILED;
2411 if (CABlockidMatches(currData, blockDataID))
2413 OIC_LOG(ERROR, TAG, "already sent");
2414 CADestroyBlockID(blockDataID);
2417 CADestroyBlockID(blockDataID);
2420 else if (sendData->responseInfo) // sendData is responseMessage
2422 OIC_LOG(DEBUG, TAG, "Send response");
2423 if (NULL != currData->blockDataId
2424 && NULL != currData->blockDataId->id
2425 && currData->blockDataId->idLength > 0
2426 && NULL != sendData->responseInfo->info.token)
2428 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2429 (CAToken_t)sendData->responseInfo->info.token,
2430 sendData->responseInfo->info.tokenLength,
2431 sendData->remoteEndpoint->port);
2433 if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2435 OIC_LOG(ERROR, TAG, "blockId is null");
2436 CADestroyBlockID(blockDataID);
2437 return CA_STATUS_FAILED;
2440 if (CABlockidMatches(currData, blockDataID))
2443 if (NULL != currData->sentData)
2445 OIC_LOG(DEBUG, TAG, "init block number");
2446 CADestroyDataSet(currData->sentData);
2448 currData->sentData = CACloneCAData(sendData);
2449 *blockData = currData;
2450 CADestroyBlockID(blockDataID);
2451 ca_mutex_unlock(g_context.blockDataListMutex);
2452 return CA_STATUS_OK;
2454 CADestroyBlockID(blockDataID);
2459 OIC_LOG(ERROR, TAG, "no CAInfo data");
2463 ca_mutex_unlock(g_context.blockDataListMutex);
2465 return CA_STATUS_FAILED;
2468 CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID)
2470 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2472 ca_mutex_lock(g_context.blockDataListMutex);
2474 size_t len = u_arraylist_length(g_context.dataList);
2475 for (size_t i = 0; i < len; i++)
2477 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2478 if (CABlockidMatches(currData, blockID))
2480 ca_mutex_unlock(g_context.blockDataListMutex);
2484 ca_mutex_unlock(g_context.blockDataListMutex);
2489 coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID,
2492 OIC_LOG(DEBUG, TAG, "IN-GetBlockOption");
2493 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2495 ca_mutex_lock(g_context.blockDataListMutex);
2497 size_t len = u_arraylist_length(g_context.dataList);
2498 for (size_t i = 0; i < len; i++)
2500 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2501 if (CABlockidMatches(currData, blockID))
2503 ca_mutex_unlock(g_context.blockDataListMutex);
2504 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
2505 if (COAP_OPTION_BLOCK2 == blockType)
2507 return &currData->block2;
2511 return &currData->block1;
2515 ca_mutex_unlock(g_context.blockDataListMutex);
2517 OIC_LOG(DEBUG, TAG, "OUT-GetBlockOption");
2521 CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID,
2522 size_t *fullPayloadLen)
2524 OIC_LOG(DEBUG, TAG, "IN-GetFullPayload");
2525 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", NULL);
2526 VERIFY_NON_NULL_RET(fullPayloadLen, TAG, "fullPayloadLen", NULL);
2528 ca_mutex_lock(g_context.blockDataListMutex);
2530 size_t len = u_arraylist_length(g_context.dataList);
2531 for (size_t i = 0; i < len; i++)
2533 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2534 if (CABlockidMatches(currData, blockID))
2536 ca_mutex_unlock(g_context.blockDataListMutex);
2537 *fullPayloadLen = currData->receivedPayloadLen;
2538 OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
2539 return currData->payload;
2542 ca_mutex_unlock(g_context.blockDataListMutex);
2544 OIC_LOG(DEBUG, TAG, "OUT-GetFullPayload");
2548 CABlockData_t *CACreateNewBlockData(const CAData_t *sendData)
2550 OIC_LOG(DEBUG, TAG, "IN-CACreateNewBlockData");
2551 VERIFY_NON_NULL_RET(sendData, TAG, "sendData", NULL);
2553 // create block data
2554 CABlockData_t *data = (CABlockData_t *) OICCalloc(1, sizeof(CABlockData_t));
2557 OIC_LOG(ERROR, TAG, "memory alloc has failed");
2561 data->block1.szx = CA_DEFAULT_BLOCK_SIZE;
2562 data->block2.szx = CA_DEFAULT_BLOCK_SIZE;
2563 data->sentData = CACloneCAData(sendData);
2566 OIC_LOG(ERROR, TAG, PCF("memory alloc has failed"));
2571 CAToken_t token = NULL;
2572 uint8_t tokenLength = 0;
2573 if (data->sentData->requestInfo)
2575 // update token info
2576 tokenLength = data->sentData->requestInfo->info.tokenLength;
2577 token = data->sentData->requestInfo->info.token;
2579 else if(data->sentData->responseInfo)
2581 tokenLength = data->sentData->responseInfo->info.tokenLength;
2582 token = data->sentData->responseInfo->info.token;
2585 CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
2587 data->sentData->remoteEndpoint->port);
2588 if (NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
2590 OIC_LOG(ERROR, TAG, "blockId is null");
2591 CADestroyBlockID(blockDataID);
2592 CADestroyDataSet(data->sentData);
2596 data->blockDataId = blockDataID;
2598 ca_mutex_lock(g_context.blockDataListMutex);
2600 bool res = u_arraylist_add(g_context.dataList, (void *) data);
2603 OIC_LOG(ERROR, TAG, "add has failed");
2604 CADestroyBlockID(data->blockDataId);
2605 CADestroyDataSet(data->sentData);
2607 ca_mutex_unlock(g_context.blockDataListMutex);
2610 ca_mutex_unlock(g_context.blockDataListMutex);
2612 OIC_LOG(DEBUG, TAG, "OUT-CreateBlockData");
2616 CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID)
2618 OIC_LOG(DEBUG, TAG, "CARemoveBlockData");
2619 VERIFY_NON_NULL(blockID, TAG, "blockID");
2621 ca_mutex_lock(g_context.blockDataListMutex);
2623 size_t len = u_arraylist_length(g_context.dataList);
2624 for (size_t i = 0; i < len; i++)
2626 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2627 if (CABlockidMatches(currData, blockID))
2629 CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i);
2632 OIC_LOG(ERROR, TAG, "data is NULL");
2633 ca_mutex_unlock(g_context.blockDataListMutex);
2634 return CA_STATUS_FAILED;
2638 if (currData->sentData)
2640 CADestroyDataSet(currData->sentData);
2642 CADestroyBlockID(currData->blockDataId);
2643 OICFree(currData->payload);
2645 ca_mutex_unlock(g_context.blockDataListMutex);
2646 return CA_STATUS_OK;
2649 ca_mutex_unlock(g_context.blockDataListMutex);
2651 return CA_STATUS_OK;
2654 bool CAIsBlockDataInList(const CABlockDataID_t *blockID)
2656 OIC_LOG(DEBUG, TAG, "IN-IsBlockDataInList");
2657 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false);
2659 ca_mutex_lock(g_context.blockDataListMutex);
2661 size_t len = u_arraylist_length(g_context.dataList);
2662 for (size_t i = 0; i < len; i++)
2664 CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
2665 if (CABlockidMatches(currData, blockID))
2667 OIC_LOG(DEBUG, TAG, "found block data");
2668 ca_mutex_unlock(g_context.blockDataListMutex);
2672 ca_mutex_unlock(g_context.blockDataListMutex);
2674 OIC_LOG(DEBUG, TAG, "OUT-IsBlockDataInList");
2678 void CADestroyDataSet(CAData_t* data)
2680 VERIFY_NON_NULL_VOID(data, TAG, "data");
2682 CAFreeEndpoint(data->remoteEndpoint);
2683 CADestroyRequestInfoInternal(data->requestInfo);
2684 CADestroyResponseInfoInternal(data->responseInfo);
2688 CABlockDataID_t* CACreateBlockDatablockId(const CAToken_t token, uint8_t tokenLength,
2689 uint16_t portNumber)
2691 char port[PORT_LENGTH] = {0,};
2692 port[0] = (char)((portNumber>>8) & 0xFF);
2693 port[1] = (char)(portNumber & 0xFF);
2695 CABlockDataID_t* blockDataID = (CABlockDataID_t *) OICMalloc(sizeof(CABlockDataID_t));
2698 OIC_LOG(ERROR, TAG, "memory alloc has failed");
2701 blockDataID->idLength = tokenLength + sizeof(port);
2702 blockDataID->id = (uint8_t *) OICMalloc(blockDataID->idLength);
2703 if (!blockDataID->id)
2705 OIC_LOG(ERROR, TAG, "memory alloc has failed");
2706 OICFree(blockDataID);
2712 memcpy(blockDataID->id, token, tokenLength);
2715 memcpy(blockDataID->id + tokenLength, port, sizeof(port));
2717 OIC_LOG(DEBUG, TAG, "BlockID is ");
2718 OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)blockDataID->id, blockDataID->idLength);
2723 void CADestroyBlockID(CABlockDataID_t *blockID)
2725 VERIFY_NON_NULL_VOID(blockID, TAG, "blockID");
2726 OICFree(blockID->id);
2731 bool CABlockidMatches(const CABlockData_t *currData, const CABlockDataID_t *blockID)
2733 VERIFY_NON_NULL_RET(currData, TAG, "currData", false);
2734 VERIFY_NON_NULL_RET(blockID, TAG, "blockID", false);
2735 VERIFY_NON_NULL_RET(blockID->id, TAG, "blockID->id", false);
2737 if ((currData->blockDataId)
2738 && (currData->blockDataId->id)
2739 && (currData->blockDataId->idLength == blockID->idLength)
2740 && !memcmp(currData->blockDataId->id, blockID->id, currData->blockDataId->idLength))
2747 void CALogBlockInfo(coap_block_t *block)
2749 VERIFY_NON_NULL_VOID(block, TAG, "block");
2751 OIC_LOG(DEBUG, TAG, "block option info");
2753 OIC_LOG_V(DEBUG, TAG, "block option-num : %d", block->num);
2755 OIC_LOG_V(DEBUG, TAG, "block option-m : %d", block->m);
2757 OIC_LOG_V(DEBUG, TAG, "block option-szx : %d", block->szx);