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");
358 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TCP_PORT, &curVal);
359 if (cbor_value_is_valid(&curVal))
361 err = cbor_value_get_int(&curVal, (int *)&resource->tcpPort);
362 VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp port value");
366 err = cbor_value_advance(&resourceMap);
367 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
369 OCDiscoveryPayloadAddNewResource(out, resource);
372 err = cbor_value_leave_container(rootValue, &resourceMap);
373 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
377 OIC_LOG(ERROR, TAG, "Malformed packet ");
381 *outPayload = (OCPayload *)out;
382 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
387 OCDiscoveryResourceDestroy(resource);
388 OCDiscoveryPayloadDestroy(out);
392 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
394 OCStackResult ret = OC_STACK_INVALID_PARAM;
395 CborError err = CborNoError;
396 OCDevicePayload *out = NULL;
397 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
398 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
402 out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
403 VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
404 out->base.type = PAYLOAD_TYPE_DEVICE;
405 ret = OC_STACK_MALFORMED_RESPONSE;
407 if (cbor_value_is_map(rootValue))
411 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
412 if (cbor_value_is_valid(&curVal))
414 err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
415 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
418 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &curVal);
419 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface tag");
420 if (cbor_value_is_valid(&curVal))
422 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &out->interfaces);
423 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
427 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
428 if (cbor_value_is_valid(&curVal))
430 if (cbor_value_is_byte_string(&curVal))
432 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&out->sid, &len, NULL);
433 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
435 else if (cbor_value_is_text_string(&curVal))
437 err = cbor_value_dup_text_string(&curVal, &out->sid, &len, NULL);
438 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
442 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
443 if (cbor_value_is_valid(&curVal))
445 err = cbor_value_dup_text_string(&curVal, &out->deviceName, &len, NULL);
446 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name in device payload");
448 // Device Spec Version
449 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &curVal);
450 if (cbor_value_is_valid(&curVal))
452 err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL);
453 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload");
455 // Data Model Version
456 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal);
457 if (cbor_value_is_valid(&curVal))
459 err = cbor_value_dup_text_string(&curVal, &out->dataModelVersion, &len, NULL);
460 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model version in device payload");
462 err = cbor_value_advance(rootValue);
463 VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload");
465 *outPayload = (OCPayload *)out;
470 OCDevicePayloadDestroy(out);
474 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *rootValue)
476 OCStackResult ret = OC_STACK_INVALID_PARAM;
477 CborError err = CborNoError;
478 OCPlatformInfo info = {0};
480 OCStringLL* interfaces = NULL;
481 OCPlatformPayload* out = NULL;
483 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
485 if (cbor_value_is_map(rootValue))
489 ret = OC_STACK_MALFORMED_RESPONSE;
492 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
493 if (cbor_value_is_valid(&repVal))
495 err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
496 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
499 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
500 if (cbor_value_is_valid(&repVal))
502 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
503 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
506 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
507 if (cbor_value_is_valid(&repVal))
509 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
510 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
513 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
514 if (cbor_value_is_valid(&repVal))
516 err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
517 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
520 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
521 if (cbor_value_is_valid(&repVal))
523 err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
524 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
527 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
528 if (cbor_value_is_valid(&repVal))
530 err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
531 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
534 err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
535 if (cbor_value_is_valid(&repVal))
537 err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
538 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
541 err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
542 if(cbor_value_is_valid(&repVal))
544 err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
545 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
548 err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
549 if(cbor_value_is_valid(&repVal))
551 err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
552 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
555 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
556 if(cbor_value_is_valid(&repVal))
558 err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
559 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
562 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
563 if(cbor_value_is_valid(&repVal))
565 err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
566 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
570 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
571 if(cbor_value_is_valid(&repVal))
573 err = cbor_value_dup_text_string(&repVal, &rt, &len, NULL);
574 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
578 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
579 if(cbor_value_is_valid(&repVal))
581 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
582 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
585 err = cbor_value_advance(rootValue);
586 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
588 out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
590 out->interfaces = interfaces;
591 *outPayload = (OCPayload *)out;
593 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
599 OCPlatformInfoDestroy(&info);
600 OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
604 static OCRepPayloadPropType DecodeCborType(CborType type)
609 return OCREP_PROP_NULL;
610 case CborIntegerType:
611 return OCREP_PROP_INT;
613 return OCREP_PROP_DOUBLE;
614 case CborBooleanType:
615 return OCREP_PROP_BOOL;
616 case CborTextStringType:
617 return OCREP_PROP_STRING;
618 case CborByteStringType:
619 return OCREP_PROP_BYTE_STRING;
621 return OCREP_PROP_OBJECT;
623 return OCREP_PROP_ARRAY;
625 return OCREP_PROP_NULL;
628 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
629 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
631 CborValue insideArray;
632 *type = OCREP_PROP_NULL;
633 dimensions[0] = dimensions[1] = dimensions[2] = 0;
635 CborError err = cbor_value_enter_container(parent, &insideArray);
636 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
638 while (cbor_value_is_valid(&insideArray))
640 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
642 if (tempType == OCREP_PROP_ARRAY)
644 size_t subdim[MAX_REP_ARRAY_DEPTH];
645 tempType = OCREP_PROP_NULL;
646 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
647 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
651 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
654 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
655 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
657 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
659 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
660 return CborUnknownError;
662 else if (*type == OCREP_PROP_NULL)
664 // We don't know the type of this array yet, so the assignment is OK
668 else if (*type == OCREP_PROP_NULL)
670 // We don't know the type of this array yet, so the assignment is OK
673 // tempType is allowed to be NULL, since it might now know the answer yet
674 else if (tempType != OCREP_PROP_NULL && *type != tempType)
676 // this is an invalid situation!
677 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
678 return CborUnknownError;
682 err = cbor_value_advance(&insideArray);
683 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
690 static size_t getAllocSize(OCRepPayloadPropType type)
695 return sizeof (int64_t);
696 case OCREP_PROP_DOUBLE:
697 return sizeof (double);
698 case OCREP_PROP_BOOL:
699 return sizeof (bool);
700 case OCREP_PROP_STRING:
701 return sizeof (char*);
702 case OCREP_PROP_BYTE_STRING:
703 return sizeof (OCByteString);
704 case OCREP_PROP_OBJECT:
705 return sizeof (OCRepPayload*);
711 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
714 (dimensions[1] == 0 ? 1 : dimensions[1]) *
715 (dimensions[2] == 0 ? 1 : dimensions[2]) *
719 static CborError OCParseArrayFillArray(const CborValue *parent,
720 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
722 CborValue insideArray;
725 char *tempStr = NULL;
726 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
728 OCRepPayload *tempPl = NULL;
730 size_t newdim[MAX_REP_ARRAY_DEPTH];
731 newdim[0] = dimensions[1];
732 newdim[1] = dimensions[2];
735 CborError err = cbor_value_enter_container(parent, &insideArray);
736 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
738 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
740 bool noAdvance = false;
741 if (cbor_value_get_type(&insideArray) != CborNullType)
746 if (dimensions[1] == 0)
748 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
752 err = OCParseArrayFillArray(&insideArray, newdim, type,
753 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
756 case OCREP_PROP_DOUBLE:
757 if (dimensions[1] == 0)
759 err = cbor_value_get_double(&insideArray, &(((double*)targetArray)[i]));
763 err = OCParseArrayFillArray(&insideArray, newdim, type,
764 &(((double*)targetArray)[arrayStep(dimensions, i)]));
767 case OCREP_PROP_BOOL:
768 if (dimensions[1] == 0)
770 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
774 err = OCParseArrayFillArray(&insideArray, newdim, type,
775 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
778 case OCREP_PROP_STRING:
779 if (dimensions[1] == 0)
781 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
782 ((char**)targetArray)[i] = tempStr;
787 err = OCParseArrayFillArray(&insideArray, newdim, type,
788 &(((char**)targetArray)[arrayStep(dimensions, i)]));
791 case OCREP_PROP_BYTE_STRING:
792 if (dimensions[1] == 0)
794 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
795 &(ocByteStr.len), NULL);
796 ((OCByteString*)targetArray)[i] = ocByteStr;
800 err = OCParseArrayFillArray(&insideArray, newdim, type,
801 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
804 case OCREP_PROP_OBJECT:
805 if (dimensions[1] == 0)
807 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
808 ((OCRepPayload**)targetArray)[i] = tempPl;
814 err = OCParseArrayFillArray(&insideArray, newdim, type,
815 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
819 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
820 err = CborErrorUnknownType;
823 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
826 if (!noAdvance && cbor_value_is_valid(&insideArray))
828 err = cbor_value_advance(&insideArray);
829 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
837 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
840 OCRepPayloadPropType type = OCREP_PROP_NULL;
841 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
843 size_t allocSize = 0;
845 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
846 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
848 if (type == OCREP_PROP_NULL)
850 res = OCRepPayloadSetNull(out, name);
851 err = (CborError) !res;
852 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
853 err = cbor_value_advance(container);
854 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
858 dimTotal = calcDimTotal(dimensions);
859 allocSize = getAllocSize(type);
860 arr = OICCalloc(dimTotal, allocSize);
861 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
863 res = OCParseArrayFillArray(container, dimensions, type, arr);
864 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
869 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
871 case OCREP_PROP_DOUBLE:
872 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
874 case OCREP_PROP_BOOL:
875 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
877 case OCREP_PROP_STRING:
878 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
880 case OCREP_PROP_BYTE_STRING:
881 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
883 case OCREP_PROP_OBJECT:
884 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
887 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
890 err = (CborError) !res;
891 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
894 if (type == OCREP_PROP_STRING)
896 for(size_t i = 0; i < dimTotal; ++i)
898 OICFree(((char**)arr)[i]);
901 if (type == OCREP_PROP_BYTE_STRING)
903 for(size_t i = 0; i < dimTotal; ++i)
905 OICFree(((OCByteString*)arr)[i].bytes);
908 if (type == OCREP_PROP_OBJECT)
910 for(size_t i = 0; i < dimTotal; ++i)
912 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
919 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
921 CborError err = CborUnknownError;
924 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
925 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
927 if (cbor_value_is_map(objMap))
931 *outPayload = OCRepPayloadCreate();
934 return CborErrorOutOfMemory;
938 OCRepPayload *curPayload = *outPayload;
942 err = cbor_value_enter_container(objMap, &repMap);
943 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
945 while (!err && cbor_value_is_valid(&repMap))
947 if (cbor_value_is_text_string(&repMap))
949 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
950 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
951 err = cbor_value_advance(&repMap);
952 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
955 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
956 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
957 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
959 err = cbor_value_advance(&repMap);
964 CborType type = cbor_value_get_type(&repMap);
968 res = OCRepPayloadSetNull(curPayload, name);
970 case CborIntegerType:
973 err = cbor_value_get_int64(&repMap, &intval);
974 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
975 res = OCRepPayloadSetPropInt(curPayload, name, intval);
980 double doubleval = 0;
981 err = cbor_value_get_double(&repMap, &doubleval);
982 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
983 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
986 case CborBooleanType:
988 bool boolval = false;
989 err = cbor_value_get_boolean(&repMap, &boolval);
990 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
991 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
994 case CborTextStringType:
997 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
998 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
999 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
1002 case CborByteStringType:
1004 uint8_t* bytestrval = NULL;
1005 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
1006 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
1007 OCByteString tmp = {.bytes = bytestrval, .len = len};
1008 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1013 OCRepPayload *pl = NULL;
1014 err = OCParseSingleRepPayload(&pl, &repMap, false);
1015 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
1016 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1020 err = OCParseArray(curPayload, name, &repMap);
1023 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1026 if (type != CborArrayType)
1028 err = (CborError) !res;
1030 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
1032 if (type != CborMapType && cbor_value_is_valid(&repMap))
1034 err = cbor_value_advance(&repMap);
1035 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
1040 if (cbor_value_is_container(objMap))
1042 err = cbor_value_leave_container(objMap, &repMap);
1043 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
1050 OCRepPayloadDestroy(*outPayload);
1055 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
1057 OCStackResult ret = OC_STACK_INVALID_PARAM;
1059 OCRepPayload *temp = NULL;
1060 OCRepPayload *rootPayload = NULL;
1061 OCRepPayload *curPayload = NULL;
1062 CborValue rootMap = *root;
1063 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1064 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
1067 if (cbor_value_is_array(root))
1069 err = cbor_value_enter_container(root, &rootMap);
1071 while (cbor_value_is_valid(&rootMap))
1073 temp = OCRepPayloadCreate();
1074 ret = OC_STACK_NO_MEMORY;
1075 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
1078 ret = OC_STACK_MALFORMED_RESPONSE;
1080 // temporary fix to check for malformed cbor payload
1081 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
1085 if (cbor_value_is_map(&rootMap))
1087 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1088 if (cbor_value_is_valid(&curVal))
1091 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1092 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1097 if (cbor_value_is_map(&rootMap))
1099 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1101 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1102 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1107 if (cbor_value_is_map(&rootMap))
1109 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1111 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1112 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1116 if (cbor_value_is_map(&rootMap))
1118 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1119 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1122 if(rootPayload == NULL)
1129 curPayload->next = temp;
1130 curPayload = curPayload->next;
1133 if (cbor_value_is_array(&rootMap))
1135 err = cbor_value_advance(&rootMap);
1136 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1139 *outPayload = (OCPayload *)rootPayload;
1143 OCRepPayloadDestroy(temp);
1144 OCRepPayloadDestroy(rootPayload);
1145 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1149 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1151 OCStackResult ret = OC_STACK_INVALID_PARAM;
1152 OCPresencePayload *payload = NULL;
1153 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1157 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1158 ret = OC_STACK_NO_MEMORY;
1159 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1160 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1161 ret = OC_STACK_MALFORMED_RESPONSE;
1163 if (cbor_value_is_map(rootValue))
1168 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1169 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1170 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1171 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1174 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1175 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1176 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1177 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1180 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1181 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1182 err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1183 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1185 // Resource type name
1186 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1187 if (cbor_value_is_valid(&curVal))
1190 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1191 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1194 err = cbor_value_advance(rootValue);
1195 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1197 *outPayload = (OCPayload *)payload;
1201 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1202 OCPresencePayloadDestroy(payload);