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, const uint8_t *payload, size_t size);
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 of Payload Type: %d, Payload:",
59 payloadSize, payloadType);
60 OIC_LOG_BUFFER(DEBUG, TAG, payload, payloadSize);
65 err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
66 VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
70 case PAYLOAD_TYPE_DISCOVERY:
71 result = OCParseDiscoveryPayload(outPayload, &rootValue);
73 case PAYLOAD_TYPE_DEVICE:
74 result = OCParseDevicePayload(outPayload, &rootValue);
76 case PAYLOAD_TYPE_PLATFORM:
77 result = OCParsePlatformPayload(outPayload, &rootValue);
79 case PAYLOAD_TYPE_REPRESENTATION:
80 result = OCParseRepPayload(outPayload, &rootValue);
82 case PAYLOAD_TYPE_PRESENCE:
83 result = OCParsePresencePayload(outPayload, &rootValue);
85 case PAYLOAD_TYPE_SECURITY:
86 result = OCParseSecurityPayload(outPayload, payload, payloadSize);
89 result = OCRDCborToPayload(&rootValue, outPayload);
92 OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
93 result = OC_STACK_INVALID_PARAM;
97 OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
103 void OCFreeOCStringLL(OCStringLL* ll);
105 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
110 *outPayload = (OCPayload *)OCSecurityPayloadCreate(payload, size);
119 static char* InPlaceStringTrim(char* str)
121 while (str[0] == ' ')
126 size_t lastchar = strlen(str);
128 while (str[lastchar] == ' ')
130 str[lastchar] = '\0';
137 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
140 CborError err = cbor_value_map_find_value(map, type, &val);
141 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
143 if (cbor_value_is_text_string(&val))
146 char *savePtr = NULL;
149 err = cbor_value_dup_text_string(&val, &input, &len, NULL);
150 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value");
154 char *curPtr = strtok_r(input, " ", &savePtr);
157 char *trimmed = InPlaceStringTrim(curPtr);
158 if (trimmed[0] !='\0')
160 if (!OCResourcePayloadAddStringLL(resource, trimmed))
162 return CborErrorOutOfMemory;
165 curPtr = strtok_r(NULL, " ", &savePtr);
174 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
176 OCStackResult ret = OC_STACK_INVALID_PARAM;
177 OCResourcePayload *resource = NULL;
178 OCDiscoveryPayload *out = NULL;
180 CborError err = CborNoError;
183 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
184 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
185 if (cbor_value_is_array(rootValue))
187 // Root value is already inside the main root array
189 ret = OC_STACK_NO_MEMORY;
190 out = OCDiscoveryPayloadCreate();
191 VERIFY_PARAM_NON_NULL(TAG, out, "Failed error initializing discovery payload");
193 // Enter the main root map
194 ret = OC_STACK_MALFORMED_RESPONSE;
195 err = cbor_value_enter_container(rootValue, &rootMap);
196 VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
200 if (!cbor_value_is_map(&rootMap))
202 OIC_LOG(ERROR, TAG, "Malformed packet!!");
205 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
206 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
207 if (cbor_value_is_valid(&curVal))
209 if (cbor_value_is_byte_string(&curVal))
211 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(out->sid), &len, NULL);
212 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
214 else if (cbor_value_is_text_string(&curVal))
216 err = cbor_value_dup_text_string(&curVal, &(out->sid), &len, NULL);
217 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
221 // BaseURI - Not a mandatory field
222 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
223 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri tag");
224 if (cbor_value_is_valid(&curVal))
226 err = cbor_value_dup_text_string(&curVal, &(out->baseURI), &len, NULL);
227 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
230 // HREF - Not a mandatory field
231 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
232 if (cbor_value_is_valid(&curVal))
234 err = cbor_value_dup_text_string(&curVal, &(out->uri), &len, NULL);
235 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri value");
238 // RT - Not a mandatory field
239 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
240 if (cbor_value_is_valid(&curVal))
242 err = cbor_value_dup_text_string(&curVal, &(out->type), &len, NULL);
243 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
246 // IF - Not a mandatory field
247 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
248 if (cbor_value_is_valid(&curVal))
250 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &out->interface);
254 if (!OCResourcePayloadAddStringLL(&out->interface, OC_RSRVD_INTERFACE_LL))
256 err = CborErrorOutOfMemory;
260 // Name - Not a mandatory field
261 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
262 if (cbor_value_is_valid(&curVal))
264 err = cbor_value_dup_text_string(&curVal, &out->name, &len, NULL);
265 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
268 // Look for Links which will have an array as the value
270 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
271 VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
273 // Enter the links array and start iterating through the array processing
274 // each resource which shows up as a map.
275 CborValue resourceMap;
276 err = cbor_value_enter_container(&linkMap, &resourceMap);
277 VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
279 while (cbor_value_is_map(&resourceMap))
281 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
282 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
285 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
286 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
287 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
288 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
291 err = OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
292 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
295 err = OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
296 if (CborNoError != err)
298 if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
300 OIC_LOG(ERROR, TAG, "Failed to add string to StringLL");
307 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
308 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
311 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
312 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
313 err = cbor_value_get_int(&curVal, (int *)&resource->bitmap);
314 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
317 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
318 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure tag");
319 if (cbor_value_is_valid(&curVal))
321 err = cbor_value_get_boolean(&curVal, &(resource->secure));
322 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
326 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
327 VERIFY_CBOR_SUCCESS(TAG, err, "to find port tag");
328 if (cbor_value_is_valid(&curVal))
330 err = cbor_value_get_int(&curVal, (int *)&resource->port);
331 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
334 err = cbor_value_advance(&resourceMap);
335 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
337 OCDiscoveryPayloadAddNewResource(out, resource);
340 err = cbor_value_leave_container(rootValue, &resourceMap);
341 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
345 OIC_LOG(ERROR, TAG, "Malformed packet ");
349 *outPayload = (OCPayload *)out;
353 OCDiscoveryResourceDestroy(resource);
354 OCDiscoveryPayloadDestroy(out);
358 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
360 OCStackResult ret = OC_STACK_INVALID_PARAM;
361 CborError err = CborNoError;
362 OCDevicePayload *out = NULL;
363 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
364 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
368 out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
369 VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
370 out->base.type = PAYLOAD_TYPE_DEVICE;
371 ret = OC_STACK_MALFORMED_RESPONSE;
373 if (cbor_value_is_map(rootValue))
377 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
378 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag");
379 if (cbor_value_is_valid(&curVal))
381 err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
382 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
385 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &curVal);
386 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface tag");
387 if (cbor_value_is_valid(&curVal))
389 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &out->interfaces);
390 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
394 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
395 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
396 if (cbor_value_is_valid(&curVal))
398 if (cbor_value_is_byte_string(&curVal))
400 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&out->sid, &len, NULL);
401 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
403 else if (cbor_value_is_text_string(&curVal))
405 err = cbor_value_dup_text_string(&curVal, &out->sid, &len, NULL);
406 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
410 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
411 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name tag");
412 if (cbor_value_is_valid(&curVal))
414 err = cbor_value_dup_text_string(&curVal, &out->deviceName, &len, NULL);
415 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name in device payload");
417 // Device Spec Version
418 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &curVal);
419 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec ver tag");
420 if (cbor_value_is_valid(&curVal))
422 err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL);
423 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload");
425 // Data Model Version
426 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal);
427 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model ver tag");
428 if (cbor_value_is_valid(&curVal))
430 err = cbor_value_dup_text_string(&curVal, &out->dataModelVersion, &len, NULL);
431 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model version in device payload");
433 err = cbor_value_advance(rootValue);
434 VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload");
436 *outPayload = (OCPayload *)out;
441 OCDevicePayloadDestroy(out);
445 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *rootValue)
447 OCStackResult ret = OC_STACK_INVALID_PARAM;
448 CborError err = CborNoError;
449 OCPlatformInfo info = {0};
451 OCStringLL* interfaces = NULL;
452 OCPlatformPayload* out = NULL;
454 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
456 if (cbor_value_is_map(rootValue))
460 ret = OC_STACK_MALFORMED_RESPONSE;
463 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
464 VERIFY_CBOR_SUCCESS(TAG, err, "to find platform id tag");
465 if (cbor_value_is_valid(&repVal))
467 err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
468 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
471 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
472 VERIFY_CBOR_SUCCESS(TAG, err, "to find mfg name tag");
473 if (cbor_value_is_valid(&repVal))
475 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
476 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
479 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
480 VERIFY_CBOR_SUCCESS(TAG, err, "to find mfg url tag");
481 if (cbor_value_is_valid(&repVal))
483 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
484 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
487 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
488 VERIFY_CBOR_SUCCESS(TAG, err, "to find model num tag");
489 if (cbor_value_is_valid(&repVal))
491 err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
492 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
495 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
496 VERIFY_CBOR_SUCCESS(TAG, err, "to find mfg date tag");
497 if (cbor_value_is_valid(&repVal))
499 err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
500 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
503 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
504 VERIFY_CBOR_SUCCESS(TAG, err, "to find platform ver tag");
505 if (cbor_value_is_valid(&repVal))
507 err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
508 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
511 err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
512 VERIFY_CBOR_SUCCESS(TAG, err, "to find os ver tag");
513 if (cbor_value_is_valid(&repVal))
515 err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
516 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
519 err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
520 VERIFY_CBOR_SUCCESS(TAG, err, "to find hw ver tag");
521 if(cbor_value_is_valid(&repVal))
523 err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
524 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
527 err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
528 VERIFY_CBOR_SUCCESS(TAG, err, "to find fw ver tag");
529 if(cbor_value_is_valid(&repVal))
531 err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
532 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
535 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
536 VERIFY_CBOR_SUCCESS(TAG, err, "to find support url tag");
537 if(cbor_value_is_valid(&repVal))
539 err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
540 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
543 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
544 VERIFY_CBOR_SUCCESS(TAG, err, "to find sys time tag");
545 if(cbor_value_is_valid(&repVal))
547 err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
548 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
552 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
553 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag");
554 if(cbor_value_is_valid(&repVal))
556 err = cbor_value_dup_text_string(&repVal, &rt, &len, NULL);
557 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
561 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
562 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface tag");
563 if(cbor_value_is_valid(&repVal))
565 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
566 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
569 err = cbor_value_advance(rootValue);
570 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
572 out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
574 out->interfaces = interfaces;
575 *outPayload = (OCPayload *)out;
576 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
581 OCPlatformInfoDestroy(&info);
582 OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
586 static OCRepPayloadPropType DecodeCborType(CborType type)
591 return OCREP_PROP_NULL;
592 case CborIntegerType:
593 return OCREP_PROP_INT;
596 return OCREP_PROP_DOUBLE;
597 case CborBooleanType:
598 return OCREP_PROP_BOOL;
599 case CborTextStringType:
600 return OCREP_PROP_STRING;
601 case CborByteStringType:
602 return OCREP_PROP_BYTE_STRING;
604 return OCREP_PROP_OBJECT;
606 return OCREP_PROP_ARRAY;
608 return OCREP_PROP_NULL;
611 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
612 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
614 CborValue insideArray;
615 *type = OCREP_PROP_NULL;
616 dimensions[0] = dimensions[1] = dimensions[2] = 0;
618 CborError err = cbor_value_enter_container(parent, &insideArray);
619 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
621 while (cbor_value_is_valid(&insideArray))
623 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
625 if (tempType == OCREP_PROP_ARRAY)
627 size_t subdim[MAX_REP_ARRAY_DEPTH];
628 tempType = OCREP_PROP_NULL;
629 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
630 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
634 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
637 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
638 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
640 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
642 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
643 return CborUnknownError;
645 else if (*type == OCREP_PROP_NULL)
647 // We don't know the type of this array yet, so the assignment is OK
651 else if (*type == OCREP_PROP_NULL)
653 // We don't know the type of this array yet, so the assignment is OK
656 // tempType is allowed to be NULL, since it might now know the answer yet
657 else if (tempType != OCREP_PROP_NULL && *type != tempType)
659 // this is an invalid situation!
660 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
661 return CborUnknownError;
665 err = cbor_value_advance(&insideArray);
666 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
673 static size_t getAllocSize(OCRepPayloadPropType type)
678 return sizeof (int64_t);
679 case OCREP_PROP_DOUBLE:
680 return sizeof (double);
681 case OCREP_PROP_BOOL:
682 return sizeof (bool);
683 case OCREP_PROP_STRING:
684 return sizeof (char*);
685 case OCREP_PROP_BYTE_STRING:
686 return sizeof (OCByteString);
687 case OCREP_PROP_OBJECT:
688 return sizeof (OCRepPayload*);
694 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
697 (dimensions[1] == 0 ? 1 : dimensions[1]) *
698 (dimensions[2] == 0 ? 1 : dimensions[2]) *
702 static CborError OCParseArrayFillArray(const CborValue *parent,
703 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
705 CborValue insideArray;
708 char *tempStr = NULL;
709 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
711 OCRepPayload *tempPl = NULL;
713 size_t newdim[MAX_REP_ARRAY_DEPTH];
714 newdim[0] = dimensions[1];
715 newdim[1] = dimensions[2];
718 CborError err = cbor_value_enter_container(parent, &insideArray);
719 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
721 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
723 bool noAdvance = false;
724 if (cbor_value_get_type(&insideArray) != CborNullType)
729 if (dimensions[1] == 0)
731 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
735 err = OCParseArrayFillArray(&insideArray, newdim, type,
736 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
739 case OCREP_PROP_DOUBLE:
740 if (dimensions[1] == 0)
742 double *d = &(((double*)targetArray)[i]);
743 if (cbor_value_get_type(&insideArray) == CborDoubleType)
745 err = cbor_value_get_double(&insideArray, d);
751 err = cbor_value_get_float(&insideArray, &f);
758 err = OCParseArrayFillArray(&insideArray, newdim, type,
759 &(((double*)targetArray)[arrayStep(dimensions, i)]));
762 case OCREP_PROP_BOOL:
763 if (dimensions[1] == 0)
765 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
769 err = OCParseArrayFillArray(&insideArray, newdim, type,
770 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
773 case OCREP_PROP_STRING:
774 if (dimensions[1] == 0)
776 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
777 ((char**)targetArray)[i] = tempStr;
782 err = OCParseArrayFillArray(&insideArray, newdim, type,
783 &(((char**)targetArray)[arrayStep(dimensions, i)]));
786 case OCREP_PROP_BYTE_STRING:
787 if (dimensions[1] == 0)
789 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
790 &(ocByteStr.len), NULL);
791 ((OCByteString*)targetArray)[i] = ocByteStr;
795 err = OCParseArrayFillArray(&insideArray, newdim, type,
796 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
799 case OCREP_PROP_OBJECT:
800 if (dimensions[1] == 0)
802 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
803 ((OCRepPayload**)targetArray)[i] = tempPl;
809 err = OCParseArrayFillArray(&insideArray, newdim, type,
810 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
814 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
815 err = CborErrorUnknownType;
818 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
821 if (!noAdvance && cbor_value_is_valid(&insideArray))
823 err = cbor_value_advance(&insideArray);
824 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
832 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
835 OCRepPayloadPropType type;
836 size_t dimensions[MAX_REP_ARRAY_DEPTH];
838 size_t allocSize = 0;
840 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
841 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
843 if (type == OCREP_PROP_NULL)
845 res = OCRepPayloadSetNull(out, name);
846 err = (CborError) !res;
847 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
848 err = cbor_value_advance(container);
849 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
853 dimTotal = calcDimTotal(dimensions);
854 allocSize = getAllocSize(type);
855 arr = OICCalloc(dimTotal, allocSize);
856 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
858 res = OCParseArrayFillArray(container, dimensions, type, arr);
859 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
864 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
866 case OCREP_PROP_DOUBLE:
867 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
869 case OCREP_PROP_BOOL:
870 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
872 case OCREP_PROP_STRING:
873 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
875 case OCREP_PROP_BYTE_STRING:
876 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
878 case OCREP_PROP_OBJECT:
879 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
882 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
885 err = (CborError) !res;
886 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
889 if (type == OCREP_PROP_STRING)
891 for(size_t i = 0; i < dimTotal; ++i)
893 OICFree(((char**)arr)[i]);
896 if (type == OCREP_PROP_BYTE_STRING)
898 for(size_t i = 0; i < dimTotal; ++i)
900 OICFree(((OCByteString*)arr)[i].bytes);
903 if (type == OCREP_PROP_OBJECT)
905 for(size_t i = 0; i < dimTotal; ++i)
907 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
914 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
916 CborError err = CborUnknownError;
919 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
920 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
922 if (cbor_value_is_map(objMap))
926 *outPayload = OCRepPayloadCreate();
929 return CborErrorOutOfMemory;
933 OCRepPayload *curPayload = *outPayload;
937 err = cbor_value_enter_container(objMap, &repMap);
938 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
940 while (!err && cbor_value_is_valid(&repMap))
942 if (cbor_value_is_text_string(&repMap))
944 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
945 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
946 err = cbor_value_advance(&repMap);
947 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
950 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
951 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
952 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
954 err = cbor_value_advance(&repMap);
959 CborType type = cbor_value_get_type(&repMap);
963 res = OCRepPayloadSetNull(curPayload, name);
965 case CborIntegerType:
968 err = cbor_value_get_int64(&repMap, &intval);
969 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
970 res = OCRepPayloadSetPropInt(curPayload, name, intval);
975 double doubleval = 0;
976 err = cbor_value_get_double(&repMap, &doubleval);
977 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
978 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
981 case CborBooleanType:
983 bool boolval = false;
984 err = cbor_value_get_boolean(&repMap, &boolval);
985 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
986 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
989 case CborTextStringType:
992 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
993 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
994 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
997 case CborByteStringType:
999 uint8_t* bytestrval = NULL;
1000 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
1001 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
1002 OCByteString tmp = {.bytes = bytestrval, .len = len};
1003 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1008 OCRepPayload *pl = NULL;
1009 err = OCParseSingleRepPayload(&pl, &repMap, false);
1010 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
1011 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1015 err = OCParseArray(curPayload, name, &repMap);
1018 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1021 if (type != CborArrayType)
1023 err = (CborError) !res;
1025 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
1027 if (type != CborMapType && cbor_value_is_valid(&repMap))
1029 err = cbor_value_advance(&repMap);
1030 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
1035 if (cbor_value_is_container(objMap))
1037 err = cbor_value_leave_container(objMap, &repMap);
1038 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
1045 OCRepPayloadDestroy(*outPayload);
1050 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
1052 OCStackResult ret = OC_STACK_INVALID_PARAM;
1054 OCRepPayload *temp = NULL;
1055 OCRepPayload *rootPayload = NULL;
1056 OCRepPayload *curPayload = NULL;
1057 CborValue rootMap = *root;
1058 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1059 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
1062 if (cbor_value_is_array(root))
1064 err = cbor_value_enter_container(root, &rootMap);
1065 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
1067 while (cbor_value_is_valid(&rootMap))
1069 temp = OCRepPayloadCreate();
1070 ret = OC_STACK_NO_MEMORY;
1071 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
1074 ret = OC_STACK_MALFORMED_RESPONSE;
1076 // temporary fix to check for malformed cbor payload
1077 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
1081 if (cbor_value_is_map(&rootMap))
1083 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1084 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
1085 if (cbor_value_is_valid(&curVal))
1088 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1089 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1094 if (cbor_value_is_map(&rootMap))
1096 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1098 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1099 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1104 if (cbor_value_is_map(&rootMap))
1106 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1108 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1109 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1113 if (cbor_value_is_map(&rootMap))
1115 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1116 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1119 if(rootPayload == NULL)
1126 curPayload->next = temp;
1127 curPayload = curPayload->next;
1130 if (cbor_value_is_array(&rootMap))
1132 err = cbor_value_advance(&rootMap);
1133 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1136 *outPayload = (OCPayload *)rootPayload;
1140 OCRepPayloadDestroy(temp);
1141 OCRepPayloadDestroy(rootPayload);
1142 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1146 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1148 OCStackResult ret = OC_STACK_INVALID_PARAM;
1149 OCPresencePayload *payload = NULL;
1150 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1154 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1155 ret = OC_STACK_NO_MEMORY;
1156 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1157 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1158 ret = OC_STACK_MALFORMED_RESPONSE;
1160 if (cbor_value_is_map(rootValue))
1165 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1166 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1167 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1168 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1171 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1172 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1173 err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1174 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1177 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1178 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1179 err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1180 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1182 // Resource type name
1183 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1184 VERIFY_CBOR_SUCCESS(TAG, err, "to find res type tag");
1185 if (cbor_value_is_valid(&curVal))
1188 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1189 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1192 err = cbor_value_advance(rootValue);
1193 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1195 *outPayload = (OCPayload *)payload;
1199 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1200 OCPresencePayloadDestroy(payload);