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_array(&val))
159 err = cbor_value_enter_container(&val, &txtStr);
160 VERIFY_CBOR_SUCCESS(TAG, err, "to enter container");
161 while (cbor_value_is_text_string(&txtStr))
165 err = cbor_value_dup_text_string(&txtStr, &input, &len, NULL);
166 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value.");
169 char *savePtr = NULL;
170 char *curPtr = strtok_r(input, " ", &savePtr);
173 char *trimmed = InPlaceStringTrim(curPtr);
174 if (trimmed[0] !='\0')
176 if (!OCResourcePayloadAddStringLL(resource, trimmed))
178 return CborErrorOutOfMemory;
181 curPtr = strtok_r(NULL, " ", &savePtr);
185 if (cbor_value_is_text_string(&txtStr))
187 err = cbor_value_advance(&txtStr);
188 VERIFY_CBOR_SUCCESS(TAG, err, "to advance string value");
196 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
198 OCStackResult ret = OC_STACK_INVALID_PARAM;
199 OCResourcePayload *resource = NULL;
200 OCDiscoveryPayload *out = NULL;
202 CborError err = CborNoError;
205 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
206 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
207 if (cbor_value_is_array(rootValue))
209 // Root value is already inside the main root array
211 ret = OC_STACK_NO_MEMORY;
212 out = OCDiscoveryPayloadCreate();
213 VERIFY_PARAM_NON_NULL(TAG, out, "Failed error initializing discovery payload");
215 // Enter the main root map
216 ret = OC_STACK_MALFORMED_RESPONSE;
217 err = cbor_value_enter_container(rootValue, &rootMap);
218 VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
222 if (!cbor_value_is_map(&rootMap))
224 OIC_LOG(ERROR, TAG, "Malformed packet!!");
227 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
228 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
229 if (cbor_value_is_valid(&curVal))
231 if (cbor_value_is_byte_string(&curVal))
233 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(out->sid), &len, NULL);
234 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
236 else if (cbor_value_is_text_string(&curVal))
238 err = cbor_value_dup_text_string(&curVal, &(out->sid), &len, NULL);
239 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
243 // BaseURI - Not a mandatory field
244 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
245 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri tag");
246 if (cbor_value_is_valid(&curVal))
248 err = cbor_value_dup_text_string(&curVal, &(out->baseURI), &len, NULL);
249 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
252 // HREF - Not a mandatory field
253 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
254 if (cbor_value_is_valid(&curVal))
256 err = cbor_value_dup_text_string(&curVal, &(out->uri), &len, NULL);
257 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri value");
260 // RT - Not a mandatory field
261 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
262 if (cbor_value_is_valid(&curVal))
264 err = cbor_value_dup_text_string(&curVal, &(out->type), &len, NULL);
265 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
268 // IF - Not a mandatory field
269 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
270 if (cbor_value_is_valid(&curVal))
272 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &out->interface);
276 if (!OCResourcePayloadAddStringLL(&out->interface, OC_RSRVD_INTERFACE_LL))
278 err = CborErrorOutOfMemory;
282 // Name - Not a mandatory field
283 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
284 if (cbor_value_is_valid(&curVal))
286 err = cbor_value_dup_text_string(&curVal, &out->name, &len, NULL);
287 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
290 // Look for Links which will have an array as the value
292 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
293 VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
295 // Enter the links array and start iterating through the array processing
296 // each resource which shows up as a map.
297 CborValue resourceMap;
298 err = cbor_value_enter_container(&linkMap, &resourceMap);
299 VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
301 while (cbor_value_is_map(&resourceMap))
303 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
304 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
307 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
308 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
309 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
310 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
313 err = OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
314 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
317 err = OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
318 if (CborNoError != err)
320 if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
322 OIC_LOG(ERROR, TAG, "Failed to add string to StringLL");
329 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
330 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
333 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
334 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
335 err = cbor_value_get_int(&curVal, (int *)&resource->bitmap);
336 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
339 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
340 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure tag");
341 if (cbor_value_is_valid(&curVal))
343 err = cbor_value_get_boolean(&curVal, &(resource->secure));
344 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
348 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
349 VERIFY_CBOR_SUCCESS(TAG, err, "to find port tag");
350 if (cbor_value_is_valid(&curVal))
352 err = cbor_value_get_int(&curVal, (int *)&resource->port);
353 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
356 err = cbor_value_advance(&resourceMap);
357 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
359 OCDiscoveryPayloadAddNewResource(out, resource);
362 err = cbor_value_leave_container(rootValue, &resourceMap);
363 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
367 OIC_LOG(ERROR, TAG, "Malformed packet ");
371 *outPayload = (OCPayload *)out;
372 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
377 OCDiscoveryResourceDestroy(resource);
378 OCDiscoveryPayloadDestroy(out);
382 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
384 OCStackResult ret = OC_STACK_INVALID_PARAM;
385 CborError err = CborNoError;
386 OCDevicePayload *out = NULL;
387 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
388 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
392 out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
393 VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
394 out->base.type = PAYLOAD_TYPE_DEVICE;
395 ret = OC_STACK_MALFORMED_RESPONSE;
397 if (cbor_value_is_map(rootValue))
401 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
402 if (cbor_value_is_valid(&curVal))
404 err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
405 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
408 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &curVal);
409 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface tag");
410 if (cbor_value_is_valid(&curVal))
412 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &out->interfaces);
413 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
417 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
418 if (cbor_value_is_valid(&curVal))
420 if (cbor_value_is_byte_string(&curVal))
422 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&out->sid, &len, NULL);
423 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
425 else if (cbor_value_is_text_string(&curVal))
427 err = cbor_value_dup_text_string(&curVal, &out->sid, &len, NULL);
428 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
432 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
433 if (cbor_value_is_valid(&curVal))
435 err = cbor_value_dup_text_string(&curVal, &out->deviceName, &len, NULL);
436 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name in device payload");
438 // Device Spec Version
439 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &curVal);
440 if (cbor_value_is_valid(&curVal))
442 err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL);
443 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload");
445 // Data Model Version
446 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal);
447 if (cbor_value_is_valid(&curVal))
449 err = cbor_value_dup_text_string(&curVal, &out->dataModelVersion, &len, NULL);
450 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model version in device payload");
452 err = cbor_value_advance(rootValue);
453 VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload");
455 *outPayload = (OCPayload *)out;
460 OCDevicePayloadDestroy(out);
464 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *rootValue)
466 OCStackResult ret = OC_STACK_INVALID_PARAM;
467 CborError err = CborNoError;
468 OCPlatformInfo info = {0};
470 OCStringLL* interfaces = NULL;
471 OCPlatformPayload* out = NULL;
473 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
475 if (cbor_value_is_map(rootValue))
479 ret = OC_STACK_MALFORMED_RESPONSE;
482 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
483 if (cbor_value_is_valid(&repVal))
485 err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
486 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
489 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
490 if (cbor_value_is_valid(&repVal))
492 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
493 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
496 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
497 if (cbor_value_is_valid(&repVal))
499 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
500 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
503 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
504 if (cbor_value_is_valid(&repVal))
506 err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
507 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
510 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
511 if (cbor_value_is_valid(&repVal))
513 err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
514 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
517 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
518 if (cbor_value_is_valid(&repVal))
520 err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
521 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
524 err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
525 if (cbor_value_is_valid(&repVal))
527 err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
528 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
531 err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
532 if(cbor_value_is_valid(&repVal))
534 err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
535 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
538 err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
539 if(cbor_value_is_valid(&repVal))
541 err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
542 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
545 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
546 if(cbor_value_is_valid(&repVal))
548 err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
549 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
552 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
553 if(cbor_value_is_valid(&repVal))
555 err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
556 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
560 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
561 if(cbor_value_is_valid(&repVal))
563 err = cbor_value_dup_text_string(&repVal, &rt, &len, NULL);
564 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
568 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
569 if(cbor_value_is_valid(&repVal))
571 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
572 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
575 err = cbor_value_advance(rootValue);
576 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
578 out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
580 out->interfaces = interfaces;
581 *outPayload = (OCPayload *)out;
583 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
589 OCPlatformInfoDestroy(&info);
590 OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
594 static OCRepPayloadPropType DecodeCborType(CborType type)
599 return OCREP_PROP_NULL;
600 case CborIntegerType:
601 return OCREP_PROP_INT;
603 return OCREP_PROP_DOUBLE;
604 case CborBooleanType:
605 return OCREP_PROP_BOOL;
606 case CborTextStringType:
607 return OCREP_PROP_STRING;
608 case CborByteStringType:
609 return OCREP_PROP_BYTE_STRING;
611 return OCREP_PROP_OBJECT;
613 return OCREP_PROP_ARRAY;
615 return OCREP_PROP_NULL;
618 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
619 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
621 CborValue insideArray;
622 *type = OCREP_PROP_NULL;
623 dimensions[0] = dimensions[1] = dimensions[2] = 0;
625 CborError err = cbor_value_enter_container(parent, &insideArray);
626 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
628 while (cbor_value_is_valid(&insideArray))
630 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
632 if (tempType == OCREP_PROP_ARRAY)
634 size_t subdim[MAX_REP_ARRAY_DEPTH];
635 tempType = OCREP_PROP_NULL;
636 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
637 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
641 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
644 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
645 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
647 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
649 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
650 return CborUnknownError;
652 else if (*type == OCREP_PROP_NULL)
654 // We don't know the type of this array yet, so the assignment is OK
658 else if (*type == OCREP_PROP_NULL)
660 // We don't know the type of this array yet, so the assignment is OK
663 // tempType is allowed to be NULL, since it might now know the answer yet
664 else if (tempType != OCREP_PROP_NULL && *type != tempType)
666 // this is an invalid situation!
667 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
668 return CborUnknownError;
672 err = cbor_value_advance(&insideArray);
673 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
680 static size_t getAllocSize(OCRepPayloadPropType type)
685 return sizeof (int64_t);
686 case OCREP_PROP_DOUBLE:
687 return sizeof (double);
688 case OCREP_PROP_BOOL:
689 return sizeof (bool);
690 case OCREP_PROP_STRING:
691 return sizeof (char*);
692 case OCREP_PROP_BYTE_STRING:
693 return sizeof (OCByteString);
694 case OCREP_PROP_OBJECT:
695 return sizeof (OCRepPayload*);
701 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
704 (dimensions[1] == 0 ? 1 : dimensions[1]) *
705 (dimensions[2] == 0 ? 1 : dimensions[2]) *
709 static CborError OCParseArrayFillArray(const CborValue *parent,
710 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
712 CborValue insideArray;
715 char *tempStr = NULL;
716 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
718 OCRepPayload *tempPl = NULL;
720 size_t newdim[MAX_REP_ARRAY_DEPTH];
721 newdim[0] = dimensions[1];
722 newdim[1] = dimensions[2];
725 CborError err = cbor_value_enter_container(parent, &insideArray);
726 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
728 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
730 bool noAdvance = false;
731 if (cbor_value_get_type(&insideArray) != CborNullType)
736 if (dimensions[1] == 0)
738 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
742 err = OCParseArrayFillArray(&insideArray, newdim, type,
743 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
746 case OCREP_PROP_DOUBLE:
747 if (dimensions[1] == 0)
749 err = cbor_value_get_double(&insideArray, &(((double*)targetArray)[i]));
753 err = OCParseArrayFillArray(&insideArray, newdim, type,
754 &(((double*)targetArray)[arrayStep(dimensions, i)]));
757 case OCREP_PROP_BOOL:
758 if (dimensions[1] == 0)
760 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
764 err = OCParseArrayFillArray(&insideArray, newdim, type,
765 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
768 case OCREP_PROP_STRING:
769 if (dimensions[1] == 0)
771 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
772 ((char**)targetArray)[i] = tempStr;
777 err = OCParseArrayFillArray(&insideArray, newdim, type,
778 &(((char**)targetArray)[arrayStep(dimensions, i)]));
781 case OCREP_PROP_BYTE_STRING:
782 if (dimensions[1] == 0)
784 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
785 &(ocByteStr.len), NULL);
786 ((OCByteString*)targetArray)[i] = ocByteStr;
790 err = OCParseArrayFillArray(&insideArray, newdim, type,
791 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
794 case OCREP_PROP_OBJECT:
795 if (dimensions[1] == 0)
797 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
798 ((OCRepPayload**)targetArray)[i] = tempPl;
804 err = OCParseArrayFillArray(&insideArray, newdim, type,
805 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
809 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
810 err = CborErrorUnknownType;
813 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
816 if (!noAdvance && cbor_value_is_valid(&insideArray))
818 err = cbor_value_advance(&insideArray);
819 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
827 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
830 OCRepPayloadPropType type = OCREP_PROP_NULL;
831 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
833 size_t allocSize = 0;
835 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
836 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
838 if (type == OCREP_PROP_NULL)
840 res = OCRepPayloadSetNull(out, name);
841 err = (CborError) !res;
842 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
843 err = cbor_value_advance(container);
844 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
848 dimTotal = calcDimTotal(dimensions);
849 allocSize = getAllocSize(type);
850 arr = OICCalloc(dimTotal, allocSize);
851 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
853 res = OCParseArrayFillArray(container, dimensions, type, arr);
854 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
859 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
861 case OCREP_PROP_DOUBLE:
862 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
864 case OCREP_PROP_BOOL:
865 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
867 case OCREP_PROP_STRING:
868 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
870 case OCREP_PROP_BYTE_STRING:
871 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
873 case OCREP_PROP_OBJECT:
874 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
877 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
880 err = (CborError) !res;
881 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
884 if (type == OCREP_PROP_STRING)
886 for(size_t i = 0; i < dimTotal; ++i)
888 OICFree(((char**)arr)[i]);
891 if (type == OCREP_PROP_BYTE_STRING)
893 for(size_t i = 0; i < dimTotal; ++i)
895 OICFree(((OCByteString*)arr)[i].bytes);
898 if (type == OCREP_PROP_OBJECT)
900 for(size_t i = 0; i < dimTotal; ++i)
902 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
909 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
911 CborError err = CborUnknownError;
914 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
915 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
917 if (cbor_value_is_map(objMap))
921 *outPayload = OCRepPayloadCreate();
924 return CborErrorOutOfMemory;
928 OCRepPayload *curPayload = *outPayload;
932 err = cbor_value_enter_container(objMap, &repMap);
933 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
935 while (!err && cbor_value_is_valid(&repMap))
937 if (cbor_value_is_text_string(&repMap))
939 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
940 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
941 err = cbor_value_advance(&repMap);
942 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
945 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
946 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
947 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
949 err = cbor_value_advance(&repMap);
954 CborType type = cbor_value_get_type(&repMap);
958 res = OCRepPayloadSetNull(curPayload, name);
960 case CborIntegerType:
963 err = cbor_value_get_int64(&repMap, &intval);
964 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
965 res = OCRepPayloadSetPropInt(curPayload, name, intval);
970 double doubleval = 0;
971 err = cbor_value_get_double(&repMap, &doubleval);
972 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
973 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
976 case CborBooleanType:
978 bool boolval = false;
979 err = cbor_value_get_boolean(&repMap, &boolval);
980 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
981 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
984 case CborTextStringType:
987 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
988 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
989 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
992 case CborByteStringType:
994 uint8_t* bytestrval = NULL;
995 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
996 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
997 OCByteString tmp = {.bytes = bytestrval, .len = len};
998 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1003 OCRepPayload *pl = NULL;
1004 err = OCParseSingleRepPayload(&pl, &repMap, false);
1005 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
1006 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1010 err = OCParseArray(curPayload, name, &repMap);
1013 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1016 if (type != CborArrayType)
1018 err = (CborError) !res;
1020 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
1022 if (type != CborMapType && cbor_value_is_valid(&repMap))
1024 err = cbor_value_advance(&repMap);
1025 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
1030 if (cbor_value_is_container(objMap))
1032 err = cbor_value_leave_container(objMap, &repMap);
1033 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
1040 OCRepPayloadDestroy(*outPayload);
1045 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
1047 OCStackResult ret = OC_STACK_INVALID_PARAM;
1049 OCRepPayload *temp = NULL;
1050 OCRepPayload *rootPayload = NULL;
1051 OCRepPayload *curPayload = NULL;
1052 CborValue rootMap = *root;
1053 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1054 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
1057 if (cbor_value_is_array(root))
1059 err = cbor_value_enter_container(root, &rootMap);
1061 while (cbor_value_is_valid(&rootMap))
1063 temp = OCRepPayloadCreate();
1064 ret = OC_STACK_NO_MEMORY;
1065 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
1068 ret = OC_STACK_MALFORMED_RESPONSE;
1070 // temporary fix to check for malformed cbor payload
1071 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
1075 if (cbor_value_is_map(&rootMap))
1077 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1078 if (cbor_value_is_valid(&curVal))
1081 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1082 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1087 if (cbor_value_is_map(&rootMap))
1089 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1091 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1092 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1097 if (cbor_value_is_map(&rootMap))
1099 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1101 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1102 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1106 if (cbor_value_is_map(&rootMap))
1108 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1109 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1112 if(rootPayload == NULL)
1119 curPayload->next = temp;
1120 curPayload = curPayload->next;
1123 if (cbor_value_is_array(&rootMap))
1125 err = cbor_value_advance(&rootMap);
1126 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1129 *outPayload = (OCPayload *)rootPayload;
1133 OCRepPayloadDestroy(temp);
1134 OCRepPayloadDestroy(rootPayload);
1135 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1139 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1141 OCStackResult ret = OC_STACK_INVALID_PARAM;
1142 OCPresencePayload *payload = NULL;
1143 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1147 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1148 ret = OC_STACK_NO_MEMORY;
1149 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1150 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1151 ret = OC_STACK_MALFORMED_RESPONSE;
1153 if (cbor_value_is_map(rootValue))
1158 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1159 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1160 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1161 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1164 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1165 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1166 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1167 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1170 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1171 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1172 err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1173 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1175 // Resource type name
1176 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1177 if (cbor_value_is_valid(&curVal))
1180 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1181 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1184 err = cbor_value_advance(rootValue);
1185 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1187 *outPayload = (OCPayload *)payload;
1191 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1192 OCPresencePayloadDestroy(payload);