From 5042acdb846cba2ebb15bc5baa678537622cff9f Mon Sep 17 00:00:00 2001 From: Habib Virji Date: Tue, 24 Nov 2015 11:17:32 +0000 Subject: [PATCH] Change REPRESENTATION payload in correct format. Updated rep without starting array, href, and removed prop strucutre. [ { "href":"/BinarySwitchResURI", "rt": "if": "rep": { "value":true } } ] to be { "rt": "if": "value":true } Change-Id: I26fd608999c88323ab1b9fae1e06a270756e9d31 Signed-off-by: Habib Virji Reviewed-on: https://gerrit.iotivity.org/gerrit/4327 Tested-by: jenkins-iotivity Reviewed-by: Jon A. Cruz Reviewed-on: https://gerrit.iotivity.org/gerrit/4493 --- resource/csdk/stack/include/ocpayload.h | 79 +++++ resource/csdk/stack/include/octypes.h | 19 ++ resource/csdk/stack/src/ocpayload.c | 187 +++++++++++ resource/csdk/stack/src/ocpayloadconvert.c | 198 ++++++------ resource/csdk/stack/src/ocpayloadparse.c | 360 +++++++++++---------- .../unittests/OCRepresentationEncodingTest.cpp | 8 - 6 files changed, 563 insertions(+), 288 deletions(-) diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h index d453621..4970bc4 100644 --- a/resource/csdk/stack/include/ocpayload.h +++ b/resource/csdk/stack/include/ocpayload.h @@ -60,6 +60,43 @@ bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64 bool OCRepPayloadSetPropDouble(OCRepPayload* payload, const char* name, double value); bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value); +/** + * This function allocates memory for the byte string and sets it in the payload. + * + * @param payload Pointer to the payload to which byte string needs to be added. + * @param name Name of the byte string. + * @param value Byte string and it's length. + * + * @return true on success, false upon failure. + */ +bool OCRepPayloadSetPropByteString(OCRepPayload* payload, const char* name, OCByteString value); + +/** + * This function sets the byte string in the payload. + * + * @param payload Pointer to the payload to which byte string needs to be added. + * @param name Name of the byte string. + * @param value Byte string and it's length. + * + * @return true on success, false upon failure. + */ +bool OCRepPayloadSetPropByteStringAsOwner(OCRepPayload* payload, const char* name, + OCByteString* value); + +/** + * This function gets the byte string from the payload. + * + * @param payload Pointer to the payload from which byte string needs to be retrieved. + * @param name Name of the byte string. + * @param value Byte string and it's length. + * + * @note: Caller needs to invoke OCFree on value.bytes after it is finished using the byte string. + * + * @return true on success, false upon failure. + */ +bool OCRepPayloadGetPropByteString(const OCRepPayload* payload, const char* name, + OCByteString* value); + bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value); bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value); bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, char** value); @@ -72,6 +109,48 @@ bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value); bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value); +/** + * This function allocates memory for the byte string array and sets it in the payload. + * + * @param payload Pointer to the payload to which byte string array needs to be added. + * @param name Name of the byte string. + * @param array Byte string array. + * @param dimensions Number of byte strings in above array. + * + * @return true on success, false upon failure. + */ +bool OCRepPayloadSetByteStringArrayAsOwner(OCRepPayload* payload, const char* name, + OCByteString* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]); + +/** + * This function sets the byte string array in the payload. + * + * @param payload Pointer to the payload to which byte string array needs to be added. + * @param name Name of the byte string. + * @param array Byte string array. + * @param dimensions Number of byte strings in above array. + * + * @return true on success, false upon failure. + */ +bool OCRepPayloadSetByteStringArray(OCRepPayload* payload, const char* name, + const OCByteString* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]); + +/** + * This function gets the byte string array from the payload. + * + * @param payload Pointer to the payload from which byte string array needs to be retrieved. + * @param name Name of the byte string array. + * @param value Byte string array. + * @param dimensions Number of byte strings in above array. + * + * @note: Caller needs to invoke OICFree on 'bytes' field of all array elements after it is + * finished using the byte string array. + * + * @return true on success, false upon failure. + */ +bool OCRepPayloadGetByteStringArray(const OCRepPayload* payload, const char* name, + OCByteString** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]); + bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name, int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]); bool OCRepPayloadSetIntArray(OCRepPayload* payload, const char* name, diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index 6486dce..69ce07d 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -931,10 +931,21 @@ typedef enum OCREP_PROP_DOUBLE, OCREP_PROP_BOOL, OCREP_PROP_STRING, + OCREP_PROP_BYTE_STRING, OCREP_PROP_OBJECT, OCREP_PROP_ARRAY }OCRepPayloadPropType; +/** This structure will be used to represent a binary string for CBOR payloads.*/ +typedef struct +{ + /** pointer to data bytes.*/ + uint8_t* bytes; + + /** number of data bytes.*/ + size_t len; +} OCByteString; + #define MAX_REP_ARRAY_DEPTH 3 typedef struct { @@ -947,6 +958,10 @@ typedef struct double* dArray; bool* bArray; char** strArray; + + /** pointer to ByteString array.*/ + OCByteString* ocByteStrArray; + struct OCRepPayload** objArray; }; } OCRepPayloadValueArray; @@ -961,6 +976,10 @@ typedef struct OCRepPayloadValue double d; bool b; char* str; + + /** ByteString object.*/ + OCByteString ocByteStr; + struct OCRepPayload* obj; OCRepPayloadValueArray arr; }; diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index cf7d754..43694bb 100755 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -197,6 +197,10 @@ static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val) { OICFree(val->str); } + else if(val->type == OCREP_PROP_BYTE_STRING) + { + OICFree(val->ocByteStr.bytes); + } else if (val->type == OCREP_PROP_OBJECT) { OCRepPayloadDestroy(val->obj); @@ -220,6 +224,13 @@ static void OCFreeRepPayloadValueContents(OCRepPayloadValue* val) } OICFree(val->arr.strArray); break; + case OCREP_PROP_BYTE_STRING: + for (size_t i = 0; i< dimTotal; ++i) + { + OICFree(val->arr.ocByteStrArray[i].bytes); + } + OICFree(val->arr.ocByteStrArray); + break; case OCREP_PROP_OBJECT: for(size_t i = 0; i< dimTotal;++i) { @@ -479,6 +490,9 @@ static bool OCRepPayloadSetProp(OCRepPayload* payload, const char* name, case OCREP_PROP_STRING: val->str = (char*)value; return val->str != NULL; + case OCREP_PROP_BYTE_STRING: + val->ocByteStr = *(OCByteString*)value; + break; case OCREP_PROP_NULL: return val != NULL; case OCREP_PROP_ARRAY: @@ -562,6 +576,62 @@ bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, ch return *value != NULL; } +bool OCRepPayloadSetPropByteString(OCRepPayload* payload, const char* name, OCByteString value) +{ + if (!value.bytes || !value.len) + { + return false; + } + + OCByteString ocByteStr = { + .bytes = (uint8_t*)OICMalloc(value.len * sizeof(uint8_t)), + .len = value.len }; + + if(!ocByteStr.bytes) + { + return false; + } + memcpy(ocByteStr.bytes, value.bytes, ocByteStr.len); + + bool b = OCRepPayloadSetPropByteStringAsOwner(payload, name, &ocByteStr); + + if(!b) + { + OICFree(ocByteStr.bytes); + } + return b; +} + +bool OCRepPayloadSetPropByteStringAsOwner(OCRepPayload* payload, const char* name, OCByteString* value) +{ + return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_BYTE_STRING); +} + +bool OCRepPayloadGetPropByteString(const OCRepPayload* payload, const char* name, OCByteString* value) +{ + OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name); + + if (!val || val->type != OCREP_PROP_BYTE_STRING) + { + return false; + } + + if (!value) + { + return false; + } + + value->bytes = (uint8_t*)OICMalloc(val->ocByteStr.len * sizeof(uint8_t)); + if (!value->bytes) + { + return false; + } + value->len = val->ocByteStr.len; + memcpy(value->bytes, val->ocByteStr.bytes, value->len); + + return true; +} + bool OCRepPayloadSetPropBool(OCRepPayload* payload, const char* name, bool value) { @@ -626,6 +696,123 @@ size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH]) return total; } + +bool OCRepPayloadSetByteStringArrayAsOwner(OCRepPayload* payload, const char* name, + OCByteString* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]) +{ + OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_ARRAY); + + if (!val) + { + return false; + } + + val->arr.type = OCREP_PROP_BYTE_STRING; + memcpy(val->arr.dimensions, dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t)); + val->arr.ocByteStrArray = array; + + return true; +} + +bool OCRepPayloadSetByteStringArray(OCRepPayload* payload, const char* name, + const OCByteString* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]) +{ + if (!array) + { + return NULL; + } + + size_t dimTotal = calcDimTotal(dimensions); + if (dimTotal == 0) + { + return false; + } + + OCByteString* newArray = (OCByteString*)OICCalloc(dimTotal, sizeof(OCByteString)); + + if (!newArray) + { + return false; + } + + for (size_t i = 0; i < dimTotal; ++i) + { + newArray[i].bytes = (uint8_t*)OICMalloc(array[i].len * sizeof(uint8_t)); + if (NULL == newArray[i].bytes) + { + for (size_t j = 0; j < i; ++j) + { + OICFree(newArray[j].bytes); + } + + OICFree(newArray); + return false; + } + newArray[i].len = array[i].len; + memcpy(newArray[i].bytes, array[i].bytes, newArray[i].len); + } + + bool b = OCRepPayloadSetByteStringArrayAsOwner(payload, name, newArray, dimensions); + if (!b) + { + for (size_t i = 0; i < dimTotal; ++i) + { + OICFree(newArray[i].bytes); + } + + OICFree(newArray); + } + return b; +} + +bool OCRepPayloadGetByteStringArray(const OCRepPayload* payload, const char* name, + OCByteString** array, size_t dimensions[MAX_REP_ARRAY_DEPTH]) +{ + OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name); + + if (!val || val->type != OCREP_PROP_ARRAY || val->arr.type != OCREP_PROP_BYTE_STRING + || !val->arr.ocByteStrArray) + { + return false; + } + + size_t dimTotal = calcDimTotal(val->arr.dimensions); + if (dimTotal == 0) + { + return false; + } + + *array = (OCByteString*)OICCalloc(dimTotal, sizeof(OCByteString)); + if (!*array) + { + return false; + } + + for (size_t i = 0; i < dimTotal; ++i) + { + OCByteString* tmp = &(*array)[i]; + tmp->bytes = (uint8_t*)OICMalloc(val->arr.ocByteStrArray[i].len * sizeof(uint8_t)); + if (NULL == tmp->bytes) + { + for (size_t j = 0; j < i; ++j) + { + OCByteString* tmp = &(*array)[j]; + OICFree(tmp->bytes); + } + OICFree(*array); + *array = NULL; + + return false; + } + tmp->len = val->arr.ocByteStrArray[i].len; + memcpy(tmp->bytes, val->arr.ocByteStrArray[i].bytes, tmp->len); + } + + memcpy(dimensions, val->arr.dimensions, MAX_REP_ARRAY_DEPTH * sizeof(size_t)); + return true; +} + + bool OCRepPayloadSetIntArrayAsOwner(OCRepPayload* payload, const char* name, int64_t* array, size_t dimensions[MAX_REP_ARRAY_DEPTH]) { diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index 588dd55..1cf257c 100644 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -50,6 +50,7 @@ static int64_t OCConvertDevicePayload(OCDevicePayload* payload, uint8_t* outPayl static int64_t OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t* outPayload, size_t* size); static int64_t OCConvertRepPayload(OCRepPayload* payload, uint8_t* outPayload, size_t* size); +static int64_t OCConvertRepMap(CborEncoder *map, const OCRepPayload* payload); static int64_t OCConvertPresencePayload(OCPresencePayload* payload, uint8_t* outPayload, size_t* size); static int64_t OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t* outPayload, @@ -586,7 +587,7 @@ static int64_t OCConvertArrayItem(CborEncoder* array, const OCRepPayloadValueArr } else { - err = OCConvertSingleRepPayload(array, valArray->objArray[index]); + err = OCConvertRepMap(array, valArray->objArray[index]); } break; case OCREP_PROP_ARRAY: @@ -645,117 +646,64 @@ static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* return err; } -static int64_t OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload) +static int64_t OCConvertRepMap(CborEncoder *map, const OCRepPayload* payload) { int64_t err = 0; - CborEncoder map; - err = err | cbor_encoder_create_map(parent, &map, CborIndefiniteLength); - - // Uri - err = err | ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF, - sizeof(OC_RSRVD_HREF) - 1, - payload->uri); - - // Prop Map - // resource types, interfaces - if(payload->types || payload->interfaces) - { - OC_LOG(INFO, TAG, "Payload has types or interfaces"); - err = err | cbor_encode_text_string(&map, - OC_RSRVD_PROPERTY, - sizeof(OC_RSRVD_PROPERTY) - 1); - CborEncoder propMap; - err = err | cbor_encoder_create_map(&map, &propMap, 2); - - if (payload->types) - { - char* joinedTypes = OCStringLLJoin(payload->types); - if (joinedTypes) - { - err = err | cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE, - sizeof(OC_RSRVD_RESOURCE_TYPE) - 1); - err = err | cbor_encode_text_string(&propMap, joinedTypes, - strlen(joinedTypes)); - OICFree(joinedTypes); - } - else - { - return OC_STACK_NO_MEMORY; - } - } - if (payload->interfaces) - { - char* joinedInterfaces = OCStringLLJoin(payload->interfaces); - if (joinedInterfaces) - { - err = err | cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE, - sizeof(OC_RSRVD_INTERFACE) - 1); - err = err | cbor_encode_text_string(&propMap, joinedInterfaces, - strlen(joinedInterfaces)); - OICFree(joinedInterfaces); - } - else - { - return OC_STACK_NO_MEMORY; - } - } - err = err | cbor_encoder_close_container(&map, &propMap); - } + CborEncoder repMap; + err = err | cbor_encoder_create_map(map, &repMap, CborIndefiniteLength); + err = err | OCConvertSingleRepPayload(&repMap, payload); + err = err | cbor_encoder_close_container(map, &repMap); + return err; +} - // Rep Map +static int64_t OCConvertSingleRepPayload(CborEncoder* repMap, const OCRepPayload* payload) +{ + int64_t err = 0; + OCRepPayloadValue* value = payload->values; + while(value) { - CborEncoder repMap; - err = err | cbor_encode_text_string(&map, - OC_RSRVD_REPRESENTATION, - sizeof(OC_RSRVD_REPRESENTATION) - 1); - err = err | cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength); - OCRepPayloadValue* value = payload->values; - while(value) + err = err | cbor_encode_text_string(repMap, + value->name, + strlen(value->name)); + switch(value->type) { - err = err | cbor_encode_text_string(&repMap, - value->name, - strlen(value->name)); - switch(value->type) - { - case OCREP_PROP_NULL: - err = err | cbor_encode_null(&repMap); - break; - case OCREP_PROP_INT: - err = err | cbor_encode_int(&repMap, - value->i); - break; - case OCREP_PROP_DOUBLE: - err = err | cbor_encode_double(&repMap, - value->d); - break; - case OCREP_PROP_BOOL: - err = err | cbor_encode_boolean(&repMap, - value->b); - break; - case OCREP_PROP_STRING: - err = err | cbor_encode_text_string(&repMap, - value->str, strlen(value->str)); - break; - case OCREP_PROP_OBJECT: - err = err | OCConvertSingleRepPayload(&repMap, value->obj); - break; - case OCREP_PROP_ARRAY: - err = err | OCConvertArray(&repMap, &value->arr); - break; - default: - OC_LOG_V(ERROR, TAG, "Invalid Prop type: %d", - value->type); - break; - } - value = value->next; + case OCREP_PROP_NULL: + err = err | cbor_encode_null(repMap); + break; + case OCREP_PROP_INT: + err = err | cbor_encode_int(repMap, + value->i); + break; + case OCREP_PROP_DOUBLE: + err = err | cbor_encode_double(repMap, + value->d); + break; + case OCREP_PROP_BOOL: + err = err | cbor_encode_boolean(repMap, + value->b); + break; + case OCREP_PROP_STRING: + err = err | cbor_encode_text_string(repMap, + value->str, strlen(value->str)); + break; + case OCREP_PROP_BYTE_STRING: + err = err | cbor_encode_byte_string(repMap, + value->ocByteStr.bytes, value->ocByteStr.len); + break; + case OCREP_PROP_OBJECT: + err = err | OCConvertRepMap(repMap, value->obj); + break; + case OCREP_PROP_ARRAY: + err = err | OCConvertArray(repMap, &value->arr); + break; + default: + OC_LOG_V(ERROR, TAG, "Invalid Prop type: %d", + value->type); + break; } - - err = err | cbor_encoder_close_container(&map, &repMap); + value = value->next; } - // Close Map - err = err | cbor_encoder_close_container(parent, &map); - return err; } @@ -765,17 +713,51 @@ static int64_t OCConvertRepPayload(OCRepPayload* payload, uint8_t* outPayload, s int64_t err = 0; cbor_encoder_init(&encoder, outPayload, *size, 0); - CborEncoder rootArray; - err = err | cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength); + CborEncoder rootMap; + err = err | cbor_encoder_create_map(&encoder, &rootMap, CborIndefiniteLength); + + if (payload->types) + { + OC_LOG(INFO, TAG, "Payload has types or interfaces"); + char* joinedTypes = OCStringLLJoin(payload->types); + if (joinedTypes) + { + err = err | cbor_encode_text_string(&rootMap, OC_RSRVD_RESOURCE_TYPE, + sizeof(OC_RSRVD_RESOURCE_TYPE) - 1); + err = err | cbor_encode_text_string(&rootMap, joinedTypes, + strlen(joinedTypes)); + OICFree(joinedTypes); + } + else + { + return OC_STACK_NO_MEMORY; + } + } + if (payload->interfaces) + { + char* joinedInterfaces = OCStringLLJoin(payload->interfaces); + if (joinedInterfaces) + { + err = err | cbor_encode_text_string(&rootMap, OC_RSRVD_INTERFACE, + sizeof(OC_RSRVD_INTERFACE) - 1); + err = err | cbor_encode_text_string(&rootMap, joinedInterfaces, + strlen(joinedInterfaces)); + OICFree(joinedInterfaces); + } + else + { + return OC_STACK_NO_MEMORY; + } + } while(payload != NULL && (err == 0 || err == CborErrorOutOfMemory)) { - err = err | OCConvertSingleRepPayload(&rootArray, payload); + err = err | OCConvertSingleRepPayload(&rootMap, payload); payload = payload->next; } // Close main array - err = err | cbor_encoder_close_container(&encoder, &rootArray); + err = err | cbor_encoder_close_container(&encoder, &rootMap); return checkError(err, &encoder, outPayload, size); } diff --git a/resource/csdk/stack/src/ocpayloadparse.c b/resource/csdk/stack/src/ocpayloadparse.c index d2aaf6a..6367419 100644 --- a/resource/csdk/stack/src/ocpayloadparse.c +++ b/resource/csdk/stack/src/ocpayloadparse.c @@ -63,45 +63,29 @@ OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType, return OC_STACK_ERROR; } - if(!cbor_value_is_array(&rootValue)) - { - OC_LOG_V(ERROR, TAG, "CBOR payload root object is not an array :%x", rootValue.type); - return OC_STACK_MALFORMED_RESPONSE; - } - - CborValue arrayValue; - // enter the array - err = err || cbor_value_enter_container(&rootValue, &arrayValue); - - if(err) - { - OC_LOG_V(ERROR, TAG, "CBOR payload parse failed :%d", err); - return OC_STACK_MALFORMED_RESPONSE; - } - OCStackResult result = OC_STACK_ERROR; switch(payloadType) { case PAYLOAD_TYPE_DISCOVERY: - result = OCParseDiscoveryPayload(outPayload, &arrayValue); + result = OCParseDiscoveryPayload(outPayload, &rootValue); break; case PAYLOAD_TYPE_DEVICE: - result = OCParseDevicePayload(outPayload, &arrayValue); + result = OCParseDevicePayload(outPayload, &rootValue); break; case PAYLOAD_TYPE_PLATFORM: - result = OCParsePlatformPayload(outPayload, &arrayValue); + result = OCParsePlatformPayload(outPayload, &rootValue); break; case PAYLOAD_TYPE_REPRESENTATION: - result = OCParseRepPayload(outPayload, &arrayValue); + result = OCParseRepPayload(outPayload, &rootValue); break; case PAYLOAD_TYPE_PRESENCE: - result = OCParsePresencePayload(outPayload, &arrayValue); + result = OCParsePresencePayload(outPayload, &rootValue); break; case PAYLOAD_TYPE_SECURITY: - result = OCParseSecurityPayload(outPayload, &arrayValue); + result = OCParseSecurityPayload(outPayload, &rootValue); break; case PAYLOAD_TYPE_RD: - result = OCRDCborToPayload(&arrayValue, outPayload); + result = OCRDCborToPayload(&rootValue, outPayload); break; default: OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType); @@ -109,15 +93,7 @@ OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType, break; } - if(result == OC_STACK_OK) - { - err = err || cbor_value_leave_container(&rootValue, &arrayValue); - if(err != CborNoError) - { - return OC_STACK_MALFORMED_RESPONSE; - } - } - else + if(result != OC_STACK_OK) { OC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result); } @@ -127,7 +103,7 @@ OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType, void OCFreeOCStringLL(OCStringLL* ll); -static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal) +static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* rootValue) { if (!outPayload) { @@ -136,11 +112,13 @@ static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* a bool err = false; char * securityData = NULL; + CborValue arrayVal; + err = err || cbor_value_enter_container(rootValue, &arrayVal); - if(cbor_value_is_map(arrayVal)) + if(cbor_value_is_map(&arrayVal)) { CborValue curVal; - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_REPRESENTATION, &curVal); if(cbor_value_is_valid(&curVal)) { @@ -154,7 +132,8 @@ static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* a return OC_STACK_MALFORMED_RESPONSE; } - err = err || cbor_value_advance(arrayVal); + err = err || cbor_value_advance(&arrayVal); + err = err || cbor_value_leave_container(rootValue, &arrayVal); if(err) { @@ -188,7 +167,7 @@ static char* InPlaceStringTrim(char* str) return str; } -static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal) +static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* rootValue) { if (!outPayload) { @@ -204,16 +183,19 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* return OC_STACK_NO_MEMORY; } - if (cbor_value_is_array(arrayVal)) + CborValue arrayVal; + err = err || cbor_value_enter_container(rootValue, &arrayVal); + + if (cbor_value_is_array(&arrayVal)) { OCLinksPayload *linksPayload = NULL; OCTagsPayload *tagsPayload = NULL; - while (cbor_value_is_container(arrayVal)) + while (cbor_value_is_container(&arrayVal)) { linksPayload = NULL; tagsPayload = NULL; CborValue colResources; - CborError cborFindResult = cbor_value_enter_container(arrayVal, &colResources); + CborError cborFindResult = cbor_value_enter_container(&arrayVal, &colResources); if (CborNoError != cborFindResult) { goto cbor_error; @@ -242,17 +224,17 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* OCDiscoveryPayloadDestroy(out); return OC_STACK_NO_MEMORY; } - if (CborNoError != cbor_value_advance(arrayVal)) + if (CborNoError != cbor_value_advance(&arrayVal)) { OC_LOG(ERROR, TAG, "Cbor value advanced failed."); goto cbor_error; } } } - if (cbor_value_is_map(arrayVal)) + if (cbor_value_is_map(&arrayVal)) { size_t resourceCount = 0; - while (cbor_value_is_map(arrayVal)) + while (cbor_value_is_map(&arrayVal)) { resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload)); if(!resource) @@ -263,7 +245,7 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* } CborValue curVal; // DI - err = cbor_value_map_find_value(arrayVal, OC_RSRVD_DEVICE_ID, &curVal); + err = cbor_value_map_find_value(&arrayVal, OC_RSRVD_DEVICE_ID, &curVal); if (CborNoError != err) { OC_LOG(ERROR, TAG, "Cbor find value failed."); @@ -279,7 +261,7 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* // Links TAG { CborValue linkArray; - err = cbor_value_map_find_value(arrayVal, OC_RSRVD_LINKS, &linkArray); + err = cbor_value_map_find_value(&arrayVal, OC_RSRVD_LINKS, &linkArray); if (CborNoError != err) { OC_LOG(ERROR, TAG, "Cbor links finding failed."); @@ -452,7 +434,7 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* } } } - err = cbor_value_advance(arrayVal); + err = cbor_value_advance(&arrayVal); if (CborNoError != err) { OC_LOG(ERROR, TAG, "Cbor advance value failed."); @@ -462,6 +444,7 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* OCDiscoveryPayloadAddNewResource(out, resource); } } + err = err || cbor_value_leave_container(rootValue, &arrayVal); *outPayload = (OCPayload*)out; return OC_STACK_OK; @@ -480,7 +463,7 @@ cbor_error: return OC_STACK_MALFORMED_RESPONSE; } -static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal) +static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* rootValue) { if (!outPayload) { @@ -489,7 +472,10 @@ static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arr bool err = false; - if(cbor_value_is_map(arrayVal)) + CborValue arrayVal; + err = err || cbor_value_enter_container(rootValue, &arrayVal); + + if(cbor_value_is_map(&arrayVal)) { char* uri = NULL; uint8_t* sid = NULL; @@ -497,13 +483,13 @@ static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arr char* specVer = NULL; char* dmVer = NULL; CborValue curVal; - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_HREF, &curVal); size_t len; err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL); // Representation { - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_REPRESENTATION, &curVal); CborValue repVal; // Device ID @@ -533,7 +519,8 @@ static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arr } } - err = err || cbor_value_advance(arrayVal); + err = err || cbor_value_advance(&arrayVal); + err = err || cbor_value_leave_container(rootValue, &arrayVal); if(err) { @@ -568,7 +555,7 @@ static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arr } -static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal) +static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* rootValue) { if (!outPayload) { @@ -577,18 +564,21 @@ static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* a bool err = false; - if(cbor_value_is_map(arrayVal)) + CborValue arrayVal; + err = err || cbor_value_enter_container(rootValue, &arrayVal); + + if(cbor_value_is_map(&arrayVal)) { char* uri = NULL; OCPlatformInfo info = {0}; CborValue curVal; - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_HREF, &curVal); size_t len; err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL); // Representation { - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_REPRESENTATION, &curVal); CborValue repVal; // Platform ID @@ -674,7 +664,8 @@ static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* a } } - err = err || cbor_value_advance(arrayVal); + err = err || cbor_value_advance(&arrayVal); + err = err || cbor_value_leave_container(rootValue, &arrayVal); if(err) { @@ -838,6 +829,7 @@ static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray)) { + bool noAdvance = false; if (cbor_value_get_type(&insideArray) != CborNullType) { switch (type) @@ -906,6 +898,7 @@ static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX err = err || OCParseSingleRepPayload(&tempPl, &insideArray); ((OCRepPayload**)targetArray)[i] = tempPl; tempPl = NULL; + noAdvance = true; } else { @@ -922,7 +915,10 @@ static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX } } ++i; - err = err || cbor_value_advance(&insideArray); + if (!noAdvance && cbor_value_is_valid(&insideArray)) + { + err = err || cbor_value_advance(&insideArray); + } } return err; @@ -1013,145 +1009,103 @@ static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* contain return err; } -static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent) +static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue *objMap) { if (!outPayload) { return false; } - *outPayload = OCRepPayloadCreate(); - OCRepPayload* curPayload = *outPayload; bool err = false; - if(!*outPayload) - { - return CborErrorOutOfMemory; - } - - size_t len; - CborValue curVal; - err = err || cbor_value_map_find_value(repParent, OC_RSRVD_HREF, &curVal); - if(cbor_value_is_valid(&curVal)) - { - err = err || cbor_value_dup_text_string(&curVal, &curPayload->uri, &len, - NULL); - } - err = err || cbor_value_map_find_value(repParent, OC_RSRVD_PROPERTY, &curVal); - if(cbor_value_is_valid(&curVal)) + if (cbor_value_is_map(objMap)) { - CborValue insidePropValue = {0}; - err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE, - &insidePropValue); - - if(cbor_value_is_text_string(&insidePropValue)) + if (!*outPayload) { - char* allRt = NULL; - err = err || cbor_value_dup_text_string(&insidePropValue, &allRt, &len, NULL); - - char* savePtr; - - if (allRt) + *outPayload = OCRepPayloadCreate(); + if(!*outPayload) { - char* curPtr = strtok_r(allRt, " ", &savePtr); - - while (curPtr) - { - char* trimmed = InPlaceStringTrim(curPtr); - if (trimmed[0] != '\0') - { - OCRepPayloadAddResourceType(curPayload, curPtr); - } - curPtr = strtok_r(NULL, " ", &savePtr); - } + return CborErrorOutOfMemory; } - OICFree(allRt); } - err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &insidePropValue); - - if(cbor_value_is_text_string(&insidePropValue)) - { - char* allIf = NULL; - err = err || cbor_value_dup_text_string(&insidePropValue, &allIf, &len, NULL); - - char* savePtr; + OCRepPayload* curPayload = *outPayload; - if (allIf) - { - char* curPtr = strtok_r(allIf, " ", &savePtr); - - while (curPtr) - { - char* trimmed = InPlaceStringTrim(curPtr); - if (trimmed[0] != '\0') - { - OCRepPayloadAddInterface(curPayload, curPtr); - } - curPtr = strtok_r(NULL, " ", &savePtr); - } - } - OICFree(allIf); - } - } - - err = err || cbor_value_map_find_value(repParent, OC_RSRVD_REPRESENTATION, &curVal); - if(cbor_value_is_map(&curVal)) - { + size_t len; CborValue repMap; - err = err || cbor_value_enter_container(&curVal, &repMap); + err = err || cbor_value_enter_container(objMap, &repMap); while(!err && cbor_value_is_valid(&repMap)) { char* name; err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL); - err = err || cbor_value_advance(&repMap); - int64_t intval = 0; - bool boolval = false; - char* strval = NULL; - double doubleval = 0; - OCRepPayload* pl; - - switch(cbor_value_get_type(&repMap)) + CborType type = cbor_value_get_type(&repMap); + switch(type) { case CborNullType: err = !OCRepPayloadSetNull(curPayload, name); break; case CborIntegerType: - err = err || cbor_value_get_int64(&repMap, &intval); - if (!err) { - err = !OCRepPayloadSetPropInt(curPayload, name, intval); + int64_t intval = 0; + err = err || cbor_value_get_int64(&repMap, &intval); + if (!err) + { + err = !OCRepPayloadSetPropInt(curPayload, name, intval); + } } break; case CborDoubleType: - err = err || cbor_value_get_double(&repMap, &doubleval); - if (!err) { - err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval); + double doubleval = 0; + err = err || cbor_value_get_double(&repMap, &doubleval); + if (!err) + { + err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval); + } } break; case CborBooleanType: - err = err || cbor_value_get_boolean(&repMap, &boolval); - if (!err) { - err = !OCRepPayloadSetPropBool(curPayload, name, boolval); + bool boolval = false; + err = err || cbor_value_get_boolean(&repMap, &boolval); + if (!err) + { + err = !OCRepPayloadSetPropBool(curPayload, name, boolval); + } } break; case CborTextStringType: - err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL); - if (!err) { - err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval); + char* strval = NULL; + err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL); + if (!err) + { + err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval); + } + } + break; + case CborByteStringType: + { + uint8_t* bytestrval = NULL; + err = err || cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL); + if (!err) + { + OCByteString tmp = {.bytes = bytestrval, .len = len}; + err = !OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp); + } } break; case CborMapType: - err = err || OCParseSingleRepPayload(&pl, &repMap); - if (!err) { - err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl); + OCRepPayload *pl = NULL; + err = err || OCParseSingleRepPayload(&pl, &repMap); + if (!err) + { + err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl); + } } break; case CborArrayType: @@ -1162,35 +1116,90 @@ static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repPar err = true; } - err = err || cbor_value_advance(&repMap); + if (type != CborMapType && cbor_value_is_valid(&repMap)) + { + err = err || cbor_value_advance(&repMap); + } OICFree(name); } - err = err || cbor_value_leave_container(&curVal, &repMap); - } - if(err) - { - OCRepPayloadDestroy(*outPayload); - *outPayload = NULL; + err = err || cbor_value_leave_container(objMap, &repMap); + + if(err) + { + OCRepPayloadDestroy(*outPayload); + *outPayload = NULL; + } } return err; } -static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal) + +static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* rootMap) { if (!outPayload) { return OC_STACK_INVALID_PARAM; } + OCRepPayload *rootPayload = NULL; + OCRepPayload *curPayload = NULL; + OCRepPayload *temp = OCRepPayloadCreate(); + if (!temp) + { + return OC_STACK_NO_MEMORY; + } + + CborValue curVal; bool err = false; + size_t len; + err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal); + if(cbor_value_is_text_string(&curVal)) + { + char* allRt = NULL; + err = err || cbor_value_dup_text_string(&curVal, &allRt, &len, NULL); + if (allRt) + { + char* savePtr; + char* curPtr = strtok_r(allRt, " ", &savePtr); + while (curPtr) + { + char* trimmed = InPlaceStringTrim(curPtr); + if (trimmed[0] != '\0') + { + OCRepPayloadAddResourceType(temp, curPtr); + } + curPtr = strtok_r(NULL, " ", &savePtr); + } + } + OICFree(allRt); + } - OCRepPayload* rootPayload = NULL; - OCRepPayload* curPayload = NULL; - OCRepPayload* temp = NULL; - while(!err && cbor_value_is_map(arrayVal)) + err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_INTERFACE, &curVal); + if(cbor_value_is_text_string(&curVal)) { - err = err || OCParseSingleRepPayload(&temp, arrayVal); + char* allIf = NULL; + err = err || cbor_value_dup_text_string(&curVal, &allIf, &len, NULL); + if (allIf) + { + char* savePtr; + char* curPtr = strtok_r(allIf, " ", &savePtr); + while (curPtr) + { + char* trimmed = InPlaceStringTrim(curPtr); + if (trimmed[0] != '\0') + { + OCRepPayloadAddInterface(temp, curPtr); + } + curPtr = strtok_r(NULL, " ", &savePtr); + } + } + OICFree(allIf); + } + + while (!err && cbor_value_is_map(rootMap)) + { + err = err || OCParseSingleRepPayload(&temp, rootMap); if(rootPayload == NULL) { @@ -1203,8 +1212,11 @@ static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayV curPayload = curPayload->next; } + if (cbor_value_is_valid(rootMap)) + { + err = err || cbor_value_advance(rootMap); + } - err = err || cbor_value_advance(arrayVal); if(err) { OCRepPayloadDestroy(rootPayload); @@ -1218,7 +1230,7 @@ static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayV return OC_STACK_OK; } -static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal) +static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* rootValue) { if (!outPayload) { @@ -1226,7 +1238,10 @@ static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* a } bool err = false; - if(cbor_value_is_map(arrayVal)) + CborValue arrayVal; + err = err || cbor_value_enter_container(rootValue, &arrayVal); + + if(cbor_value_is_map(&arrayVal)) { uint64_t seqNum = 0; uint64_t maxAge = 0; @@ -1236,28 +1251,29 @@ static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* a CborValue curVal; // Sequence Number - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_NONCE, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_NONCE, &curVal); err = err || cbor_value_get_uint64(&curVal, &seqNum); // Max Age - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TTL, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_TTL, &curVal); err = err || cbor_value_get_uint64(&curVal, &maxAge); // Trigger - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TRIGGER, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_TRIGGER, &curVal); err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL); trigger = convertTriggerStringToEnum(tempStr); OICFree(tempStr); tempStr = NULL; // Resource type name - err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal); + err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal); if(cbor_value_is_valid(&curVal)) { err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL); } - err = err || cbor_value_advance(arrayVal); + err = err || cbor_value_advance(&arrayVal); + err = err || cbor_value_leave_container(rootValue, &arrayVal); if(!err) { diff --git a/resource/unittests/OCRepresentationEncodingTest.cpp b/resource/unittests/OCRepresentationEncodingTest.cpp index c679495..2898769 100644 --- a/resource/unittests/OCRepresentationEncodingTest.cpp +++ b/resource/unittests/OCRepresentationEncodingTest.cpp @@ -913,7 +913,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, SingleItemNormal) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, "rt.firstitem"); OCRepPayloadAddInterface(payload, "if.firstitem"); @@ -940,7 +939,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, SingleItemFrontTrim) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, " rt.firstitem"); OCRepPayloadAddInterface(payload, " if.firstitem"); @@ -967,7 +965,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, SingleItemBackTrim) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, "rt.firstitem "); OCRepPayloadAddInterface(payload, "if.firstitem "); @@ -994,7 +991,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, SingleItemBothTrim) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, " rt.firstitem "); OCRepPayloadAddInterface(payload, " if.firstitem "); @@ -1021,7 +1017,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, MultiItemsNormal) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, "rt.firstitem"); OCRepPayloadAddResourceType(payload, "rt.seconditem"); OCRepPayloadAddInterface(payload, "if.firstitem"); @@ -1052,7 +1047,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, MultiItemExtraLeadSpaces) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, " rt.firstitem"); OCRepPayloadAddResourceType(payload, " rt.seconditem"); OCRepPayloadAddInterface(payload, " if.firstitem"); @@ -1083,7 +1077,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, MultiItemExtraTrailSpaces) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, "rt.firstitem "); OCRepPayloadAddResourceType(payload, "rt.seconditem "); OCRepPayloadAddInterface(payload, "if.firstitem "); @@ -1114,7 +1107,6 @@ namespace OCRepresentationEncodingTest TEST(RepresentationEncodingRTandIF, MultiItemExtraMiddleSpaces) { OCRepPayload* payload = OCRepPayloadCreate(); - OCRepPayloadSetUri(payload, "/this/uri"); OCRepPayloadAddResourceType(payload, " rt.firstitem "); OCRepPayloadAddResourceType(payload, " rt.seconditem "); OCRepPayloadAddInterface(payload, " if.firstitem "); -- 2.7.4