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: %zu", payloadSize);
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 OCStackResult result = OC_STACK_ERROR;
69 case PAYLOAD_TYPE_DISCOVERY:
70 result = OCParseDiscoveryPayload(outPayload, &rootValue);
72 case PAYLOAD_TYPE_DEVICE:
73 result = OCParseDevicePayload(outPayload, &rootValue);
75 case PAYLOAD_TYPE_PLATFORM:
76 result = OCParsePlatformPayload(outPayload, &rootValue);
78 case PAYLOAD_TYPE_REPRESENTATION:
79 result = OCParseRepPayload(outPayload, &rootValue);
81 case PAYLOAD_TYPE_PRESENCE:
82 result = OCParsePresencePayload(outPayload, &rootValue);
84 case PAYLOAD_TYPE_SECURITY:
85 result = OCParseSecurityPayload(outPayload, &rootValue);
88 result = OCRDCborToPayload(&rootValue, outPayload);
91 OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
92 result = OC_STACK_ERROR;
96 if(result != OC_STACK_OK)
98 OC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
104 void OCFreeOCStringLL(OCStringLL* ll);
106 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* rootValue)
110 return OC_STACK_INVALID_PARAM;
114 char * securityData = NULL;
116 err = err || cbor_value_enter_container(rootValue, &arrayVal);
118 if(cbor_value_is_map(&arrayVal))
121 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
123 if(cbor_value_is_valid(&curVal))
126 err = err || cbor_value_dup_text_string(&curVal, &securityData, &len, NULL);
131 OC_LOG(ERROR, TAG, "Cbor main value not a map");
132 return OC_STACK_MALFORMED_RESPONSE;
135 err = err || cbor_value_advance(&arrayVal);
136 err = err || cbor_value_leave_container(rootValue, &arrayVal);
140 OC_LOG(ERROR, TAG, "Cbor in error condition");
141 OICFree(securityData);
142 return OC_STACK_MALFORMED_RESPONSE;
145 *outPayload = (OCPayload*)OCSecurityPayloadCreate(securityData);
146 OICFree(securityData);
152 static char* InPlaceStringTrim(char* str)
154 while (str[0] == ' ')
159 size_t lastchar = strlen(str);
161 while (str[lastchar] == ' ')
163 str[lastchar] = '\0';
170 static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* rootValue)
174 return OC_STACK_INVALID_PARAM;
178 OCResourcePayload* resource = NULL;
180 OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
183 return OC_STACK_NO_MEMORY;
187 err = err || cbor_value_enter_container(rootValue, &arrayVal);
189 if (cbor_value_is_array(&arrayVal))
191 OCLinksPayload *linksPayload = NULL;
192 OCTagsPayload *tagsPayload = NULL;
193 while (cbor_value_is_container(&arrayVal))
197 CborValue colResources;
198 CborError cborFindResult = cbor_value_enter_container(&arrayVal, &colResources);
199 if (CborNoError != cborFindResult)
204 if (OC_STACK_OK != OCTagsCborToPayload(&colResources, &tagsPayload))
206 OC_LOG(ERROR, TAG, "Tags cbor parsing failed.");
207 OCFreeTagsResource(tagsPayload);
211 if (OC_STACK_OK != OCLinksCborToPayload(&colResources, &linksPayload))
213 OC_LOG(ERROR, TAG, "Links cbor parsing failed.");
214 OCFreeTagsResource(tagsPayload);
215 OCFreeLinksResource(linksPayload);
219 if (OC_STACK_OK != OCDiscoveryCollectionPayloadAddResource(out, tagsPayload, linksPayload))
221 OC_LOG(ERROR, TAG, "Memory allocation failed");
222 OCFreeLinksResource(linksPayload);
223 OCFreeTagsResource(tagsPayload);
224 OCDiscoveryPayloadDestroy(out);
225 return OC_STACK_NO_MEMORY;
227 if (CborNoError != cbor_value_advance(&arrayVal))
229 OC_LOG(ERROR, TAG, "Cbor value advanced failed.");
234 if (cbor_value_is_map(&arrayVal))
236 size_t resourceCount = 0;
237 while (cbor_value_is_map(&arrayVal))
239 resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
242 OC_LOG(ERROR, TAG, "Memory allocation failed");
243 OCDiscoveryPayloadDestroy(out);
244 return OC_STACK_NO_MEMORY;
248 err = cbor_value_map_find_value(&arrayVal, OC_RSRVD_DEVICE_ID, &curVal);
249 if (CborNoError != err)
251 OC_LOG(ERROR, TAG, "Cbor find value failed.");
255 err = cbor_value_dup_byte_string(&curVal, &(resource->sid), &len, NULL);
256 if (CborNoError != err)
258 OC_LOG(ERROR, TAG, "Cbor di finding failed.");
264 err = cbor_value_map_find_value(&arrayVal, OC_RSRVD_LINKS, &linkArray);
265 if (CborNoError != err)
267 OC_LOG(ERROR, TAG, "Cbor links finding failed.");
271 err = cbor_value_enter_container(&linkArray, &linkMap);
272 if (CborNoError != err)
274 OC_LOG(ERROR, TAG, "Cbor entering map failed.");
278 err = cbor_value_map_find_value(&linkMap, OC_RSRVD_HREF, &curVal);
279 if (CborNoError != err)
281 OC_LOG(ERROR, TAG, "Cbor finding href type failed.");
284 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
285 if (CborNoError != err)
287 OC_LOG(ERROR, TAG, "Cbor finding href value failed.");
292 err = cbor_value_map_find_value(&linkMap, OC_RSRVD_RESOURCE_TYPE, &rtVal);
293 if (CborNoError != err)
295 OC_LOG(ERROR, TAG, "Cbor finding rt type failed.");
298 if (cbor_value_is_text_string(&rtVal))
302 err = cbor_value_dup_text_string(&rtVal, &input, &len, NULL);
303 if (CborNoError != err)
305 OC_LOG(ERROR, TAG, "Cbor finding rt value failed.");
310 char* curPtr = strtok_r(input, " ", &savePtr);
314 char* trimmed = InPlaceStringTrim(curPtr);
315 if (trimmed[0] !='\0')
317 if (!OCResourcePayloadAddResourceType(resource, trimmed))
319 OICFree(resource->uri);
320 OICFree(resource->sid);
321 OCFreeOCStringLL(resource->types);
323 OCDiscoveryPayloadDestroy(out);
324 return OC_STACK_NO_MEMORY;
327 curPtr = strtok_r(NULL, " ", &savePtr);
335 err = cbor_value_map_find_value(&linkMap, OC_RSRVD_INTERFACE, &ifVal);
336 if (CborNoError != err)
338 OC_LOG(ERROR, TAG, "Cbor finding if type failed.");
341 if (!err && cbor_value_is_text_string(&ifVal))
345 err = cbor_value_dup_text_string(&ifVal, &input, &len, NULL);
346 if (CborNoError != err)
348 OC_LOG(ERROR, TAG, "Cbor finding if value failed.");
353 char* curPtr = strtok_r(input, " ", &savePtr);
357 char* trimmed = InPlaceStringTrim(curPtr);
358 if (trimmed[0] !='\0')
360 if (!OCResourcePayloadAddInterface(resource, trimmed))
362 OICFree(resource->uri);
363 OICFree(resource->sid);
364 OCFreeOCStringLL(resource->types);
366 OCDiscoveryPayloadDestroy(out);
367 return OC_STACK_NO_MEMORY;
370 curPtr = strtok_r(NULL, " ", &savePtr);
378 err = cbor_value_map_find_value(&linkMap, OC_RSRVD_POLICY, &policyMap);
379 if (CborNoError != err)
381 OC_LOG(ERROR, TAG, "Cbor finding policy type failed.");
386 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &val);
387 if (CborNoError != err)
389 OC_LOG(ERROR, TAG, "Cbor finding bitmap type failed.");
393 err = cbor_value_get_uint64(&val, &temp);
394 if (CborNoError != err)
396 OC_LOG(ERROR, TAG, "Cbor finding bitmap value failed.");
399 resource->bitmap = (uint8_t)temp;
401 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
402 if (CborNoError != err)
404 OC_LOG(ERROR, TAG, "Cbor finding secure type failed.");
407 if(cbor_value_is_valid(&val))
409 err = cbor_value_get_boolean(&val, &(resource->secure));
410 if (CborNoError != err)
412 OC_LOG(ERROR, TAG, "Cbor finding secure value failed.");
417 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT,
419 if (CborNoError != err)
421 OC_LOG(ERROR, TAG, "Cbor finding port type failed.");
424 if(cbor_value_is_valid(&port))
426 err = cbor_value_get_uint64(&port, &temp);
427 if (CborNoError != err)
429 OC_LOG(ERROR, TAG, "Cbor finding port value failed.");
432 resource->port = (uint16_t)temp;
437 err = cbor_value_advance(&arrayVal);
438 if (CborNoError != err)
440 OC_LOG(ERROR, TAG, "Cbor advance value failed.");
444 OCDiscoveryPayloadAddNewResource(out, resource);
447 err = err || cbor_value_leave_container(rootValue, &arrayVal);
449 *outPayload = (OCPayload*)out;
453 OICFree(resource->uri);
454 OICFree(resource->sid);
455 OCFreeOCStringLL(resource->types);
456 OCFreeOCStringLL(resource->interfaces);
458 OCDiscoveryPayloadDestroy(out);
459 return OC_STACK_MALFORMED_RESPONSE;
462 OCDiscoveryCollectionPayloadDestroy(out);
463 return OC_STACK_MALFORMED_RESPONSE;
466 static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* rootValue)
470 return OC_STACK_INVALID_PARAM;
476 err = err || cbor_value_enter_container(rootValue, &arrayVal);
478 if(cbor_value_is_map(&arrayVal))
483 char* specVer = NULL;
486 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_HREF, &curVal);
488 err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
492 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
496 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_ID, &repVal);
497 if(cbor_value_is_valid(&repVal))
499 err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
502 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_NAME, &repVal);
503 if(cbor_value_is_valid(&repVal))
505 err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
507 // Device Spec Version
508 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SPEC_VERSION, &repVal);
509 if(cbor_value_is_valid(&repVal))
511 err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
514 // Data Model Version
515 err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
516 if (cbor_value_is_valid(&repVal))
518 err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
522 err = err || cbor_value_advance(&arrayVal);
523 err = err || cbor_value_leave_container(rootValue, &arrayVal);
532 OC_LOG_V(ERROR, TAG, "CBOR in error condition %d", err);
533 return OC_STACK_MALFORMED_RESPONSE;
536 *outPayload = (OCPayload*)OCDevicePayloadCreate(uri, sid, dname, specVer, dmVer);
545 return OC_STACK_NO_MEMORY;
552 OC_LOG(ERROR, TAG, "Root device node was not a map");
553 return OC_STACK_MALFORMED_RESPONSE;
558 static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* rootValue)
562 return OC_STACK_INVALID_PARAM;
567 if(cbor_value_is_map(rootValue))
569 OCPlatformInfo info = {0};
574 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
575 if(cbor_value_is_valid(&repVal))
577 err = err || cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
581 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
582 if(cbor_value_is_valid(&repVal))
584 err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
588 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
589 if(cbor_value_is_valid(&repVal))
591 err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
595 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
596 if(cbor_value_is_valid(&repVal))
598 err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
602 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
603 if(cbor_value_is_valid(&repVal))
605 err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
610 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
611 if(cbor_value_is_valid(&repVal))
613 err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
617 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
618 if(cbor_value_is_valid(&repVal))
620 err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
625 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
626 if(cbor_value_is_valid(&repVal))
628 err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
633 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
634 if(cbor_value_is_valid(&repVal))
636 err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
641 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
642 if(cbor_value_is_valid(&repVal))
644 err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
648 err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
649 if(cbor_value_is_valid(&repVal))
651 err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
654 err = err || cbor_value_advance(rootValue);
658 OICFree(info.dateOfManufacture);
659 OICFree(info.firmwareVersion);
660 OICFree(info.hardwareVersion);
661 OICFree(info.manufacturerName);
662 OICFree(info.manufacturerUrl);
663 OICFree(info.modelNumber);
664 OICFree(info.operatingSystemVersion);
665 OICFree(info.platformID);
666 OICFree(info.platformVersion);
667 OICFree(info.supportUrl);
668 OICFree(info.systemTime);
669 OC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
670 return OC_STACK_MALFORMED_RESPONSE;
673 *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(&info);
677 return OC_STACK_NO_MEMORY;
684 OC_LOG(ERROR, TAG, "Root device node was not a map");
685 return OC_STACK_MALFORMED_RESPONSE;
689 static OCRepPayloadPropType DecodeCborType(CborType type)
694 return OCREP_PROP_NULL;
695 case CborIntegerType:
696 return OCREP_PROP_INT;
698 return OCREP_PROP_DOUBLE;
699 case CborBooleanType:
700 return OCREP_PROP_BOOL;
701 case CborTextStringType:
702 return OCREP_PROP_STRING;
703 case CborByteStringType:
704 return OCREP_PROP_BYTE_STRING;
706 return OCREP_PROP_OBJECT;
708 return OCREP_PROP_ARRAY;
710 return OCREP_PROP_NULL;
713 static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
714 OCRepPayloadPropType* type)
717 CborValue insideArray;
718 *type = OCREP_PROP_NULL;
719 dimensions[0] = dimensions[1] = dimensions[2] = 0;
721 err = err || cbor_value_enter_container(parent, &insideArray);
723 while (cbor_value_is_valid(&insideArray))
725 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
727 if (tempType == OCREP_PROP_ARRAY)
729 size_t subdim[MAX_REP_ARRAY_DEPTH];
730 tempType = OCREP_PROP_NULL;
731 err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
735 OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
738 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
739 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
741 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
742 && *type != tempType)
744 OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
747 else if (*type == OCREP_PROP_NULL)
749 // We don't know the type of this array yet, so the assignment is OK
753 else if (*type == OCREP_PROP_NULL)
755 // We don't know the type of this array yet, so the assignment is OK
758 // tempType is allowed to be NULL, since it might now know the answer yet
759 else if (tempType != OCREP_PROP_NULL && *type != tempType)
761 // this is an invalid situation!
762 OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
767 cbor_value_advance(&insideArray);
773 static size_t getAllocSize(OCRepPayloadPropType type)
778 return sizeof (int64_t);
779 case OCREP_PROP_DOUBLE:
780 return sizeof (double);
781 case OCREP_PROP_BOOL:
782 return sizeof (bool);
783 case OCREP_PROP_STRING:
784 return sizeof (char*);
785 case OCREP_PROP_BYTE_STRING:
786 return sizeof (OCByteString);
787 case OCREP_PROP_OBJECT:
788 return sizeof (OCRepPayload*);
794 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
797 (dimensions[1] == 0 ? 1 : dimensions[1]) *
798 (dimensions[2] == 0 ? 1 : dimensions[2]) *
802 static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
803 OCRepPayloadPropType type, void* targetArray)
806 CborValue insideArray;
808 err = err || cbor_value_enter_container(parent, &insideArray);
811 char* tempStr = NULL;
812 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
814 OCRepPayload* tempPl = NULL;
816 size_t newdim[MAX_REP_ARRAY_DEPTH];
817 newdim[0] = dimensions[1];
818 newdim[1] = dimensions[2];
821 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
823 bool noAdvance = false;
824 if (cbor_value_get_type(&insideArray) != CborNullType)
829 if (dimensions[1] == 0)
831 err = err || cbor_value_get_int64(&insideArray,
832 &(((int64_t*)targetArray)[i]));
836 err = err || OCParseArrayFillArray(&insideArray, newdim,
838 &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
842 case OCREP_PROP_DOUBLE:
843 if (dimensions[1] == 0)
845 err = err || cbor_value_get_double(&insideArray,
846 &(((double*)targetArray)[i]));
850 err = err || OCParseArrayFillArray(&insideArray, newdim,
852 &(((double*)targetArray)[arrayStep(dimensions, i)])
856 case OCREP_PROP_BOOL:
857 if (dimensions[1] == 0)
859 err = err || cbor_value_get_boolean(&insideArray,
860 &(((bool*)targetArray)[i]));
864 err = err || OCParseArrayFillArray(&insideArray, newdim,
866 &(((bool*)targetArray)[arrayStep(dimensions, i)])
870 case OCREP_PROP_STRING:
871 if (dimensions[1] == 0)
873 err = err || cbor_value_dup_text_string(&insideArray,
874 &tempStr, &tempLen, NULL);
875 ((char**)targetArray)[i] = tempStr;
880 err = err || OCParseArrayFillArray(&insideArray, newdim,
882 &(((char**)targetArray)[arrayStep(dimensions, i)])
886 case OCREP_PROP_BYTE_STRING:
887 if (dimensions[1] == 0)
889 err = err || cbor_value_dup_byte_string(&insideArray,
890 &(ocByteStr.bytes), &(ocByteStr.len), NULL);
891 ((OCByteString*)targetArray)[i] = ocByteStr;
895 err = err || OCParseArrayFillArray(&insideArray, newdim,
897 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)])
901 case OCREP_PROP_OBJECT:
902 if (dimensions[1] == 0)
904 err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
905 ((OCRepPayload**)targetArray)[i] = tempPl;
911 err = err || OCParseArrayFillArray(&insideArray, newdim,
913 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
918 OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
924 if (!noAdvance && cbor_value_is_valid(&insideArray))
926 err = err || cbor_value_advance(&insideArray);
933 static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
935 OCRepPayloadPropType type;
936 size_t dimensions[MAX_REP_ARRAY_DEPTH];
937 bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
941 OC_LOG(ERROR, TAG, "Array details weren't clear");
945 if (type == OCREP_PROP_NULL)
947 err = err || OCRepPayloadSetNull(out, name);
948 err = err || cbor_value_advance(container);
952 size_t dimTotal = calcDimTotal(dimensions);
953 size_t allocSize = getAllocSize(type);
954 void* arr = OICCalloc(dimTotal, allocSize);
958 OC_LOG(ERROR, TAG, "Array Parse allocation failed");
962 err = err || OCParseArrayFillArray(container, dimensions, type, arr);
967 if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
973 case OCREP_PROP_DOUBLE:
974 if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
980 case OCREP_PROP_BOOL:
981 if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
987 case OCREP_PROP_STRING:
988 if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
990 for(size_t i = 0; i < dimTotal; ++i)
992 OICFree(((char**)arr)[i]);
998 case OCREP_PROP_BYTE_STRING:
999 if (err || !OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString*)arr, dimensions))
1001 for (size_t i = 0; i < dimTotal; ++i)
1003 OICFree(((OCByteString*)arr)[i].bytes);
1009 case OCREP_PROP_OBJECT:
1010 if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
1012 for(size_t i = 0; i < dimTotal; ++i)
1014 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
1021 OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
1029 static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue *objMap)
1038 if (cbor_value_is_map(objMap))
1042 *outPayload = OCRepPayloadCreate();
1045 return CborErrorOutOfMemory;
1049 OCRepPayload* curPayload = *outPayload;
1053 err = err || cbor_value_enter_container(objMap, &repMap);
1055 while(!err && cbor_value_is_valid(&repMap))
1058 err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
1059 err = err || cbor_value_advance(&repMap);
1061 CborType type = cbor_value_get_type(&repMap);
1065 err = !OCRepPayloadSetNull(curPayload, name);
1067 case CborIntegerType:
1070 err = err || cbor_value_get_int64(&repMap, &intval);
1073 err = !OCRepPayloadSetPropInt(curPayload, name, intval);
1077 case CborDoubleType:
1079 double doubleval = 0;
1080 err = err || cbor_value_get_double(&repMap, &doubleval);
1083 err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval);
1087 case CborBooleanType:
1089 bool boolval = false;
1090 err = err || cbor_value_get_boolean(&repMap, &boolval);
1093 err = !OCRepPayloadSetPropBool(curPayload, name, boolval);
1097 case CborTextStringType:
1099 char* strval = NULL;
1100 err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
1103 err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
1107 case CborByteStringType:
1109 uint8_t* bytestrval = NULL;
1110 err = err || cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
1113 OCByteString tmp = {.bytes = bytestrval, .len = len};
1114 err = !OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1120 OCRepPayload *pl = NULL;
1121 err = err || OCParseSingleRepPayload(&pl, &repMap);
1124 err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1129 err = err || OCParseArray(curPayload, name, &repMap);
1132 OC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1136 if (type != CborMapType && cbor_value_is_valid(&repMap))
1138 err = err || cbor_value_advance(&repMap);
1143 err = err || cbor_value_leave_container(objMap, &repMap);
1147 OCRepPayloadDestroy(*outPayload);
1155 static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* rootMap)
1159 return OC_STACK_INVALID_PARAM;
1162 OCRepPayload *rootPayload = NULL;
1163 OCRepPayload *curPayload = NULL;
1164 OCRepPayload *temp = OCRepPayloadCreate();
1167 return OC_STACK_NO_MEMORY;
1173 err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
1174 if(cbor_value_is_text_string(&curVal))
1177 err = err || cbor_value_dup_text_string(&curVal, &allRt, &len, NULL);
1181 char* curPtr = strtok_r(allRt, " ", &savePtr);
1184 char* trimmed = InPlaceStringTrim(curPtr);
1185 if (trimmed[0] != '\0')
1187 OCRepPayloadAddResourceType(temp, curPtr);
1189 curPtr = strtok_r(NULL, " ", &savePtr);
1195 err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_INTERFACE, &curVal);
1196 if(cbor_value_is_text_string(&curVal))
1199 err = err || cbor_value_dup_text_string(&curVal, &allIf, &len, NULL);
1203 char* curPtr = strtok_r(allIf, " ", &savePtr);
1206 char* trimmed = InPlaceStringTrim(curPtr);
1207 if (trimmed[0] != '\0')
1209 OCRepPayloadAddInterface(temp, curPtr);
1211 curPtr = strtok_r(NULL, " ", &savePtr);
1217 while (!err && cbor_value_is_map(rootMap))
1219 err = err || OCParseSingleRepPayload(&temp, rootMap);
1221 if(rootPayload == NULL)
1228 curPayload->next = temp;
1229 curPayload = curPayload->next;
1232 if (cbor_value_is_valid(rootMap))
1234 err = err || cbor_value_advance(rootMap);
1239 OCRepPayloadDestroy(rootPayload);
1240 OC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1241 return OC_STACK_MALFORMED_RESPONSE;
1245 *outPayload = (OCPayload*)rootPayload;
1250 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* rootValue)
1254 return OC_STACK_INVALID_PARAM;
1259 err = err || cbor_value_enter_container(rootValue, &arrayVal);
1261 if(cbor_value_is_map(&arrayVal))
1263 uint64_t seqNum = 0;
1264 uint64_t maxAge = 0;
1265 OCPresenceTrigger trigger = OC_PRESENCE_TRIGGER_CREATE;
1266 char* tempStr = NULL;
1271 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_NONCE, &curVal);
1272 err = err || cbor_value_get_uint64(&curVal, &seqNum);
1275 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_TTL, &curVal);
1276 err = err || cbor_value_get_uint64(&curVal, &maxAge);
1279 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_TRIGGER, &curVal);
1280 err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1281 trigger = convertTriggerStringToEnum(tempStr);
1285 // Resource type name
1286 err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
1287 if(cbor_value_is_valid(&curVal))
1289 err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1292 err = err || cbor_value_advance(&arrayVal);
1293 err = err || cbor_value_leave_container(rootValue, &arrayVal);
1297 *outPayload = (OCPayload*)OCPresencePayloadCreate(seqNum, maxAge, trigger, tempStr);
1303 OCPayloadDestroy(*outPayload);
1304 OC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1305 return OC_STACK_MALFORMED_RESPONSE;
1310 return OC_STACK_NO_MEMORY;
1317 OC_LOG(ERROR, TAG, "Root presence node was not a map");
1318 return OC_STACK_MALFORMED_RESPONSE;