1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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 _POSIX_C_SOURCE macro with 200112L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2001 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2001 base specification,
26 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
27 // Required for strok_r
28 #define _POSIX_C_SOURCE 200112L
30 #include "ocpayloadcbor.h"
33 #include "oic_string.h"
34 #include "oic_malloc.h"
35 #include "ocstackinternal.h"
36 #include "ocpayload.h"
38 #include "oic_string.h"
39 #include "payload_logging.h"
40 #include "rdpayload.h"
42 #define TAG "OCPayloadParse"
44 static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal);
45 static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal);
46 static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal);
47 static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent);
48 static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal);
49 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal);
50 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal);
52 OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType,
53 const uint8_t* payload, size_t payloadSize)
59 OC_LOG_V(INFO, TAG, "CBOR Parsing size: %d %d", payloadSize, payloadType);
60 if((err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue)) != false)
62 OC_LOG_V(ERROR, TAG, "CBOR Parser init failed: %d", err);
63 return OC_STACK_ERROR;
66 if(!cbor_value_is_array(&rootValue))
68 OC_LOG_V(ERROR, TAG, "CBOR payload root object is not an array :%x", rootValue.type);
69 return OC_STACK_MALFORMED_RESPONSE;
74 err = err || cbor_value_enter_container(&rootValue, &arrayValue);
78 OC_LOG_V(ERROR, TAG, "CBOR payload parse failed :%d", err);
79 return OC_STACK_MALFORMED_RESPONSE;
82 OCStackResult result = OC_STACK_ERROR;
85 case PAYLOAD_TYPE_DISCOVERY:
86 result = OCParseDiscoveryPayload(outPayload, &arrayValue);
88 case PAYLOAD_TYPE_DEVICE:
89 result = OCParseDevicePayload(outPayload, &arrayValue);
91 case PAYLOAD_TYPE_PLATFORM:
92 result = OCParsePlatformPayload(outPayload, &arrayValue);
94 case PAYLOAD_TYPE_REPRESENTATION:
95 result = OCParseRepPayload(outPayload, &arrayValue);
97 case PAYLOAD_TYPE_PRESENCE:
98 result = OCParsePresencePayload(outPayload, &arrayValue);
100 case PAYLOAD_TYPE_SECURITY:
101 result = OCParseSecurityPayload(outPayload, &arrayValue);
103 case PAYLOAD_TYPE_RD:
104 result = OCRDCborToPayload(&arrayValue, outPayload);
107 OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
108 result = OC_STACK_ERROR;
112 if(result == OC_STACK_OK)
114 err = err || cbor_value_leave_container(&rootValue, &arrayValue);
115 if(err != CborNoError)
117 return OC_STACK_MALFORMED_RESPONSE;
122 OC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
128 void OCFreeOCStringLL(OCStringLL* ll);
130 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal)
134 return OC_STACK_INVALID_PARAM;
138 char * securityData = NULL;
140 if(cbor_value_is_map(arrayVal))
143 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
145 if(cbor_value_is_valid(&curVal))
148 err = err || cbor_value_dup_text_string(&curVal, &securityData, &len, NULL);
153 OC_LOG(ERROR, TAG, "Cbor main value not a map");
154 return OC_STACK_MALFORMED_RESPONSE;
157 err = err || cbor_value_advance(arrayVal);
161 OC_LOG(ERROR, TAG, "Cbor in error condition");
162 OICFree(securityData);
163 return OC_STACK_MALFORMED_RESPONSE;
166 *outPayload = (OCPayload*)OCSecurityPayloadCreate(securityData);
167 OICFree(securityData);
173 static char* InPlaceStringTrim(char* str)
175 while (str[0] == ' ')
180 size_t lastchar = strlen(str);
182 while (str[lastchar] == ' ')
184 str[lastchar] = '\0';
191 static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal)
195 return OC_STACK_INVALID_PARAM;
200 OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
204 return OC_STACK_NO_MEMORY;
207 if (cbor_value_is_array(arrayVal))
209 OCLinksPayload *linksPayload = NULL;
210 OCTagsPayload *tagsPayload = NULL;
211 while (cbor_value_is_container(arrayVal))
215 CborValue colResources;
216 CborError cborFindResult = cbor_value_enter_container(arrayVal, &colResources);
217 if (CborNoError != cborFindResult)
222 if (OC_STACK_OK != OCTagsCborToPayload(&colResources, &tagsPayload))
224 OC_LOG(ERROR, TAG, "Tags cbor parsing failed.");
225 OCFreeTagsResource(tagsPayload);
229 if (OC_STACK_OK != OCLinksCborToPayload(&colResources, &linksPayload))
231 OC_LOG(ERROR, TAG, "Links cbor parsing failed.");
232 OCFreeTagsResource(tagsPayload);
233 OCFreeLinksResource(linksPayload);
237 if (OC_STACK_OK != OCDiscoveryCollectionPayloadAddResource(out, tagsPayload, linksPayload))
239 OC_LOG(ERROR, TAG, "Memory allocation failed");
240 OCFreeLinksResource(linksPayload);
241 OCFreeTagsResource(tagsPayload);
242 OCDiscoveryPayloadDestroy(out);
243 return OC_STACK_NO_MEMORY;
245 if (CborNoError != cbor_value_advance(arrayVal))
247 OC_LOG(ERROR, TAG, "Cbor value advanced failed.");
252 if (cbor_value_is_map(arrayVal))
254 size_t resourceCount = 0;
256 cbor_value_is_map(arrayVal))
258 OCResourcePayload* resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
261 OC_LOG(ERROR, TAG, "Memory allocation failed");
262 OCDiscoveryPayloadDestroy(out);
263 return OC_STACK_NO_MEMORY;
268 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
270 err = err || cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
273 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_SERVER_INSTANCE_ID, &curVal);
274 err = err || cbor_value_dup_byte_string(&curVal, &(resource->sid), &len, NULL);
278 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_PROPERTY, &curVal);
281 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE, &rtVal);
283 if (!err && cbor_value_is_text_string(&rtVal))
287 err = err || cbor_value_dup_text_string(&rtVal, &input, &len, NULL);
291 char* curPtr = strtok_r(input, " ", &savePtr);
295 char* trimmed = InPlaceStringTrim(curPtr);
296 if (trimmed[0] !='\0')
298 if (!OCResourcePayloadAddResourceType(resource, trimmed))
300 OICFree(resource->uri);
301 OICFree(resource->sid);
302 OCFreeOCStringLL(resource->types);
304 OCDiscoveryPayloadDestroy(out);
305 return OC_STACK_NO_MEMORY;
308 curPtr = strtok_r(NULL, " ", &savePtr);
316 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &ifVal);
318 if (!err && cbor_value_is_text_string(&ifVal))
322 err = err || cbor_value_dup_text_string(&ifVal, &input, &len, NULL);
326 char* curPtr = strtok_r(input, " ", &savePtr);
330 char* trimmed = InPlaceStringTrim(curPtr);
331 if (trimmed[0] !='\0')
333 if (!OCResourcePayloadAddInterface(resource, trimmed))
335 OICFree(resource->uri);
336 OICFree(resource->sid);
337 OCFreeOCStringLL(resource->types);
339 OCDiscoveryPayloadDestroy(out);
340 return OC_STACK_NO_MEMORY;
343 curPtr = strtok_r(NULL, " ", &savePtr);
352 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_POLICY, &policyMap);
356 err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &val);
358 err = err || cbor_value_get_uint64(&val, &temp);
359 resource->bitmap = (uint8_t)temp;
361 err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
362 if(cbor_value_is_valid(&val))
364 err = err || cbor_value_get_boolean(&val, &(resource->secure));
367 err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT,
369 if(cbor_value_is_valid(&port))
371 err = err || cbor_value_get_uint64(&port, &temp);
372 resource->port = (uint16_t)temp;
378 err = err || cbor_value_advance(arrayVal);
381 OICFree(resource->uri);
382 OICFree(resource->sid);
383 OCFreeOCStringLL(resource->types);
384 OCFreeOCStringLL(resource->interfaces);
386 OCDiscoveryPayloadDestroy(out);
387 OC_LOG_V(ERROR, TAG, "CBOR in error condition: %d", err);
388 return OC_STACK_MALFORMED_RESPONSE;
391 OCDiscoveryPayloadAddNewResource(out, resource);
397 OCDiscoveryPayloadDestroy(out);
398 return OC_STACK_MALFORMED_RESPONSE;
402 *outPayload = (OCPayload*)out;
406 OCDiscoveryCollectionPayloadDestroy(out);
407 return OC_STACK_MALFORMED_RESPONSE;
410 static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal)
414 return OC_STACK_INVALID_PARAM;
419 if(cbor_value_is_map(arrayVal))
424 char* specVer = NULL;
427 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
429 err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
433 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
437 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_ID, &repVal);
438 if(cbor_value_is_valid(&repVal))
440 err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
443 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_NAME, &repVal);
444 if(cbor_value_is_valid(&repVal))
446 err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
448 // Device Spec Version
449 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SPEC_VERSION, &repVal);
450 if(cbor_value_is_valid(&repVal))
452 err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
455 // Data Model Version
456 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
457 if (cbor_value_is_valid(&repVal))
459 err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
463 err = err || cbor_value_advance(arrayVal);
472 OC_LOG_V(ERROR, TAG, "CBOR in error condition %d", err);
473 return OC_STACK_MALFORMED_RESPONSE;
476 *outPayload = (OCPayload*)OCDevicePayloadCreate(uri, sid, dname, specVer, dmVer);
485 return OC_STACK_NO_MEMORY;
492 OC_LOG(ERROR, TAG, "Root device node was not a map");
493 return OC_STACK_MALFORMED_RESPONSE;
498 static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal)
502 return OC_STACK_INVALID_PARAM;
507 if(cbor_value_is_map(arrayVal))
510 OCPlatformInfo info = {0};
512 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
514 err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
518 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
522 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_PLATFORM_ID, &repVal);
523 if(cbor_value_is_valid(&repVal))
525 err = err || cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
529 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_NAME, &repVal);
530 if(cbor_value_is_valid(&repVal))
532 err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
536 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_URL, &repVal);
537 if(cbor_value_is_valid(&repVal))
539 err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
543 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MODEL_NUM, &repVal);
544 if(cbor_value_is_valid(&repVal))
546 err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
550 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_DATE, &repVal);
551 if(cbor_value_is_valid(&repVal))
553 err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
558 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_PLATFORM_VERSION, &repVal);
559 if(cbor_value_is_valid(&repVal))
561 err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len,
566 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_OS_VERSION, &repVal);
567 if(cbor_value_is_valid(&repVal))
569 err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
574 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_HARDWARE_VERSION, &repVal);
575 if(cbor_value_is_valid(&repVal))
577 err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
582 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_FIRMWARE_VERSION, &repVal);
583 if(cbor_value_is_valid(&repVal))
585 err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
590 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SUPPORT_URL, &repVal);
591 if(cbor_value_is_valid(&repVal))
593 err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
597 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SYSTEM_TIME, &repVal);
598 if(cbor_value_is_valid(&repVal))
600 err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
604 err = err || cbor_value_advance(arrayVal);
608 OICFree(info.dateOfManufacture);
609 OICFree(info.firmwareVersion);
610 OICFree(info.hardwareVersion);
611 OICFree(info.manufacturerName);
612 OICFree(info.manufacturerUrl);
613 OICFree(info.modelNumber);
614 OICFree(info.operatingSystemVersion);
615 OICFree(info.platformID);
616 OICFree(info.platformVersion);
617 OICFree(info.supportUrl);
618 OICFree(info.systemTime);
619 OC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
620 return OC_STACK_MALFORMED_RESPONSE;
623 *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(uri, &info);
627 return OC_STACK_NO_MEMORY;
634 OC_LOG(ERROR, TAG, "Root device node was not a map");
635 return OC_STACK_MALFORMED_RESPONSE;
639 static OCRepPayloadPropType DecodeCborType(CborType type)
644 return OCREP_PROP_NULL;
645 case CborIntegerType:
646 return OCREP_PROP_INT;
648 return OCREP_PROP_DOUBLE;
649 case CborBooleanType:
650 return OCREP_PROP_BOOL;
651 case CborTextStringType:
652 return OCREP_PROP_STRING;
654 return OCREP_PROP_OBJECT;
656 return OCREP_PROP_ARRAY;
658 return OCREP_PROP_NULL;
661 static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
662 OCRepPayloadPropType* type)
665 CborValue insideArray;
666 *type = OCREP_PROP_NULL;
667 dimensions[0] = dimensions[1] = dimensions[2] = 0;
669 err = err || cbor_value_enter_container(parent, &insideArray);
671 while (cbor_value_is_valid(&insideArray))
673 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
675 if (tempType == OCREP_PROP_ARRAY)
677 size_t subdim[MAX_REP_ARRAY_DEPTH];
678 tempType = OCREP_PROP_NULL;
679 err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
683 OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
686 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
687 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
689 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
690 && *type != tempType)
692 OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
695 else if (*type == OCREP_PROP_NULL)
697 // We don't know the type of this array yet, so the assignment is OK
701 else if (*type == OCREP_PROP_NULL)
703 // We don't know the type of this array yet, so the assignment is OK
706 // tempType is allowed to be NULL, since it might now know the answer yet
707 else if (tempType != OCREP_PROP_NULL && *type != tempType)
709 // this is an invalid situation!
710 OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
715 cbor_value_advance(&insideArray);
721 static size_t getAllocSize(OCRepPayloadPropType type)
726 return sizeof (int64_t);
727 case OCREP_PROP_DOUBLE:
728 return sizeof (double);
729 case OCREP_PROP_BOOL:
730 return sizeof (bool);
731 case OCREP_PROP_STRING:
732 return sizeof (char*);
733 case OCREP_PROP_OBJECT:
734 return sizeof (OCRepPayload*);
740 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
743 (dimensions[1] == 0 ? 1 : dimensions[1]) *
744 (dimensions[2] == 0 ? 1 : dimensions[2]) *
748 static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
749 OCRepPayloadPropType type, void* targetArray)
752 CborValue insideArray;
754 err = err || cbor_value_enter_container(parent, &insideArray);
757 char* tempStr = NULL;
759 OCRepPayload* tempPl = NULL;
761 size_t newdim[MAX_REP_ARRAY_DEPTH];
762 newdim[0] = dimensions[1];
763 newdim[1] = dimensions[2];
766 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
768 if (cbor_value_get_type(&insideArray) != CborNullType)
773 if (dimensions[1] == 0)
775 err = err || cbor_value_get_int64(&insideArray,
776 &(((int64_t*)targetArray)[i]));
780 err = err || OCParseArrayFillArray(&insideArray, newdim,
782 &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
786 case OCREP_PROP_DOUBLE:
787 if (dimensions[1] == 0)
789 err = err || cbor_value_get_double(&insideArray,
790 &(((double*)targetArray)[i]));
794 err = err || OCParseArrayFillArray(&insideArray, newdim,
796 &(((double*)targetArray)[arrayStep(dimensions, i)])
800 case OCREP_PROP_BOOL:
801 if (dimensions[1] == 0)
803 err = err || cbor_value_get_boolean(&insideArray,
804 &(((bool*)targetArray)[i]));
808 err = err || OCParseArrayFillArray(&insideArray, newdim,
810 &(((bool*)targetArray)[arrayStep(dimensions, i)])
814 case OCREP_PROP_STRING:
815 if (dimensions[1] == 0)
817 err = err || cbor_value_dup_text_string(&insideArray,
818 &tempStr, &tempLen, NULL);
819 ((char**)targetArray)[i] = tempStr;
824 err = err || OCParseArrayFillArray(&insideArray, newdim,
826 &(((char**)targetArray)[arrayStep(dimensions, i)])
830 case OCREP_PROP_OBJECT:
831 if (dimensions[1] == 0)
833 err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
834 ((OCRepPayload**)targetArray)[i] = tempPl;
839 err = err || OCParseArrayFillArray(&insideArray, newdim,
841 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
846 OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
852 err = err || cbor_value_advance(&insideArray);
858 static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
860 OCRepPayloadPropType type;
861 size_t dimensions[MAX_REP_ARRAY_DEPTH];
862 bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
866 OC_LOG(ERROR, TAG, "Array details weren't clear");
870 if (type == OCREP_PROP_NULL)
872 err = err || OCRepPayloadSetNull(out, name);
873 err = err || cbor_value_advance(container);
877 size_t dimTotal = calcDimTotal(dimensions);
878 size_t allocSize = getAllocSize(type);
879 void* arr = OICCalloc(dimTotal, allocSize);
883 OC_LOG(ERROR, TAG, "Array Parse allocation failed");
887 err = err || OCParseArrayFillArray(container, dimensions, type, arr);
892 if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
898 case OCREP_PROP_DOUBLE:
899 if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
905 case OCREP_PROP_BOOL:
906 if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
912 case OCREP_PROP_STRING:
913 if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
915 for(size_t i = 0; i < dimTotal; ++i)
917 OICFree(((char**)arr)[i]);
923 case OCREP_PROP_OBJECT:
924 if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
926 for(size_t i = 0; i < dimTotal; ++i)
928 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
935 OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
943 static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent)
950 *outPayload = OCRepPayloadCreate();
951 OCRepPayload* curPayload = *outPayload;
955 return CborErrorOutOfMemory;
960 err = err || cbor_value_map_find_value(repParent, OC_RSRVD_HREF, &curVal);
961 if(cbor_value_is_valid(&curVal))
963 err = err || cbor_value_dup_text_string(&curVal, &curPayload->uri, &len,
967 err = err || cbor_value_map_find_value(repParent, OC_RSRVD_PROPERTY, &curVal);
968 if(cbor_value_is_valid(&curVal))
970 CborValue insidePropValue = {0};
971 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE,
974 if(cbor_value_is_text_string(&insidePropValue))
977 err = err || cbor_value_dup_text_string(&insidePropValue, &allRt, &len, NULL);
983 char* curPtr = strtok_r(allRt, " ", &savePtr);
987 char* trimmed = InPlaceStringTrim(curPtr);
988 if (trimmed[0] != '\0')
990 OCRepPayloadAddResourceType(curPayload, curPtr);
992 curPtr = strtok_r(NULL, " ", &savePtr);
998 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &insidePropValue);
1000 if(cbor_value_is_text_string(&insidePropValue))
1003 err = err || cbor_value_dup_text_string(&insidePropValue, &allIf, &len, NULL);
1009 char* curPtr = strtok_r(allIf, " ", &savePtr);
1013 char* trimmed = InPlaceStringTrim(curPtr);
1014 if (trimmed[0] != '\0')
1016 OCRepPayloadAddInterface(curPayload, curPtr);
1018 curPtr = strtok_r(NULL, " ", &savePtr);
1025 err = err || cbor_value_map_find_value(repParent, OC_RSRVD_REPRESENTATION, &curVal);
1026 if(cbor_value_is_map(&curVal))
1029 err = err || cbor_value_enter_container(&curVal, &repMap);
1031 while(!err && cbor_value_is_valid(&repMap))
1034 err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
1036 err = err || cbor_value_advance(&repMap);
1039 bool boolval = false;
1040 char* strval = NULL;
1041 double doubleval = 0;
1044 switch(cbor_value_get_type(&repMap))
1047 err = !OCRepPayloadSetNull(curPayload, name);
1049 case CborIntegerType:
1050 err = err || cbor_value_get_int64(&repMap, &intval);
1053 err = !OCRepPayloadSetPropInt(curPayload, name, intval);
1056 case CborDoubleType:
1057 err = err || cbor_value_get_double(&repMap, &doubleval);
1060 err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval);
1063 case CborBooleanType:
1064 err = err || cbor_value_get_boolean(&repMap, &boolval);
1067 err = !OCRepPayloadSetPropBool(curPayload, name, boolval);
1070 case CborTextStringType:
1071 err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
1074 err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
1078 err = err || OCParseSingleRepPayload(&pl, &repMap);
1081 err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1085 err = err || OCParseArray(curPayload, name, &repMap);
1088 OC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1092 err = err || cbor_value_advance(&repMap);
1095 err = err || cbor_value_leave_container(&curVal, &repMap);
1100 OCRepPayloadDestroy(*outPayload);
1106 static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal)
1110 return OC_STACK_INVALID_PARAM;
1115 OCRepPayload* rootPayload = NULL;
1116 OCRepPayload* curPayload = NULL;
1117 OCRepPayload* temp = NULL;
1118 while(!err && cbor_value_is_map(arrayVal))
1120 err = err || OCParseSingleRepPayload(&temp, arrayVal);
1122 if(rootPayload == NULL)
1129 curPayload->next = temp;
1130 curPayload = curPayload->next;
1134 err = err || cbor_value_advance(arrayVal);
1137 OCRepPayloadDestroy(rootPayload);
1138 OC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1139 return OC_STACK_MALFORMED_RESPONSE;
1143 *outPayload = (OCPayload*)rootPayload;
1148 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal)
1152 return OC_STACK_INVALID_PARAM;
1156 if(cbor_value_is_map(arrayVal))
1158 uint64_t seqNum = 0;
1159 uint64_t maxAge = 0;
1160 OCPresenceTrigger trigger = OC_PRESENCE_TRIGGER_CREATE;
1161 char* tempStr = NULL;
1166 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_NONCE, &curVal);
1167 err = err || cbor_value_get_uint64(&curVal, &seqNum);
1170 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TTL, &curVal);
1171 err = err || cbor_value_get_uint64(&curVal, &maxAge);
1174 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TRIGGER, &curVal);
1175 err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1176 trigger = convertTriggerStringToEnum(tempStr);
1180 // Resource type name
1181 err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
1182 if(cbor_value_is_valid(&curVal))
1184 err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1187 err = err || cbor_value_advance(arrayVal);
1191 *outPayload = (OCPayload*)OCPresencePayloadCreate(seqNum, maxAge, trigger, tempStr);
1197 OCPayloadDestroy(*outPayload);
1198 OC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1199 return OC_STACK_MALFORMED_RESPONSE;
1204 return OC_STACK_NO_MEMORY;
1211 OC_LOG(ERROR, TAG, "Root presence node was not a map");
1212 return OC_STACK_MALFORMED_RESPONSE;