From b3bde9b3efd85ae9ec0ef00b2dfef232ed36ad20 Mon Sep 17 00:00:00 2001 From: Ziran Sun Date: Tue, 30 Aug 2016 15:26:22 +0100 Subject: [PATCH] Add generic APIs for set/get header option. These APIs should be applicable for setting/getting header option operations for version number and proxy-uri. Bug: https://jira.iotivity.org/browse/IOT-1223 Change-Id: Ifd2d1b6ad30dff3a247c84b63d139c9552bfb32f Signed-off-by: Ziran Sun Reviewed-on: https://gerrit.iotivity.org/gerrit/11161 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi Reviewed-by: Ashok Babu Channa --- resource/csdk/octbstack_product.def | 2 + resource/csdk/stack/include/ocstack.h | 38 +++++++++++ resource/csdk/stack/include/octypes.h | 1 - .../samples/linux/SimpleClientServer/occlient.cpp | 26 ++++--- .../samples/linux/SimpleClientServer/ocserver.cpp | 53 ++++++++++++--- resource/csdk/stack/src/ocstack.c | 79 ++++++++++++++++++++++ resource/csdk/stack/test/stacktests.cpp | 44 ++++++++++++ 7 files changed, 222 insertions(+), 21 deletions(-) diff --git a/resource/csdk/octbstack_product.def b/resource/csdk/octbstack_product.def index 1c81e28..5f47fac 100644 --- a/resource/csdk/octbstack_product.def +++ b/resource/csdk/octbstack_product.def @@ -106,3 +106,5 @@ OCStartPresence OCStop OCStopPresence OCUnBindResource +OCSetHeaderOption +OCGetHeaderOption diff --git a/resource/csdk/stack/include/ocstack.h b/resource/csdk/stack/include/ocstack.h index ce06117..e7d257e 100644 --- a/resource/csdk/stack/include/ocstack.h +++ b/resource/csdk/stack/include/ocstack.h @@ -597,6 +597,44 @@ OCResourceHandle OCGetResourceHandleAtUri(const char *uri); #endif //#endif // DIRECT_PAIRING +/** + * Add a header option to the given header option array. + * + * @param ocHdrOpt Pointer to existing options. + * @param numOptions Number of existing options. + * @param optionID COAP option ID. + * @param optionData Option data value. + * @param optionDataLength Size of Option data value. + * + * @return ::OC_STACK_OK on success and other value otherwise. + */ +OCStackResult +OCSetHeaderOption(OCHeaderOption* ocHdrOpt, + size_t* numOptions, + uint16_t optionID, + void* optionData, + size_t optionDataLength); + +/** + * Get data value of the option with specified option ID from given header option array. + * + * @param ocHdrOpt Pointer to existing options. + * @param numOptions Number of existing options. + * @param optionID COAP option ID. + * @param optionData Pointer to option data. + * @param optionDataLength Size of option data value. + * @param receivedDatalLength Pointer to the actual length of received data. + * + * @return ::OC_STACK_OK on success and other value otherwise. + */ +OCStackResult +OCGetHeaderOption(OCHeaderOption* ocHdrOpt, + size_t numOptions, + uint16_t optionID, + void* optionData, + size_t optionDataLength, + uint16_t* receivedDatalLength); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index 7fc8300..0864196 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -1141,7 +1141,6 @@ typedef struct OCHeaderOption #endif } OCHeaderOption; - /** * This structure describes the platform properties. All non-Null properties will be * included in a platform discovery request. diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp index c99f939..3c5470f 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp @@ -707,17 +707,25 @@ int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptio if (withVendorSpecificHeaderOptions) { + memset(options, 0, sizeof(OCHeaderOption)* MAX_HEADER_OPTIONS); + size_t numOptions = 0; uint8_t option0[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + uint16_t optionID = 2048; + size_t optionDataSize = sizeof(option0); + OCSetHeaderOption(options, + &numOptions, + optionID, + option0, + optionDataSize); + uint8_t option1[] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; - memset(options, 0, sizeof(OCHeaderOption) * MAX_HEADER_OPTIONS); - options[0].protocolID = OC_COAP_ID; - options[0].optionID = 2048; - memcpy(options[0].optionData, option0, sizeof(option0)); - options[0].optionLength = 10; - options[1].protocolID = OC_COAP_ID; - options[1].optionID = 3000; - memcpy(options[1].optionData, option1, sizeof(option1)); - options[1].optionLength = 10; + optionID = 3000; + optionDataSize = sizeof(option1); + OCSetHeaderOption(options, + &numOptions, + optionID, + option1, + optionDataSize); } if (withVendorSpecificHeaderOptions) { diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp index 68c592f..2acfc24 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp @@ -618,17 +618,48 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag, MAX_HEADER_OPTION_DATA_LENGTH); } } - OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions; - uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30}; - uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40}; - sendOptions[0].protocolID = OC_COAP_ID; - sendOptions[0].optionID = 2248; - memcpy(sendOptions[0].optionData, option2, sizeof(option2)); - sendOptions[0].optionLength = 10; - sendOptions[1].protocolID = OC_COAP_ID; - sendOptions[1].optionID = 2600; - memcpy(sendOptions[1].optionData, option3, sizeof(option3)); - sendOptions[1].optionLength = 10; + + OCHeaderOption* sendOptions = response.sendVendorSpecificHeaderOptions; + size_t numOptions = response.numSendVendorSpecificHeaderOptions; + // Check if the option header has already existed before adding it in. + uint8_t optionData[MAX_HEADER_OPTION_DATA_LENGTH]; + size_t optionDataSize = sizeof(optionData); + uint16_t actualDataSize = 0; + OCGetHeaderOption(response.sendVendorSpecificHeaderOptions, + response.numSendVendorSpecificHeaderOptions, + 2248, + optionData, + optionDataSize, + &actualDataSize); + if (actualDataSize == 0) + { + uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30}; + uint16_t optionID2 = 2248; + size_t optionDataSize2 = sizeof(option2); + OCSetHeaderOption(sendOptions, + &numOptions, + optionID2, + option2, + optionDataSize2); + } + + OCGetHeaderOption(response.sendVendorSpecificHeaderOptions, + response.numSendVendorSpecificHeaderOptions, + 2600, + optionData, + optionDataSize, + &actualDataSize); + if (actualDataSize == 0) + { + uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40}; + uint16_t optionID3 = 2600; + size_t optionDataSize3 = sizeof(option3); + OCSetHeaderOption(sendOptions, + &numOptions, + optionID3, + option3, + optionDataSize3); + } response.numSendVendorSpecificHeaderOptions = 2; } diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index 950def9..b7eef64 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -4917,6 +4917,85 @@ OCStackResult OCGetResourceIns(OCResourceHandle handle, uint8_t *ins) } return OC_STACK_ERROR; } + +OCStackResult OCSetHeaderOption(OCHeaderOption* ocHdrOpt, size_t* numOptions, uint16_t optionID, + void* optionData, size_t optionDataLength) +{ + if (!ocHdrOpt) + { + OIC_LOG (INFO, TAG, "Header options are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!optionData) + { + OIC_LOG (INFO, TAG, "optionData are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!numOptions) + { + OIC_LOG (INFO, TAG, "numOptions is NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (*numOptions >= MAX_HEADER_OPTIONS) + { + OIC_LOG (INFO, TAG, "Exceeding MAX_HEADER_OPTIONS"); + return OC_STACK_NO_MEMORY; + } + + ocHdrOpt += *numOptions; + ocHdrOpt->protocolID = OC_COAP_ID; + ocHdrOpt->optionID = optionID; + ocHdrOpt->optionLength = + optionDataLength < MAX_HEADER_OPTION_DATA_LENGTH ? + optionDataLength : MAX_HEADER_OPTION_DATA_LENGTH; + memcpy(ocHdrOpt->optionData, (const void*) optionData, ocHdrOpt->optionLength); + *numOptions += 1; + + return OC_STACK_OK; +} +OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, uint16_t optionID, + void* optionData, size_t optionDataLength, uint16_t* receivedDataLength) +{ + if (!ocHdrOpt || !numOptions) + { + OIC_LOG (INFO, TAG, "No options present"); + return OC_STACK_OK; + } + + if (!optionData) + { + OIC_LOG (INFO, TAG, "optionData are NULL"); + return OC_STACK_INVALID_PARAM; + } + + if (!receivedDataLength) + { + OIC_LOG (INFO, TAG, "receivedDataLength is NULL"); + return OC_STACK_INVALID_PARAM; + } + + for (uint8_t i = 0; i < numOptions; i++) + { + if (ocHdrOpt[i].optionID == optionID) + { + if (optionDataLength >= ocHdrOpt->optionLength) + { + memcpy(optionData, ocHdrOpt->optionData, ocHdrOpt->optionLength); + *receivedDataLength = ocHdrOpt->optionLength; + return OC_STACK_OK; + } + else + { + OIC_LOG (ERROR, TAG, "optionDataLength is less than the length of received data"); + return OC_STACK_ERROR; + } + } + } + return OC_STACK_OK; +} #endif void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled) diff --git a/resource/csdk/stack/test/stacktests.cpp b/resource/csdk/stack/test/stacktests.cpp index 8cae176..222802f 100644 --- a/resource/csdk/stack/test/stacktests.cpp +++ b/resource/csdk/stack/test/stacktests.cpp @@ -1907,3 +1907,47 @@ TEST(StackUri, Rfc6874_NoOverflow_2) EXPECT_EQ(OC_STACK_ERROR, result); } +TEST(StackHeaderOption, setHeaderOption) +{ + uint8_t optionValue1[MAX_HEADER_OPTION_DATA_LENGTH] = + { 1 }; + OCHeaderOption options[MAX_HEADER_OPTIONS] = + { + { OC_COAP_ID, 6, 8, optionValue1 }, }; + uint8_t optionData = 255; + size_t optionDataSize = sizeof(optionData); + size_t numOptions = 1; + uint16_t optionID = 2048; + EXPECT_EQ(OC_STACK_OK, OCSetHeaderOption(options, + &numOptions, + optionID, + &optionData, + optionDataSize)); + EXPECT_EQ(options[1].optionID, optionID); + EXPECT_EQ(options[1].optionData[0], 255); +} + +TEST(StackHeaderOption, getHeaderOption) +{ + uint8_t optionValue1[MAX_HEADER_OPTION_DATA_LENGTH] = + { 1 }; + uint8_t optionValue2[MAX_HEADER_OPTION_DATA_LENGTH] = + { 255 }; + OCHeaderOption options[MAX_HEADER_OPTIONS] = + { + { OC_COAP_ID, 6, 8, optionValue1 }, + { OC_COAP_ID, 2048, 16, optionValue2 }, }; + uint8_t optionData[MAX_HEADER_OPTION_DATA_LENGTH]; + size_t optionDataSize = sizeof(optionData); + size_t numOptions = 2; + uint16_t optionID = 6; + uint16_t actualDataSize = 0; + EXPECT_EQ(OC_STACK_OK, OCGetHeaderOption(options, + numOptions, + optionID, + optionData, + optionDataSize, + &actualDataSize)); + EXPECT_EQ(optionData[0], 1); + EXPECT_EQ(actualDataSize, 8); +} -- 2.7.4