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
31 #include "oic_string.h"
32 #include "oic_malloc.h"
33 #include "ocpayload.h"
34 #include "ocpayloadcbor.h"
35 #include "ocstackinternal.h"
36 #include "payload_logging.h"
37 #include "rdpayload.h"
39 #define TAG "OIC_RI_PAYLOADPARSE"
41 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *arrayVal);
42 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *arrayVal);
43 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *arrayVal);
44 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *repParent, bool isRoot);
45 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *arrayVal);
46 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *arrayVal);
47 static OCStackResult OCParseSecurityPayload(OCPayload **outPayload, CborValue * rrayVal);
49 OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType,
50 const uint8_t *payload, size_t payloadSize)
52 OCStackResult result = OC_STACK_MALFORMED_RESPONSE;
55 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Conversion of outPayload failed");
56 VERIFY_PARAM_NON_NULL(TAG, payload, "Invalid cbor payload value");
58 OIC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu", payloadSize);
63 err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
64 VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
68 case PAYLOAD_TYPE_DISCOVERY:
69 result = OCParseDiscoveryPayload(outPayload, &rootValue);
71 case PAYLOAD_TYPE_DEVICE:
72 result = OCParseDevicePayload(outPayload, &rootValue);
74 case PAYLOAD_TYPE_PLATFORM:
75 result = OCParsePlatformPayload(outPayload, &rootValue);
77 case PAYLOAD_TYPE_REPRESENTATION:
78 result = OCParseRepPayload(outPayload, &rootValue);
80 case PAYLOAD_TYPE_PRESENCE:
81 result = OCParsePresencePayload(outPayload, &rootValue);
83 case PAYLOAD_TYPE_SECURITY:
84 result = OCParseSecurityPayload(outPayload, &rootValue);
87 result = OCRDCborToPayload(&rootValue, outPayload);
90 OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
91 result = OC_STACK_INVALID_PARAM;
95 OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
101 void OCFreeOCStringLL(OCStringLL* ll);
103 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* rootValue)
105 OCStackResult ret = OC_STACK_MALFORMED_RESPONSE;
107 char *securityData = NULL;
109 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid parameter");
110 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid cbor");
114 err = cbor_value_enter_container(rootValue, &strVal);
115 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering container");
116 if (cbor_value_is_text_string(&strVal))
119 err = cbor_value_dup_text_string(&strVal, &securityData, &len, NULL);
120 VERIFY_CBOR_SUCCESS(TAG, err, "Failed reading security data");
121 *outPayload = (OCPayload *)OCSecurityPayloadCreate(securityData);
122 VERIFY_PARAM_NON_NULL(TAG, *outPayload, "Invalid cbor");
127 OICFree(securityData);
132 static char* InPlaceStringTrim(char* str)
134 while (str[0] == ' ')
139 size_t lastchar = strlen(str);
141 while (str[lastchar] == ' ')
143 str[lastchar] = '\0';
150 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
153 CborError err = cbor_value_map_find_value(map, type, &val);
154 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
156 if (cbor_value_is_text_string(&val))
159 char *savePtr = NULL;
162 err = cbor_value_dup_text_string(&val, &input, &len, NULL);
163 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value");
167 char *curPtr = strtok_r(input, " ", &savePtr);
170 char *trimmed = InPlaceStringTrim(curPtr);
171 if (trimmed[0] !='\0')
173 if (!OCResourcePayloadAddStringLL(resource, trimmed))
175 return CborErrorOutOfMemory;
178 curPtr = strtok_r(NULL, " ", &savePtr);
187 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
189 OCStackResult ret = OC_STACK_INVALID_PARAM;
190 OCResourcePayload *resource = NULL;
191 OCDiscoveryPayload *out = NULL;
193 CborError err = CborNoError;
196 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
197 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
199 // Root value is already inside the main root array
201 ret = OC_STACK_NO_MEMORY;
202 out = OCDiscoveryPayloadCreate();
203 VERIFY_PARAM_NON_NULL(TAG, out, "Failed error initializing discovery payload");
205 // Enter the main root map
206 ret = OC_STACK_MALFORMED_RESPONSE;
207 err = cbor_value_enter_container(rootValue, &rootMap);
208 VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
212 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
213 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
214 if (cbor_value_is_valid(&curVal))
216 if (cbor_value_is_byte_string(&curVal))
218 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(out->sid), &len, NULL);
219 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
221 else if (cbor_value_is_text_string(&curVal))
223 err = cbor_value_dup_text_string(&curVal, &(out->sid), &len, NULL);
224 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
228 // BaseURI - Not a mandatory field
229 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
230 if (cbor_value_is_valid(&curVal))
232 err = cbor_value_dup_text_string(&curVal, &(out->baseURI), &len, NULL);
233 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
236 // HREF - Not a mandatory field
237 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
238 if (cbor_value_is_valid(&curVal))
240 err = cbor_value_dup_text_string(&curVal, &(out->uri), &len, NULL);
241 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri value");
244 // RT - Not a mandatory field
245 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
246 if (cbor_value_is_valid(&curVal))
248 err = cbor_value_dup_text_string(&curVal, &(out->type), &len, NULL);
249 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
252 // IF - Not a mandatory field
253 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
254 if (cbor_value_is_valid(&curVal))
256 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &out->interface);
260 if (!OCResourcePayloadAddStringLL(&out->interface, OC_RSRVD_INTERFACE_LL))
262 err = CborErrorOutOfMemory;
266 // Name - Not a mandatory field
267 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
268 if (cbor_value_is_valid(&curVal))
270 err = cbor_value_dup_text_string(&curVal, &out->name, &len, NULL);
271 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
274 // Look for Links which will have an array as the value
276 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
277 VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
279 // Enter the links array and start iterating through the array processing
280 // each resource which shows up as a map.
281 CborValue resourceMap;
282 err = cbor_value_enter_container(&linkMap, &resourceMap);
283 VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
285 while (cbor_value_is_map(&resourceMap))
287 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
288 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
291 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
292 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
293 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
294 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
297 err = OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
298 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
301 err = OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
302 if (CborNoError != err)
304 if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
306 err = CborErrorOutOfMemory;
312 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
313 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
316 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
317 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
318 err = cbor_value_get_int(&curVal, (int *)&resource->bitmap);
319 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
322 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
323 if (cbor_value_is_valid(&curVal))
325 err = cbor_value_get_boolean(&curVal, &(resource->secure));
326 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
330 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
331 if (cbor_value_is_valid(&curVal))
333 err = cbor_value_get_int(&curVal, (int *)&resource->port);
334 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
337 err = cbor_value_advance(&resourceMap);
338 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
340 OCDiscoveryPayloadAddNewResource(out, resource);
343 err = cbor_value_leave_container(rootValue, &resourceMap);
344 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
346 *outPayload = (OCPayload *)out;
347 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
352 OCDiscoveryResourceDestroy(resource);
353 OCDiscoveryPayloadDestroy(out);
357 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
359 OCStackResult ret = OC_STACK_INVALID_PARAM;
360 CborError err = CborNoError;
361 OCDevicePayload *out = NULL;
362 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
363 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
367 out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
368 VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
369 out->base.type = PAYLOAD_TYPE_DEVICE;
370 ret = OC_STACK_MALFORMED_RESPONSE;
372 if (cbor_value_is_map(rootValue))
376 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
377 if (cbor_value_is_valid(&curVal))
379 err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
380 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
384 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
385 if (cbor_value_is_valid(&curVal))
387 if (cbor_value_is_byte_string(&curVal))
389 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&out->sid, &len, NULL);
390 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
392 else if (cbor_value_is_text_string(&curVal))
394 err = cbor_value_dup_text_string(&curVal, &out->sid, &len, NULL);
395 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
399 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
400 if (cbor_value_is_valid(&curVal))
402 err = cbor_value_dup_text_string(&curVal, &out->deviceName, &len, NULL);
403 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name in device payload");
405 // Device Spec Version
406 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &curVal);
407 if (cbor_value_is_valid(&curVal))
409 err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL);
410 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload");
412 // Data Model Version
413 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal);
414 if (cbor_value_is_valid(&curVal))
416 err = cbor_value_dup_text_string(&curVal, &out->dataModelVersion, &len, NULL);
417 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model version in device payload");
419 err = cbor_value_advance(rootValue);
420 VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload");
422 *outPayload = (OCPayload *)out;
427 OCDevicePayloadDestroy(out);
431 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *rootValue)
433 OCStackResult ret = OC_STACK_INVALID_PARAM;
434 CborError err = CborNoError;
435 OCPlatformInfo info = {0};
437 OCStringLL* interfaces = NULL;
438 OCPlatformPayload* out = NULL;
440 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
442 if (cbor_value_is_map(rootValue))
446 ret = OC_STACK_MALFORMED_RESPONSE;
449 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
450 if (cbor_value_is_valid(&repVal))
452 err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
453 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
456 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
457 if (cbor_value_is_valid(&repVal))
459 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
460 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
463 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
464 if (cbor_value_is_valid(&repVal))
466 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
467 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
470 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
471 if (cbor_value_is_valid(&repVal))
473 err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
474 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
477 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
478 if (cbor_value_is_valid(&repVal))
480 err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
481 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
484 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
485 if (cbor_value_is_valid(&repVal))
487 err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
488 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
491 err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
492 if (cbor_value_is_valid(&repVal))
494 err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
495 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
498 err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
499 if(cbor_value_is_valid(&repVal))
501 err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
502 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
505 err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
506 if(cbor_value_is_valid(&repVal))
508 err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
509 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
512 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
513 if(cbor_value_is_valid(&repVal))
515 err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
516 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
519 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
520 if(cbor_value_is_valid(&repVal))
522 err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
523 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
527 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
528 if(cbor_value_is_valid(&repVal))
530 err = cbor_value_dup_text_string(&repVal, &rt, &len, NULL);
531 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
535 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
536 if(cbor_value_is_valid(&repVal))
538 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
539 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
542 err = cbor_value_advance(rootValue);
543 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
545 out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
547 out->interfaces = interfaces;
548 *outPayload = (OCPayload *)out;
553 OCPlatformInfoDestroy(&info);
554 OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
558 static OCRepPayloadPropType DecodeCborType(CborType type)
563 return OCREP_PROP_NULL;
564 case CborIntegerType:
565 return OCREP_PROP_INT;
567 return OCREP_PROP_DOUBLE;
568 case CborBooleanType:
569 return OCREP_PROP_BOOL;
570 case CborTextStringType:
571 return OCREP_PROP_STRING;
572 case CborByteStringType:
573 return OCREP_PROP_BYTE_STRING;
575 return OCREP_PROP_OBJECT;
577 return OCREP_PROP_ARRAY;
579 return OCREP_PROP_NULL;
582 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
583 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
585 CborValue insideArray;
586 *type = OCREP_PROP_NULL;
587 dimensions[0] = dimensions[1] = dimensions[2] = 0;
589 CborError err = cbor_value_enter_container(parent, &insideArray);
590 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
592 while (cbor_value_is_valid(&insideArray))
594 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
596 if (tempType == OCREP_PROP_ARRAY)
598 size_t subdim[MAX_REP_ARRAY_DEPTH];
599 tempType = OCREP_PROP_NULL;
600 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
601 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
605 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
608 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
609 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
611 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
613 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
614 return CborUnknownError;
616 else if (*type == OCREP_PROP_NULL)
618 // We don't know the type of this array yet, so the assignment is OK
622 else if (*type == OCREP_PROP_NULL)
624 // We don't know the type of this array yet, so the assignment is OK
627 // tempType is allowed to be NULL, since it might now know the answer yet
628 else if (tempType != OCREP_PROP_NULL && *type != tempType)
630 // this is an invalid situation!
631 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
632 return CborUnknownError;
636 err = cbor_value_advance(&insideArray);
637 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
644 static size_t getAllocSize(OCRepPayloadPropType type)
649 return sizeof (int64_t);
650 case OCREP_PROP_DOUBLE:
651 return sizeof (double);
652 case OCREP_PROP_BOOL:
653 return sizeof (bool);
654 case OCREP_PROP_STRING:
655 return sizeof (char*);
656 case OCREP_PROP_BYTE_STRING:
657 return sizeof (OCByteString);
658 case OCREP_PROP_OBJECT:
659 return sizeof (OCRepPayload*);
665 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
668 (dimensions[1] == 0 ? 1 : dimensions[1]) *
669 (dimensions[2] == 0 ? 1 : dimensions[2]) *
673 static CborError OCParseArrayFillArray(const CborValue *parent,
674 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
676 CborValue insideArray;
679 char *tempStr = NULL;
680 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
682 OCRepPayload *tempPl = NULL;
684 size_t newdim[MAX_REP_ARRAY_DEPTH];
685 newdim[0] = dimensions[1];
686 newdim[1] = dimensions[2];
689 CborError err = cbor_value_enter_container(parent, &insideArray);
690 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
692 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
694 bool noAdvance = false;
695 if (cbor_value_get_type(&insideArray) != CborNullType)
700 if (dimensions[1] == 0)
702 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
706 err = OCParseArrayFillArray(&insideArray, newdim, type,
707 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
710 case OCREP_PROP_DOUBLE:
711 if (dimensions[1] == 0)
713 err = cbor_value_get_double(&insideArray, &(((double*)targetArray)[i]));
717 err = OCParseArrayFillArray(&insideArray, newdim, type,
718 &(((double*)targetArray)[arrayStep(dimensions, i)]));
721 case OCREP_PROP_BOOL:
722 if (dimensions[1] == 0)
724 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
728 err = OCParseArrayFillArray(&insideArray, newdim, type,
729 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
732 case OCREP_PROP_STRING:
733 if (dimensions[1] == 0)
735 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
736 ((char**)targetArray)[i] = tempStr;
741 err = OCParseArrayFillArray(&insideArray, newdim, type,
742 &(((char**)targetArray)[arrayStep(dimensions, i)]));
745 case OCREP_PROP_BYTE_STRING:
746 if (dimensions[1] == 0)
748 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
749 &(ocByteStr.len), NULL);
750 ((OCByteString*)targetArray)[i] = ocByteStr;
754 err = OCParseArrayFillArray(&insideArray, newdim, type,
755 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
758 case OCREP_PROP_OBJECT:
759 if (dimensions[1] == 0)
761 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
762 ((OCRepPayload**)targetArray)[i] = tempPl;
768 err = OCParseArrayFillArray(&insideArray, newdim, type,
769 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
773 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
774 err = CborErrorUnknownType;
777 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
780 if (!noAdvance && cbor_value_is_valid(&insideArray))
782 err = cbor_value_advance(&insideArray);
783 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
791 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
794 OCRepPayloadPropType type = OCREP_PROP_NULL;
795 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
797 size_t allocSize = 0;
799 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
800 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
802 if (type == OCREP_PROP_NULL)
804 res = OCRepPayloadSetNull(out, name);
805 err = (CborError) !res;
806 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
807 err = cbor_value_advance(container);
808 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
812 dimTotal = calcDimTotal(dimensions);
813 allocSize = getAllocSize(type);
814 arr = OICCalloc(dimTotal, allocSize);
815 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
817 res = OCParseArrayFillArray(container, dimensions, type, arr);
818 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
823 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
825 case OCREP_PROP_DOUBLE:
826 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
828 case OCREP_PROP_BOOL:
829 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
831 case OCREP_PROP_STRING:
832 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
834 case OCREP_PROP_BYTE_STRING:
835 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
837 case OCREP_PROP_OBJECT:
838 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
841 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
844 err = (CborError) !res;
845 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
848 if (type == OCREP_PROP_STRING)
850 for(size_t i = 0; i < dimTotal; ++i)
852 OICFree(((char**)arr)[i]);
855 if (type == OCREP_PROP_BYTE_STRING)
857 for(size_t i = 0; i < dimTotal; ++i)
859 OICFree(((OCByteString*)arr)[i].bytes);
862 if (type == OCREP_PROP_OBJECT)
864 for(size_t i = 0; i < dimTotal; ++i)
866 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
873 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
875 CborError err = CborUnknownError;
878 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
879 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
881 if (cbor_value_is_map(objMap))
885 *outPayload = OCRepPayloadCreate();
888 return CborErrorOutOfMemory;
892 OCRepPayload *curPayload = *outPayload;
896 err = cbor_value_enter_container(objMap, &repMap);
897 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
899 while (!err && cbor_value_is_valid(&repMap))
901 if (cbor_value_is_text_string(&repMap))
903 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
904 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
905 err = cbor_value_advance(&repMap);
906 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
909 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
910 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
911 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
913 err = cbor_value_advance(&repMap);
918 CborType type = cbor_value_get_type(&repMap);
922 res = OCRepPayloadSetNull(curPayload, name);
924 case CborIntegerType:
927 err = cbor_value_get_int64(&repMap, &intval);
928 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
929 res = OCRepPayloadSetPropInt(curPayload, name, intval);
934 double doubleval = 0;
935 err = cbor_value_get_double(&repMap, &doubleval);
936 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
937 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
940 case CborBooleanType:
942 bool boolval = false;
943 err = cbor_value_get_boolean(&repMap, &boolval);
944 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
945 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
948 case CborTextStringType:
951 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
952 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
953 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
956 case CborByteStringType:
958 uint8_t* bytestrval = NULL;
959 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
960 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
961 OCByteString tmp = {.bytes = bytestrval, .len = len};
962 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
967 OCRepPayload *pl = NULL;
968 err = OCParseSingleRepPayload(&pl, &repMap, false);
969 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
970 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
974 err = OCParseArray(curPayload, name, &repMap);
977 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
980 if (type != CborArrayType)
982 err = (CborError) !res;
984 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
986 if (type != CborMapType && cbor_value_is_valid(&repMap))
988 err = cbor_value_advance(&repMap);
989 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
994 if (cbor_value_is_container(objMap))
996 err = cbor_value_leave_container(objMap, &repMap);
997 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
1004 OCRepPayloadDestroy(*outPayload);
1009 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
1011 OCStackResult ret = OC_STACK_INVALID_PARAM;
1013 OCRepPayload *temp = NULL;
1014 OCRepPayload *rootPayload = NULL;
1015 OCRepPayload *curPayload = NULL;
1016 CborValue rootMap = *root;
1017 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1018 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
1021 if (cbor_value_is_array(root))
1023 err = cbor_value_enter_container(root, &rootMap);
1025 while (cbor_value_is_valid(&rootMap))
1027 temp = OCRepPayloadCreate();
1028 ret = OC_STACK_NO_MEMORY;
1029 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
1032 ret = OC_STACK_MALFORMED_RESPONSE;
1034 // temporary fix to check for malformed cbor payload
1035 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
1039 if (cbor_value_is_map(&rootMap))
1041 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1042 if (cbor_value_is_valid(&curVal))
1045 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1046 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1051 if (cbor_value_is_map(&rootMap))
1053 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1055 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1056 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1061 if (cbor_value_is_map(&rootMap))
1063 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1065 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1066 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1070 if (cbor_value_is_map(&rootMap))
1072 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1073 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1076 if(rootPayload == NULL)
1083 curPayload->next = temp;
1084 curPayload = curPayload->next;
1087 if (cbor_value_is_array(&rootMap))
1089 err = cbor_value_advance(&rootMap);
1090 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1093 *outPayload = (OCPayload *)rootPayload;
1097 OCRepPayloadDestroy(temp);
1098 OCRepPayloadDestroy(rootPayload);
1099 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1103 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1105 OCStackResult ret = OC_STACK_INVALID_PARAM;
1106 OCPresencePayload *payload = NULL;
1107 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1111 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1112 ret = OC_STACK_NO_MEMORY;
1113 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1114 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1115 ret = OC_STACK_MALFORMED_RESPONSE;
1117 if (cbor_value_is_map(rootValue))
1122 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1123 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1124 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1125 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1128 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1129 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1130 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1131 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1134 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1135 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1136 err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1137 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1139 // Resource type name
1140 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1141 if (cbor_value_is_valid(&curVal))
1144 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1145 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1148 err = cbor_value_advance(rootValue);
1149 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1151 *outPayload = (OCPayload *)payload;
1155 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1156 OCPresencePayloadDestroy(payload);