// Try for multiple URI path components that still total less than 128 TEST(CAProtocolMessage, CAParseURIManyPath) { char sampleURI[] = "coap://[::]" "/medium/a/b/c/d/e/f/g/h/i/j/" "?rt=core.sensor;if=core.mi.ll"; CoAPOptionCase cases[] = { {COAP_OPTION_URI_PATH, 6, "medium"}, {COAP_OPTION_URI_PATH, 1, "a"}, {COAP_OPTION_URI_PATH, 1, "b"}, {COAP_OPTION_URI_PATH, 1, "c"}, {COAP_OPTION_URI_PATH, 1, "d"}, {COAP_OPTION_URI_PATH, 1, "e"}, {COAP_OPTION_URI_PATH, 1, "f"}, {COAP_OPTION_URI_PATH, 1, "g"}, {COAP_OPTION_URI_PATH, 1, "h"}, {COAP_OPTION_URI_PATH, 1, "i"}, {COAP_OPTION_URI_PATH, 1, "j"}, {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"}, {COAP_OPTION_URI_QUERY, 13, "if=core.mi.ll"}, }; size_t numCases = sizeof(cases) / sizeof(cases[0]); coap_list_t *optlist = NULL; CAParseURI(sampleURI, &optlist); verifyParsedOptions(cases, numCases, optlist); coap_delete_list(optlist); }
// Try for multiple URI parameters that still total less than 128 TEST(CAProtocolMessage, CAParseURIManyParams) { char sampleURI[] = "coap://[::]/oic/res/" "?rt=core.sensor;a=0;b=1;c=2;d=3;e=4;f=5;g=6;h=7;i=8;j=9"; CoAPOptionCase cases[] = { {COAP_OPTION_URI_PATH, 3, "oic"}, {COAP_OPTION_URI_PATH, 3, "res"}, {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"}, {COAP_OPTION_URI_QUERY, 3, "a=0"}, {COAP_OPTION_URI_QUERY, 3, "b=1"}, {COAP_OPTION_URI_QUERY, 3, "c=2"}, {COAP_OPTION_URI_QUERY, 3, "d=3"}, {COAP_OPTION_URI_QUERY, 3, "e=4"}, {COAP_OPTION_URI_QUERY, 3, "f=5"}, {COAP_OPTION_URI_QUERY, 3, "g=6"}, {COAP_OPTION_URI_QUERY, 3, "h=7"}, {COAP_OPTION_URI_QUERY, 3, "i=8"}, {COAP_OPTION_URI_QUERY, 3, "j=9"}, }; size_t numCases = sizeof(cases) / sizeof(cases[0]); coap_list_t *optlist = NULL; CAParseURI(sampleURI, &optlist); verifyParsedOptions(cases, numCases, optlist); coap_delete_list(optlist); }
// Test that an initial long path component won't hide latter ones. TEST(CAProtocolMessage, CAParseURILongPath) { char sampleURI[] = "coap://[::]/oic" "123456789012345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "/res?rt=core.sensor;if=core.mi.ll"; CoAPOptionCase cases[] = { {COAP_OPTION_URI_PATH, 113, "oic" "123456789012345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890"}, {COAP_OPTION_URI_PATH, 3, "res"}, {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"}, {COAP_OPTION_URI_QUERY, 13, "if=core.mi.ll"}, }; size_t numCases = sizeof(cases) / sizeof(cases[0]); coap_list_t *optlist = NULL; CAParseURI(sampleURI, &optlist); verifyParsedOptions(cases, numCases, optlist); coap_delete_list(optlist); }
TEST_F(CABlockTransferTests, CAGetBlockSizeOptionFromPduTest) { CAEndpoint_t* tempRep = NULL; CACreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_IP, "127.0.0.1", 5683, &tempRep); coap_pdu_t *pdu = NULL; coap_list_t *options = NULL; coap_transport_t transport = COAP_UDP; CAToken_t tempToken = NULL; CAGenerateToken(&tempToken, CA_MAX_TOKEN_LEN); CAInfo_t requestData; memset(&requestData, 0, sizeof(CAInfo_t)); requestData.token = tempToken; requestData.tokenLength = CA_MAX_TOKEN_LEN; requestData.type = CA_MSG_NONCONFIRM; pdu = CAGeneratePDU(CA_GET, &requestData, tempRep, &options, &transport); size_t totalPayloadLen = 0; EXPECT_FALSE(CAIsPayloadLengthInPduWithBlockSizeOption(pdu, COAP_OPTION_SIZE1, &totalPayloadLen)); coap_delete_list(options); coap_delete_pdu(pdu); CADestroyToken(tempToken); CADestroyEndpoint(tempRep); free(requestData.payload); }
void coap_delete_list(coap_list_t *queue) { if (!queue) return; coap_delete_list(queue->next); coap_delete(queue); }
// response and block option2 TEST_F(CABlockTransferTests, CAAddBlockOption2InResponse) { CAEndpoint_t* tempRep = NULL; CACreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_IP, "127.0.0.1", 5683, &tempRep); coap_pdu_t *pdu = NULL; coap_list_t *options = NULL; coap_transport_t transport = COAP_UDP; CAToken_t tempToken = NULL; CAGenerateToken(&tempToken, CA_MAX_TOKEN_LEN); CAInfo_t responseData; memset(&responseData, 0, sizeof(CAInfo_t)); responseData.token = tempToken; responseData.tokenLength = CA_MAX_TOKEN_LEN; responseData.type = CA_MSG_NONCONFIRM; responseData.messageId = 1; responseData.payload = (CAPayload_t) calloc(LARGE_PAYLOAD_LENGTH, sizeof(char)); if(!responseData.payload) { CADestroyToken(tempToken); FAIL() << "requestData.payload allocation failed"; } memset(responseData.payload, '1', sizeof(responseData.payload) - 1); responseData.payloadSize = sizeof(responseData.payload); pdu = CAGeneratePDU(CA_CREATED, &responseData, tempRep, &options, &transport); CAData_t *cadata = CACreateNewDataSet(pdu, tempRep); EXPECT_TRUE(cadata != NULL); CABlockData_t *currData = CACreateNewBlockData(cadata); EXPECT_TRUE(currData != NULL); if (currData) { EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId, COAP_OPTION_BLOCK2)); EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption2(&pdu, &responseData, responseData.payloadSize, currData->blockDataId, &options)); } CADestroyDataSet(cadata); coap_delete_list(options); coap_delete_pdu(pdu); CADestroyToken(tempToken); CADestroyEndpoint(tempRep); free(responseData.payload); }
TEST_F(CABlockTransferTests, CAGetPayloadFromBlockDataListTest) { CAEndpoint_t* tempRep = NULL; CACreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_IP, "127.0.0.1", 5683, &tempRep); coap_pdu_t *pdu = NULL; coap_list_t *options = NULL; coap_transport_t transport = COAP_UDP; CAToken_t tempToken = NULL; CAGenerateToken(&tempToken, CA_MAX_TOKEN_LEN); CAInfo_t requestData; memset(&requestData, 0, sizeof(CAInfo_t)); requestData.token = tempToken; requestData.tokenLength = CA_MAX_TOKEN_LEN; requestData.type = CA_MSG_NONCONFIRM; pdu = CAGeneratePDU(CA_GET, &requestData, tempRep, &options, &transport); CAData_t *cadata = CACreateNewDataSet(pdu, tempRep); EXPECT_TRUE(cadata != NULL); CABlockData_t *currData = CACreateNewBlockData(cadata); EXPECT_TRUE(currData != NULL); if (currData) { size_t fullPayload = 0; CAPayload_t payload = CAGetPayloadFromBlockDataList(currData->blockDataId, &fullPayload); size_t payloadLen = (payload != NULL) ? strlen((const char*) payload) : 0; EXPECT_TRUE(fullPayload == payloadLen); CARemoveBlockDataFromList(currData->blockDataId); } CADestroyDataSet(cadata); coap_delete_list(options); coap_delete_pdu(pdu); CADestroyToken(tempToken); CADestroyEndpoint(tempRep); free(requestData.payload); }
TEST_F(CABlockTransferTests, CASetNextBlockOption2WithResponse) { CAEndpoint_t* tempRep = NULL; CACreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_IP, "127.0.0.1", 5683, &tempRep); coap_pdu_t *pdu = NULL; coap_list_t *options = NULL; coap_transport_t transport = COAP_UDP; CAToken_t tempToken = NULL; CAGenerateToken(&tempToken, CA_MAX_TOKEN_LEN); CAInfo_t responseData; memset(&responseData, 0, sizeof(CAInfo_t)); responseData.token = tempToken; responseData.tokenLength = CA_MAX_TOKEN_LEN; responseData.type = CA_MSG_NONCONFIRM; responseData.messageId = 1; pdu = CAGeneratePDU(CA_CREATED, &responseData, tempRep, &options, &transport); CAData_t *cadata = CACreateNewDataSet(pdu, tempRep); EXPECT_TRUE(cadata != NULL); CABlockData_t *currData = CACreateNewBlockData(cadata); EXPECT_TRUE(currData != NULL); coap_block_t block = {0, 0, 0}; EXPECT_EQ(CA_STATUS_OK, CASetNextBlockOption2(pdu, tempRep, cadata, block, pdu->length)); CADestroyDataSet(cadata); coap_delete_list(options); coap_delete_pdu(pdu); CADestroyToken(tempToken); CADestroyEndpoint(tempRep); free(responseData.payload); }
// request and block option1 TEST_F(CABlockTransferTests, CAAddBlockOptionTest) { CAEndpoint_t* tempRep = NULL; CACreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_IP, "127.0.0.1", 5683, &tempRep); coap_pdu_t *pdu = NULL; coap_list_t *options = NULL; coap_transport_t transport = COAP_UDP; CAToken_t tempToken = NULL; CAGenerateToken(&tempToken, CA_MAX_TOKEN_LEN); CAInfo_t requestData; memset(&requestData, 0, sizeof(CAInfo_t)); requestData.token = tempToken; requestData.tokenLength = CA_MAX_TOKEN_LEN; requestData.payload = (CAPayload_t) calloc(LARGE_PAYLOAD_LENGTH, sizeof(char)); if(!requestData.payload) { CADestroyToken(tempToken); FAIL() << "requestData.payload allocation failed"; } memset(requestData.payload, '1', sizeof(requestData.payload) - 1); requestData.payloadSize = sizeof(requestData.payload); requestData.type = CA_MSG_NONCONFIRM; pdu = CAGeneratePDU(CA_GET, &requestData, tempRep, &options, &transport); EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption(&pdu, &requestData, tempRep, &options)); coap_delete_list(options); coap_delete_pdu(pdu); CADestroyToken(tempToken); CADestroyEndpoint(tempRep); free(requestData.payload); }
coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info, const CAEndpoint_t *endpoint) { OIC_LOG(DEBUG, TAG, "IN"); VERIFY_NON_NULL_RET(info, TAG, "info", NULL); VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL); coap_pdu_t *pdu = NULL; // RESET have to use only 4byte (empty message) // and ACKNOWLEDGE can use empty message when code is empty. if (CA_MSG_RESET == info->type || (CA_EMPTY == code && CA_MSG_ACKNOWLEDGE == info->type)) { OIC_LOG(DEBUG, TAG, "code is empty"); if (!(pdu = CAGeneratePDUImpl((code_t) code, NULL, info, endpoint))) { OIC_LOG(ERROR, TAG, "pdu NULL"); return NULL; } } else { coap_list_t *optlist = NULL; if (CA_MSG_ACKNOWLEDGE != info->type) { const char *uri = info->resourceUri; if (NULL == uri) { OIC_LOG(ERROR, TAG, "uri NULL"); return NULL; } uint32_t length = strlen(uri); if (CA_MAX_URI_LENGTH < length) { OIC_LOG(ERROR, TAG, "URI len err"); return NULL; } uint32_t uriLength = length + sizeof(COAP_URI_HEADER); char *coapUri = (char *) OICCalloc(1, uriLength); if (NULL == coapUri) { OIC_LOG(ERROR, TAG, "out of memory"); return NULL; } OICStrcat(coapUri, uriLength, COAP_URI_HEADER); OICStrcat(coapUri, uriLength, uri); // parsing options in URI CAResult_t res = CAParseURI(coapUri, &optlist); if (CA_STATUS_OK != res) { if (optlist) { coap_delete_list(optlist); } OICFree(coapUri); return NULL; } OICFree(coapUri); } // parsing options in HeadOption CAResult_t ret = CAParseHeadOption(code, info, &optlist); if (CA_STATUS_OK != ret) { coap_delete_list(optlist); return NULL; } pdu = CAGeneratePDUImpl((code_t) code, optlist, info, endpoint); if (NULL == pdu) { OIC_LOG(ERROR, TAG, "pdu NULL"); coap_delete_list(optlist); return NULL; } // free option list coap_delete_list(optlist); } // pdu print method : coap_show_pdu(pdu); OIC_LOG(DEBUG, TAG, "OUT"); return pdu; }
static CAResult_t CAProcessSendData(const CAData_t *data) { VERIFY_NON_NULL(data, TAG, "data"); VERIFY_NON_NULL(data->remoteEndpoint, TAG, "remoteEndpoint"); CAResult_t res = CA_STATUS_FAILED; CASendDataType_t type = data->type; coap_pdu_t *pdu = NULL; CAInfo_t *info = NULL; coap_list_t *options = NULL; coap_transport_type transport; if (SEND_TYPE_UNICAST == type) { OIC_LOG(DEBUG,TAG,"Unicast message"); #ifdef ROUTING_GATEWAY /* * When forwarding a packet, do not attempt retransmission as its the responsibility of * packet originator node */ bool skipRetransmission = false; #endif if (NULL != data->requestInfo) { OIC_LOG(DEBUG, TAG, "requestInfo is available.."); info = &data->requestInfo->info; #ifdef ROUTING_GATEWAY skipRetransmission = data->requestInfo->info.skipRetransmission; #endif pdu = CAGeneratePDU(data->requestInfo->method, info, data->remoteEndpoint, &options, &transport); } else if (NULL != data->responseInfo) { OIC_LOG(DEBUG, TAG, "responseInfo is available.."); info = &data->responseInfo->info; #ifdef ROUTING_GATEWAY skipRetransmission = data->responseInfo->info.skipRetransmission; #endif pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint, &options, &transport); } else { OIC_LOG(DEBUG, TAG, "request info, response info is empty"); return CA_STATUS_INVALID_PARAM; } // interface controller function call. if (NULL != pdu) { #ifdef WITH_BWT if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter #ifdef TCP_ADAPTER && CA_ADAPTER_TCP != data->remoteEndpoint->adapter #endif ) { // Blockwise transfer if (NULL != info) { CAResult_t res = CAAddBlockOption(&pdu, info, data->remoteEndpoint, &options); if (CA_STATUS_OK != res) { OIC_LOG(INFO, TAG, "to write block option has failed"); CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res); coap_delete_list(options); coap_delete_pdu(pdu); return res; } } } #endif CALogPDUInfo(pdu, data->remoteEndpoint); res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length); if (CA_STATUS_OK != res) { OIC_LOG_V(ERROR, TAG, "send failed:%d", res); CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res); coap_delete_list(options); coap_delete_pdu(pdu); return res; } #ifdef TCP_ADAPTER if (CA_ADAPTER_TCP == data->remoteEndpoint->adapter) { OIC_LOG(INFO, TAG, "retransmission will be not worked"); } else #endif #ifdef ROUTING_GATEWAY if(!skipRetransmission) #endif { // for retransmission res = CARetransmissionSentData(&g_retransmissionContext, data->remoteEndpoint, pdu->hdr, pdu->length); if ((CA_STATUS_OK != res) && (CA_NOT_SUPPORTED != res)) { //when retransmission not supported this will return CA_NOT_SUPPORTED, ignore OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res); coap_delete_list(options); coap_delete_pdu(pdu); return res; } } coap_delete_list(options); coap_delete_pdu(pdu); } else { OIC_LOG(ERROR,TAG,"Failed to generate unicast PDU"); CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED); return CA_SEND_FAILED; } } else if (SEND_TYPE_MULTICAST == type) { OIC_LOG(DEBUG,TAG,"Multicast message"); if (NULL != data->requestInfo) { OIC_LOG(DEBUG, TAG, "requestInfo is available.."); info = &data->requestInfo->info; pdu = CAGeneratePDU(CA_GET, info, data->remoteEndpoint, &options, &transport); if (NULL != pdu) { #ifdef WITH_BWT if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter #ifdef TCP_ADAPTER && CA_ADAPTER_TCP != data->remoteEndpoint->adapter #endif ) { // Blockwise transfer CAResult_t res = CAAddBlockOption(&pdu, &data->requestInfo->info, data->remoteEndpoint, &options); if (CA_STATUS_OK != res) { OIC_LOG(DEBUG, TAG, "CAAddBlockOption has failed"); CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res); coap_delete_list(options); coap_delete_pdu(pdu); return res; } } #endif } else { OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU"); CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED); return CA_SEND_FAILED; } } else if (NULL != data->responseInfo) { OIC_LOG(DEBUG, TAG, "responseInfo is available.."); info = &data->responseInfo->info; pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint, &options, &transport); if (NULL != pdu) { #ifdef WITH_BWT if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter #ifdef TCP_ADAPTER && CA_ADAPTER_TCP != data->remoteEndpoint->adapter #endif ) { // Blockwise transfer if (NULL != info) { CAResult_t res = CAAddBlockOption(&pdu, info, data->remoteEndpoint, &options); if (CA_STATUS_OK != res) { OIC_LOG(INFO, TAG, "to write block option has failed"); CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res); coap_delete_list(options); coap_delete_pdu(pdu); return res; } } } #endif } else { OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU"); CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED); return CA_SEND_FAILED; } } else { OIC_LOG(ERROR, TAG, "request or response info is empty"); return CA_SEND_FAILED; } CALogPDUInfo(pdu, data->remoteEndpoint); OIC_LOG(DEBUG, TAG, "pdu to send :"); OIC_LOG_BUFFER(DEBUG, TAG, (uint8_t*)pdu->hdr, pdu->length); res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length); if (CA_STATUS_OK != res) { OIC_LOG_V(ERROR, TAG, "send failed:%d", res); CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res); coap_delete_list(options); coap_delete_pdu(pdu); return res; } coap_delete_list(options); coap_delete_pdu(pdu); } return CA_STATUS_OK; }
// List initialization void coap_init_options () { coap_delete_list (optlist); optlist = NULL; }