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 "platform_features.h"
39 #if defined(RD_CLIENT) || defined(RD_SERVER)
40 #include "rdpayload.h"
43 #define TAG "OIC_RI_PAYLOADPARSE"
45 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *arrayVal);
46 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *arrayVal);
47 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *arrayVal);
48 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *repParent, bool isRoot);
49 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *arrayVal);
50 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *arrayVal);
51 static OCStackResult OCParseSecurityPayload(OCPayload **outPayload, const uint8_t *payload, size_t size);
53 OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType,
54 const uint8_t *payload, size_t payloadSize)
56 OCStackResult result = OC_STACK_MALFORMED_RESPONSE;
59 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Conversion of outPayload failed");
60 VERIFY_PARAM_NON_NULL(TAG, payload, "Invalid cbor payload value");
62 OIC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu of Payload Type: %d, Payload:",
63 payloadSize, payloadType);
64 OIC_LOG_BUFFER(DEBUG, TAG, payload, payloadSize);
69 err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
70 VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
74 case PAYLOAD_TYPE_DISCOVERY:
75 result = OCParseDiscoveryPayload(outPayload, &rootValue);
77 case PAYLOAD_TYPE_DEVICE:
78 result = OCParseDevicePayload(outPayload, &rootValue);
80 case PAYLOAD_TYPE_PLATFORM:
81 result = OCParsePlatformPayload(outPayload, &rootValue);
83 case PAYLOAD_TYPE_REPRESENTATION:
84 result = OCParseRepPayload(outPayload, &rootValue);
86 case PAYLOAD_TYPE_PRESENCE:
87 result = OCParsePresencePayload(outPayload, &rootValue);
89 case PAYLOAD_TYPE_SECURITY:
90 result = OCParseSecurityPayload(outPayload, payload, payloadSize);
92 #if defined(RD_CLIENT) || defined(RD_SERVER)
94 result = OCRDCborToPayload(&rootValue, outPayload);
98 OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
99 result = OC_STACK_INVALID_PARAM;
103 OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
109 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
114 *outPayload = (OCPayload *)OCSecurityPayloadCreate(payload, size);
123 static char* InPlaceStringTrim(char* str)
125 while (str[0] == ' ')
130 size_t lastchar = strlen(str);
132 while (str[lastchar] == ' ')
134 str[lastchar] = '\0';
141 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
144 CborError err = cbor_value_map_find_value(map, type, &val);
145 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
147 if (cbor_value_is_array(&val))
150 err = cbor_value_enter_container(&val, &txtStr);
151 VERIFY_CBOR_SUCCESS(TAG, err, "to enter container");
152 while (cbor_value_is_text_string(&txtStr))
156 err = cbor_value_dup_text_string(&txtStr, &input, &len, NULL);
157 VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value.");
160 char *savePtr = NULL;
161 char *curPtr = strtok_r(input, " ", &savePtr);
164 char *trimmed = InPlaceStringTrim(curPtr);
165 if (trimmed[0] !='\0')
167 if (!OCResourcePayloadAddStringLL(resource, trimmed))
169 return CborErrorOutOfMemory;
172 curPtr = strtok_r(NULL, " ", &savePtr);
176 if (cbor_value_is_text_string(&txtStr))
178 err = cbor_value_advance(&txtStr);
179 VERIFY_CBOR_SUCCESS(TAG, err, "to advance string value");
187 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
189 OCStackResult ret = OC_STACK_INVALID_PARAM;
190 OCResourcePayload *resource = NULL;
191 OCDiscoveryPayload *temp = NULL;
192 OCDiscoveryPayload *rootPayload = NULL;
193 OCDiscoveryPayload *curPayload = NULL;
195 CborError err = CborNoError;
198 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
199 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
200 if (cbor_value_is_array(rootValue))
202 // Root value is already inside the main root array
205 // Enter the main root map
206 ret = OC_STACK_MALFORMED_RESPONSE;
207 err = cbor_value_enter_container(rootValue, &rootMap);
208 VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
209 while (cbor_value_is_map(&rootMap))
211 ret = OC_STACK_NO_MEMORY;
212 temp = OCDiscoveryPayloadCreate();
213 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed error initializing discovery payload");
217 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
218 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
219 if (cbor_value_is_valid(&curVal))
221 if (cbor_value_is_byte_string(&curVal))
223 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(temp->sid), &len, NULL);
224 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
226 else if (cbor_value_is_text_string(&curVal))
228 err = cbor_value_dup_text_string(&curVal, &(temp->sid), &len, NULL);
229 VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
233 // BaseURI - Not a mandatory field
234 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
235 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri tag");
236 if (cbor_value_is_valid(&curVal))
238 err = cbor_value_dup_text_string(&curVal, &(temp->baseURI), &len, NULL);
239 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
242 // HREF - Not a mandatory field
243 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
244 if (cbor_value_is_valid(&curVal))
246 err = cbor_value_dup_text_string(&curVal, &(temp->uri), &len, NULL);
247 VERIFY_CBOR_SUCCESS(TAG, err, "to find uri value");
250 // RT - Not a mandatory field
251 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
252 if (cbor_value_is_valid(&curVal))
254 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->type);
255 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
258 // IF - Not a mandatory field
259 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
260 if (cbor_value_is_valid(&curVal))
262 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->iface);
266 if (!OCResourcePayloadAddStringLL(&temp->iface, OC_RSRVD_INTERFACE_LL))
268 err = CborErrorOutOfMemory;
272 // Name - Not a mandatory field
273 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
274 if (cbor_value_is_valid(&curVal))
276 err = cbor_value_dup_text_string(&curVal, &temp->name, &len, NULL);
277 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
280 // Look for Links which will have an array as the value
282 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
283 VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
285 // Enter the links array and start iterating through the array processing
286 // each resource which shows up as a map.
287 CborValue resourceMap;
288 err = cbor_value_enter_container(&linkMap, &resourceMap);
289 VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
291 while (cbor_value_is_map(&resourceMap))
295 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
296 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
299 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
300 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
301 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
302 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
305 err = OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
306 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
309 err = OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
310 if (CborNoError != err)
312 if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
314 OIC_LOG(ERROR, TAG, "Failed to add string to StringLL");
321 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
322 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
325 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
326 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
327 err = cbor_value_get_int(&curVal, &bitmap);
328 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
329 resource->bitmap = (uint8_t)bitmap;
332 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
333 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure tag");
334 if (cbor_value_is_valid(&curVal))
336 err = cbor_value_get_boolean(&curVal, &(resource->secure));
337 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
341 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
342 VERIFY_CBOR_SUCCESS(TAG, err, "to find port tag");
343 if (cbor_value_is_valid(&curVal))
347 err = cbor_value_get_int(&curVal, &port);
348 VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
349 resource->port = (uint16_t)port;
354 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TCP_PORT, &curVal);
355 if (cbor_value_is_valid(&curVal))
359 err = cbor_value_get_int(&curVal, &tcpPort);
360 VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp port value");
361 resource->tcpPort = (uint16_t)tcpPort;
365 err = cbor_value_advance(&resourceMap);
366 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
368 OCDiscoveryPayloadAddNewResource(temp, resource);
371 err = cbor_value_leave_container(&linkMap, &resourceMap);
372 VERIFY_CBOR_SUCCESS(TAG, err, "to leave resource map");
374 err = cbor_value_advance(&rootMap);
375 VERIFY_CBOR_SUCCESS(TAG, err, "to advance root map");
377 if(rootPayload == NULL)
384 curPayload->next = temp;
385 curPayload = curPayload->next;
389 err = cbor_value_leave_container(rootValue, &rootMap);
390 VERIFY_CBOR_SUCCESS(TAG, err, "to leave root map");
395 OIC_LOG(ERROR, TAG, "Malformed packet ");
399 *outPayload = (OCPayload *)rootPayload;
400 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
405 OCDiscoveryResourceDestroy(resource);
406 OCDiscoveryPayloadDestroy(rootPayload);
410 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
412 OCStackResult ret = OC_STACK_INVALID_PARAM;
413 CborError err = CborNoError;
414 OCDevicePayload *out = NULL;
415 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
416 VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
420 out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
421 VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
422 out->base.type = PAYLOAD_TYPE_DEVICE;
423 ret = OC_STACK_MALFORMED_RESPONSE;
425 if (cbor_value_is_map(rootValue))
429 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
430 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag");
432 if (cbor_value_is_valid(&curVal))
434 err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
435 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
438 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &curVal);
439 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface tag");
440 if (cbor_value_is_valid(&curVal))
442 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &out->interfaces);
443 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
447 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
448 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
449 if (cbor_value_is_valid(&curVal))
451 if (cbor_value_is_byte_string(&curVal))
453 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&out->sid, &len, NULL);
454 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
456 else if (cbor_value_is_text_string(&curVal))
458 err = cbor_value_dup_text_string(&curVal, &out->sid, &len, NULL);
459 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
463 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
464 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name tag");
465 if (cbor_value_is_valid(&curVal))
467 err = cbor_value_dup_text_string(&curVal, &out->deviceName, &len, NULL);
468 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name in device payload");
470 // Device Spec Version
471 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &curVal);
472 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec ver tag");
473 if (cbor_value_is_valid(&curVal))
475 err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL);
476 VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload");
478 // Data Model Versions
479 err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal);
480 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model versions tag");
481 if (cbor_value_is_valid(&curVal))
485 err = cbor_value_dup_text_string(&curVal, &str, &len, NULL);
486 VERIFY_CBOR_SUCCESS(TAG, err, "to find data model versions in device payload");
487 out->dataModelVersions = OCCreateOCStringLL(str);
490 err = cbor_value_advance(rootValue);
491 VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload");
493 *outPayload = (OCPayload *)out;
498 OCDevicePayloadDestroy(out);
502 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *rootValue)
504 OCStackResult ret = OC_STACK_INVALID_PARAM;
505 CborError err = CborNoError;
506 OCPlatformInfo info = {0};
507 OCStringLL* rt = NULL;
508 OCStringLL* interfaces = NULL;
509 OCPlatformPayload* out = NULL;
511 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
513 if (cbor_value_is_map(rootValue))
517 ret = OC_STACK_MALFORMED_RESPONSE;
520 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
521 VERIFY_CBOR_SUCCESS(TAG, err, "to find platform id tag");
522 if (cbor_value_is_valid(&repVal))
524 err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
525 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
528 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
529 VERIFY_CBOR_SUCCESS(TAG, err, "to find mfg name tag");
530 if (cbor_value_is_valid(&repVal))
532 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
533 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
536 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
537 VERIFY_CBOR_SUCCESS(TAG, err, "to find mfg url tag");
538 if (cbor_value_is_valid(&repVal))
540 err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
541 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
544 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
545 VERIFY_CBOR_SUCCESS(TAG, err, "to find model num tag");
546 if (cbor_value_is_valid(&repVal))
548 err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
549 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
552 err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
553 VERIFY_CBOR_SUCCESS(TAG, err, "to find mfg date tag");
554 if (cbor_value_is_valid(&repVal))
556 err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
557 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
560 err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
561 VERIFY_CBOR_SUCCESS(TAG, err, "to find platform ver tag");
562 if (cbor_value_is_valid(&repVal))
564 err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
565 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
568 err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
569 VERIFY_CBOR_SUCCESS(TAG, err, "to find os ver tag");
570 if (cbor_value_is_valid(&repVal))
572 err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
573 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
576 err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
577 VERIFY_CBOR_SUCCESS(TAG, err, "to find hw ver tag");
578 if(cbor_value_is_valid(&repVal))
580 err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
581 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
584 err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
585 VERIFY_CBOR_SUCCESS(TAG, err, "to find fw ver tag");
586 if(cbor_value_is_valid(&repVal))
588 err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
589 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
592 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
593 VERIFY_CBOR_SUCCESS(TAG, err, "to find support url tag");
594 if(cbor_value_is_valid(&repVal))
596 err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
597 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
600 err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
601 VERIFY_CBOR_SUCCESS(TAG, err, "to find sys time tag");
602 if(cbor_value_is_valid(&repVal))
604 err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
605 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
609 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
610 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag");
612 if(cbor_value_is_valid(&repVal))
614 err = OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &rt);
615 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
619 err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
620 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface tag");
622 if(cbor_value_is_valid(&repVal))
624 err = OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
625 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
628 err = cbor_value_advance(rootValue);
629 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
631 out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
633 out->interfaces = interfaces;
634 *outPayload = (OCPayload *)out;
635 OIC_LOG_PAYLOAD(DEBUG, *outPayload);
640 OCPlatformInfoDestroy(&info);
641 OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
645 static OCRepPayloadPropType DecodeCborType(CborType type)
650 return OCREP_PROP_NULL;
651 case CborIntegerType:
652 return OCREP_PROP_INT;
655 return OCREP_PROP_DOUBLE;
656 case CborBooleanType:
657 return OCREP_PROP_BOOL;
658 case CborTextStringType:
659 return OCREP_PROP_STRING;
660 case CborByteStringType:
661 return OCREP_PROP_BYTE_STRING;
663 return OCREP_PROP_OBJECT;
665 return OCREP_PROP_ARRAY;
667 return OCREP_PROP_NULL;
670 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
671 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
673 CborValue insideArray;
674 *type = OCREP_PROP_NULL;
675 dimensions[0] = dimensions[1] = dimensions[2] = 0;
677 CborError err = cbor_value_enter_container(parent, &insideArray);
678 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
680 while (cbor_value_is_valid(&insideArray))
682 OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
684 if (tempType == OCREP_PROP_ARRAY)
686 size_t subdim[MAX_REP_ARRAY_DEPTH];
687 tempType = OCREP_PROP_NULL;
688 err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
689 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
693 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
696 dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
697 dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
699 if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
701 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
702 return CborUnknownError;
704 else if (*type == OCREP_PROP_NULL)
706 // We don't know the type of this array yet, so the assignment is OK
710 else if (*type == OCREP_PROP_NULL)
712 // We don't know the type of this array yet, so the assignment is OK
715 // tempType is allowed to be NULL, since it might now know the answer yet
716 else if (tempType != OCREP_PROP_NULL && *type != tempType)
718 // this is an invalid situation!
719 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
720 return CborUnknownError;
724 err = cbor_value_advance(&insideArray);
725 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
732 static size_t getAllocSize(OCRepPayloadPropType type)
737 return sizeof (int64_t);
738 case OCREP_PROP_DOUBLE:
739 return sizeof (double);
740 case OCREP_PROP_BOOL:
741 return sizeof (bool);
742 case OCREP_PROP_STRING:
743 return sizeof (char*);
744 case OCREP_PROP_BYTE_STRING:
745 return sizeof (OCByteString);
746 case OCREP_PROP_OBJECT:
747 return sizeof (OCRepPayload*);
753 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
756 (dimensions[1] == 0 ? 1 : dimensions[1]) *
757 (dimensions[2] == 0 ? 1 : dimensions[2]) *
761 static CborError OCParseArrayFillArray(const CborValue *parent,
762 size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
764 CborValue insideArray;
767 char *tempStr = NULL;
768 OCByteString ocByteStr = { .bytes = NULL, .len = 0};
770 OCRepPayload *tempPl = NULL;
772 size_t newdim[MAX_REP_ARRAY_DEPTH];
773 newdim[0] = dimensions[1];
774 newdim[1] = dimensions[2];
777 CborError err = cbor_value_enter_container(parent, &insideArray);
778 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
780 while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
782 bool noAdvance = false;
783 if (cbor_value_get_type(&insideArray) != CborNullType)
788 if (dimensions[1] == 0)
790 err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
794 err = OCParseArrayFillArray(&insideArray, newdim, type,
795 &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
798 case OCREP_PROP_DOUBLE:
799 if (dimensions[1] == 0)
801 double *d = &(((double*)targetArray)[i]);
802 if (cbor_value_get_type(&insideArray) == CborDoubleType)
804 err = cbor_value_get_double(&insideArray, d);
810 err = cbor_value_get_float(&insideArray, &f);
817 err = OCParseArrayFillArray(&insideArray, newdim, type,
818 &(((double*)targetArray)[arrayStep(dimensions, i)]));
821 case OCREP_PROP_BOOL:
822 if (dimensions[1] == 0)
824 err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
828 err = OCParseArrayFillArray(&insideArray, newdim, type,
829 &(((bool*)targetArray)[arrayStep(dimensions, i)]));
832 case OCREP_PROP_STRING:
833 if (dimensions[1] == 0)
835 err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
836 ((char**)targetArray)[i] = tempStr;
841 err = OCParseArrayFillArray(&insideArray, newdim, type,
842 &(((char**)targetArray)[arrayStep(dimensions, i)]));
845 case OCREP_PROP_BYTE_STRING:
846 if (dimensions[1] == 0)
848 err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
849 &(ocByteStr.len), NULL);
850 ((OCByteString*)targetArray)[i] = ocByteStr;
854 err = OCParseArrayFillArray(&insideArray, newdim, type,
855 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
858 case OCREP_PROP_OBJECT:
859 if (dimensions[1] == 0)
861 err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
862 ((OCRepPayload**)targetArray)[i] = tempPl;
868 err = OCParseArrayFillArray(&insideArray, newdim, type,
869 &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
873 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
874 err = CborErrorUnknownType;
877 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
880 if (!noAdvance && cbor_value_is_valid(&insideArray))
882 err = cbor_value_advance(&insideArray);
883 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
891 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
895 OCRepPayloadPropType type = OCREP_PROP_NULL;
896 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
899 size_t allocSize = 0;
901 CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
902 VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
904 if (type == OCREP_PROP_NULL)
906 res = OCRepPayloadSetNull(out, name);
907 err = (CborError) !res;
908 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
909 err = cbor_value_advance(container);
910 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
914 dimTotal = calcDimTotal(dimensions);
915 allocSize = getAllocSize(type);
916 arr = OICCalloc(dimTotal, allocSize);
917 VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
919 res = OCParseArrayFillArray(container, dimensions, type, arr);
920 VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
925 res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
927 case OCREP_PROP_DOUBLE:
928 res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
930 case OCREP_PROP_BOOL:
931 res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
933 case OCREP_PROP_STRING:
934 res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
936 case OCREP_PROP_BYTE_STRING:
937 res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
939 case OCREP_PROP_OBJECT:
940 res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
943 OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
946 err = (CborError) !res;
947 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
950 if (type == OCREP_PROP_STRING)
952 for(size_t i = 0; i < dimTotal; ++i)
954 OICFree(((char**)arr)[i]);
957 if (type == OCREP_PROP_BYTE_STRING)
959 for(size_t i = 0; i < dimTotal; ++i)
961 OICFree(((OCByteString*)arr)[i].bytes);
964 if (type == OCREP_PROP_OBJECT)
966 for(size_t i = 0; i < dimTotal; ++i)
968 OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
975 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
977 CborError err = CborUnknownError;
980 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
981 VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
983 if (cbor_value_is_map(objMap))
987 *outPayload = OCRepPayloadCreate();
990 return CborErrorOutOfMemory;
994 OCRepPayload *curPayload = *outPayload;
998 err = cbor_value_enter_container(objMap, &repMap);
999 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
1001 while (!err && cbor_value_is_valid(&repMap))
1003 if (cbor_value_is_text_string(&repMap))
1005 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
1006 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
1007 err = cbor_value_advance(&repMap);
1008 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
1011 ((0 == strcmp(OC_RSRVD_HREF, name)) ||
1012 (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
1013 (0 == strcmp(OC_RSRVD_INTERFACE, name))))
1015 err = cbor_value_advance(&repMap);
1020 CborType type = cbor_value_get_type(&repMap);
1024 res = OCRepPayloadSetNull(curPayload, name);
1026 case CborIntegerType:
1029 err = cbor_value_get_int64(&repMap, &intval);
1030 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
1031 res = OCRepPayloadSetPropInt(curPayload, name, intval);
1034 case CborDoubleType:
1036 double doubleval = 0;
1037 err = cbor_value_get_double(&repMap, &doubleval);
1038 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
1039 res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
1042 case CborBooleanType:
1044 bool boolval = false;
1045 err = cbor_value_get_boolean(&repMap, &boolval);
1046 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
1047 res = OCRepPayloadSetPropBool(curPayload, name, boolval);
1050 case CborTextStringType:
1052 char *strval = NULL;
1053 err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
1054 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
1055 res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
1058 case CborByteStringType:
1060 uint8_t* bytestrval = NULL;
1061 err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
1062 VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
1063 OCByteString tmp = {.bytes = bytestrval, .len = len};
1064 res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1069 OCRepPayload *pl = NULL;
1070 err = OCParseSingleRepPayload(&pl, &repMap, false);
1071 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
1072 res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1076 err = OCParseArray(curPayload, name, &repMap);
1079 OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1082 if (type != CborArrayType)
1084 err = (CborError) !res;
1086 VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
1088 if (type != CborMapType && cbor_value_is_valid(&repMap))
1090 err = cbor_value_advance(&repMap);
1091 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
1096 if (cbor_value_is_container(objMap))
1098 err = cbor_value_leave_container(objMap, &repMap);
1099 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
1106 OCRepPayloadDestroy(*outPayload);
1111 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
1113 OCStackResult ret = OC_STACK_INVALID_PARAM;
1115 OCRepPayload *temp = NULL;
1116 OCRepPayload *rootPayload = NULL;
1117 OCRepPayload *curPayload = NULL;
1118 CborValue rootMap = *root;
1119 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1120 VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
1123 if (cbor_value_is_array(root))
1125 err = cbor_value_enter_container(root, &rootMap);
1126 VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
1128 while (cbor_value_is_valid(&rootMap))
1130 temp = OCRepPayloadCreate();
1131 ret = OC_STACK_NO_MEMORY;
1132 VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
1135 ret = OC_STACK_MALFORMED_RESPONSE;
1137 // temporary fix to check for malformed cbor payload
1138 if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
1142 if (cbor_value_is_map(&rootMap))
1144 err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
1145 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
1146 if (cbor_value_is_valid(&curVal))
1149 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1150 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1155 if (cbor_value_is_map(&rootMap))
1157 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1159 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1160 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1165 if (cbor_value_is_map(&rootMap))
1167 if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1169 err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1170 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1174 if (cbor_value_is_map(&rootMap))
1176 err = OCParseSingleRepPayload(&temp, &rootMap, true);
1177 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1180 if(rootPayload == NULL)
1187 curPayload->next = temp;
1188 curPayload = curPayload->next;
1191 if (cbor_value_is_array(&rootMap))
1193 err = cbor_value_advance(&rootMap);
1194 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1197 *outPayload = (OCPayload *)rootPayload;
1201 OCRepPayloadDestroy(temp);
1202 OCRepPayloadDestroy(rootPayload);
1203 OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1207 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1209 OCStackResult ret = OC_STACK_INVALID_PARAM;
1210 OCPresencePayload *payload = NULL;
1211 VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1215 payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1216 ret = OC_STACK_NO_MEMORY;
1217 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1218 payload->base.type = PAYLOAD_TYPE_PRESENCE;
1219 ret = OC_STACK_MALFORMED_RESPONSE;
1221 if (cbor_value_is_map(rootValue))
1228 CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1229 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1230 err = cbor_value_get_uint64(&curVal, &temp);
1231 payload->sequenceNumber = (uint32_t)temp;
1232 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1235 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1236 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1238 err = cbor_value_get_uint64(&curVal, &temp);
1239 payload->maxAge = (uint32_t)temp;
1240 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1243 err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1244 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1245 err = cbor_value_get_simple_type(&curVal, &trigger);
1246 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1247 payload->trigger = (OCPresenceTrigger)trigger;
1249 // Resource type name
1250 err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1251 VERIFY_CBOR_SUCCESS(TAG, err, "to find res type tag");
1252 if (cbor_value_is_valid(&curVal))
1255 err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1256 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1259 err = cbor_value_advance(rootValue);
1260 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1262 *outPayload = (OCPayload *)payload;
1266 OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1267 OCPresencePayloadDestroy(payload);